async def create_action(db_session, form_directory, ax_form, action): """ Creates new AxAction """ err = "marketplace_schema -> create_action" with ax_model.try_catch(db_session, err) as db_session: code = None action_id = str(action['guid']) if action['db_name']: action_id = action['db_name'] action_py_path = form_directory / f'action_{action_id}.py' if os.path.exists(action_py_path): with open(action_py_path, 'r', encoding="utf-8") as action_file: code = action_file.read() new_action = AxAction() new_action.guid = ax_misc.guid_or_none(action['guid']) new_action.name = action['name'] new_action.db_name = action['db_name'] new_action.form_guid = ax_form.guid new_action.from_state_guid = ax_misc.guid_or_none( action['from_state_guid']) new_action.to_state_guid = ax_misc.guid_or_none( action['to_state_guid']) new_action.code = code new_action.confirm_text = action['confirm_text'] new_action.close_modal = action['close_modal'] new_action.icon = action['icon'] new_action.radius = float(action['radius'] or 0) db_session.add(new_action) for role_guid in action['roles']: await create_action2role(db_session=db_session, action_guid=action['guid'], role_guid=role_guid)
async def create_form(db_session, form): """ Create or update AxForm """ err = "marketplace_schema -> create_form" with ax_model.try_catch(db_session, err) as db_session: existing_form = db_session.query(AxForm).filter( AxForm.guid == ax_misc.guid_or_none(form['guid'])).first() new_form = None form_is_new = False if existing_form: existing_form.name = form['name'] existing_form.tom_label = form['tom_label'] existing_form.icon = form['icon'] else: form_is_new = True new_form = AxForm() new_form.guid = ax_misc.guid_or_none(form['guid']) new_form.name = form['name'] new_form.db_name = form['db_name'] new_form.position = int(form['position'] or 0) new_form.parent = ax_misc.guid_or_none(form['parent']) new_form.tom_label = form['tom_label'] new_form.icon = form['icon'] db_session.add(new_form) await ax_dialects.dialect.create_data_table( db_session=db_session, db_name=form['db_name']) db_session.commit() ret_form = existing_form or new_form return form_is_new, ret_form
async def create_role(db_session, ax_form, role, form_path): """ Create or update AxRole """ err = "marketplace_schema -> create_role" with ax_model.try_catch(db_session, err) as db_session: existing_role = db_session.query(AxRole).filter( AxRole.guid == ax_misc.guid_or_none(role['guid'])).first() new_role = None code = None role_db_name = re.sub(r'[\W_]+', '', role['name']) role_py_path = form_path / f'role_{role_db_name}.py' if os.path.exists(role_py_path): with open(role_py_path, 'r', encoding="utf-8") as role_file: code = role_file.read() if existing_role: existing_role.name = role['name'] existing_role.icon = role.get('icon', None) else: new_role = AxRole() new_role.guid = ax_misc.guid_or_none(role['guid']) new_role.name = role['name'] new_role.form_guid = ax_form.guid new_role.icon = role.get('icon', None) new_role.is_dynamic = role.get('is_dynamic', False) new_role.code = code db_session.add(new_role)
async def create_state(db_session, ax_form, state): """ Create or update AxState """ err = "marketplace_schema -> create_state" with ax_model.try_catch(db_session, err) as db_session: existing_state = db_session.query(AxState).filter( AxState.guid == ax_misc.guid_or_none(state['guid'])).first() new_state = None if existing_state: existing_state.name = state['name'] existing_state.x = float(state['x'] or 0) existing_state.y = float(state['y'] or 0) else: new_state = AxState() new_state.guid = ax_misc.guid_or_none(state['guid']) new_state.name = state['name'] new_state.form_guid = ax_form.guid new_state.is_start = state['is_start'] new_state.is_deleted = state['is_deleted'] new_state.is_all = state['is_all'] new_state.x = float(state['x'] or 0) new_state.y = float(state['y'] or 0) db_session.add(new_state) for role_guid in state['roles']: await create_state2role(db_session=db_session, state_guid=state['guid'], role_guid=role_guid)
async def mutate(self, info, **args): # pylint: disable=missing-docstring err = 'Error in gql mutation - fields_schema -> CreateMessage.' with ax_model.try_catch(info.context['session'], err) as db_session: thread_guid = args.get('thread_guid') text = args.get('text') data_json = args.get('data_json') current_user = info.context['user'] user_guid = current_user.get('user_id', None) user_email = current_user.get('email', None) parent = args.get('parent') data = None if data_json: try: data = json.loads(data_json) except ValueError: logger.exception( 'Error decoding data_json on creating AxMessage') thread = db_session.query(AxMessageThread).filter( AxMessageThread.guid == uuid.UUID(args.get('thread_guid')) ).first() if not thread: thread = AxMessageThread() thread.guid = uuid.UUID(thread_guid) db_session.add(thread) db_session.flush() new_message = AxMessage() new_message.author_guid = ax_misc.guid_or_none(user_guid) new_message.author_email = user_email new_message.text = text new_message.data_json = data new_message.thread_guid = thread.guid new_message.parent = ax_misc.guid_or_none(parent) db_session.add(new_message) db_session.flush() created_message = db_session.query(AxMessage).filter( AxMessage.guid == new_message.guid ).options(joinedload(AxMessage.author)).first() # joinedload(Event.user) db_session.expunge(created_message) db_session.expunge(created_message.author) ax_pubsub.publisher.publish( aiopubsub.Key('thread_message'), { "thread_guid": str(created_message.thread_guid), "ax_message": created_message }) return CreateMessage(message=new_message, ok=True)
async def create_role_field_perm(db_session, ax_form, perm): """ AxRoleFieldPermission creaes new """ err = "marketplace_schema -> create_role_field_perm" with ax_model.try_catch(db_session, err) as db_session: new_perm = AxRoleFieldPermission() new_perm.role_guid = ax_misc.guid_or_none(str(perm['role_guid'])) new_perm.state_guid = ax_misc.guid_or_none(str(perm['state_guid'])) new_perm.field_guid = ax_misc.guid_or_none(str(perm['field_guid'])) new_perm.form_guid = ax_form.guid new_perm.read = perm['read'] new_perm.edit = perm['edit'] db_session.add(new_perm)
async def create_metric(db_session, metric): """ Create AxMetric if not exists """ err = "marketplace_schema -> create_metric" with ax_model.try_catch(db_session, err) as db_session: existing_metric = db_session.query(AxMetric).filter( AxMetric.guid == ax_misc.guid_or_none(metric['guid'])).first() if not existing_metric: new_metric = AxMetric() new_metric.guid = ax_misc.guid_or_none(metric['guid']) new_metric.key = metric['key'] new_metric.value = metric['value'] db_session.add(new_metric)
async def create_action2role(db_session, action_guid, role_guid): """ Create or update AxAction2Role """ err = "marketplace_schema -> create_action2role" with ax_model.try_catch(db_session, err) as db_session: existing_a2r = db_session.query(AxAction2Role).filter( AxAction2Role.action_guid == ax_misc.guid_or_none( action_guid)).filter(AxAction2Role.role_guid == ax_misc.guid_or_none(role_guid)).first() if not existing_a2r: new_a2r = AxAction2Role() new_a2r.action_guid = ax_misc.guid_or_none(action_guid) new_a2r.role_guid = ax_misc.guid_or_none(role_guid) db_session.add(new_a2r)
async def create_tom_references(db_session, ax_form, form_directory): """ # Ax1tomReference[] - only insert if not exists """ err = "marketplace_schema -> create_tom_references" with ax_model.try_catch(db_session, err) as db_session: tom_yaml_path = form_directory / 'tom_reference.yaml' if not os.path.exists(tom_yaml_path): return False with open(tom_yaml_path, 'r', encoding="utf-8") as tom_yaml_file: tom_yaml = yaml.load(tom_yaml_file) for ref in tom_yaml: new_ref = Ax1tomReference() new_ref.form_guid = ax_form.guid new_ref.field_guid = ax_misc.guid_or_none(ref['field_guid']) new_ref.row_guid = ax_misc.guid_or_none(ref['row_guid']) new_ref.child_guid = ax_misc.guid_or_none(ref['child_guid']) new_ref.field_guid = ax_misc.guid_or_none(ref['field_guid']) db_session.add(new_ref)
async def create_folder(db_session, folder): """ Create or update AxForm that is folder """ err = "marketplace_schema -> create_folder" with ax_model.try_catch(db_session, err) as db_session: existing_folder = db_session.query(AxForm).filter( AxForm.guid == ax_misc.guid_or_none(folder['guid'])).filter( AxForm.is_folder.is_(True)).first() if existing_folder: existing_folder.name = folder['name'] else: new_folder = AxForm() new_folder.guid = ax_misc.guid_or_none(folder['guid']) new_folder.name = folder['name'] new_folder.is_folder = True new_folder.position = int(folder['position'] or 0) new_folder.parent = ax_misc.guid_or_none(folder['parent']) db_session.add(new_folder)
async def resolve_ax_role(self, info, guid, update_time=None): """Get AxRole with code""" del update_time err = 'Error in GQL query - resolve_ax_role.' with ax_model.try_catch(info.context['session'], err, no_commit=True): query = Role.get_query(info) # SQLAlchemy query role_guid = ax_misc.guid_or_none(guid) ret_role = query.filter(AxRole.guid == role_guid).first() return ret_role
async def create_field(db_session, ax_form, field): """ Create or update AxField """ err = "marketplace_schema -> create_field" with ax_model.try_catch(db_session, err) as db_session: existing_field = db_session.query(AxField).filter( AxField.guid == ax_misc.guid_or_none(field['guid'])).first() if existing_field: existing_field.name = field['name'] existing_field.options_json = field['options_json'] existing_field.private_options_json = field['private_options_json'] existing_field.is_required = field['is_required'] existing_field.is_whole_row = field['is_whole_row'] existing_field.parent = ax_misc.guid_or_none(field['parent']) existing_field.position = int(field['position'] or 0) else: new_field = AxField() new_field.guid = ax_misc.guid_or_none(field['guid']) new_field.form_guid = ax_form.guid new_field.name = field['name'] new_field.db_name = field['db_name'] new_field.options_json = field['options_json'] new_field.private_options_json = field['private_options_json'] new_field.field_type_tag = field['field_type_tag'] new_field.is_tab = field['is_tab'] new_field.is_required = field['is_required'] new_field.is_whole_row = field['is_whole_row'] new_field.parent = ax_misc.guid_or_none(field['parent']) new_field.position = int(field['position'] or 0) db_session.add(new_field) # Field is not tab if field['field_type_tag']: ax_field_type = db_session.query(AxFieldType).filter( AxFieldType.tag == field['field_type_tag']).first() if not ax_field_type.is_virtual: await ax_dialects.dialect.add_column( db_session=db_session, table=ax_form.db_name, db_name=field['db_name'], type_name=ax_field_type.value_type) db_session.commit()
async def create_grid(db_session, form_directory, ax_form, grid): """ Create or update AxGrid """ err = "marketplace_schema -> create_grid" with ax_model.try_catch(db_session, err) as db_session: code = None existing_grid = db_session.query(AxGrid).filter( AxGrid.guid == ax_misc.guid_or_none(grid['guid'])).first() new_grid = None grid_py_path = form_directory / f'grid_{grid["db_name"]}.py' if os.path.exists(grid_py_path): with open(grid_py_path, 'r', encoding="utf-8") as grid_file: code = grid_file.read() if existing_grid: existing_grid.name = grid['name'] existing_grid.db_name = grid['db_name'] existing_grid.position = int(grid['position'] or 0) existing_grid.options_json = grid['options_json'] existing_grid.code = code existing_grid.is_default_view = grid['is_default_view'] else: new_grid = AxGrid() new_grid.guid = ax_misc.guid_or_none(grid['guid']) new_grid.name = grid['name'] new_grid.db_name = grid['db_name'] new_grid.position = int(grid['position'] or 0) new_grid.options_json = grid['options_json'] new_grid.code = code new_grid.form_guid = ax_form.guid new_grid.is_default_view = grid['is_default_view'] db_session.add(new_grid) for column in grid['columns']: await create_column(db_session=db_session, grid_guid=grid['guid'], column=column) return existing_grid or new_grid
async def create_column(db_session, grid_guid, column): """ Create or update AxColumn """ err = "marketplace_schema -> create_column" with ax_model.try_catch(db_session, err) as db_session: existing_column = db_session.query(AxColumn).filter( AxColumn.guid == ax_misc.guid_or_none(column['guid'])).first() new_column = None if existing_column: existing_column.position = int(column['position'] or 0) existing_column.options_json = column['options_json'] existing_column.column_type = column['column_type'] existing_column.aggregation_type = column['aggregation_type'] else: new_column = AxColumn() new_column.guid = ax_misc.guid_or_none(column['guid']) new_column.position = int(column['position'] or 0) new_column.options_json = column['options_json'] new_column.field_guid = ax_misc.guid_or_none(column['field_guid']) new_column.grid_guid = ax_misc.guid_or_none(grid_guid) new_column.column_type = column['column_type'] new_column.aggregation_type = column['aggregation_type'] db_session.add(new_column)
async def create_page(db_session, page, package_directory, ax_root_guid, app_root_guid): """ Create AxPage from application package data """ err = "marketplace_schema -> create_page" with ax_model.try_catch(db_session, err) as db_session: code = None page_name = str(page['guid']) if page['db_name']: page_name = page['db_name'] page_md_path = package_directory / '_pages' / f'page_{page_name}.md' if os.path.exists(page_md_path): with open(page_md_path, 'r', encoding="utf-8") as page_file: code = page_file.read() existing_page = db_session.query(AxPage).filter( AxPage.guid == ax_misc.guid_or_none(page['guid'])).first() if existing_page: existing_page.name = page['name'] existing_page.db_name = page['db_name'] existing_page.position = int(page['position'] or 0) existing_page.parent = ax_misc.guid_or_none(page['parent']) existing_page.code = code else: cur_parent = page['parent'] if page['guid'] == app_root_guid: cur_parent = ax_root_guid new_page = AxPage() new_page.guid = ax_misc.guid_or_none(page['guid']) new_page.name = page['name'] new_page.db_name = page['db_name'] new_page.position = int(page['position'] or 0) new_page.parent = ax_misc.guid_or_none(cur_parent) new_page.code = code db_session.add(new_page)
async def check_existing_form(db_session, package_directory, form_db_name): """ Checks if AxForm with such db_name already exists. Aborts installation if found """ form_directory = package_directory / form_db_name yaml_path = form_directory / f'{form_db_name}.yaml' form_guid = None with open(yaml_path, 'r', encoding="utf-8") as form_yaml_file: form_yaml = yaml.load(form_yaml_file) form_guid = form_yaml["AxForm"]["guid"] existing_form = db_session.query(AxForm).filter( AxForm.db_name == form_db_name).first() if existing_form.guid != ax_misc.guid_or_none(form_guid): err = (f'Can not create AxForm [{form_db_name}]. Form with same ' f'db_name already exists.\nInstallation is aborted ☠️') logger.exception(err) await terminal_log(f'\n\n\n{err}') raise Exception(err)
async def create_message(thread_guid, text): thread = None if thread_guid and thread_guid != 'None': thread = db_session.query(AxMessageThread).filter( AxMessageThread.guid == uuid.UUID(str(thread_guid))).first() if not thread: thread = AxMessageThread() thread.guid = uuid.UUID(str(thread_guid)) db_session.add(thread) db_session.flush() new_message = AxMessage() new_message.author_guid = ax_misc.guid_or_none(current_user_guid) new_message.author_email = current_user_email new_message.text = text new_message.data_json = None new_message.thread_guid = thread.guid db_session.add(new_message) db_session.flush()
async def mutate(self, info, **args): # pylint: disable=missing-docstring # avatar_tmp = args.get('avatar_tmp') guid = args.get('guid') err = 'Error in gql mutation - users_schema -> ChangeUserPassword.' with ax_model.try_catch(info.context['session'], err) as db_session: ax_user = db_session.query(AxUser).filter( AxUser.guid == uuid.UUID(guid)).first() current_user = info.context['user'] user_guid = current_user.get('user_id', None) if current_user else None if not ax_user or ax_user.guid != ax_misc.guid_or_none(user_guid): return None ax_user.password = pbkdf2_sha256.hash(args.get('password')) ax_user.password_must_change = False db_session.flush() return ChangeUserPassword(user=ax_user, ok=True)
async def retrieve_user(request, payload, *args, **kwargs): """ Get user info. This info is transfered into routes with inject_user """ del request, args, kwargs if payload: user_id = payload.get('user_id') or None if not ax_misc.string_is_guid(user_id): return None email = await ax_cache.cache.get(f'user_email_{user_id}') if not email: msg = "Auth -> retrieve_user" with ax_model.scoped_session(msg) as db_session: user = db_session.query(AxUser).filter( AxUser.guid == ax_misc.guid_or_none(user_id) ).first() if user is not None: # raise exceptions.AuthenticationFailed("User not found.") await check_if_admin( user_guid=user_id, db_session=db_session) await write_perm_cache( db_session=db_session, user_guid=user_id) await write_info_cache(user) email = await ax_cache.cache.get(f'user_email_{user_id}') short_name = await ax_cache.cache.get(f'user_short_name_{user_id}') is_admin = await ax_cache.cache.get(f'user_is_admin_{user_id}') user = { "user_id": str(user_id), "is_admin": is_admin, "short_name": short_name, "email": email } return user else: return None
async def insert_data(db_session, ax_form, form_directory): """ Inserts data from package """ err = "marketplace_schema -> insert_data" with ax_model.try_catch(db_session, err) as db_session: data_yaml_path = form_directory / 'data.yaml' if not os.path.exists(data_yaml_path): return False with open(data_yaml_path, 'r', encoding="utf-8") as data_yaml_file: data_yaml = yaml.load(data_yaml_file) for row in data_yaml: tobe_form = db_session.query(AxForm).filter( AxForm.guid == ax_form.guid).first() for field in tobe_form.db_fields: if field.db_name in row.keys(): field.value = clean_yaml_value(row=row, field=field) field.needs_sql_update = True await ax_dialects.dialect.insert(db_session=db_session, form=tobe_form, to_state_name=row["axState"], new_guid=ax_misc.guid_or_none( row['guid']))
async def mutate(self, info, **args): # pylint: disable=missing-docstring err = "marketplace_schema -> CreateMarketplaceApplication" code_name = args.get('db_name') root_page_db_name = args.get('root_page') unique_guid = str(uuid.uuid4()) include_data = args.get('include_data') create_readme = args.get('create_readme') with ax_model.try_catch(info.context['session'], err) as db_session: # Create tmp folder for new package archive_directory = ax_misc.tmp_root_dir / unique_guid package_directory = archive_directory / 'archive_me' / code_name dir_to_zip = archive_directory / 'archive_me' os.makedirs(package_directory) # Get AxForms and folders to dump root_folder = db_session.query(AxForm).filter( AxForm.guid == ax_misc.guid_or_none( str(args.get('folder_guid')))).first() if not root_folder: raise Exception('Cant find app root folder') # AxPage[] # Get AxPage if db_name is provided pages_data = [] root_page = None root_page_guid = None if root_page_db_name: root_page = db_session.query(AxPage).filter( AxPage.db_name == root_page_db_name).first() if not root_page: raise Exception('Cant find app root page') # Сreate readme.md if create_readme: await do_create_readme(root_page=root_page, package_directory=package_directory) root_page_guid = str(root_page.guid) pages_data = await dump_pages( db_session=db_session, package_directory=package_directory, root_page=root_page) all_forms = await get_child_forms(db_session=db_session, form=root_folder) app_forms, app_folders = await get_folders_and_forms(all_forms) # Create app.yaml app_yaml_path = package_directory / 'ax_app.yaml' with open(app_yaml_path, 'w', encoding="utf-8") as yaml_file: app_info = { "Code name": code_name, "Root folder": args.get('folder_guid'), "Forms": await get_forms_db_names(app_forms), "Folders": await get_folders_dump(app_folders), "Root page": root_page_guid, "Pages": pages_data, "Ax version": os.environ.get('AX_VERSION') } yaml.dump(app_info, yaml_file) for form in app_forms: await dump_form(db_session=db_session, package_directory=package_directory, form=form, include_data=include_data) # version_str = str(app_version).replace(',', '-') # app_file_name = f'{code_name}-{version_str}.zip' app_file_name = f'{code_name}.zip' output_file_path = archive_directory / app_file_name await ax_misc.zip_folder(output_filename=output_file_path, source_dir=dir_to_zip) shutil.rmtree(dir_to_zip) url = f'/api/file/null/null/null/{unique_guid}/{app_file_name}' return CreateMarketplaceApplication(download_url=url, ok=True)
async def mutate(self, info, **args): # pylint: disable=missing-docstring import backend.schema as ax_schema err = 'Error in gql mutation - form_schema -> CreateTab' with ax_model.try_catch(info.context['session'], err) as db_session: current_user = info.context['user'] form_guid = args.get('form_guid') name = args.get('name') tag = args.get('tag') position = args.get('position') positions = args.get('positions') parent = args.get('parent') cur_name = None cur_db_name = None name_is_checked = False cur_num = 1 ax_field_type = db_session.query(AxFieldType).filter( AxFieldType.tag == tag).first() ax_form = db_session.query(AxForm).filter( AxForm.guid == uuid.UUID(form_guid)).first() # If db table already have {db_name} column -> add digit to db_name while name_is_checked is False: error_flag = False if cur_num > 1: cur_name = name + " " + str(cur_num) cur_db_name = ax_field_type.default_db_name + str(cur_num) else: cur_name = name cur_db_name = ax_field_type.default_db_name for field in ax_form.fields: if field.name == cur_name or field.db_name == cur_db_name: error_flag = True if error_flag is True: cur_num = cur_num + 1 else: name_is_checked = True break if not positions: positions = [] if not parent: for fld in ax_form.fields: if fld.is_tab and not parent: parent = fld.guid if not position: flds_num = 0 for fld in ax_form.fields: if str(fld.parent) == str(parent): flds_num += 1 position = flds_num ax_field = AxField() ax_field.name = cur_name ax_field.db_name = cur_db_name ax_field.form_guid = ax_form.guid ax_field.value_type = ax_field_type.value_type ax_field.field_type_tag = ax_field_type.tag ax_field.options_json = "{}" ax_field.position = position ax_field.parent = ax_misc.guid_or_none(parent) if ax_field_type.is_always_whole_row: ax_field.is_whole_row = True db_session.add(ax_field) if not ax_field_type.is_virtual: await ax_dialects.dialect.add_column( db_session=db_session, table=ax_form.db_name, db_name=ax_field.db_name, type_name=ax_field_type.value_type) db_session.flush() # Update positions of all fields that are lower then created field for field in ax_form.fields: for pos in positions: if field.guid == uuid.UUID(pos.guid): current_parent = None if pos.parent != '#': current_parent = uuid.UUID(pos.parent) field.position = pos.position field.parent = current_parent # Run after_create if needed if ax_field.field_type.is_backend_available: tag = ax_field.field_type_tag field_py = globals().get(f'AxField{tag}', None) if field_py and hasattr(field_py, "after_field_create"): method_to_call = getattr(field_py, "after_field_create") await method_to_call(db_session=db_session, field=ax_field, before_form=ax_form, tobe_form=ax_form, action=None, current_user=current_user) db_session.commit() ax_schema.init_schema(db_session) # re-create GQL schema roles = ax_form.roles ok = True return CreateField(field=ax_field, roles=roles, ok=ok)