예제 #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
예제 #2
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([])
예제 #3
0
def test_connection():
    DBConn.reset()
    with pytest.raises(TypeError):
        DBConn.Session()
    DBConn()
    with DBConn.get_session() as sess:
        assert sess
예제 #4
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
예제 #5
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
예제 #6
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
예제 #7
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)
예제 #8
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')
예제 #9
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}')
예제 #10
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
예제 #11
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
예제 #12
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
예제 #13
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})
예제 #14
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()
예제 #15
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()
예제 #16
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')
        })
예제 #17
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()
예제 #18
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]
예제 #19
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]
예제 #20
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
예제 #21
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
예제 #22
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
예제 #23
0
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_})
예제 #24
0
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
    })
예제 #25
0
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_})
예제 #26
0
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
예제 #27
0
파일: app.py 프로젝트: SqrtMinusOne/ERMaket
 def get_user(login):
     with DBConn.get_session() as session:
         user = session.query(User).filter(User.login == login).first()
     return user
예제 #28
0
 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')
예제 #29
0
 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')