Exemplo n.º 1
0
    def on_get_changes(self, req: Request, resp: Response):
        since = req.get_param_as_int('since', required=False, default=0)
        batch_size = req.get_param_as_int('batch_size',
                                          required=False,
                                          default=50)

        i = 0
        end = False
        items = []
        with scoped_session() as session:
            while i < batch_size and not end:
                obj = session.query(Change).filter(Change.id > since).first()
                if obj is None:
                    end = True
                    break
                item, errors = ChangeSchema().dump(obj)

                if errors is not None:
                    errors_num = len(errors)
                    if errors_num > 0:
                        resp.status = HTTP_BAD_REQUEST
                        resp.body = json.dumps({'errors': errors})
                        return

                if self.__can_read_change(req, item):
                    items.append(item)

                since = since + 1
                i = i + 1

        resp.status = HTTP_OK
        resp.body = json.dumps(items)
Exemplo n.º 2
0
    def on_get_doc(self, resp: Response, obj_id=None):
        if obj_id is None:
            resp.status = HTTP_METHOD_NOT_ALLOWED
            return

        try:
            cid = int(obj_id)
        except (TypeError, ValueError):
            resp.status = HTTP_BAD_REQUEST
            resp.body = '{"message": "Invalid id"}'
            return

        with scoped_session() as session:
            change = session.query(Change).filter(Change.id == cid).first()
            if change is None:
                resp.status = HTTP_NOT_FOUND
                return

            obj = self.__get_object_dump_by_change(session, change)

            if obj is None:
                resp.status = HTTP_NOT_FOUND
                return

        resp.status = HTTP_OK
        resp.body = json.dumps(obj)
Exemplo n.º 3
0
    def on_post_docs(self, req: Request, resp: Response):
        try:
            input_data = json.loads(req.stream.read(req.content_length or 0))
            changes_ids = [int(c) for c in input_data['changes']]
        except (ValueError, KeyError):
            resp.status = HTTP_BAD_REQUEST
            return

        if changes_ids is None:
            resp.status = HTTP_BAD_REQUEST
            return

        results = []
        with scoped_session() as session:
            changes = session.query(Change).filter(
                Change.id.in_(changes_ids)).all()

            for change in changes:
                obj = self.__get_object_dump_by_change(session, change)
                if obj is None:
                    continue

                change_dump, _ = ChangeSchema().dump(change)
                change_dump.update({'object': obj})
                results.append(change_dump)

        resp.status = HTTP_OK
        resp.body = json.dumps(results)
Exemplo n.º 4
0
def import_labels(args):
    from gam.database import scoped_session
    from locales.models import LanguageLabel

    context = args.context
    labels_file = args.file

    if context not in (
            'WMS',
            'WAPP',
    ):
        print('\nInvalid context. Use web or app.\n')
        return

    try:
        with open(labels_file, 'r') as f:
            cont = f.read()
        labels = json.loads(cont)
        with scoped_session() as session:
            for key in labels:
                exists = session.query(
                    session.query(LanguageLabel).filter(
                        LanguageLabel.label == key).exists()).scalar()
                if not exists:
                    session.add(LanguageLabel(context=context, label=key))
                    session.commit()
    except (FileNotFoundError, IsADirectoryError, TypeError, ValueError):
        print('\nInvalid labels file\n')
        return
Exemplo n.º 5
0
def check_triggers(model_cls):
    with scoped_session() as session:
        __create_change_entry_creation_function(session)
        __create_after_insert_trigger(session, model_cls)
        __create_after_update_trigger(session, model_cls,
                                      issubclass(model_cls, SoftDelete))
        __create_after_delete_trigger(session, model_cls)
Exemplo n.º 6
0
def get_user_roles_map(uid, extended=False):
    roles = {}
    with scoped_session() as session:
        q = session.query(UserRole).filter(UserRole.user_id == uid)
        for role in q:
            extra = {**role.extra}
            roles[role.role_id] = extra
    return roles
