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)
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))
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
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