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}
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}')
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'
def run(self, name): ( Q(Organisation) .insert( name=name, entity=Q(Entity).insert().select('id') ) .execute() )
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
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
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())
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'
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())
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'
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
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
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
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
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}
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)
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 }
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
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())
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())
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
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
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']
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
def test_delete_sql(db, factory): movie = factory.Movie.create() (Q(movie).delete().execute())
def test_get_sql_nested(db, factory): factory.Movie.create_batch(2) (Q(Movie).filter(star__id=1).select('id', star=S('id')).execute())
def test_get_sql(db, factory): factory.Movie.create_batch(2) (Q(Movie).filter(star__id=1).select('id', 'title').execute())
def _create(cls, model_class, *args, **kwargs): inst = model_class(*args, **kwargs) Q(inst).insert().into(inst) return inst