示例#1
0
    def get(self):
        """
        ---
        summary: Get list of attribute keys
        description: |
            Returns list of attribute key definitions.
        security:
            - bearerAuth: []
        tags:
            - attribute
        parameters:
            - in: query
              name: access
              schema:
                type: string
                enum: [read, set, manage]
                default: read
              description: Type of desired access
        responses:
            200:
                description: List of attribute key definitions
                content:
                  application/json:
                    schema: AttributeDefinitionListResponseSchema
            400:
                description: When used unknown access type
            403:
                description: |
                    When requested `manage` access
                    but user doesn't have 'manage_users' capability
            503:
                description: |
                    Request canceled due to database statement timeout.
        """
        schema = AttributeDefinitionListRequestSchema()
        obj = load_schema(request.args, schema)
        access = obj["access"]

        if access == "read":
            attribute_definitions = AttributeDefinition.query_for_read()
        elif access == "set":
            attribute_definitions = AttributeDefinition.query_for_set()
        elif access == "manage":
            if not g.auth_user.has_rights(Capabilities.manage_users):
                raise Forbidden("You are not permitted to manage attributes")
            attribute_definitions = db.session.query(AttributeDefinition)
        else:
            raise BadRequest(f"Unknown desired access type '{access}'")

        attribute_definitions = attribute_definitions.order_by(
            AttributeDefinition.key
        ).all()
        schema = AttributeDefinitionListResponseSchema()
        return schema.dump({"attribute_definitions": attribute_definitions})
示例#2
0
    def get_condition(self, expression: Expression,
                      remainder: List[str]) -> Any:
        if len(remainder) > 1:
            raise FieldNotQueryableException(
                f"Attribute doesn't have subfields: {'.'.join(remainder[1:])}")

        if remainder:
            attribute_key = remainder[0]
        else:
            raise UnsupportedGrammarException(
                "Missing attribute key (meta.<key>:)")

        attribute_definition = AttributeDefinition.query_for_read(
            key=attribute_key, include_hidden=True).first()

        if attribute_definition is None:
            raise ObjectNotFoundException(
                f"No such attribute: {attribute_key}")

        if (attribute_definition.hidden and expression.has_wildcard()
                and not g.auth_user.has_rights(
                    Capabilities.reading_all_attributes)):
            raise FieldNotQueryableException(
                "Wildcards are not allowed for hidden attributes")

        value = get_term_value(expression)
        attribute_value = Attribute.value[()].astext
        if expression.has_wildcard():
            value_condition = attribute_value.like(value)
        else:
            value_condition = attribute_value == value

        return self.column.any(
            and_(Attribute.key == attribute_key, value_condition))
示例#3
0
    def post(self):
        """
        ---
        summary: Create attribute key
        description: |
            Creates attribute key definition.

            Requires `manage_users` capability.
        security:
            - bearerAuth: []
        tags:
            - attribute
        requestBody:
            description: Attribute key definition
            content:
              application/json:
                schema: AttributeDefinitionCreateRequestSchema
        responses:
            200:
                description: When attribute definition is successfully added
                content:
                  application/json:
                    schema: AttributeDefinitionItemResponseSchema
            400:
                description: |
                    When one of attribute definition fields is missing or incorrect.
            403:
                description: When user doesn't have `manage_users` capability.
            409:
                description: If attribute key is already defined
            503:
                description: |
                    Request canceled due to database statement timeout.
        """
        schema = AttributeDefinitionCreateRequestSchema()
        obj = loads_schema(request.get_data(as_text=True), schema)

        attribute_definition = (
            db.session.query(AttributeDefinition).filter(
                AttributeDefinition.key == obj["key"]
            )
        ).first()

        if attribute_definition:
            raise Conflict(f"Attribute key '{obj['key']}' is already defined")

        attribute_definition = AttributeDefinition(
            key=obj["key"],
            url_template=obj["url_template"],
            label=obj["label"],
            description=obj["description"],
            hidden=obj["hidden"],
        )
        db.session.add(attribute_definition)
        db.session.commit()

        hooks.on_created_attribute_key(attribute_definition)
        schema = AttributeDefinitionItemResponseSchema()
        return schema.dump(attribute_definition)
示例#4
0
    def post(self, key):
        """
        ---
        summary: Create attribute key
        description: |
            Creates attribute key definition.

            Requires `manage_users` capability.
        security:
            - bearerAuth: []
        tags:
            - deprecated
        parameters:
            - in: path
              name: key
              schema:
                type: string
              description: Attribute key
        requestBody:
            description: Attribute key definition
            content:
              application/json:
                schema: MetakeyDefinitionItemRequestBodySchema
        responses:
            200:
                description: When metakey definition is successfully added
                content:
                  application/json:
                    schema: MetakeyDefinitionItemResponseSchema
            400:
                description: |
                    When one of attribute definition fields is missing or incorrect.
            403:
                description: When user doesn't have `manage_users` capability.
            503:
                description: |
                    Request canceled due to database statement timeout.
        """
        schema = MetakeyDefinitionItemRequestArgsSchema()
        args_obj = load_schema({"key": key}, schema)

        schema = MetakeyDefinitionItemRequestBodySchema()
        obj = loads_schema(request.get_data(as_text=True), schema)

        metakey_definition = AttributeDefinition(
            key=args_obj["key"],
            url_template=obj["url_template"],
            label=obj["label"],
            description=obj["description"],
            hidden=obj["hidden"],
        )
        metakey_definition = db.session.merge(metakey_definition)
        db.session.commit()

        schema = MetakeyDefinitionItemResponseSchema()
        return schema.dump(metakey_definition)
