Beispiel #1
0
class Pagination(PartialSchema):
    get_total = fields.Boolean(
        required=False, description="Request the total number of elements"
    )
    page = fields.Int(
        required=False,
        description="Current page number",
        validate=validate.Range(min=1),
    )
    size = fields.Int(
        required=False,
        description="Number of elements to retrieve",
        validate=validate.Range(min=1, max=100),
    )
    sort_order = fields.Str(
        validate=validate.OneOf(["asc", "desc"]), required=False, missing="asc"
    )
    sort_by = fields.Str(required=False, missing=None)
    input_filter = fields.Str(required=False, missing=None)

    @post_load
    def verify_parameters(self, data, **kwargs):
        if "get_total" in data:
            data["page"] = None
            data["size"] = None
        else:
            data.setdefault("get_total", False)
            data.setdefault("page", 1)
            data.setdefault("size", 20)

        return data
def getInputSchema(request: FlaskRequest, is_post: bool) -> Type[Schema]:
    graph = neo4j.get_instance()
    # as defined in Marshmallow.schema.from_dict
    attributes: Dict[str, Union[fields.Field, type]] = {}

    attributes["name"] = fields.Str(required=True)
    attributes["age"] = fields.Integer(allow_none=True, validate=validate.Range(min=0))
    attributes["sex"] = fields.Str(
        required=True, validate=validate.OneOf(SEX), metadata={"description": ""}
    )
    attributes["hpo"] = fields.List(
        fields.Str(),
        metadata={
            "label": "HPO",
            "autocomplete_endpoint": "/api/hpo",
            "autocomplete_show_id": True,
            "autocomplete_id_bind": "hpo_id",
            "autocomplete_label_bind": "label",
        },
    )

    geodata_keys = []
    geodata_labels = []

    for g in graph.GeoData.nodes.all():
        geodata_keys.append(g.uuid)
        geodata_labels.append(g.province)

    if len(geodata_keys) == 1:
        default_geodata = geodata_keys[0]
    else:
        default_geodata = None

    attributes["birth_place"] = fields.Str(
        required=False,
        allow_none=True,
        metadata={
            "label": "Birth Place",
            "description": "",
        },
        dump_default=default_geodata,
        validate=validate.OneOf(choices=geodata_keys, labels=geodata_labels),
    )

    return Schema.from_dict(attributes, name="PhenotypeDefinition")
Beispiel #3
0
class TechmetaPutSchema(Schema):
    name = fields.Str(required=False)
    sequencing_date = fields.Date(format=DATE_FORMAT)
    platform = fields.Str(allow_none=True, validate=validate.OneOf(PLATFORMS))
    enrichment_kit = fields.Str()

    @pre_load
    def null_platform(self, data: Dict[str, Any], **kwargs: Any) -> Dict[str, Any]:
        if "platform" in data and data["platform"] == "":
            data["platform"] = None
        return data
class PhenotypeOutputSchema(Schema):
    uuid = fields.Str(required=True)
    name = fields.Str(required=True)
    age = fields.Integer()
    sex = fields.Str(required=True, validate=validate.OneOf(SEX))
    hpo = fields.List(fields.Nested(Hpo), required=False)
    birth_place = fields.Nested(GeoData, required=False)
    relationships = fields.Nested(
        Relationships,
        metadata={"description": "family relationships between phenotypes"},
    )
Beispiel #5
0
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)
Beispiel #6
0
class TechmetaInputSchema(Schema):
    name = fields.Str(required=True)
    sequencing_date = fields.Date(format=DATE_FORMAT)
    platform = fields.Str(validate=validate.OneOf(PLATFORMS))
    enrichment_kit = fields.Str()
