예제 #1
0
 def resolve(self, ctx):
     input = ctx.parse_input()
     try:
         token = input['token']
         claims = jwt_decode(token)
         query = Q(User).filter(id=claims['user_id'])
         # TODO: This is a little inefficient, but is needed to
         # confirm the user actually exists.
         if query.select('id').get() is None:
             raise Exception
     except Exception:
         # TODO: Check more.
         # TODO: These should be composable, but the nested select
         # from Polecat doesn't seem to be working as expected.
         entity_id = Q(Entity).insert().select('id').get()['id']
         query = (Q(User).insert(entity=entity_id, anonymous=True))
         token = None
     if ctx.selector and 'user' in ctx.selector.lookups:
         query = query.select(
             S(entity=S('id')).merge(ctx.selector.lookups.get('user')))
     user = query.get()
     if not token:
         token = jwt({
             'user_id': user['id'],
             'entity_id': (user['entity'] or {}).get('id'),
             'role': 'default'
         })
     return {'token': token, 'user': user}
예제 #2
0
 def run(self, purpose, user_email=None, organisation=None):
     if not user_email and not organisation:
         # TODO: Better error.
         raise Exception('Must supply one of "user" or "organisation"')
     api_token_id = (
         Q(APIToken)
         .insert(purpose=purpose)
         .select('id')
         .get()
     )['id']
     claims = {
         'api_token_id': api_token_id,
         'role': 'user'
     }
     if user_email:
         results = (
             Q(User)
             .filter(email=user_email)
             .select('id', entity=S('id'))
             .get()
         )
         claims['user_id'] = results['id']
     elif organisation:
         results = (
             Q(Organisation)
             .filter(name=organisation)
             .select('id', entity=S('id'))
             .get()
         )
     if results['entity']['id']:
         claims['entity_id'] = results['entity']['id']
     token = jwt(claims)
     print(f'Claims: {repr(claims)}')
     print(f'API token: {token}')
예제 #3
0
def test_update_sql(db):
    inst = Address(country='AU')
    Q(inst).insert().into(inst)
    init_id = inst.id
    (Q(inst).update(country='NZ').select('country').into(inst))
    assert inst.id == init_id
    assert inst.country == 'NZ'
예제 #4
0
 def run(self, name):
     (
         Q(Organisation)
         .insert(
             name=name,
             entity=Q(Entity).insert().select('id')
         )
         .execute()
     )
예제 #5
0
def test_delete(db, factory):
    movie = factory.Movie.create()
    result = (Q(movie).filter(id=movie.id))
    result = [r for r in result]
    assert len(result) == 1
    (Q(movie).delete().execute())
    result = (Q(movie).filter(id=movie.id))
    result = [r for r in result]
    assert len(result) == 0
예제 #6
0
def test_transaction(migrateddb, factory):
    n_movies_pre = len(list(Q(Movie).select()))
    try:
        with transaction():
            factory.Movie()
            raise Exception
    except Exception:
        pass
    n_movies_post = len(list(Q(Movie).select()))
    assert n_movies_pre == n_movies_post
예제 #7
0
def test_select_sql(db):
    # query = Q(DummyModel).select('id', 'n_related_dummies')
    query = Q(RelatedDummyModel).select('id',
                                        dummy=S('id', 'n_related_dummies',
                                                'max_timestamp'))
    # print(list(query))
    print(query.to_sql())
예제 #8
0
def register_user(email, password, password_confirmation, token=None, selector=None):
    if password != password_confirmation:
        raise Exception('Passwords don\'t match')
    selector = selector or S()
    if token:
        claims = jwt_decode(token)
        try:
            user = Q(User).filter(id=claims['user_id']).select('id', 'email').get()
            if user['email']:
                raise Exception('Cannot register existing user')
        except (KeyError, AttributeError):
            raise Exception('Invalid token for user registration')
        user = upgrade_user(
            user['id'],
            email,
            password,
            selector=(selector.get('user') or S()).merge(S(entity=S('id')))
        )
    else:
        user = create_user(
            email,
            password=password,
            selector=(selector.get('user') or S()).merge(S(entity=S('id')))
        )
    token = jwt({
        'user_id': user['id'],
        'entity_id': user['entity']['id'],
        'role': 'default'
    })
    return {
        'token': token,
        'user': user
    }