Exemplo n.º 7
0
 def on_get(self, req: Request, resp: Response):
     user = req.context['user']
     with scoped_session() as session:
         instance = session.query(User).filter(
             User.id == user.id
         ).first()
         payload = UserSchema().dump(instance)
         resp.body = json.dumps(payload)
     resp.status = HTTP_OK
Exemplo n.º 8
0
def get_authenticated_user(payload):
    try:
        user_id = payload['user']['user_id']
        with scoped_session() as session:
            user = session.query(User).filter(User.id == user_id).one_or_none()
            session.expunge_all()
        return user
    except KeyError:
        return None
Exemplo n.º 9
0
def authenticate_user(username, password):
    with scoped_session() as session:
        user = session.query(User).filter(
            User.username == username, User.is_active.is_(True),
            User.deleted.is_(False)).one_or_none()
        session.expunge_all()
    if user is not None and not verify_password(password, user.password):
        return None
    return user
Exemplo n.º 10
0
def __import_json_data(fixtures):
    from gam.database import scoped_session
    with scoped_session() as session:
        for fixture in fixtures:
            print('Importing {} json data'.format(fixture[0]))
            fixture_file = path.join('.', 'data', '{}.json'.format(fixture[0]))
            f = open(fixture_file, 'r')
            data = json.loads(f.read())
            f.close()
            for d in data:
                instance = fixture[1]().load(d, session=session)
                session.add(instance)
            print('Successfully imported {} json data'.format(fixture[0]))
Exemplo n.º 11
0
 def on_post(self, req: Request, resp: Response):
     """Unprotected user login endpoint.
     ---
     post:
         description: Logs an existing user returning valid tokens
         consumes: ["json"]
         parameters:
         -   in: body
             name: credentials
             description: The username and password chosen during the registration
             schema: {}
             required: true
         responses:
             200:
                 description: Tokens needed for authorization and refresh token
                 schema: TokenPayloadSchema
             401:
                 description: Submitted invalid credentials
     """
     resp.content_type = MEDIA_JSON
     try:
         params = json.loads(req.stream.read(req.content_length or 0))
         username = params['username']
         password = params['password']
     except (KeyError, TypeError, ValueError):
         resp.body = '{"message": "Please provide username and password"}'
         resp.status = HTTP_BAD_REQUEST
         return
     user = authenticate_user(username, password)
     if user is None:
         resp.body = '{"message": "Invalid credentials"}'
         resp.status = HTTP_BAD_REQUEST
         return
     payload = TokenPayloadSchema().dump(user)
     payload['token'] = auth_backend.get_auth_token(payload)
     with scoped_session() as session:
         rt = session.query(RefreshToken).filter(
             RefreshToken.user_id == payload['user_id']
         ).first()
         if rt is None:
             rt = RefreshToken(user_id=payload['user_id'])
             session.add(rt)
             session.commit()
         refresh_token = rt.token
         user_instance = session.query(User).filter(User.id == user.id).first()
         payload['user'] = UserSchema().dump(user_instance)
     payload['refresh_token'] = refresh_token
     resp.body = json.dumps(payload)
     resp.status = HTTP_OK
Exemplo n.º 12
0
 def on_post(self, req: Request, resp: Response):
     """User logout endpoint.
     ---
     post:
         description: Logs out an already logged user
         responses:
             200:
                 description: Logs out the user deleting the refresh token
             401:
                 description: Fails on unauthorized (tokenless) request
     """
     user = req.context['user']
     with scoped_session() as session:
         rt = session.query(RefreshToken).filter(
             RefreshToken.user_id == user.id
         ).first()
         if rt is not None:
             session.delete(rt)
     resp.status = HTTP_OK
