def create_args(): """Defines and validates params for index""" return { "team_id": fields.UUID(missing=None), "file_ids": fields.List(fields.UUID(), load_from="image_ids", location="json"), }
class DumpHoleSchema(Schema): uuid = fields.UUID() course_uuid = fields.UUID() ctime = fields.Integer() mtime = fields.Integer() name = fields.String() number = fields.Integer() par = fields.Integer() distance = fields.Integer()
class CourseApprovedSchema(Schema): uuid = fields.UUID(attribute='course.uuid') created_by = fields.UUID(attribute='course.created_by') message = fields.String() @pre_dump def prepare(self, data, **kwargs): course = data['course'] data['message'] = f"{course.name} has been approved" return data
class TemperatureReadingsSchema(ma.mallow.Schema): # class Meta: # fields = ("log_id", "device_id", "temperature", "time", "url") log_id = fields.UUID() device_id = fields.UUID() temperature = fields.Decimal(attribute='value') timestamp = fields.Method('get_time') device_name = fields.String() location = fields.String() units = fields.String() url = ma.mallow.URLFor('TemperatureReadingsView:get', log_id='<log_id>', _external=True) def get_time(self, obj): return obj['time']
def update_args(): """Defines and validates params for update""" return { "id": fields.UUID(required=True, location="view_args"), "user_tags": fields.List(fields.String(), missing=[], load_from="tags"), }
class TestListSchema(ma.Schema): _links = ma.Hyperlinks({ 'collection': ma.AbsoluteURLFor('testlistresource'), }) id = fields.UUID() name = fields.Str()
def suggested_tags_args(): """Defines and validates suggested tags params""" return { "team_id": fields.UUID(required=True), "tags": fields.List(fields.String(), missing=[]), "min_support": fields.Number(missing=0.25, validate=lambda val: val <= 1), "limit": fields.Integer(missing=3), }
def create_args(): """Defines and validates params for create""" return { "drive_id": fields.String(required=True), "team_id": fields.UUID(required=True, location="view_args"), "url": fields.String(), "name": fields.String(), }
class PatientResource(Resource): @api.doc("get_patient") @use_args( { "patient_uuid": fields.UUID(location="view_args"), "only_dermographic": fields.Boolean( location="querystring", missing=False ), } ) def get(self, args, **kwargs): """Get patient with the UUID""" if args["only_dermographic"]: patient_schema = PatientSchema( many=False, exclude=PatientModel.relationship_keys ) else: patient_schema = PatientSchema(many=False) patient = PatientModel.query.filter_by(id=args["patient_uuid"]).first() return patient_schema.dump(patient), 200 @api.doc("modify_existing_patient") def patch(self, patient_uuid): """Modify patient with the UUID""" patient_schema = PatientSchema(many=False) patient_payload = parser.parse(PatientSchema, request) patient_payload = patient_schema.dump(patient_payload) patient = PatientModel.query.filter_by(id=patient_uuid).first() if patient: patient.update(**patient_payload) db.session.add(patient) db.session.commit() return patient_schema.dump(patient), 200 else: abort(404, "Patient not found.") @api.doc("delete_existing_patient") def delete(self, patient_uuid): """Delete patient with the UUID""" patient = PatientModel.query.filter_by(id=patient_uuid).first() if patient: patient.deleted = True db.session.add(patient) db.session.commit() return None, 204
def update_args(): """Defines and validates params for update""" return { "id": fields.UUID(required=True, load_from="id", location="view_args"), "username": fields.String(validate=validate.Length(min=1)), "email": fields.Email(), "password": fields.String(), "old_password": fields.String(), }
class CodeListSchema(ma.Schema): _links = ma.Hyperlinks({ 'self': ma.AbsoluteURLFor('coderesource', cid='<id>'), 'collection': ma.AbsoluteURLFor('codelistresource'), }) id = fields.UUID() name = fields.Str()
class DumpSportSchema(Schema): uuid = fields.UUID() ctime = fields.Integer() mtime = fields.Integer() name = fields.String() def get_attribute(self, obj, attr, default): return getattr(obj, attr, default) @post_dump def make_obj(self, data, **kwargs): return data
def update_many_args(): """Defines and validates params for update many""" return { "artifacts": fields.List( fields.Nested({ "id": fields.UUID(required=True), "user_tags": fields.List(fields.String(), required=True, load_from="tags"), })) }
class CodeCommandListSchema(ma.Schema): _links = ma.Hyperlinks({ 'self': ma.AbsoluteURLFor('codecommandresource', cid='<code_id>', mid='<machine_id>'), 'collection': ma.AbsoluteURLFor('codecommandlistresource', cid='<code_id>'), }) machine_id = fields.UUID() machine_name = fields.Str(attribute='machine.name') machine_shortname = fields.Str(attribute='machine.shortname')
def search_args(): """Defines and validates params for index""" return { "search": fields.String(missing=None), "team_id": fields.UUID(missing=None), "types": fields.String(load_from="type", missing="image"), "pipeline": fields.Integer(), "start_date": fields.DateTime(), "end_date": fields.DateTime(), "offset": fields.Integer(missing=0), "limit": fields.Integer(missing=12), "notify_clients": fields.Boolean(missing=False), }
def create_args(): """Defines and validates params for create""" return { "type": fields.String(missing="image"), "file": fields.Function(deserialize=validate_image, required=True, location="files", load_from="image"), "team_id": fields.UUID(missing=None), "user_tags": fields.List(fields.String(), load_from="tags"), }
class CalculationSchema(CalculationListSchema): id = fields.UUID() collection = fields.Str(attribute='collection.name') code = fields.Str(attribute='code.name') structure = fields.Nested('StructureSchema', only=( 'id', 'name', '_links', )) test = fields.Str(attribute='test.name') tasks = fields.Nested('Task2ListSchema', many=True) testresults = fields.Nested('TestResultSchema', many=True, exclude=('calculations', )) metadata = fields.Dict(attribute='mdata') _links = ma.Hyperlinks({ 'self': ma.AbsoluteURLFor('calculationresource', cid='<id>'), 'preview': ma.AbsoluteURLFor('calculationpreviewresource', cid='<id>'), 'collection': ma.AbsoluteURLFor('calculationlistresource'), 'tasks': ma.AbsoluteURLFor('calculationtask2listresource', cid='<id>'), }) basis_sets = fields.Nested(CalculationBasisSetAssociationSchema, attribute='basis_set_associations', many=True) pseudos = fields.Nested(PseudopotentialSchema, many=True, exclude=( 'pseudo', 'converted_from', )) class Meta: model = Calculation exclude = ( 'basis_set_associations', 'tasks_query', 'testresults_query', 'mdata', )
class CalculationListSchema(ma.Schema): id = fields.UUID() collection = fields.Str(attribute='collection.name') code = fields.Str(attribute='code.name') structure = fields.Str(attribute='structure.name') test = fields.Str(attribute='test.name') results_available = fields.Bool() current_task = fields.Nested('Task2ListSchema') _links = ma.Hyperlinks({ 'self': ma.AbsoluteURLFor('calculationresource', cid='<id>'), 'preview': ma.AbsoluteURLFor('calculationpreviewresource', cid='<id>'), 'collection': ma.AbsoluteURLFor('calculationlistresource'), 'tasks': ma.AbsoluteURLFor('calculationtask2listresource', cid='<id>'), })
class Task2ListSchema(ma.Schema): id = fields.UUID() status = fields.Str(attribute='status.name') ctime = fields.DateTime() mtime = fields.DateTime() machine = fields.Str(attribute='machine.name') priority = fields.Int() _links = ma.Hyperlinks({ 'self': ma.AbsoluteURLFor('task2resource', tid='<id>'), 'collection': ma.AbsoluteURLFor('task2listresource'), 'uploads': ma.AbsoluteURLFor('task2uploadresource', tid='<id>'), 'calculation': ma.AbsoluteURLFor('calculationresource', cid='<calculation_id>'), })
class DumpCourseSchema(Schema): uuid = fields.UUID() ctime = fields.Integer() mtime = fields.Integer() name = fields.String() status = EnumField(StatusEnum) line_1 = fields.String() line_2 = fields.String() city = fields.String() province = fields.String() country = fields.String() holes = fields.List(fields.Nested('DumpHoleSchema')) def get_attribute(self, obj, attr, default): if attr == 'country': return obj.country.code if getattr(obj, 'country', None) else default return getattr(obj, attr, default) @post_dump def make_obj(self, data, **kwargs): return data
class ObjectResource(ContentNegotiatedMethodView): """Object item resource.""" delete_args = { 'version_id': fields.UUID( location='query', load_from='versionId', missing=None, ), 'upload_id': fields.UUID( location='query', load_from='uploadId', missing=None, ), 'uploads': fields.Raw( location='query', validate=invalid_subresource_validator, ), } get_args = dict( delete_args, download=fields.Raw( location='query', missing=None, ) ) post_args = { 'uploads': fields.Raw( location='query', ), 'upload_id': fields.UUID( location='query', load_from='uploadId', missing=None, ) } put_args = { 'upload_id': fields.UUID( location='query', load_from='uploadId', missing=None, ), } multipart_init_args = { 'size': fields.Int( locations=('query', 'json'), missing=None, ), 'part_size': fields.Int( locations=('query', 'json'), missing=None, load_from='partSize', ), } def __init__(self, *args, **kwargs): """Instantiate content negotiated view.""" super(ObjectResource, self).__init__(*args, **kwargs) # # ObjectVersion helpers # @staticmethod def check_object_permission(obj): """Retrieve object and abort if it doesn't exists.""" check_permission(current_permission_factory( obj, 'object-read' )) if not obj.is_head: check_permission( current_permission_factory(obj, 'object-read-version'), hidden=False ) @classmethod def get_object(cls, bucket, key, version_id): """Retrieve object and abort if it doesn't exists. If the file is not found, the connection is aborted and the 404 error is returned. :param bucket: The bucket (instance or id) to get the object from. :param key: The file key. :param version_id: The version ID. :returns: A :class:`invenio_files_rest.models.ObjectVersion` instance. """ obj = ObjectVersion.get(bucket, key, version_id=version_id) if not obj: abort(404, 'Object does not exists.') cls.check_object_permission(obj) return obj def create_object(self, bucket, key): """Create a new object. :param bucket: The bucket (instance or id) to get the object from. :param key: The file key. :returns: A Flask response. """ # Initial validation of size based on Content-Length. # User can tamper with Content-Length, so this is just an initial up # front check. The storage subsystem must validate the size limit as # well. stream, content_length, content_md5, tags = \ current_files_rest.upload_factory() size_limit = bucket.size_limit if content_length and size_limit and content_length > size_limit: desc = 'File size limit exceeded.' \ if isinstance(size_limit, int) else size_limit.reason raise FileSizeError(description=desc) with db.session.begin_nested(): obj = ObjectVersion.create(bucket, key) obj.set_contents( stream, size=content_length, size_limit=size_limit) # Check add tags if tags: for key, value in tags.items(): ObjectVersionTag.create(obj, key, value) db.session.commit() return self.make_response( data=obj, context={ 'class': ObjectVersion, 'bucket': bucket, }, etag=obj.file.checksum ) @need_permissions( lambda self, bucket, obj, *args: obj, 'object-delete', hidden=False, # Because get_object permission check has already run ) def delete_object(self, bucket, obj, version_id): """Delete an existing object. :param bucket: The bucket (instance or id) to get the object from. :param obj: A :class:`invenio_files_rest.models.ObjectVersion` instance. :param version_id: The version ID. :returns: A Flask response. """ if version_id is None: # Create a delete marker. with db.session.begin_nested(): ObjectVersion.delete(bucket, obj.key) else: # Permanently delete specific object version. check_permission( current_permission_factory(bucket, 'object-delete-version'), hidden=False, ) obj.remove() # Set newest object as head if obj.is_head: obj_to_restore = \ ObjectVersion.get_versions(obj.bucket, obj.key, desc=True).first() if obj_to_restore: obj_to_restore.is_head = True if obj.file_id: remove_file_data.delay(str(obj.file_id)) db.session.commit() return self.make_response('', 204) @staticmethod def send_object(bucket, obj, expected_chksum=None, logger_data=None, restricted=True, as_attachment=False): """Send an object for a given bucket. :param bucket: The bucket (instance or id) to get the object from. :param obj: A :class:`invenio_files_rest.models.ObjectVersion` instance. :params expected_chksum: Expected checksum. :param logger_data: The python logger. :param kwargs: Keyword arguments passed to ``Object.send_file()`` :returns: A Flask response. """ if not obj.is_head: check_permission( current_permission_factory(obj, 'object-read-version'), hidden=False ) if expected_chksum and obj.file.checksum != expected_chksum: current_app.logger.warning( 'File checksum mismatch detected.', extra=logger_data) file_downloaded.send(current_app._get_current_object(), obj=obj) return obj.send_file(restricted=restricted, as_attachment=as_attachment) # # MultipartObject helpers # @pass_multipart(with_completed=True) @need_permissions( lambda self, multipart: multipart, 'multipart-read' ) def multipart_listparts(self, multipart): """Get parts of a multipart upload. :param multipart: A :class:`invenio_files_rest.models.MultipartObject` instance. :returns: A Flask response. """ return self.make_response( data=Part.query_by_multipart( multipart).order_by(Part.part_number).limit(1000).all(), context={ 'class': Part, 'multipart': multipart, 'many': True, } ) @use_kwargs(multipart_init_args) def multipart_init(self, bucket, key, size=None, part_size=None): """Initialize a multipart upload. :param bucket: The bucket (instance or id) to get the object from. :param key: The file key. :param size: The total size. :param part_size: The part size. :raises invenio_files_rest.errors.MissingQueryParameter: If size or part_size are not defined. :returns: A Flask response. """ if size is None: raise MissingQueryParameter('size') if part_size is None: raise MissingQueryParameter('partSize') multipart = MultipartObject.create(bucket, key, size, part_size) db.session.commit() return self.make_response( data=multipart, context={ 'class': MultipartObject, 'bucket': bucket, } ) @pass_multipart(with_completed=True) def multipart_uploadpart(self, multipart): """Upload a part. :param multipart: A :class:`invenio_files_rest.models.MultipartObject` instance. :returns: A Flask response. """ content_length, part_number, stream, content_type, content_md5, tags =\ current_files_rest.multipart_partfactory() if content_length: ck = multipart.last_part_size if \ part_number == multipart.last_part_number \ else multipart.chunk_size if ck != content_length: raise MultipartInvalidChunkSize() # Create part try: p = Part.get_or_create(multipart, part_number) p.set_contents(stream) db.session.commit() except Exception: # We remove the Part since incomplete data may have been written to # disk (e.g. client closed connection etc.) so it must be # reuploaded. db.session.rollback() Part.delete(multipart, part_number) raise return self.make_response( data=p, context={ 'class': Part, }, etag=p.checksum ) @pass_multipart(with_completed=True) def multipart_complete(self, multipart): """Complete a multipart upload. :param multipart: A :class:`invenio_files_rest.models.MultipartObject` instance. :returns: A Flask response. """ multipart.complete() db.session.commit() version_id = str(uuid.uuid4()) return self.make_response( data=multipart, context={ 'class': MultipartObject, 'bucket': multipart.bucket, 'object_version_id': version_id, }, # This will wait for the result, and send whitespace on the # connection until the task has finished (or max timeout reached). task_result=merge_multipartobject.delay( str(multipart.upload_id), version_id=version_id, ), ) @pass_multipart() @need_permissions( lambda self, multipart: multipart, 'multipart-delete', ) def multipart_delete(self, multipart): """Abort a multipart upload. :param multipart: A :class:`invenio_files_rest.models.MultipartObject` instance. :returns: A Flask response. """ multipart.delete() db.session.commit() if multipart.file_id: remove_file_data.delay(str(multipart.file_id)) return self.make_response('', 204) # # HTTP methods implementations # @use_kwargs(get_args) @pass_bucket def get(self, bucket=None, key=None, version_id=None, upload_id=None, uploads=None, download=None): """Get object or list parts of a multpart upload. :param bucket: The bucket (instance or id) to get the object from. (Default: ``None``) :param key: The file key. (Default: ``None``) :param version_id: The version ID. (Default: ``None``) :param upload_id: The upload ID. (Default: ``None``) :param download: The download flag. (Default: ``None``) :returns: A Flask response. """ if upload_id: return self.multipart_listparts(bucket, key, upload_id) else: obj = self.get_object(bucket, key, version_id) # If 'download' is missing from query string it will have # the value None. return self.send_object(bucket, obj, as_attachment=download is not None) @use_kwargs(post_args) @pass_bucket @need_bucket_permission('bucket-update') @ensure_input_stream_is_not_exhausted def post(self, bucket=None, key=None, uploads=missing, upload_id=None): """Upload a new object or start/complete a multipart upload. :param bucket: The bucket (instance or id) to get the object from. (Default: ``None``) :param key: The file key. (Default: ``None``) :param upload_id: The upload ID. (Default: ``None``) :returns: A Flask response. """ if uploads is not missing: return self.multipart_init(bucket, key) elif upload_id is not None: return self.multipart_complete(bucket, key, upload_id) abort(403) @use_kwargs(put_args) @pass_bucket @need_bucket_permission('bucket-update') @ensure_input_stream_is_not_exhausted def put(self, bucket=None, key=None, upload_id=None): """Update a new object or upload a part of a multipart upload. :param bucket: The bucket (instance or id) to get the object from. (Default: ``None``) :param key: The file key. (Default: ``None``) :param upload_id: The upload ID. (Default: ``None``) :returns: A Flask response. """ if upload_id is not None: return self.multipart_uploadpart(bucket, key, upload_id) else: return self.create_object(bucket, key) @use_kwargs(delete_args) @pass_bucket def delete(self, bucket=None, key=None, version_id=None, upload_id=None, uploads=None): """Delete an object or abort a multipart upload. :param bucket: The bucket (instance or id) to get the object from. (Default: ``None``) :param key: The file key. (Default: ``None``) :param version_id: The version ID. (Default: ``None``) :param upload_id: The upload ID. (Default: ``None``) :returns: A Flask response. """ if upload_id is not None: return self.multipart_delete(bucket, key, upload_id) else: obj = self.get_object(bucket, key, version_id) return self.delete_object(bucket, obj, version_id)
class ObjectResource(ContentNegotiatedMethodView): """"Object item resource.""" get_args = { 'version_id': fields.UUID( location='query', load_from='versionId', missing=None, ), 'upload_id': fields.UUID( location='query', load_from='uploadId', missing=None, ) } delete_args = get_args post_args = { 'uploads': fields.Raw( location='query', missing=False, ), 'upload_id': fields.UUID( location='query', load_from='uploadId', missing=None, ) } put_args = { 'upload_id': fields.UUID( location='query', load_from='uploadId', missing=None, ), } upload_headers = { 'content_md5': fields.Str( load_from='Content-MD5', location='headers', missing=None, ), 'content_length': fields.Int( load_from='Content-Length', location='headers', required=True, validate=minsize_validator, ) } multipart_init_args = { 'size': fields.Int( locations=('query', 'json'), required=True, ), 'part_size': fields.Int( locations=('query', 'json'), required=True, ), } # # ObjectVersion helpers # @staticmethod def get_object(bucket, key, version_id): """Retrieve object and abort if it doesn't exists.""" obj = ObjectVersion.get(bucket, key, version_id=version_id) if not obj: abort(404, 'Object does not exists.') check_permission(current_permission_factory(obj, 'object-read')) if not obj.is_head: check_permission(current_permission_factory( obj, 'object-read-version'), hidden=False) return obj @staticmethod @use_kwargs(upload_headers) def create_object(bucket, key, uploaded_file=None, content_md5=None, content_length=None): """Create a new object.""" # Initial validation of size based on Content-Length. # User can tamper with Content-Length, so this is just an initial up # front check. The storage subsystem must validate the size limit as # well. size_limit = bucket.size_limit if size_limit and content_length > size_limit: desc = 'File size limit exceeded.' \ if isinstance(size_limit, int) else size_limit.reason raise FileSizeError(description=desc) with db.session.begin_nested(): obj = ObjectVersion.create(bucket, key) obj.set_contents(request.stream, size=content_length, size_limit=size_limit) db.session.commit() return obj @need_permissions( lambda self, bucket, obj, *args: obj, 'object-delete', hidden=False, # Because get_object permission check has already run ) def delete_object(self, bucket, obj, version_id): """Delete an existing object.""" if version_id is None: # Create a delete marker. with db.session.begin_nested(): ObjectVersion.delete(bucket, obj.key) db.session.commit() else: # Permanently delete specific object version. check_permission( current_permission_factory(bucket, 'object-delete-version'), hidden=False, ) obj.remove() db.session.commit() if obj.file_id: remove_file_data.delay(str(obj.file_id)) return self.make_response('', 204) @staticmethod def send_object(bucket, obj, expected_chksum=None, logger_data=None, restricted=True): """Send an object for a given bucket.""" if not obj.is_head: check_permission(current_permission_factory( obj, 'object-read-version'), hidden=False) if expected_chksum and obj.file.checksum != expected_chksum: current_app.logger.warning('File checksum mismatch detected.', extra=logger_data) file_downloaded.send(current_app._get_current_object(), obj=obj) return obj.send_file(restricted=restricted) # # MultipartObject helpers # @pass_multipart(with_completed=True) @need_permissions(lambda self, multipart: multipart, 'multipart-read') def multipart_listparts(self, multipart): """Get parts of a multpart upload.""" return self.make_response( data=Part.query_by_multipart(multipart).order_by( Part.part_number).limit(1000).all(), context={ 'class': Part, 'multipart': multipart, 'many': True, }) @use_kwargs(multipart_init_args) def multipart_init(self, bucket, key, size=None, part_size=None): """Initiate a multipart upload.""" multipart = MultipartObject.create(bucket, key, size, part_size) db.session.commit() return self.make_response(data=multipart, context={ 'class': MultipartObject, 'bucket': bucket, }) @use_kwargs(upload_headers) @pass_multipart(with_completed=True) def multipart_uploadpart(self, multipart, content_md5=None, content_length=None): """Upload a part.""" if content_length != multipart.chunk_size: raise MultipartInvalidChunkSize() # Extract part number from request. data = None for schema in current_files_rest.uploadparts_schema_factory: try: data = parser.parse(schema) if data: break except UnprocessableEntity: pass if not data or data.get('part_number') is None: raise MultipartInvalidPartNumber() part_number = data['part_number'] # Create part try: p = Part.get_or_create(multipart, part_number) p.set_contents(request.stream) db.session.commit() except Exception: # We remove the Part since incomplete data may have been written to # disk (e.g. client closed connection etc.) db.session.rollback() Part.delete(multipart, part_number) raise return self.make_response(data=p, context={ 'class': Part, }, etag=p.checksum) @pass_multipart(with_completed=True) def multipart_complete(self, multipart): """Complete a multipart upload.""" multipart.complete() db.session.commit() merge_multipartobject.delay(str(multipart.upload_id)) return self.make_response(data=multipart, context={ 'class': MultipartObject, 'bucket': multipart.bucket, }) @pass_multipart() @need_permissions( lambda self, multipart: multipart, 'multipart-delete', ) def multipart_delete(self, multipart): """Abort a multipart upload.""" multipart.delete() db.session.commit() if multipart.file_id: remove_file_data.delay(str(multipart.file_id)) return self.make_response('', 204) # # HTTP methods implementations # @use_kwargs(get_args) @pass_bucket def get(self, bucket=None, key=None, version_id=None, upload_id=None): """Get object or list parts of a multpart upload.""" if upload_id: return self.multipart_listparts(bucket, key, upload_id) else: obj = self.get_object(bucket, key, version_id) return self.send_object(bucket, obj) @use_kwargs(post_args) @pass_bucket @need_bucket_permission('bucket-update') def post(self, bucket=None, key=None, uploads=None, upload_id=None): """Upload a new object or start/complete a multipart upload.""" if uploads is not False: return self.multipart_init(bucket, key) elif upload_id is not None: return self.multipart_complete(bucket, key, upload_id) abort(403) @use_kwargs(put_args) @pass_bucket @need_bucket_permission('bucket-update') def put(self, bucket=None, key=None, upload_id=None): """Update a new object or upload a part of a multipart upload.""" if upload_id is not None: return self.multipart_uploadpart(bucket, key, upload_id) else: return self.create_object(bucket, key) @use_kwargs(delete_args) @pass_bucket def delete(self, bucket=None, key=None, version_id=None, upload_id=None): """Delete an object or abort a multipart upload.""" if upload_id is not None: return self.multipart_delete(bucket, key, upload_id) else: obj = self.get_object(bucket, key, version_id) return self.delete_object(bucket, obj, version_id)
def update_args(): """Defines and validates params for update""" return { "id": fields.UUID(required=True, location="view_args"), "name": fields.String(required=True, validate=validate.Length(min=1)), }
def get_args(): """Defines and validates params for show""" return {"id": fields.UUID(required=True, location="view_args")}
def create_args(): """Defines and validates params for create""" return { "id": fields.UUID(required=True, location="view_args"), "id_token": fields.String(required=True) }
def revoke_access_args(): """Defines and validates params for revoke_access""" return {"id": fields.UUID(required=True, location="view_args")}
def update_args(): """Defines and validates params for update""" return { "id": fields.UUID(required=True, location="view_args"), "auth_code": fields.String(required=True) }
class DepositFileResource(ContentNegotiatedMethodView): """Deposit files resource.""" view_name = '{0}_file' get_args = dict(version_id=fields.UUID( location='headers', load_from='version_id', ), ) """GET query arguments.""" def __init__(self, serializers, pid_type, ctx, *args, **kwargs): """Constructor.""" super(DepositFileResource, self).__init__(serializers, *args, **kwargs) for key, value in ctx.items(): setattr(self, key, value) @use_kwargs(get_args) @pass_record @need_record_permission('read_permission_factory') def get(self, pid, record, key, version_id=None, **kwargs): """Get file. Permission required: `read_permission_factory`. :param pid: Pid object (from url). :param record: Record object resolved from the pid. :param key: Unique identifier for the file in the deposit. :param version_id: File version. Optional. If no version is provided, the last version is retrieved. :returns: the file content. """ try: obj = record.files[str(key)].get_version(version_id=version_id) return self.make_response(obj=obj or abort(404), pid=pid, record=record) except KeyError: abort(404) @require_api_auth() @require_oauth_scopes(write_scope.id) @pass_record @need_record_permission('update_permission_factory') def put(self, pid, record, key): """Handle the file rename through the PUT deposit file. Permission required: `update_permission_factory`. :param pid: Pid object (from url). :param record: Record object resolved from the pid. :param key: Unique identifier for the file in the deposit. """ try: data = json.loads(request.data.decode('utf-8')) new_key = data['filename'] except KeyError: raise WrongFile() new_key_secure = secure_filename(new_key) if not new_key_secure or new_key != new_key_secure: raise WrongFile() try: obj = record.files.rename(str(key), new_key_secure) except KeyError: abort(404) record.commit() db.session.commit() return self.make_response(obj=obj, pid=pid, record=record) @require_api_auth() @require_oauth_scopes(write_scope.id) @pass_record @need_record_permission('update_permission_factory') def delete(self, pid, record, key): """Handle DELETE deposit file. Permission required: `update_permission_factory`. :param pid: Pid object (from url). :param record: Record object resolved from the pid. :param key: Unique identifier for the file in the deposit. """ try: del record.files[str(key)] record.commit() db.session.commit() return make_response('', 204) except KeyError: abort( 404, 'The specified object does not exist or has already ' 'been deleted.')
if headers: return jsonify({"errors": messages}), err.code, headers else: return jsonify({"errors": messages}), 422 @app.errorhandler(400) def handle_error2(err): """Flask error handler.""" messages = err.data.get("messages", ["Invalid request."]) return jsonify({"_0": "Internal data mismatch", "errors": messages}), 400 @app.route('/', methods=['POST']) @use_args({ 'sender': fields.UUID(required=True), 'receiver': fields.UUID(required=True), 'amount': fields.Decimal(required=True, validate=lambda x: x > 0) }) def api_main(args): """Put json to DB to make a transaction. Example: { "sender": "40e6815d-b5c6-4896-987c-f30f3678f608", "receiver": "6ecd8c99-4036-403d-bf84-cf8400f67836", "amount": 1 } Args: args (dict):
class DepositFileResource(ContentNegotiatedMethodView): """Deposit files resource.""" view_name = '{0}_file' get_args = dict(version_id=fields.UUID( location='headers', load_from='version_id', ), ) """GET query arguments.""" def __init__(self, serializers, pid_type, ctx, *args, **kwargs): """Constructor.""" super(DepositFileResource, self).__init__(serializers, *args, **kwargs) for key, value in ctx.items(): setattr(self, key, value) @use_kwargs(get_args) @pass_record @need_record_permission('read_permission_factory') def get(self, pid, record, key, version_id, **kwargs): """Get deposit/depositions/:id/files/:key.""" try: obj = record.files[str(key)].get_version(version_id=version_id) return self.make_response(obj=obj or abort(404)) except KeyError: abort(404) @require_api_auth() @require_oauth_scopes(write_scope.id) @pass_record @need_record_permission('update_permission_factory') def put(self, pid, record, key): """Handle PUT deposit files.""" try: data = json.loads(request.data.decode('utf-8')) new_key = data['filename'] except KeyError: raise WrongFile() new_key_secure = secure_filename(new_key) if not new_key_secure or new_key != new_key_secure: raise WrongFile() try: obj = record.files.rename(str(key), new_key_secure) except KeyError: abort(404) record.commit() db.session.commit() return self.make_response(obj=obj) @require_api_auth() @require_oauth_scopes(write_scope.id) @pass_record @need_record_permission('update_permission_factory') def delete(self, pid, record, key): """Handle DELETE deposit files.""" try: del record.files[str(key)] record.commit() db.session.commit() return make_response('', 204) except KeyError: abort( 404, 'The specified object does not exist or has already ' 'been deleted.')