def test_query(testdb, push_blueprint):
    with patch('polecat_filefield.resolvers.get_s3_client') as mocked_s3_client:
        TestModel = build_test_model()
        with fixture.server() as server:
            sync()
            key = str(uuid4())
            Q(Tmpfile).insert(key=key, filename='a.txt').execute()
            with filefield_config():
                server.create_mutation(TestModel, {'file': key})
            result = Q(TestModel).select('file').get()
            assert result['file'] == 'a.txt'
            with filefield_config():
                results = server.all_query(TestModel)
                # TODO: Test the input to the magicmock.
                assert results[0]['file'] is not None
                assert results[0]['file'] != 'a.txt'
예제 #10
0
def test_select_sql(db, factory):
    factory.Movie.create_batch(10)
    (Q(Movie).select('id',
                     'title',
                     star=S('id',
                            'first_name',
                            'last_name',
                            address=S('id', 'country'))).execute())
예제 #11
0
def test_bulk_insert(db, factory):
    query = (Q(Address).bulk_insert(['country'],
                                    [('AU', ),
                                     ('US', )]).select('id', 'country'))
    results = list(query)
    assert len(results) == 2
    assert results[0]['id'] == 1
    assert results[0]['country'] == 'AU'
    assert results[1]['id'] == 2
    assert results[1]['country'] == 'US'
예제 #12
0
def test_delete(db, factory):
    schema = build_graphql_schema()
    movie = factory.Movie.create()
    result = execute_query(schema,
                           delete_movie_query,
                           variables={'id': movie.id})
    assert result.errors is None
    data = result.data['deleteMovie']
    assert data['id'] == movie.id
    result = Q(movie).filter(id=movie.id).get()
    assert result is None
def test_mutation(testdb, push_blueprint):
    with patch('polecat_filefield.resolvers.get_s3_client') as mocked_s3_client:
        TestModel = build_test_model()
        with fixture.server() as server:
            sync()
            key = str(uuid4())
            Q(Tmpfile).insert(key=key, filename='a.txt').execute()
            with filefield_config():
                server.create_mutation(TestModel, {'file': key})
        # TODO: I can check the arguments here.
        assert len(mocked_s3_client.mock_calls) == 3
예제 #14
0
def upgrade_user(user_id, email, password, selector=None):
    user = (
        Q(User)
        .filter(id=user_id)
        .update(
            email=email,
            password=password
        )
        .select(S('id').merge(selector))
        .get()
    )
    return user
예제 #15
0
 def build_model(self, context, **kwargs):
     model = context(**kwargs)
     user_id = context.session.variables.get('claims.user_id')
     # TODO: Improve this query with better filtering.
     entity_id = (Q(Membership).filter(
         active=True,
         user=user_id).select(organisation=S(entity=S('id'))).get())
     try:
         entity_id = entity_id['organisation']['entity']['id']
     except (KeyError, TypeError):
         entity_id = None
     setattr(model, self.column_name, entity_id)
     return model
예제 #16
0
def test_insert_reverse_sql(db):
    inst = Address(country='AU',
                   actors_by_address=[{
                       'first_name': 'a'
                   }, {
                       'first_name': 'b'
                   }])
    assert getattr(inst, 'id', None) is None
    (Q(inst).insert().select('id',
                             'country',
                             actors_by_address=S('first_name')).into(inst))
    assert inst.id is not None
    assert len(inst.actors_by_address) == 2
    for actor in inst.actors_by_address:
        assert actor.first_name is not None
예제 #17
0
def upload_resolver(mutation, context):
    input = context.parse_input()
    file_id = (Q(Tmpfile).insert(
        filename=input['filename']).select('key').get())['key']
    tmp_path = temporary_path_from_file_id(file_id)
    tmp_path = remove_leading_slash(tmp_path)
    s3 = get_s3_client()
    bucket = default_config.filefield.aws_bucket
    params = {
        'Bucket': bucket,
        'Key': tmp_path,
        # 'ACL': 'bucket-owner-full-control'
    }
    expiry = default_config.filefield.upload_expiry
    presigned_url = s3.generate_presigned_url('put_object',
                                              Params=params,
                                              ExpiresIn=expiry)
    return {'file_id': file_id, 'presigned_url': presigned_url}