Exemplo n.º 13
0
    def __process_upward_delete_change(self, change):
        with scoped_session() as session:
            instance, schema_cls = self.__get_object_by_change(session, change)

            if instance is None:
                raise exc.ModelNotFound(change.table_name, change.object_id)

            model_cls = schema_cls.Meta.model

            if issubclass(model_cls, Fixed) and instance.fixed:
                raise exc.FixedModel(change.table_name, change.object_id)

            if issubclass(model_cls, SoftDelete):
                instance.deleted = True
                session.add(instance)
            else:
                session.delete(instance)

            return {'sequence': change.sequence, 'ok': True}
Exemplo n.º 14
0
    def __can_create_mobile_roles(cls, roles, user_roles, user_roles_ids):
        if ROLE_ADMIN not in roles or 'countries' not in roles[ROLE_ADMIN]:
            return False
        countries = roles[ROLE_ADMIN]['countries']
        countries_num = len(countries)
        if countries_num == 0:
            return False

        user_projects = cls.__get_admin_projects(user_roles, user_roles_ids)
        user_projects_num = len(user_projects)
        if user_projects_num == 0:
            return False

        with scoped_session() as session:
            for c in session.query(Project.country_id).filter(
                    Project.id.in_(user_projects)):
                if c[0] not in countries:
                    return False
        return True
Exemplo n.º 15
0
    def __process_upward_update_change(self, change):
        with scoped_session() as session:
            instance, schema_cls = self.__get_object_by_change(session, change)

            if instance is None:
                raise exc.ModelNotFound(change.table_name, change.object_id)

            update, err = schema_cls().load(change.object,
                                            session=session,
                                            instance=instance)
            if err is not None:
                err_num = len(err)
                if err_num > 0:
                    raise exc.InvalidSyncEntry(change.table_name,
                                               change.object)

            session.add(update)

            return {'sequence': change.sequence, 'ok': True}
Exemplo n.º 16
0
def test(args):
    import pytest
    import gam.models  # noqa
    from sqlalchemy.exc import ProgrammingError
    from gam.database import Base, scoped_session

    with scoped_session() as session:
        session.execute("""
            DO $$
            DECLARE
                record RECORD;
            BEGIN
                FOR record IN SELECT trigger_name, event_object_table FROM information_schema.triggers WHERE trigger_schema = 'public' LOOP
                    EXECUTE 'DROP TRIGGER ' || record.trigger_name || ' ON ' || record.event_object_table || ';';
                END LOOP;
                IF EXISTS (SELECT 1 FROM pg_proc WHERE proname = 'sync_create_change_entry') THEN
                    DROP FUNCTION sync_create_change_entry();
                END IF;
            END $$;
        """)
        session.commit()
        for table in reversed(Base.metadata.sorted_tables):
            try:
                session.execute("""
                    DO $$
                    BEGIN
                        IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = '{table}') THEN
                            DELETE FROM {table};
                            DROP TABLE {table} CASCADE;
                        END IF;
                    END $$;
                """.format(table=table))
                session.commit()
            except ProgrammingError:
                pass
        try:
            session.execute('DELETE FROM alembic_version')
            session.commit()
        except ProgrammingError:
            pass
    migrate(args)
    pytest.main(args=[])
Exemplo n.º 17
0
 def on_post(self, req: Request, resp: Response):
     """Refresh token endpoint for getting new auth tokens.
     ---
     post:
         description: Returns a new token both on valid and expired submitted token
         consumes: ["json"]
         parameters:
         -   in: body
             name: refresh_token
             description: refresh token needed to access the endpoint
             required: true
         responses:
             200:
                 description: User info, and tokens needed for new requests
             401:
                 description: Submitted a tokenless request
             400:
                 description: Missing a valid refresh token
     """
     user = req.context['user']
     try:
         params = json.loads(req.stream.read(req.content_length or 0))
         refresh_token = params['refresh_token']
     except (KeyError, TypeError, ValueError):
         resp.body = '{"message": "Please provide a refresh token"}'
         resp.status = HTTP_BAD_REQUEST
         return
     with scoped_session() as session:
         rt = session.query(RefreshToken).filter(
             RefreshToken.user_id == user.id,
             RefreshToken.token == refresh_token
         ).first()
         if rt is None:
             resp.body = '{"message": "Invalid refresh token"}'
             resp.status = HTTP_BAD_REQUEST
             return
     payload = TokenPayloadSchema().dump(user).data
     payload['token'] = auth_backend.get_auth_token(payload)
     payload['refresh_token'] = refresh_token
     resp.body = json.dumps(payload)
     resp.status = HTTP_OK
