Example #1
0
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
Example #2
0
def test_connection():
    DBConn.reset()
    with pytest.raises(TypeError):
        DBConn.Session()
    DBConn()
    with DBConn.get_session() as sess:
        assert sess
Example #3
0
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([])
Example #4
0
 def add_role(self, db=None, **kwargs):
     Role = self.models['system']['Role']
     with DBConn.ensure_session(db) as db:
         role = Role(**kwargs)
         db.add(role)
         db.commit()
     return role
Example #5
0
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
Example #6
0
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
Example #7
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
Example #8
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)
Example #9
0
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')
Example #10
0
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}')
Example #11
0
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
Example #12
0
 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
Example #13
0
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
Example #14
0
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})
Example #15
0
 def _create_users(self):
     self._users.create_user(self._config.Users['readonly'], ('SELECT', ))
     self._users.create_user(
         self._config.Users['sql'],
         ('SELECT', 'INSERT', 'UPDATE', 'DELETE', 'CREATE')
     )
     self._get_session = {
         'readonly':
             DBConn.make_get_session(
                 user=self._config.Users['readonly']['user'],
                 password=self._config.Users['readonly']['password']
             ),
         'sql':
             DBConn.make_get_session(
                 user=self._config.Users['sql']['user'],
                 password=self._config.Users['sql']['password']
             ),
     }
Example #16
0
 def add_user(self, login, password, db=None, role_names=None):
     with DBConn.ensure_session(db) as db:
         user = self._User(login=login)
         user.set_password(password)
         db.add(user)
         roles = self.add_roles(db, role_names)
         user.roles = roles
         db.commit()
     return user
Example #17
0
 def check_user(self, login, password, db=None):
     User = self._User
     with DBConn.ensure_session(db) as db:
         user = db.query(User).filter(User.login == login).first()
         if not user:
             return
         if not user.check_password(password):
             return
         return user
Example #18
0
 def __init__(self, system_only=False):
     if DBConn.engine is None:
         DBConn()
     self.config = Config()
     self.schemas = {}
     self.Base = None
     self._paths = {}
     self._import_base()
     self._system_only = system_only
     self._import()
Example #19
0
    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()
Example #20
0
 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()
Example #21
0
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')
        })
Example #22
0
def drop(schema, y):
    if not y:
        if not click.confirm("Drop cannot be undone. Continue?"):
            return
    DBConn()
    if schema:
        seeder = Seeder(None)
        seeder.drop_models(schema)
    else:
        models = Models()
        seeder = Seeder(models)
        seeder.drop_models(schema)
Example #23
0
    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()
Example #24
0
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]
Example #25
0
 def reset_password(self, token, login, password, db=None):
     with DBConn.ensure_session(db) as db:
         token_hash = generate_password_hash(token, method='plain')
         token = db.query(self._Token).get(token_hash)
         if (token is None or not token.valid
                 or not token.description['purpose'] == 'password'
                 or token.description['login'] != login):
             return False
         user = db.query(self._User).get(login)
         user.set_password(password)
         token.use()
         db.commit()
     return True
Example #26
0
 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]
Example #27
0
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
Example #28
0
 def register_user(self, token, login, password, db=None):
     with DBConn.ensure_session(db) as db:
         token_hash = generate_password_hash(token, method='plain')
         token = db.query(self._Token).get(token_hash)
         if (token is None or not token.valid
                 or not token.description['purpose'] == 'registration'):
             return None
         user = self.add_user(login,
                              password,
                              role_names=token.description['roles'],
                              db=db)
         if user is not None:
             token.use()
             db.commit()
     return user
Example #29
0
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
Example #30
0
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