class TestDownload(EndpointResource): labels = ["tests"] # Set an invalid baseuri to test the automatic fallback to /api baseuri = "/invalid" @decorators.use_kwargs({"stream": fields.Bool()}, location="query") @decorators.endpoint( path="/tests/download", summary="Test missing filename", description="Only enabled in testing mode", responses={200: "Tests executed"}, ) @decorators.endpoint( path="/tests/download/<fname>", summary="Execute tests with the downloader", description="Only enabled in testing mode", responses={ 200: "Tests executed", 206: "Sent partial content", 416: "Range Not Satisfiable", }, ) def get(self, fname: Optional[str] = None, stream: bool = False) -> Response: if stream: fpath = Uploader.absolute_upload_file(fname, subfolder=UPLOAD_PATH) return Downloader.send_file_streamed(fpath) return Downloader.download(fname)
class TestDownload(EndpointResource): labels = ["tests"] @decorators.use_kwargs({"stream": fields.Bool()}, location="query") @decorators.endpoint( # forgot the leading slash to test the automatic fix path="tests/download/<folder>/<fname>", summary="Execute tests with the downloader", description="Only enabled in testing mode", responses={ 200: "Tests executed", 206: "Sent partial content", 403: "Invalid file path", 404: "The requested file does not exist", 416: "Range Not Satisfiable", }, ) def get(self, folder: str, fname: str, stream: bool = False) -> Response: # The same as defined in test_upload subfolder = DATA_PATH.joinpath(folder) if stream: return Downloader.send_file_streamed(fname, subfolder=subfolder) return Downloader.send_file_content(fname, subfolder=subfolder)
class DatasetOutput(Schema): uuid = fields.Str(required=True) name = fields.Str(required=True) description = fields.Str(required=False) status = fields.Str(required=False) technical = fields.Neo4jRelationshipToSingle(TechnicalMetadata) phenotype = fields.Neo4jRelationshipToSingle(Phenotype) files = fields.Neo4jRelationshipToCount() readonly = fields.Bool(dump_default=True)
class StudyOutput(Schema): uuid = fields.Str(required=True) name = fields.Str(required=True) description = fields.Str(required=True) # Number of related datasets datasets = fields.Neo4jRelationshipToCount() phenotypes = fields.Neo4jRelationshipToCount() technicals = fields.Neo4jRelationshipToCount() readonly = fields.Bool(dump_default=True) owning_group_name = fields.Str()
class TestPreloadCallback(EndpointResource): @decorators.auth.require() @decorators.preload(callback=verify_uuid_value) @decorators.use_kwargs({"test": fields.Bool(required=True)}, location="query") @decorators.endpoint( path="/tests/preloadcallback/<uuid>", summary="Only authorized if uuid corresponds to an admin user", description="Only enabled in testing mode", responses={200: "Tests executed"}, ) # Note: target_user is injected by the preload decorator def get(self, uuid: str, test: bool, user: User, target_user: User) -> Response: return self.response({"email": target_user.email})
class Force(PartialSchema): force = fields.Bool()
def admin_user_input(request: FlaskRequest, is_post: bool) -> Type[Schema]: is_admin = HTTPTokenAuth.is_session_user_admin(request, auth) attributes: MarshmallowSchema = {} if is_post: # This is because Email is not typed on marshmallow attributes["email"] = fields.Email( # type: ignore required=is_post, validate=validate.Length(max=100)) attributes["name"] = fields.Str( required=is_post, validate=validate.Length(min=1), metadata={"label": "First Name"}, ) attributes["surname"] = fields.Str( required=is_post, validate=validate.Length(min=1), metadata={"label": "Last Name"}, ) attributes["password"] = fields.Str( required=is_post, validate=validate.Length(min=auth.MIN_PASSWORD_LENGTH), metadata={"password": True}, ) if Connector.check_availability("smtp"): attributes["email_notification"] = fields.Bool( metadata={"label": "Notify password by email"}) attributes["is_active"] = fields.Bool( dump_default=True, required=False, metadata={"label": "Activate user"}, ) roles = {r.name: r.description for r in auth.get_roles()} if not is_admin and RoleEnum.ADMIN.value in roles: roles.pop(RoleEnum.ADMIN.value) attributes["roles"] = fields.List( fields.Str(validate=validate.OneOf( choices=[r for r in roles.keys()], labels=[r for r in roles.values()], )), dump_default=[auth.default_role], required=False, unique=True, metadata={ "label": "Roles", "description": "", "extra_descriptions": auth.role_descriptions, }, ) group_keys = [] group_labels = [] for g in auth.get_groups(): group_keys.append(g.uuid) group_labels.append(f"{g.shortname} - {g.fullname}") if len(group_keys) == 1: default_group = group_keys[0] else: default_group = None attributes["group"] = fields.Str( required=is_post, dump_default=default_group, validate=validate.OneOf(choices=group_keys, labels=group_labels), metadata={ "label": "Group", "description": "The group to which the user belongs", }, ) attributes["expiration"] = fields.DateTime( required=False, allow_none=True, metadata={ "label": "Account expiration", "description": "This user will be blocked after this date", }, ) if custom_fields := mem.customizer.get_custom_input_fields( request=request, scope=mem.customizer.ADMIN): attributes.update(custom_fields)
def test_responses(self, faker: Faker) -> None: class MySchema(Schema): name = fields.Str() f = "myfield" assert ( ResponseMaker.get_schema_type(f, fields.Str(metadata={"password": True})) == "password" ) assert ResponseMaker.get_schema_type(f, fields.Bool()) == "boolean" assert ResponseMaker.get_schema_type(f, fields.Boolean()) == "boolean" assert ResponseMaker.get_schema_type(f, fields.Date()) == "date" assert ResponseMaker.get_schema_type(f, fields.DateTime()) == "datetime" assert ResponseMaker.get_schema_type(f, fields.AwareDateTime()) == "datetime" assert ResponseMaker.get_schema_type(f, fields.NaiveDateTime()) == "datetime" assert ResponseMaker.get_schema_type(f, fields.Decimal()) == "number" # This is because Email is not typed on marshmallow assert ResponseMaker.get_schema_type(f, fields.Email()) == "email" # type: ignore assert ResponseMaker.get_schema_type(f, fields.Float()) == "number" assert ResponseMaker.get_schema_type(f, fields.Int()) == "int" assert ResponseMaker.get_schema_type(f, fields.Integer()) == "int" assert ResponseMaker.get_schema_type(f, fields.Number()) == "number" assert ResponseMaker.get_schema_type(f, fields.Str()) == "string" assert ResponseMaker.get_schema_type(f, fields.String()) == "string" assert ResponseMaker.get_schema_type(f, fields.Dict()) == "dictionary" assert ResponseMaker.get_schema_type(f, fields.List(fields.Str())) == "string[]" assert ResponseMaker.get_schema_type(f, fields.Nested(MySchema())) == "nested" # Unsupported types, fallback to string assert ResponseMaker.get_schema_type(f, fields.URL()) == "string" assert ResponseMaker.get_schema_type(f, fields.Url()) == "string" assert ResponseMaker.get_schema_type(f, fields.UUID()) == "string" # assert ResponseMaker.get_schema_type(f, fields.Constant("x")) == "string" assert ResponseMaker.get_schema_type(f, fields.Field()) == "string" # assert ResponseMaker.get_schema_type(f, fields.Function()) == "string" # assert ResponseMaker.get_schema_type(f, fields.Mapping()) == "string" # assert ResponseMaker.get_schema_type(f, fields.Method()) == "string" # assert ResponseMaker.get_schema_type(f, fields.Raw()) == "string" # assert ResponseMaker.get_schema_type(f, fields.TimeDelta()) == "string" assert not ResponseMaker.is_binary(None) assert not ResponseMaker.is_binary("") assert not ResponseMaker.is_binary("application/json") assert ResponseMaker.is_binary("application/octet-stream") assert ResponseMaker.is_binary("application/x-bzip") assert ResponseMaker.is_binary("application/x-bzip2") assert ResponseMaker.is_binary("application/pdf") assert ResponseMaker.is_binary("application/msword") assert ResponseMaker.is_binary("application/rtf") assert ResponseMaker.is_binary("application/x-tar") assert ResponseMaker.is_binary("application/gzip") assert ResponseMaker.is_binary("application/zip") assert ResponseMaker.is_binary("application/x-7z-compressed") assert not ResponseMaker.is_binary("text/plain") assert not ResponseMaker.is_binary("text/css") assert not ResponseMaker.is_binary("text/csv") assert not ResponseMaker.is_binary("text/html") assert not ResponseMaker.is_binary("text/javascript") assert not ResponseMaker.is_binary("text/xml") assert ResponseMaker.is_binary("image/gif") assert ResponseMaker.is_binary("image/jpeg") assert ResponseMaker.is_binary("image/png") assert ResponseMaker.is_binary("image/svg+xml") assert ResponseMaker.is_binary("image/tiff") assert ResponseMaker.is_binary("image/webp") assert ResponseMaker.is_binary("image/bmp") assert ResponseMaker.is_binary("image/aac") assert ResponseMaker.is_binary("audio/midi") assert ResponseMaker.is_binary("audio/mpeg") assert ResponseMaker.is_binary("audio/wav") assert ResponseMaker.is_binary("audio/anyother") assert ResponseMaker.is_binary("video/mpeg") assert ResponseMaker.is_binary("video/ogg") assert ResponseMaker.is_binary("video/webm") assert ResponseMaker.is_binary("video/anyother") assert ResponseMaker.is_binary("video/anyother") assert not ResponseMaker.is_binary(faker.pystr()) response = EndpointResource.response("", code=200) assert response[1] == 200 # type: ignore response = EndpointResource.response(None, code=200) assert response[1] == 204 # type: ignore response = EndpointResource.response(None, code=200, head_method=True) assert response[1] == 200 # type: ignore
def getInputSchema(request, is_post): # as defined in Marshmallow.schema.from_dict attributes: Dict[str, Union[fields.Field, type]] = {} if is_post: attributes["email"] = fields.Email(required=is_post) attributes["name"] = fields.Str(required=is_post, validate=validate.Length(min=1)) attributes["surname"] = fields.Str(required=is_post, validate=validate.Length(min=1)) attributes["password"] = fields.Str( required=is_post, password=True, validate=validate.Length(min=auth.MIN_PASSWORD_LENGTH), ) if Connector.check_availability("smtp"): attributes["email_notification"] = fields.Bool( label="Notify password by email") attributes["is_active"] = fields.Bool(label="Activate user", default=True, required=False) roles = {r.name: r.description for r in auth.get_roles()} attributes["roles"] = AdvancedList( fields.Str(validate=validate.OneOf( choices=[r for r in roles.keys()], labels=[r for r in roles.values()], )), required=False, label="Roles", description="", unique=True, multiple=True, ) group_keys = [] group_labels = [] for g in auth.get_groups(): group_keys.append(g.uuid) group_labels.append(f"{g.shortname} - {g.fullname}") if len(group_keys) == 1: default_group = group_keys[0] else: default_group = None attributes["group"] = fields.Str( label="Group", description="The group to which the user belongs", required=is_post, default=default_group, validate=validate.OneOf(choices=group_keys, labels=group_labels), ) attributes["expiration"] = fields.DateTime( required=False, allow_none=True, label="Account expiration", description="This user will be blocked after this date", ) if custom_fields := mem.customizer.get_custom_input_fields( request=request, scope=mem.customizer.ADMIN): attributes.update(custom_fields)