Beispiel #7
0
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)
Beispiel #8
0
def getInputSchema(request: FlaskRequest, is_post: bool) -> Type[Schema]:
    graph = neo4j.get_instance()
    # as defined in Marshmallow.schema.from_dict
    attributes: Dict[str, Union[fields.Field, type]] = {}

    attributes["name"] = fields.Str(required=is_post)
    attributes["description"] = fields.Str(required=is_post)
    if request:
        if is_post:
            study_uuid = request.view_args["uuid"]
            study = graph.Study.nodes.get_or_none(uuid=study_uuid)
        else:
            dataset_uuid = request.view_args["uuid"]
            dataset = graph.Dataset.nodes.get_or_none(uuid=dataset_uuid)
            study = dataset.parent_study.single()

        phenotype_keys = []
        phenotype_labels = []

        for p in study.phenotypes.all():
            phenotype_keys.append(p.uuid)
            phenotype_labels.append(p.name)

        if len(phenotype_keys) == 1:
            default_phenotype = phenotype_keys[0]
        else:
            default_phenotype = None

        if not is_post:
            # add option to remove the technical
            phenotype_keys.append("-1")
            phenotype_labels.append(" - ")

        attributes["phenotype"] = fields.Str(
            required=False,
            allow_none=True,
            dump_default=default_phenotype,
            validate=validate.OneOf(choices=phenotype_keys,
                                    labels=phenotype_labels),
        )

        techmeta_keys = []
        techmeta_labels = []

        for t in study.technicals.all():
            techmeta_keys.append(t.uuid)
            techmeta_labels.append(t.name)

        if len(techmeta_keys) == 1:
            default_techmeta = techmeta_keys[0]
        else:
            default_techmeta = None

        if not is_post:
            # add option to remove the technical
            techmeta_keys.append("-1")
            techmeta_labels.append(" - ")

        attributes["technical"] = fields.Str(
            required=False,
            allow_none=True,
            dump_default=default_techmeta,
            validate=validate.OneOf(choices=techmeta_keys,
                                    labels=techmeta_labels),
        )

    return Schema.from_dict(attributes, name="DatasetDefinition")
Beispiel #9
0
        path="/dataset/<uuid>",
        summary="Modify the status of a dataset",
        responses={
            200:
            "Status successfully modified",
            400:
            "Status can't be modified",
            404:
            "This dataset cannot be found or you are not authorized to access",
        },
    )
    @decorators.preload(callback=verify_dataset_status_update)
    @decorators.use_kwargs({
        "status":
        fields.Str(required=True,
                   validate=validate.OneOf(["UPLOAD COMPLETED", "-1"]))
    })
    @decorators.database_transaction
    def patch(
        self,
        uuid: str,
        study: Any,
        dataset: Any,
        status: str,
        user: User,
    ) -> Response:

        # patch can only be done on dataset with status UPLOAD COMPLETED
        if (dataset.status and dataset.status != "UPLOAD COMPLETED"
                and not self.auth.is_admin(user)):
            raise BadRequest(
Beispiel #10
0
    class InputSchema(Schema):
        # lowercase key without label defined. label will be key.title() in schema
        mystr = fields.Str(required=True, validate=validate.Length(min=4))
        # non-lowercase key without label defined. label will be == to key in schema
        MYDATE = fields.Date(required=True)
        MYDATETIME = fields.AwareDateTime(
            required=True,
            format=ISO8601UTC,
            default_timezone=pytz.utc,
            validate=validate.Range(
                max=datetime.now(pytz.utc).replace(hour=23, minute=59, second=59),
                min=datetime(1900, 1, 1, tzinfo=pytz.utc),
                max_inclusive=True,
                error="Invalid date",
            ),
        )
        myint_exclusive = fields.Int(
            required=True,
            # Explicit label definition... but missing description
            validate=validate.Range(
                min=1, max=10, min_inclusive=False, max_inclusive=False
            ),
            metadata={
                "label": "Int exclusive field",
            },
        )
        myint_inclusive = fields.Int(
            required=True,
            # Both label and description explicit definition
            validate=validate.Range(min=1, max=10),
            metadata={
                "label": "Int inclusive field",
                "description": "This field accepts values in a defined range",
            },
        )

        myselect = fields.Str(
            required=True,
            validate=validate.OneOf(choices=["a", "b"], labels=["A", "B"]),
        )

        myselect2 = fields.Str(
            required=True,
            # Wrong definition, number labels < number of choices
            # Labels will be ignored and replaced by choices
            validate=validate.OneOf(choices=["a", "b"], labels=["A"]),
        )

        mymaxstr = fields.Str(required=True, validate=validate.Length(max=7))

        myequalstr = fields.Str(required=True, validate=validate.Length(equal=6))

        # Note: requests (from pytest) has to json-dump the arrays and objects,
        # but the normal Marshmallow fields does not json-load the inputs

        # fields.Nested is a replacement of the default Nested field with the ability
        # to receive json dumped data from requests or pytest
        mynested = fields.Nested(Nested, required=True)

        mynullablenested = fields.Nested(Nested, required=True, allow_none=True)

        # fields.List is a replacement of the default List field with the ability
        # to receive json dumped data from requests or pytest

        # In json model the type of this field will be resolved as string[]
        mylist = fields.List(fields.Str(), required=True)
        # In json model the type of this field will be resolved as int[]
        mylist2 = fields.List(CustomInt, required=True)
        # In json model the type of this field will be resolved as mylist3[]
        # The type is key[] ... should be something more explicative like FieldName[]
        mylist3 = fields.List(CustomGenericField, required=True)