class SettingsAPI(object): def __init__(self, request, context): self.request = request self.context = context @view(permission='view', response_schemas={ '200': SettingsResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def get(self): "Retrieve Settings" return self.request.repository.settings @view(permission='edit', schema=SettingsSchema(), validators=(colander_body_validator, ), response_schemas={ '200': TypeResponseSchema(description='Ok'), '400': ErrorResponseSchema(description='Bad Request'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def put(self): "Update Settings" settings = self.request.json self.request.repository.update_settings(settings) return self.request.repository.settings
class TypeAPI(object): def __init__(self, request, context): self.request = request self.context = context @view(permission='view', response_schemas={ '200': TypeResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def get(self): "Retrieve a Type Scheme" return TypeSchema().serialize(self.context.to_dict()) @view(permission='edit', schema=TypeSchema(), validators=(colander_body_validator, ), response_schemas={ '200': TypeResponseSchema(description='Ok'), '400': ErrorResponseSchema(description='Bad Request'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def put(self): "Update a Type Scheme" self.context.from_dict(self.request.validated) return TypeSchema().serialize(self.context.to_dict()) @view(permission='view', response_schemas={ '200': TypeListingResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized') }) def collection_get(self): listing = self.context.list() return TypeListingSchema().serialize(listing)
class BlobRecordAPI(object): def __init__(self, request, context): self.request = request self.context = context @view(permission='view', response_schemas={ '200': BlobResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def get(self): "Retrieve a Blob" result = BlobSchema().to_json(self.context.model.to_dict()) return result @view(permission='delete', response_schemas={ '200': StatusResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def delete(self): "Delete an Blob" self.context.delete() return {'status': 'ok'} @view(permission='add', schema=BlobPostSchema(), validators=(colander_bound_repository_body_validator, ), cors_origins=('*', ), response_schemas={ '201': BlobResponseSchema(description='Created'), '400': ErrorResponseSchema(description='Bad Request'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), }) def collection_post(self): "Create a new Blob" blob = Blob.from_dict(self.request.validated) blob.blob_key = self.request.repository.blob.new_blobkey() try: self.context.put(blob) except StorageError as err: self.request.errors.status = 400 self.request.errors.add('body', err.location, str(err)) return self.request.response.status = 201 result = BlobSchema().to_json(blob.to_dict()) result['upload_url'] = self.request.repository.blob.upload_url( result['blob_key']) return result @view(permission='view', schema=BlobListingRequestSchema(), validators=(colander_validator), cors_origins=('*', ), response_schemas={ '200': BlobListingResponseSchema(description='Ok'), '400': ErrorResponseSchema(description='Bad Request'), '401': ErrorResponseSchema(description='Unauthorized') }) def collection_get(self): offset = self.request.validated['querystring']['offset'] limit = self.request.validated['querystring']['limit'] order_by = [Blob.family_name.asc(), Blob.name.asc()] listing = self.context.search( offset=offset, limit=limit, order_by=order_by, format=format, principals=self.request.effective_principals) schema = BlobSchema() result = { 'total': listing['total'], 'records': [], 'snippets': [], 'limit': limit, 'offset': offset, 'status': 'ok' } result['records'] = [ schema.to_json(blob.to_dict()) for blob in listing['hits'] ] return result
class WorkRecordAPI(object): def __init__(self, request, context): self.request = request self.context = context @view(permission='view', response_schemas={ '200': WorkResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def get(self): "Retrieve a Work" return WorkSchema().to_json(self.context.model.to_dict()) @view(permission='edit', schema=WorkSchema(), validators=(colander_bound_repository_body_validator,), response_schemas={ '200': WorkResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def put(self): "Modify a Work" body = self.request.validated body['id'] = int(self.request.matchdict['id']) self.context.model.update_dict(body) try: self.context.put() except StorageError as err: self.request.errors.status = 400 self.request.errors.add('body', err.location, str(err)) return return WorkSchema().to_json(self.context.model.to_dict()) @view(permission='delete', response_schemas={ '200': StatusResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def delete(self): "Delete a Work" self.context.delete() return {'status': 'ok'} @view(permission='add', schema=WorkPostSchema(), validators=(colander_bound_repository_body_validator,), response_schemas={ '201': WorkResponseSchema(description='Created'), '400': ErrorResponseSchema(description='Bad Request'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), }) def collection_post(self): "Create a new Work" work = Work.from_dict(self.request.validated) try: self.context.put(work) except StorageError as err: self.request.errors.status = 400 self.request.errors.add('body', err.location, str(err)) return self.request.response.status = 201 return WorkSchema().to_json(work.to_dict()) @view(permission='view', schema=WorkListingRequestSchema(), validators=(colander_validator), cors_origins=('*', ), response_schemas={ '200': WorkListingResponseSchema(description='Ok'), '400': ErrorResponseSchema(description='Bad Request'), '401': ErrorResponseSchema(description='Unauthorized')}) def collection_get(self): qs = self.request.validated['querystring'] offset = qs['offset'] limit = qs['limit'] order_by = [func.lower(Work.during).desc()] format = qs.get('format') query = qs.get('query') filters = [] if qs.get('start_date') or qs.get('end_date'): duration = DateInterval([qs.get('start_date'), qs.get('end_date')]) filters.append(Work.during.op('&&')(duration)) if query: filters.append(Work.search_terms.match(query)) filter_type = self.request.validated['querystring'].get('filter_type') if filter_type: filter_types = filter_type.split(',') filters.append(sql.or_(*[Work.type == f for f in filter_types])) from_query=None listing = self.context.search( filters=filters, offset=offset, limit=limit, order_by=order_by, format=format, from_query=from_query, principals=self.request.effective_principals) schema = WorkSchema() result = {'total': listing['total'], 'records': [schema.to_json(work.to_dict()) for work in listing['hits']], 'snippets': [], 'limit': limit, 'offset': offset, 'status': 'ok'} return result
'limit': limit, 'offset': offset, 'status': 'ok'} return result work_bulk = Service(name='WorkBulk', path='/api/v1/work/bulk', factory=ResourceFactory(WorkResource), api_security=[{'jwt':[]}], tags=['work'], cors_origins=('*', ), schema=WorkBulkRequestSchema(), validators=(colander_bound_repository_body_validator,), response_schemas={ '200': OKStatusResponseSchema(description='Ok'), '400': ErrorResponseSchema(description='Bad Request'), '401': ErrorResponseSchema(description='Unauthorized')}) @work_bulk.post(permission='import') def work_bulk_import_view(request): # get existing resources from submitted bulk keys = [r['id'] for r in request.validated['records'] if r.get('id')] existing_records = {r.id:r for r in request.context.get_many(keys) if r} models = [] for record in request.validated['records']: if record['id'] in existing_records: model = existing_records[record['id']] model.update_dict(record) else: model = request.context.orm_class.from_dict(record) models.append(model)
class GroupRecordAPI(object): def __init__(self, request, context): self.request = request self.context = context @view(permission='view', response_schemas={ '200': GroupResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def get(self): "Retrieve a Group" return GroupSchema().to_json(self.context.model.to_dict()) @view(permission='edit', schema=GroupSchema(), validators=(colander_bound_repository_body_validator, ), response_schemas={ '200': GroupResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def put(self): "Modify an Group" body = self.request.validated body['id'] = int(self.request.matchdict['id']) self.context.model.update_dict(body) try: self.context.put() except StorageError as err: self.request.errors.status = 400 self.request.errors.add('body', err.location, str(err)) return return GroupSchema().to_json(self.context.model.to_dict()) @view(permission='delete', response_schemas={ '200': StatusResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def delete(self): "Delete an Group" self.context.delete() return {'status': 'ok'} @view(permission='add', schema=GroupPostSchema(), validators=(colander_bound_repository_body_validator, ), response_schemas={ '201': GroupResponseSchema(description='Created'), '400': ErrorResponseSchema(description='Bad Request'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), }) def collection_post(self): "Create a new Group" group = Group.from_dict(self.request.validated) try: self.context.put(group) except StorageError as err: self.request.errors.status = 400 self.request.errors.add('body', err.location, str(err)) return self.request.response.status = 201 return GroupSchema().to_json(group.to_dict()) @view(permission='view', schema=GroupListingRequestSchema(), validators=(colander_validator), cors_origins=('*', ), response_schemas={ '200': GroupListingResponseSchema(description='Ok'), '400': ErrorResponseSchema(description='Bad Request'), '401': ErrorResponseSchema(description='Unauthorized') }) def collection_get(self): offset = self.request.validated['querystring']['offset'] limit = self.request.validated['querystring']['limit'] order_by = [Group.name.asc()] format = self.request.validated['querystring'].get('format') if format == 'record': format = None query = self.request.validated['querystring'].get('query') filters = [] if query: filters.append(Group.name.ilike('%%%s%%' % query)) filter_type = self.request.validated['querystring'].get('filter_type') if filter_type: filter_types = filter_type.split(',') filters.append(sql.or_(*[Group.type == f for f in filter_types])) filter_parent = self.request.validated['querystring'].get( 'filter_parent') if filter_parent: filters.append(Group.parent_id == filter_parent) from_query = None query_callback = None if format == 'snippet': from_query = self.context.session.query(Group) from_query = from_query.options( Load(Group).load_only('id', 'type', 'name')).group_by( Group.id, Group.type, Group.name) def query_callback(from_query): filtered_groups = from_query.cte('filtered_groups') with_memberships = self.context.session.query( filtered_groups, func.count(Membership.id.distinct()).label( 'membership_count')).outerjoin(Membership).group_by( filtered_groups.c.id, filtered_groups.c.type, filtered_groups.c.name) filtered_memberships = with_memberships.order_by( filtered_groups.c.name).cte('memberships') with_work_counts = self.context.session.query( filtered_memberships, func.count( Affiliation.work_id.distinct()).label('work_count'), ).outerjoin(Affiliation).group_by(filtered_memberships) return with_work_counts listing = self.context.search( filters=filters, offset=offset, limit=limit, order_by=order_by, format=format, from_query=from_query, post_query_callback=query_callback, principals=self.request.effective_principals) schema = GroupSchema() result = { 'total': listing['total'], 'records': [], 'snippets': [], 'limit': limit, 'offset': offset, 'status': 'ok' } if format == 'snippet': snippets = [] for hit in listing['hits']: snippets.append({ 'id': hit.id, 'name': hit.name, 'type': hit.type, 'works': hit.work_count, 'members': hit.membership_count }) result['snippets'] = snippets else: result['records'] = [ schema.to_json(group.to_dict()) for group in listing['hits'] ] return result
class MembershipRecordAPI(object): def __init__(self, request, context): self.request = request self.context = context @view(permission='view', response_schemas={ '200': MembershipResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def get(self): "Retrieve a Membership" return MembershipSchema().to_json(self.context.model.to_dict()) @view(permission='edit', schema=MembershipSchema(), validators=(colander_bound_repository_body_validator, ), response_schemas={ '200': MembershipResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def put(self): "Modify a Membership" body = self.request.validated body['id'] = int(self.request.matchdict['id']) self.context.model.update_dict(body) try: self.context.put() except StorageError as err: self.request.errors.status = 400 self.request.errors.add('body', err.location, str(err)) return return MembershipSchema().to_json(self.context.model.to_dict()) @view(permission='delete', response_schemas={ '200': StatusResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def delete(self): "Delete an Membership" self.context.delete() return {'status': 'ok'} @view(permission='add', schema=MembershipPostSchema(), validators=(colander_bound_repository_body_validator, ), response_schemas={ '201': MembershipResponseSchema(description='Created'), '400': ErrorResponseSchema(description='Bad Request'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), }) def collection_post(self): "Create a new Membership" membership = Membership.from_dict(self.request.validated) try: self.context.put(membership) except StorageError as err: self.request.errors.status = 400 self.request.errors.add('body', err.location, str(err)) return self.request.response.status = 201 return MembershipSchema().to_json(membership.to_dict()) @view(permission='view', schema=MembershipListingRequestSchema(), validators=(colander_validator), cors_origins=('*', ), response_schemas={ '200': MembershipListingResponseSchema(description='Ok'), '400': ErrorResponseSchema(description='Bad Request'), '401': ErrorResponseSchema(description='Unauthorized') }) def collection_get(self): qs = self.request.validated['querystring'] offset = qs['offset'] limit = qs['limit'] person_id = qs.get('person_id') group_id = qs.get('group_id') format = qs.get('format') order_by = [] query = qs.get('query') filters = [] if person_id: filters.append(Membership.person_id == person_id) if qs.get('start_date') or qs.get('end_date'): duration = DateInterval([qs.get('start_date'), qs.get('end_date')]) filters.append(Membership.during.op('&&')(duration)) if group_id: if qs['transitive']: # find group_ids = [group_id] group_ids.extend( ResourceFactory(GroupResource)(self.request, group_id).child_groups()) filters.append( sql.or_(*[Membership.group_id == g for g in group_ids])) else: filters.append(Membership.group_id == group_id) cte_total = None from_query = None query_callback = None if format == 'record': format = None elif format == 'snippet': from_query = self.context.session.query(Membership) def query_callback(from_query): filtered_members = from_query.cte('filtered_members') with_members = self.context.session.query( func.min( func.coalesce(func.lower(filtered_members.c.during), datetime.date(1900, 1, 1))).label('earliest'), func.max( func.coalesce(func.upper(filtered_members.c.during), datetime.date(2100, 1, 1))).label('latest'), func.count( filtered_members.c.id.distinct()).label('memberships'), func.count(Contributor.work_id.distinct()).label('works'), func.array_agg(Group.id.distinct()).label('group_ids'), func.array_agg(Group.name.distinct()).label('group_names'), func.max(filtered_members.c.id).label('id'), Person.id.label('person_id'), Person.name.label('person_name')).join(Person).join( Group).outerjoin(Person.contributors) if query and group_id: with_members = with_members.filter( Person.family_name.ilike('%%%s%%' % query)) with_members = with_members.group_by(Person.id, Person.name) return with_members.order_by(Person.name) listing = self.context.search( from_query=from_query, filters=filters, offset=offset, limit=limit, order_by=order_by, post_query_callback=query_callback, apply_limits_post_query={'snippet': True}.get(format, False), principals=self.request.effective_principals) schema = MembershipSchema() result = { 'total': listing['total'] or cte_total, 'records': [], 'snippets': [], 'limit': limit, 'status': 'ok', 'offset': offset } if format == 'snippet': snippets = [] for hit in listing['hits']: #start_date, end_date = parse_duration(hit.during, # format='%Y-%m-%d') earliest = hit.earliest if earliest: if earliest.year == 1900: earliest = None else: earliest = earliest.strftime('%Y-%m-%d') latest = hit.latest if latest: if latest.year == 2100: latest = None else: latest = latest.strftime('%Y-%m-%d') groups = [{ 'id': i[0], 'name': i[1] } for i in zip(hit.group_ids, hit.group_names)] snippets.append({ 'id': hit.id, 'person_id': hit.person_id, 'person_name': hit.person_name, 'groups': groups, 'earliest': earliest, 'latest': latest, 'works': hit.works, 'memberships': hit.memberships }) result['snippets'] = snippets else: result['records'] = [ schema.to_json(person.to_dict()) for person in listing['hits'] ] return result
class ContributorRecordAPI(object): def __init__(self, request, context): self.request = request self.context = context @view(permission='view', response_schemas={ '200': ContributorResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def get(self): "Retrieve a Contributor" return ContributorSchema().to_json(self.context.model.to_dict()) @view(permission='edit', schema=ContributorSchema(), validators=(colander_bound_repository_body_validator, ), response_schemas={ '200': ContributorResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def put(self): "Modify a Contributor" body = self.request.validated body['id'] = int(self.request.matchdict['id']) self.context.model.update_dict(body) try: self.context.put() except StorageError as err: self.request.errors.status = 400 self.request.errors.add('body', err.location, str(err)) return return ContributorSchema().to_json(self.context.model.to_dict()) @view(permission='delete', response_schemas={ '200': StatusResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def delete(self): "Delete a Contributor" self.context.delete() return {'status': 'ok'} @view(permission='add', schema=ContributorPostSchema(), validators=(colander_bound_repository_body_validator, ), response_schemas={ '201': ContributorResponseSchema(description='Created'), '400': ErrorResponseSchema(description='Bad Request'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), }) def collection_post(self): "Create a new Contributor" contributor = Contributor.from_dict(self.request.validated) try: self.context.put(contributor) except StorageError as err: self.request.errors.status = 400 self.request.errors.add('body', err.location, str(err)) return self.request.response.status = 201 return ContributorSchema().to_json(contributor.to_dict()) @view(permission='view', schema=ContributorListingRequestSchema(), validators=(colander_validator), cors_origins=('*', ), response_schemas={ '200': ContributorListingResponseSchema(description='Ok'), '400': ErrorResponseSchema(description='Bad Request'), '401': ErrorResponseSchema(description='Unauthorized') }) def collection_get(self): qs = self.request.validated['querystring'] offset = qs['offset'] limit = qs['limit'] person_id = qs.get('person_id') group_id = qs.get('group_id') work_id = qs.get('group_id') format = qs.get('format') order_by = [] query = qs.get('query') filters = [] if person_id: filters.append(Contributor.person_id == person_id) if work_id: filters.append(Contributor.work_id == work_id) if group_id: if qs['transitive']: # find group_ids = [group_id] group_ids.extend( ResourceFactory(GroupResource)(self.request, group_id).child_groups()) filters.append( sql.or_(*[Contributor.group_id == g for g in group_ids])) else: filters.append(Contributor.group_id == group_id) cte_total = None from_query = None query_callback = None if format == 'record': format = None elif format == 'snippet': from_query = self.context.session.query(Contributor) listing = self.context.search( from_query=from_query, filters=filters, offset=offset, limit=limit, order_by=order_by, post_query_callback=query_callback, apply_limits_post_query={'snippet': True}.get(format, False), principals=self.request.effective_principals) schema = ContributorSchema() result = { 'total': listing['total'] or cte_total, 'records': [], 'snippets': [], 'limit': limit, 'status': 'ok', 'offset': offset } if format == 'snippet': snippets = [] for hit in listing['hits']: snippets.append({ 'id': hit.id, 'person_id': hit.person_id, 'person_name': hit.person_name, 'group_id': hit.group_id, 'group_name': hit.group_name, 'work_id': hit.work_id, 'work_name': hit.work_name }) result['snippets'] = snippets else: result['records'] = [ schema.to_json(contributor.to_dict()) for contributor in listing['hits'] ] return result
class UserAPI(object): def __init__(self, request, context): self.request = request self.context = context @view(permission='view', cors_origins=('*', ), response_schemas={ '200': UserResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def get(self): "Retrieve a User" return UserSchema().to_json(self.context.model.to_dict()) @view(permission='edit', schema=UserSchema(), validators=(colander_body_validator, ), cors_origins=('*', ), response_schemas={ '200': UserResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def put(self): "Modify a User" body = self.request.validated body['id'] = int(self.request.matchdict['id']) if body['credentials'].startswith('$pbkdf2'): del body['credentials'] self.context.model.update_dict(body) try: self.context.put() except StorageError as err: self.request.errors.status = 400 self.request.errors.add('body', err.location, str(err)) return return UserSchema().to_json(self.context.model.to_dict()) @view(permission='delete', cors_origins=('*', ), response_schemas={ '200': StatusResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def delete(self): "Delete a User" self.context.delete() return {'status': 'ok'} @view(permission='add', cors_origins=('*', ), schema=UserSchema(), validators=(colander_body_validator, ), response_schemas={ '201': UserResponseSchema(description='Created'), '400': ErrorResponseSchema(description='Bad Request'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), }) def collection_post(self): "Create a new User" user = User.from_dict(self.request.validated) self.context.put(user) # force reload the user from db to retrieve the credentials hash self.context.session.refresh(user) user = self.context.get(user.id) self.request.response.status = 201 return UserSchema().to_json(user.to_dict()) @view(permission='view', cors_origins=('*', ), schema=UserListingRequestSchema(), validators=(colander_validator), response_schemas={ '200': UserListingResponseSchema(description='Ok'), '400': ErrorResponseSchema(description='Bad Request'), '401': ErrorResponseSchema(description='Unauthorized') }) def collection_get(self): offset = self.request.validated['querystring']['offset'] limit = self.request.validated['querystring']['limit'] order_by = [User.userid.asc()] format = self.request.validated['querystring'].get('format') if format == 'record': format = None query = self.request.validated['querystring'].get('query') filters = [] if query: filters.append(User.userid.like(query + '%')) listing = self.context.search( filters=filters, offset=offset, limit=limit, order_by=order_by, format=format, principals=self.request.effective_principals) schema = UserSchema() result = { 'total': listing['total'], 'records': [], 'snippets': [], 'limit': limit, 'offset': offset, 'status': 'ok' } if format == 'snippet': result['snippets'] = [ schema.to_json(user.to_dict()) for user in listing['hits'] ] else: result['records'] = [ schema.to_json(user.to_dict()) for user in listing['hits'] ] return result listing = self.context.search( offset=offset, limit=limit, principals=self.request.effective_principals) schema = UserSchema() format = self.request.validated['querystring'].get('format') if format == 'record': format = None return { 'total': listing['total'], 'records': [schema.to_json(user.to_dict()) for user in listing['hits']], 'limit': limit, 'offset': offset, 'status': 'ok' }
class PersonRecordAPI(object): def __init__(self, request, context): self.request = request self.context = context @view(permission='view', response_schemas={ '200': PersonResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def get(self): "Retrieve a Person" return PersonSchema().to_json(self.context.model.to_dict()) @view(permission='edit', schema=PersonSchema(), validators=(colander_bound_repository_body_validator,), cors_origins=('*', ), response_schemas={ '200': PersonResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def put(self): "Modify a Person" body = self.request.validated body['id'] = int(self.request.matchdict['id']) self.context.model.update_dict(body) try: self.context.put() except StorageError as err: self.request.errors.status = 400 self.request.errors.add('body', err.location, str(err)) return return PersonSchema().to_json(self.context.model.to_dict()) @view(permission='delete', response_schemas={ '200': StatusResponseSchema(description='Ok'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), '404': ErrorResponseSchema(description='Not Found'), }) def delete(self): "Delete an Person" self.context.delete() return {'status': 'ok'} @view(permission='add', schema=PersonPostSchema(), validators=(colander_bound_repository_body_validator,), cors_origins=('*', ), response_schemas={ '201': PersonResponseSchema(description='Created'), '400': ErrorResponseSchema(description='Bad Request'), '401': ErrorResponseSchema(description='Unauthorized'), '403': ErrorResponseSchema(description='Forbidden'), }) def collection_post(self): "Create a new Person" person = Person.from_dict(self.request.validated) try: self.context.put(person) except StorageError as err: self.request.errors.status = 400 self.request.errors.add('body', err.location, str(err)) return self.request.response.status = 201 return PersonSchema().to_json(person.to_dict()) @view(permission='view', schema=PersonListingRequestSchema(), validators=(colander_validator), cors_origins=('*', ), response_schemas={ '200': PersonListingResponseSchema(description='Ok'), '400': ErrorResponseSchema(description='Bad Request'), '401': ErrorResponseSchema(description='Unauthorized')}) def collection_get(self): offset = self.request.validated['querystring']['offset'] limit = self.request.validated['querystring']['limit'] order_by = [Person.family_name.asc(), Person.name.asc()] format = self.request.validated['querystring'].get('format') if format == 'record': format = None query = self.request.validated['querystring'].get('query') filters = [] if query: filters.append(Person.search_terms.match(query)) from_query=None query_callback = None if format == 'snippet': from_query = self.context.session.query(Person) from_query = from_query.options( Load(Person).load_only('id', 'name')).group_by(Person.id, Person.name) def query_callback(from_query): filtered_persons = from_query.cte('filtered_persons') with_memberships = self.context.session.query( filtered_persons, func.count(Membership.id.distinct()).label('membership_count'), func.array_agg(Group.id.distinct()).label('group_ids'), func.array_agg(Group.name.distinct()).label('group_names'), func.count(Contributor.work_id.distinct()).label('work_count') ).outerjoin(Contributor).outerjoin(Membership).outerjoin( Group).group_by(filtered_persons.c.id, filtered_persons.c.name) return with_memberships.order_by(filtered_persons.c.name) listing = self.context.search( filters=filters, offset=offset, limit=limit, order_by=order_by, format=format, from_query=from_query, post_query_callback=query_callback, principals=self.request.effective_principals) schema = PersonSchema() result = {'total': listing['total'], 'records': [], 'snippets': [], 'limit': limit, 'offset': offset, 'status': 'ok'} if format == 'snippet': snippets = [] for hit in listing['hits']: groups = [{'id': i[0], 'name': i[1]} for i in zip(hit.group_ids, hit.group_names)] snippets.append( {'id': hit.id, 'name': hit.name, 'groups': groups, 'works': hit.work_count, 'memberships': hit.membership_count}) result['snippets'] = snippets else: result['records'] = [schema.to_json(person.to_dict()) for person in listing['hits']] return result