def test_dump(test_db): dumper = Dumper() seeder = dumper._seeder model = test_db.model with DBConn.get_session() as db: count_before = db.query(model).count() assert count_before > 0 dumper.dump_schema(test_db.schema) dumper.dump_schema('system') seeder.drop_models() seeder.create_models() with DBConn.get_session() as db: count_empty = db.query(model).count() assert count_empty == 0 dumper.load_schema('system') dumper.load_schema(test_db.schema) with DBConn.get_session() as db: count_after = db.query(model).count() assert count_after == count_before
def test_abort_request(client, test_db): test_db.entry.triggerList = Triggers([Trigger(Activation.READ, TEAPOT_ID)]) login(client, test_db.admin_user) schema, name = test_db.entry.schema, test_db.entry.tableName table_url = f'/tables/table/{schema}/{name}' entry_url = f'/tables/entry/{schema}/{name}' assert client.get(table_url).status_code == 418 assert client.get(entry_url).status_code == 418 mgr = ScriptManager() mgr.global_triggers.append(Trigger(Activation.TRANSACTION, TEAPOT_ID)) model = test_db.model entry = test_db.entry with DBConn.get_session() as db: item = db.query(model).first() data = model.__marshmallow__().dump(item) key = data[entry.pk.rowName] transaction = {entry.id: {'delete': {key: True}}} response = client.post('/transaction/execute', data=json.dumps({'transaction': transaction}), content_type='application/json') assert response.status_code == 418 client.post('/auth/logout') mgr.global_triggers.append(Trigger(Activation.LOGIN, TEAPOT_ID)) response = client.post('/auth/login', data={ "login": test_db.admin_user.login, "password": test_db.admin_user.password }) assert response.status_code == 418 mgr.global_triggers = Triggers([])
def test_connection(): DBConn.reset() with pytest.raises(TypeError): DBConn.Session() DBConn() with DBConn.get_session() as sess: assert sess
def test_create(test_db, models): model = test_db.model entry = test_db.entry with DBConn.get_session() as db: count = db.query(model).count() faker = Faker(models, db=db) faked = faker.fake_one(model, db) data = faked.__marshmallow__().dump(faked) db.rollback() transaction = {} transaction[entry.id] = { 'create': { 'dummy_key': { 'newData': data, 'links': [] } } } bad_t = Transaction(db, transaction, role_names=['dummy']) with pytest.raises(InsufficientRightsError): bad_t.execute() assert db.query(model).count() == count t = Transaction(db, transaction) t.execute() assert db.query(model).count() == count + 1
def test_fetch_many(test_db): with DBConn.get_session() as db: obj, criterion = _get_sample(db, test_db) builder = QueryBuilder(db) result = builder.fetch_data(test_db.model, filter_by=[criterion]) assert len(result) > 0
def test_exception_handling(test_db): entry = test_db.entry with DBConn.get_session() as db: transaction = { entry.id: { 'create': { 'dummy_key': { 'newData': { 'jackshit': True, 'jackshit2': '12345' }, 'links': [] } } } } t = Transaction(db, transaction) try: t.execute() except Exception as exp: error, _ = ErrorsParser.parse(exp) assert len(error.info) > 0
def test_integration(config, sample_xml, models, alg_test_options): erd = ERD(sample_xml) alg = Algorithm(erd, options=alg_test_options) alg.run_algorithm() tables = alg.tables gen = Generator(tables, 'er1', add_check=True) gen.generate_folder() gen.generate_system_models() assert len(list(models)) - len(models['system']) == len(tables) manager = HierachyManager() manager.drop() manager.hierarchy.merge(HierachyConstructor(tables, 'er1').construct()) seeder = Seeder(models) seeder.drop_models() seeder.create_models() faker = Faker(models) faker.fake_all(10) firsts = [] with DBConn.get_session() as db: for table in faker.faked_models(): firsts.append(db.query(table).first()) for first in firsts: assert first assert repr(erd) assert repr(alg) assert repr(gen)
def test_db(empty_db): alg, models = empty_db manager = UserManager() hierarchy_manager = HierachyManager() hierarchy_manager.drop() with DBConn.get_session() as db: admin_user = manager.add_user('admin', 'password', db) normal_user = manager.add_user('user', 'password', db) admin_role = manager.add_role(db=db, name='admin', can_reset_password=True, has_sql_access=True, linked_entity_schema='er1', linked_entity_name='user', can_register_all=True) db.add(admin_role) admin_user.roles = [admin_role] db.commit() constuctor = HierachyConstructor(alg.tables, 'er1', admin_role=admin_role) h = constuctor.construct() constuctor.insert_system_pages(h) hierarchy_manager.h.merge(h) faker = Faker(models) faker.fake_all(10) model = next( iter(model for model in models if model.__table__.schema != 'system')) model_name = model.__name__ field_name = next(iter(model.__table__.columns)).name entry = hierarchy_manager.h.get_table_entry(model.__table__.schema, model.__tablename__) if entry is None: logging.warning('Entry not found') logging.info(f"{model.__table__.schema}, {model.__tablename__}") logging.info(hierarchy_manager.h.pretty_xml()) User = namedtuple('User', ['user', 'login', 'password']) admin = User(admin_user, 'admin', 'password') normal = User(normal_user, 'user', 'password') TestData = namedtuple('TestData', [ 'admin_user', 'normal_user', 'model', 'model_name', 'field_name', 'schema', 'hierarchy', 'entry' ]) return TestData(admin_user=admin, normal_user=normal, model=model, entry=entry, hierarchy=hierarchy_manager.h, model_name=model_name, field_name=field_name, schema='er1')
def print_roles(test_db): from ermaket.api.database import DBConn normal, admin = test_db.normal_user.user, test_db.admin_user.user with DBConn.get_session() as db: db.add(normal) db.add(admin) print(f'Normal roles: {normal.role_names}') print(f'Admin roles: {admin.role_names}')
def test_fetch_one(test_db): with DBConn.get_session() as db: obj, criterion = _get_sample(db, test_db) builder = QueryBuilder(db) found_obj = builder.fetch_one(test_db.model, filter_by=[criterion]) assert found_obj['_display'] is not None del found_obj['_display'] assert obj == found_obj
def drop_user(self, name): with DBConn.get_session() as db: try: db.execute(f'DROP OWNED BY {name}') db.execute(f'DROP USER {name}') return True except Exception: return False
def test_marshmallow(models): dumps = [] with DBConn.get_session() as db: for model in iter(models): item = db.query(model).first() obj = model.__marshmallow__(session=db).dump(item) dumps.append(obj) for obj in dumps: assert obj is not None
def password(): data = request.form or request.json with DBConn.get_session() as sess: sess.add(current_user) success = current_user.change_password(data['old_pass'], data['new_pass']) if success: sess.commit() return jsonify({"ok": success})
def fake_schema(self, schema, entries={}, default_num=5): """Fill the database schema tables with fake data raises ResolveError if could not resolve foreign keys :param schema: schema name :param entries: {model_name: number_of_entries} model_name is generated camelCase :param default_num: number of entries, if t_name is not in entries """ if 'system' in self._models.schemas and not self._silence_system_warn: logging.warning('If the model has references to system tables, ' 'it may be required to fake schema `system` first') generated = {name: 0 for name in self._models[schema].keys()} not_resolved = {name: 0 for name in self._models[schema].keys()} if schema in self._config.Faker['ignore']: for key in self._config.Faker['ignore'][schema]: del generated[key] del not_resolved[key] total = sum([ entries.get(name, default_num) for name in self._models[schema].keys() ]) try: if self._verbose: bar = tqdm.tqdm(total=total) with DBConn.get_session(autoflush=False) as db: self._init_mixer(db) while len(generated) > 0: finished = [] for name, i in generated.items(): if i >= entries.get(name, default_num): finished.append(name) continue model = self._models[schema][name] if self._fake_model(model, db): generated[name] += 1 if self._verbose: bar.update(1) not_resolved[name] = 0 else: not_resolved[name] += 1 if not_resolved[name] > self._max_resolve: raise ResolveError( f"Can't resolve foreign keys for {name}") for name in finished: del generated[name] self._flush_faked(db) finally: if self._verbose: bar.close()
def create_user(self, config, rights): with DBConn.get_session() as db: config = {**self._config.Database, **config} self._try_create_user(config, db) if isinstance(rights, list) or isinstance(rights, tuple): for schema in self._models.schema_names: self._grant_rights_on_schema(config, db, schema, rights) else: for schema, rights_ in rights.items(): self._grant_rights_on_schema(config, db, schema, rights_) db.commit()
def current(): with DBConn.get_session() as sess: sess.add(current_user) user = current_user.__marshmallow__().dump(current_user) return jsonify({ "ok": True, "user": user, "hierarchy": session.get('hierarchy'), "rights": session.get('rights'), "profile_forms": session.get('profile_forms') })
def drop_models(self, schema=None): """Drops models :param schema: if given, drops only ones in the given schema """ with DBConn.get_session() as db: if schema is not None: db.execute(f'DROP SCHEMA IF EXISTS {schema} CASCADE') return for schema in self._models.schemas.keys(): db.execute(f'DROP SCHEMA IF EXISTS {schema} CASCADE') db.commit()
def test_update(test_db, models): model = test_db.model entry = test_db.entry not_pk = next( col for col in entry.columns if not col.isPk and not isinstance(col, LinkedTableColumn) ) with DBConn.get_session() as db: item = db.query(model).first() old_data = model.__marshmallow__().dump(item) key = old_data[entry.pk.rowName] faker = Faker(models, db=db) faked = faker.fake_one(model, db) fake_data = faked.__marshmallow__().dump(faked) db.rollback() new_data = old_data.copy() new_data[not_pk.rowName] = fake_data[not_pk.rowName] transaction = { entry.id: { 'update': { key: { 'newData': new_data, 'oldData': old_data } } } } bad_t = Transaction(db, transaction, role_names=['dummy']) with pytest.raises(InsufficientRightsError): bad_t.execute() not_changed_item = db.query(model).filter_by( **{ entry.pk.rowName: key } ).first() assert getattr(not_changed_item, not_pk.rowName) == old_data[not_pk.rowName] t = Transaction(db, transaction) t.execute() changed_item = db.query(model).filter_by(**{ entry.pk.rowName: key }).first() assert getattr(changed_item, not_pk.rowName) == new_data[not_pk.rowName]
def test_faker(self): models = Models() seeder = Seeder(models) faker = Faker(models) seeder.drop_models() seeder.create_models() faker.fake_all(10) assertions = [] with DBConn.get_session() as db: for model in faker.faked_models(): ok = db.query(model).first() is not None assertions.append(ok) [self.assertTrue(ok) for ok in assertions]
def login(): data = request.form or request.json if not scripts.process_global(Activation.LOGIN): return scripts.return_ with DBConn.get_session() as db: user = manager.check_user(data['login'], data['password'], db) if user: manager.login_user(user, session) login_user(user) return jsonify({"ok": True, **scripts.append_}) return jsonify({ "ok": False, "message": "Incorrect username or password", **scripts.append_ }), 401
def test_init(test_db, config): u1 = config.Users['readonly']['user'] u2 = config.Users['sql']['user'] users = DatabaseUserManager() users.drop_user(u1) users.drop_user(u2) SqlExecutor() with DBConn.get_session() as db: user_select = db.execute( f"SELECT 1 from pg_roles WHERE rolname='{u1}'").first() assert user_select user_select = db.execute( f"SELECT 1 from pg_roles WHERE rolname='{u2}'").first() assert user_select
def test_transaction(client, test_db): model = test_db.model entry = test_db.entry with DBConn.get_session() as db: item = db.query(model).first() data = model.__marshmallow__().dump(item) key = data[entry.pk.rowName] transaction = {entry.id: {'delete': {key: True}}} login(client, test_db.admin_user) response = client.post('/transaction/execute', data=json.dumps({'transaction': transaction}), content_type='application/json') assert response.status_code == 200
def register(): data = request.form or request.json user = manager.register_user(data['token'], data['login'], data['password']) if user is None: return jsonify({ "ok": False, "message": ("Registration error. Perhaps the token is incorrect or" " the user is already registered") }), 401 if not scripts.process_global(Activation.LOGIN): return scripts.return_ with DBConn.get_session() as db: db.add(user) manager.login_user(user, session) login_user(user) return jsonify({"ok": True, **scripts.append_})
def register_token(): data = request.form or request.json with DBConn.get_session() as sess: sess.add(current_user) if not current_user.can_register(data.get('roles', [])): abort(403) token = manager.add_register_token(name=data['name'], roles=data.get('roles', []), uses=data.get('uses', 1), time_limit=data.get( 'time_limit', None)) ctx = ReturnContext() ctx.add_message(f""" Registration token: <pre>{token}</pre> The token won't be shown anywhere except this message. """) return jsonify({ "ok": True, "token": token, "businessLogic": ctx.append_request })
def process(): data = request.form or request.json with DBConn.get_session(autoflush=False) as db: transaction = Transaction(db, data['transaction']) info = TransactionRequestInfo(transaction) if not scripts.process_global(Activation.TRANSACTION, info): return scripts.return_ try: transaction.execute() except Exception as exp: error, code = ErrorsParser.parse(exp) response = { "ok": False, "message": error.message, "data": error.info } if os.environ.get('FLASK_ENV') == 'development': response['traceback'] = traceback.format_exc() return jsonify(response), code return jsonify({"ok": True, **scripts.append_})
def test_delete(test_db): model = test_db.model entry = test_db.entry with DBConn.get_session() as db: count = db.query(model).count() item = db.query(model).first() data = model.__marshmallow__().dump(item) key = data[entry.pk.rowName] transaction = {entry.id: {'delete': {key: True}}} bad_t = Transaction(db, transaction, role_names=['dummy']) with pytest.raises(InsufficientRightsError): bad_t.execute() count_after_bad = db.query(model).count() t = Transaction(db, transaction) t.execute() count_after_good = db.query(model).count() assert count == count_after_bad assert count == count_after_good + 1
def get_user(login): with DBConn.get_session() as session: user = session.query(User).filter(User.login == login).first() return user
def dump_schema(self, *args, format='csv', **kwargs): if format == 'csv': with DBConn.get_session() as db: return self._dump_csv(*args, db=db, **kwargs) raise ValueError(f'Format {format} is unknown')
def load_schema(self, *args, format='csv', **kwargs): if format == 'csv': with DBConn.get_session(autoflush=False) as db: return self._load_csv(*args, db=db, **kwargs) raise ValueError(f'Format {format} is unknown')