Beispiel #1
0
    def __init__(self, smtp_conf=None, **kwargs):
        super(SubmissionTransaction, self).__init__(role="submit", **kwargs)

        self.app_config = capp.config
        if utils.should_send_email(self.app_config):
            self.smtp_conf = smtp_conf

        try:
            program, project = self.transaction.project_id.split("-", 1)
            authorize(program, project, [ROLE_SUBMIT])
        except AuthZError:
            return self.record_error(
                "You do not have submit permission for project {}".format(
                    self.project_id),
                type=EntityErrors.INVALID_PERMISSIONS,
            )

        self.project_node = utils.lookup_project(self.db_driver, self.program,
                                                 self.project)
Beispiel #2
0
    def __init__(self, transaction, node):
        super(DeletionEntity, self).__init__(transaction, node)
        self.action = "delete"
        self.dependents = {
            # entity.node.node_id: entity
        }

        if isinstance(node, MissingNode):
            self.neighbors = ()
            return

        self.neighbors = (edge.src for edge in node.edges_in)

        # Check user permissions for deleting nodes
        try:
            program, project = self.transaction.project_id.split("-", 1)
            authorize(program, project, ["delete"])
        except AuthZError:
            return self.record_error(
                "You do not have delete permission for project {}".format(
                    self.transaction.project_id))
Beispiel #3
0
    def get_node_merge(self):
        """
        This is called for a PATCH operation and supports upsert. It will
        lookup an existing node or create one if it doesn't exist.

        Return:
            Optional[psqlgraph.Node]
        """
        # Expect one existing node matching the secondary keys.
        try:
            node = lookup_node(
                self.transaction.db_driver,
                self.entity_type,
                self.entity_id,
                self.secondary_keys,
            ).one()
        except sqlalchemy.orm.exc.NoResultFound:
            return self.get_node_create()
        except sqlalchemy.orm.exc.MultipleResultsFound:
            self.record_error(
                "Entity is not unique, multiple entities found with {}".format(
                    self.secondary_keys
                ),
                type=EntityErrors.NOT_UNIQUE,
            )
            return None

        # Check user permissions for updating nodes
        try:
            program, project = self.transaction.project_id.split("-", 1)
            authorize(program, project, ["update"])
        except AuthZError:
            return self.record_error(
                "You do not have update permission for project {}".format(
                    self.transaction.project_id
                ),
                type=EntityErrors.INVALID_PERMISSIONS,
            )

        self.old_props = {k: v for k, v in node.props.items()}

        if node.label != self.entity_type:
            self.record_error(
                "Existing {} entity found with type different from {}".format(
                    node.label, self.entity_type
                ),
                type=EntityErrors.NOT_UNIQUE,
            )
            return None

        # Verify that the node is in the correct project
        if not self._verify_node_project_id(node):
            self.record_error(
                "Entity is owned by project {}, not {}".format(
                    node.project_id, self.transaction.project_id
                ),
                type=EntityErrors.INVALID_PERMISSIONS,
            )
        self._merge_doc_links(node)

        if self.entity_id and node.node_id != self.entity_id:
            self.record_error(
                "Existing {} entity found with id different from {}".format(
                    node, self.entity_id
                ),
                type=EntityErrors.NOT_UNIQUE,
            )
            return None

        # Since we are updating the node, we have to set its state to
        # ``validated``.  This means that this version of the node has
        # not been submitted and will not be displayed on the portal.
        # The node is now essential a draft.
        if node.state is None:
            node.state = "validated"

        # Fill in default system property values
        for key in self.get_system_property_defaults():
            self.logger.debug(
                "{}: setting system prop self.doc['{}'] to '{}'".format(
                    node, key, node._props.get(key)
                )
            )
            if self.doc.get(key) and self.doc.get(key) != node._props.get(key):
                msg = (
                    "Property '{}' ({}) is a system property and will be" " ignored."
                ).format(key, self.doc.get(key))
                self.record_warning(msg, keys=[key], type=EntityErrors.INVALID_PROPERTY)
            self.doc[key] = node._props.get(key)

        self.action = "update"
        self.entity_id = node.node_id

        return node
Beispiel #4
0
    def get_node_create(self, skip_node_lookup=False):
        """
        This is called for a POST operation.

        Check that:

        #. The user isn't supplying an id
        #. If not `skip_node_lookup`, the node does not already exist

        Return:
            psqlgraph.Node
        """
        # Check user permissions for updating nodes
        try:
            program, project = self.transaction.project_id.split("-", 1)
            authorize(program, project, ["create"])
        except AuthZError:
            return self.record_error(
                "You do not have create permission for project {}".format(
                    self.transaction.project_id
                ),
                type=EntityErrors.INVALID_PERMISSIONS,
            )

        # Check to see if it's registered in dbGaP is is an exception
        # to the rule
        if self.entity_type == "case":
            submitter_id = self.doc.get("submitter_id")

            allowed = True
            try:
                if self._config.get("USE_DBGAP", False):
                    allowed = self.is_case_creation_allowed(submitter_id)

            except InternalError as e:
                return self.record_error(
                    "Unable to validate case against dbGaP. {}".format(str(e)),
                    keys=["submitter_id"],
                    type=EntityErrors.NOT_FOUND,
                )

            else:
                if not allowed:
                    return self.record_error(
                        "Case submitter_id '{}' not found in dbGaP.".format(
                            submitter_id
                        ),
                        keys=["submitter_id"],
                        type=EntityErrors.NOT_FOUND,
                    )

        if not self.entity_id:
            self.entity_id = str(uuid.uuid4())

        # Assert that the node doesn't already exist
        if not skip_node_lookup:
            nodes = lookup_node(
                self.transaction.db_driver,
                self.entity_type,
                self.entity_id,
                self.secondary_keys,
            )
            if nodes.count():
                return self.record_error(
                    "Cannot create entity that already exists. "
                    "Try updating entity (PUT instead of POST)",
                    keys=["id"],
                    type=EntityErrors.NOT_UNIQUE,
                )

        # Fill in default system property values
        for key, val in self.get_system_property_defaults().items():
            if self.doc.get(key, None) is None:
                self.doc[key] = val

        # Create the node and populate its properties
        cls = psqlgraph.Node.get_subclass(self.entity_type)
        self.logger.debug("Creating new {}".format(cls.__name__))
        node = cls(self.entity_id)

        self.action = "create"

        return node