Exemplo n.º 18
0
def fix_sequences(_args):
    import gam.models  # noqa
    from gam.database import Base, scoped_session

    with scoped_session() as session:
        for table in reversed(Base.metadata.sorted_tables):
            session.execute("""
                DO $$
                DECLARE
                    cur_val INTEGER;
                    max_id INTEGER;
                BEGIN
                    IF EXISTS (SELECT 1 FROM pg_class where relname = '{table}_id_seq') THEN
                        SELECT last_value FROM {table}_id_seq INTO cur_val;
                        SELECT MAX(id) FROM {table} INTO max_id;
                        IF cur_val < max_id THEN
                            PERFORM setval('{table}_id_seq', max_id);
                        END IF;
                    END IF;
                END $$;
            """.format(table=table))
Exemplo n.º 19
0
    def __process_upward_insert_change(self, change):
        with scoped_session() as session:
            existing, schema_cls = self.__get_object_by_change(session, change)
            if existing is not None:
                return {
                    'sequence': change.sequence,
                    'ok': False,
                    'error': 'conflict',
                    'extra': {
                        'next_id': self.__reserve_id(change.table_name)
                    }
                }

            instance, err = schema_cls().load(change.object)
            if err is not None:
                err_num = len(err)
                if err_num > 0:
                    raise exc.InvalidSyncEntry(change.table_name,
                                               change.object)

            session.add(instance)

            return {'sequence': change.sequence, 'ok': True}
Exemplo n.º 20
0
    def can_read_change(cls, ctx, itm):
        roles = ctx['roles']
        user = ctx['user']

        if itm['object_id'] == user.id:
            return True

        with scoped_session() as session:
            user_roles = session.query(UserRole).filter(
                UserRole.user_id == itm['object_id']).all()

            if ROLE_SUPER_ADMIN in roles and cls.__super_admin_can_read_change(
                    user_roles):
                return True
            if (ROLE_COUNTRY_ADMIN in roles
                    and 'countries' in roles[ROLE_COUNTRY_ADMIN] and
                    cls.__country_admin_can_read_change(roles, user_roles)):
                return True
            if ROLE_ADMIN in roles and 'countries' in roles[
                    ROLE_ADMIN] and cls.__admin_can_read_change(
                        roles, user_roles):
                return True
        return False
Exemplo n.º 21
0
def test_right_expired_refresh_token_post(client, john_snow):
    auth_backend = JWTAuthBackend(get_authenticated_user, settings.SECRET_KEY, expiration_delta=0)
    uid = john_snow.id
    with scoped_session() as session:
        refresh_token = session.query(RefreshToken).filter(RefreshToken.user_id == uid).first().token
        token = auth_backend.get_auth_token(TokenPayloadSchema().dump(john_snow).data)
    decoded = jwt.decode(token, key=settings.SECRET_KEY, algorithms='HS256')

    assert decoded is not None and 'exp' in decoded
    time.sleep(1)
    assert decoded['exp'] < int(time.time())

    response = client.simulate_post(
        '/auth/refresh_token',
        headers={
            'authorization': 'jwt %s' % token
        },
        body=json.dumps({
            'refresh_token': refresh_token
        })
    )
    assert response.status == falcon.HTTP_200
    assert response.json['token'] != token
Exemplo n.º 22
0
 def __reserve_id(self, change):
     sequence_name = '{}_id_seq'.format(change.table_name)
     with scoped_session() as session:
         return session.execute(
             Sequence(sequence_name).next_value()).scalar()  # noqa