def _find_and_check_workflow_version(cls, user: User, uuid, version=None): w = None if not version: _w = models.Workflow.get_user_workflow(user, uuid) if _w: w = _w.latest_version else: w = models.WorkflowVersion.get_user_workflow_version(user, uuid, version) if not w: w = cls._find_and_check_shared_workflow_version(user, uuid, version=version) if w is None: raise lm_exceptions.EntityNotFoundException(models.WorkflowVersion, f"{uuid}_{version}") # Check whether the user can access the workflow. # As a general rule, we grant user access to the workflow # 1. if the user belongs to the owners group # 2. or the user belongs to the viewers group # if user not in w.owners and user not in w.viewers: if not user.has_permission(w): # if the user is not the submitter # and the workflow is associated with a registry # then we try to check whether the user is allowed to view the workflow if w.workflow_registry is None or w.workflow not in w.workflow_registry.get_user_workflows(user): raise lm_exceptions.NotAuthorizedException(f"User {user.username} is not allowed to access workflow") return w
def add_version(self, version, uri, submitter: User, uuid=None, name=None, hosting_service: models.WorkflowRegistry = None): if hosting_service: if self.external_id and hasattr(hosting_service, 'get_external_uuid'): try: self.uuid = hosting_service.get_external_uuid( self.external_id, version, submitter) except RuntimeError as e: raise lm_exceptions.NotAuthorizedException(details=str(e)) elif not self.external_id and hasattr(hosting_service, 'get_external_id'): try: self.external_id = hosting_service.get_external_id( self.uuid, version, submitter) except lm_exceptions.EntityNotFoundException: logger.warning( "Unable to associate an external ID to the workflow") return WorkflowVersion(self, uri, version, submitter, uuid=uuid, name=name, hosting_service=hosting_service)
def deregister_user_workflow(cls, workflow_uuid, workflow_version, user: User): workflow = cls._find_and_check_workflow_version(user, workflow_uuid, workflow_version) logger.debug("WorkflowVersion to delete: %r", workflow) if not workflow: raise lm_exceptions.EntityNotFoundException(models.WorkflowVersion, (workflow_uuid, workflow_version)) if workflow.submitter != user: raise lm_exceptions.NotAuthorizedException("Only the workflow submitter can delete the workflow") workflow.delete() logger.debug("Deleted workflow wf_uuid: %r - version: %r", workflow_uuid, workflow_version) return workflow_uuid, workflow_version
def _get(self, user, *args, **kwargs): with requests.Session() as session: for auth in user.get_authorization(self.registry): session.headers['Authorization'] = auth.as_http_header() r = session.get(*args, **kwargs) if r.status_code == 401 or r.status_code == 403: raise lm_exceptions.NotAuthorizedException( details=r.content) r.raise_for_status() return r
def register_test_suite(workflow_uuid, workflow_version, submitter: models.User, test_suite_metadata) -> models.TestSuite: workflow = models.WorkflowVersion.get_user_workflow_version(submitter, workflow_uuid, workflow_version) if not workflow: raise lm_exceptions.EntityNotFoundException(models.WorkflowVersion, (workflow_uuid, workflow_version)) # For now only the workflow submitter can add test suites if workflow.submitter != submitter: raise lm_exceptions.NotAuthorizedException("Only the workflow submitter can add test suites") suite = workflow.add_test_suite(submitter, test_suite_metadata) suite.save() return suite
def add_version(self, version, uri, submitter: User, uuid=None, name=None, hosting_service: models.WorkflowRegistry = None): try: if hosting_service: if self.external_id and hasattr(hosting_service, 'get_external_uuid'): self.uuid = hosting_service.get_external_uuid(self.external_id, version, submitter) elif not self.external_id and hasattr(hosting_service, 'get_external_id'): self.external_id = hosting_service.get_external_id(self.uuid, version, submitter) except lm_exceptions.EntityNotFoundException as e: raise lm_exceptions.NotAuthorizedException(details=str(e)) return WorkflowVersion(self, uri, version, submitter, uuid=uuid, name=name, hosting_service=hosting_service)
def get_workflow(self, uuid_or_identifier) -> models.Workflow: try: w = next(( w for w in self.registered_workflow_versions if w.workflow.uuid == lm_utils.uuid_param(uuid_or_identifier)), None) return w.workflow if w is not None else None except ValueError: w = next((w for w in self.registered_workflow_versions if w.workflow.external_id == uuid_or_identifier), None) return w.workflow if w is not None else None except Exception: if models.Workflow.find_by_uuid(uuid_or_identifier) is not None: raise lm_exceptions.NotAuthorizedException()
def load_metadata(self) -> dict: errors = [] # try either with authorization header and without authorization for authorization in self._get_authorizations(): try: auth_header = authorization.as_http_header() if authorization else None logger.debug(auth_header) self.__roc_helper, self._metadata = \ self.load_metadata_files(self.uri, authorization_header=auth_header) self._metadata_loaded = True return self._metadata except lm_exceptions.NotAuthorizedException as e: logger.info("Caught authorization error exception while downloading and processing RO-crate: %s", e) errors.append(str(e)) raise lm_exceptions.NotAuthorizedException(detail=f"Not authorized to download {self.uri}", original_errors=errors)
def test_post_workflow_by_registry_not_authorized(m, request_context, mock_registry): assert auth.current_user.is_anonymous, "Unexpected user in session" assert auth.current_registry, "Unexpected registry in session" # add one fake workflow data = { "uuid": "1212121212121212", "version": "1.0", "submitter_id": "1", "roc_link": "https://registry.org/roc_crate/download" } w = MagicMock() w.uuid = data['uuid'] w.version = data['version'] m.register_workflow.side_effect = lm_exceptions.NotAuthorizedException() response = controllers.workflows_post(body=data) logger.debug("Response: %r", response) assert_status_code(response.status_code, 403) assert messages.not_authorized_registry_access\ .format(mock_registry.name) in response.data.decode()
def _get(self, user, *args, **kwargs): authorizations = [] if user: authorizations.extend([ auth.as_http_header() for auth in user.get_authorization(self.registry) ]) authorizations.append(None) response = None for auth in authorizations: with requests.Session() as session: session.headers['Authorization'] = auth response = session.get(*args, **kwargs) if response.status_code == 200: break if response.status_code == 401 or response.status_code == 403: raise lm_exceptions.NotAuthorizedException( details=response.content) response.raise_for_status() return response
def load_metadata(self): errors = [] # try either with authorization hedaer and without authorization for authorization in self._get_authorizations(): try: auth_header = authorization.as_http_header( ) if authorization else None logger.debug(auth_header) self._crate_helper, self._metadata, self._test_metadata = \ self.load_metadata_files(self.uri, authorization_header=auth_header) self._metadata_loaded = True return self._metadata, self._test_metadata except Exception as e: errors.append(e) if len([ e for e in errors if isinstance(e, lm_exceptions.NotAuthorizedException) ]) == len(errors): raise lm_exceptions.NotAuthorizedException() raise lm_exceptions.LifeMonitorException("ROCrate download error", errors=errors)