示例#5
0
    def get(self, access):
        """
        ---
        summary: Get list of attribute keys
        description: |
            Returns list of attribute keys which currently authenticated user
            can read or set.
        security:
            - bearerAuth: []
        tags:
            - deprecated
        parameters:
            - in: path
              name: access
              schema:
                type: string
                enum: [read, set]
              description: Type of desired access
        responses:
            200:
                description: List of attribute keys and definitions
                content:
                  application/json:
                    schema: MetakeyDefinitionListResponseSchema
            400:
                description: When used unknown access type (other than read or set)
            503:
                description: |
                    Request canceled due to database statement timeout.
        """
        if access == "read":
            metakeys = AttributeDefinition.query_for_read()
        elif access == "set":
            metakeys = AttributeDefinition.query_for_set()
        else:
            raise BadRequest(f"Unknown desired access type '{access}'")

        metakeys = metakeys.order_by(AttributeDefinition.key).all()
        schema = MetakeyDefinitionListResponseSchema()
        return schema.dump({"metakeys": metakeys})
示例#6
0
    def get_condition(self, expression: Expression,
                      remainder: List[str]) -> Any:
        if remainder:
            attribute_key = remainder[0]
        else:
            raise UnsupportedGrammarException(
                "Missing attribute key (attribute.<key>:)")

        attribute_definition = AttributeDefinition.query_for_read(
            key=attribute_key, include_hidden=True).first()

        if attribute_definition is None:
            raise ObjectNotFoundException(
                f"No such attribute: {attribute_key}")

        if (attribute_definition.hidden and expression.has_wildcard()
                and not g.auth_user.has_rights(
                    Capabilities.reading_all_attributes)):
            raise FieldNotQueryableException(
                "Wildcards are not allowed for hidden attributes")

        value = get_term_value(expression)
        json_path = make_jsonpath(remainder[1:])
        # Make aliased function call
        json_elements = func.jsonb_path_query(Attribute.value,
                                              json_path).alias("json_element")
        # Use #>>'{}' to extract value as text
        json_element = column("json_element").operate(JSONPATH_ASTEXT,
                                                      "{}",
                                                      result_type=Text)
        if expression.has_wildcard():
            condition = json_element.like(value)
        else:
            condition = json_element == value
        value_condition = exists(
            select([1]).select_from(json_elements).where(condition))
        return self.column.any(
            and_(Attribute.key == attribute_key, value_condition))
示例#7
0
    def create_object(self, params):
        params = dict(params)

        # Validate parent object
        if params["parent"] is not None:
            if not g.auth_user.has_rights(Capabilities.adding_parents):
                raise Forbidden("You are not permitted to link with parent")

            parent_object = Object.access(params["parent"])

            if parent_object is None:
                raise NotFound("Parent object not found")
        else:
            parent_object = None

        # Validate metakeys and Karton assignment
        analysis_id = params.get("karton_id")

        if params["metakeys"]:
            # If 'metakeys' are defined: keep legacy behavior
            if "attributes" in params and params["attributes"]:
                raise BadRequest(
                    "'attributes' and 'metakeys' options can't be mixed")

            attributes = params["metakeys"]
            for attribute in params["metakeys"]:
                key = attribute["key"]
                if key == "karton":
                    if analysis_id is not None:
                        raise BadRequest(
                            "You can't provide more than one Karton analysis identifier"
                        )
                    try:
                        analysis_id = UUID(attribute["value"])
                    except (ValueError, AttributeError):
                        raise BadRequest(
                            "'karton' attribute accepts only UUID values")
                elif not AttributeDefinition.query_for_set(key).first():
                    raise NotFound(
                        f"Attribute '{key}' not defined or insufficient "
                        "permissions to set that one")
        else:
            # If not, rely on 'attributes'
            attributes = params["attributes"]
            for attribute in params["attributes"]:
                key = attribute["key"]
                if not AttributeDefinition.query_for_set(key).first():
                    raise NotFound(
                        f"Attribute '{key}' not defined or insufficient "
                        "permissions to set that one")

        if analysis_id is not None:
            if not g.auth_user.has_rights(Capabilities.karton_assign):
                raise Forbidden(
                    "You are not permitted to assign Karton analysis to object"
                )

        # Validate upload_as argument
        share_with = get_shares_for_upload(params["upload_as"])

        # Tags argument
        tags = params.get("tags")

        item, is_new = self._create_object(params, parent_object, share_with,
                                           attributes, analysis_id, tags)

        try:
            db.session.commit()

            if is_new:
                self.on_created(item, params)
            else:
                self.on_reuploaded(item, params)
        finally:
            item.release_after_upload()

        logger.info(
            f"{self.ObjectType.__name__} added",
            extra={
                "dhash": item.dhash,
                "is_new": is_new
            },
        )
        schema = self.ItemResponseSchema()
        return schema.dump(item)