예제 #18
0
 def __call__(self, context, model, field, field_name):
     file_id = getattr(model, field_name)
     bucket = default_config.filefield.aws_bucket
     tmpfile_query = (Q(Tmpfile).filter(key=file_id))
     try:
         filename = (tmpfile_query.select('filename').get())['filename']
     except TypeError:
         # TODO: Better error.
         raise Exception('Invalid file ID')
     if self.prefix:
         filename = str(Path(self.prefix) / filename)
     dst_path = destination_path_from_filename(filename)
     dst_path = remove_leading_slash(dst_path)
     tmp_path = temporary_path_from_file_id(file_id)
     tmp_path = remove_leading_slash(tmp_path)
     s3 = get_s3_client()
     self.copy_file(s3, bucket, tmp_path, dst_path)
     self.delete_tmpfile(s3, bucket, tmp_path, tmpfile_query)
     setattr(model, field_name, filename)
예제 #19
0
 def resolve(self, ctx):
     input = ctx.parse_input()
     email = input['email']
     password = input['password']
     result = (Q(User).filter(email=email, password=password))
     selector = S('id', entity=S('id'))
     selector.merge(ctx.selector.get('user'))
     result = result.select(selector).get()
     if not result:
         raise AuthError('Invalid email/password')
     return {
         'token':
         jwt({
             'user_id': result['id'],
             'entity_id': result['entity']['id'],
             'role': 'user'
         }),
         'user':
         result
     }
예제 #20
0
def create_user(email, password=None, name=None, organisation=None, selector=None):
    with transaction():
        # TODO: These should be composable, but the nested select
        # from Polecat doesn't seem to be working as expected.
        entity_id = Q(Entity).insert().select('id').get()['id']
        user = (
            Q(User)
            .insert(
                email=email,
                password=password,
                name=name,
                entity=entity_id
            )
            .select(S('id').merge(selector))
            .get()
        )
        user_id = user['id']
        if organisation is not None:
            org = (
                Q(Organisation)
                .insert_if_missing({'name': organisation})
                .select('id', 'entity')
                .get()
            )
            if not org['entity']:
                (
                    Q(Organisation)
                    .filter(id=org['id'])
                    .update(entity=Q(Entity).insert())
                    .execute()
                )
            # TODO: Update "active" to be a query against other actives.
            (
                Q(Membership)
                .insert(
                    user=user_id,
                    organisation=org['id'],
                    active=True
                )
                .execute()
            )
        return user
예제 #21
0
class DummyModel(model.Model):
    n_related_dummies = model.QueryField(
        lambda: Q(RelatedDummyModel).filter(dummy=Ref('id')).count())
    max_timestamp = model.QueryField(lambda: Q(RelatedDummyModel).filter(
        dummy=Ref('id')).select('timestamp').max())
예제 #22
0
def test_set_role(db):
    with pytest.raises(ProgrammingError):
        (Q(Address,
           session=Session(DefaultRole.Meta.dbrole)).select('id').execute())
    (Q(Address).select('id').execute())
    (Q(Address, session=Session(UserRole.Meta.dbrole)).select('id').execute())
예제 #23
0
def test_insert_sql_with_app(db):
    inst = User(email='*****@*****.**')
    assert getattr(inst, 'id', None) is None
    Q(inst).insert().into(inst)
    assert inst.id is not None
예제 #24
0
def test_insert_and_select(db, factory):
    actor = factory.Actor()
    movie = Movie(title='test', star=actor)
    (Q(movie).insert().select('title', star=S('first_name',
                                              'last_name')).into(movie))
    assert getattr(movie, 'id', None) is None
예제 #25
0
def test_insert_subquery(db, factory):
    store = factory.Store()
    copied_store = (Q(Store).insert(
        Q(Store).filter(id=1).select('name')).select('id', 'name').get())
    assert store.id != copied_store['id']
    assert store.name == copied_store['name']
예제 #26
0
def test_insert_sql(db):
    inst = Address(country='AU')
    assert getattr(inst, 'id', None) is None
    Q(inst).insert().into(inst)
    assert inst.id is not None
예제 #27
0
def test_delete_sql(db, factory):
    movie = factory.Movie.create()
    (Q(movie).delete().execute())
예제 #28
0
def test_get_sql_nested(db, factory):
    factory.Movie.create_batch(2)
    (Q(Movie).filter(star__id=1).select('id', star=S('id')).execute())
예제 #29
0
def test_get_sql(db, factory):
    factory.Movie.create_batch(2)
    (Q(Movie).filter(star__id=1).select('id', 'title').execute())
예제 #30
0
 def _create(cls, model_class, *args, **kwargs):
     inst = model_class(*args, **kwargs)
     Q(inst).insert().into(inst)
     return inst