def get_permissions(self, trans, encoded_folder_id, **kwd): """ * GET /api/folders/{id}/permissions Load all permissions for the given folder id and return it. :param encoded_folder_id: the encoded id of the folder :type encoded_folder_id: an encoded id string :param scope: either 'current' or 'available' :type scope: string :returns: dictionary with all applicable permissions' values :rtype: dictionary :raises: InsufficientPermissionsException """ current_user_roles = trans.get_current_user_roles() is_admin = trans.user_is_admin decoded_folder_id = self.folder_manager.cut_and_decode( trans, encoded_folder_id) folder = self.folder_manager.get(trans, decoded_folder_id) if not (is_admin or trans.app.security_agent.can_manage_library_item( current_user_roles, folder)): raise exceptions.InsufficientPermissionsException( 'You do not have proper permission to access permissions of this folder.' ) scope = kwd.get('scope', None) if scope == 'current' or scope is None: return self.folder_manager.get_current_roles(trans, folder) # Return roles that are available to select. elif scope == 'available': page = kwd.get('page', None) if page is not None: page = int(page) else: page = 1 page_limit = kwd.get('page_limit', None) if page_limit is not None: page_limit = int(page_limit) else: page_limit = 10 query = kwd.get('q', None) roles, total_roles = trans.app.security_agent.get_valid_roles( trans, folder, query, page, page_limit) return_roles = [] for role in roles: role_id = trans.security.encode_id(role.id) return_roles.append( dict(id=role_id, name=role.name, type=role.type)) return dict(roles=return_roles, page=page, page_limit=page_limit, total=total_roles) else: raise exceptions.RequestParameterInvalidException( "The value of 'scope' parameter is invalid. Alllowed values: current, available" )
def delete(self, trans, id, **kwd): """ DELETE /api/users/{id} delete the user with the given ``id`` Functionality restricted based on admin status :param id: the encoded id of the user to delete :type id: str :param purge: (optional) if True, purge the user :type purge: bool """ user_to_update = self.user_manager.by_id(self.decode_id(id)) if trans.user_is_admin: purge = util.string_as_bool(kwd.get('purge', False)) if purge: log.debug("Purging user %s", user_to_update) self.user_manager.purge(user_to_update) else: self.user_manager.delete(user_to_update) else: if trans.user == user_to_update: self.user_manager.delete(user_to_update) else: raise exceptions.InsufficientPermissionsException( 'You may only delete your own account.', id=id) return self.user_serializer.serialize_to_view(user_to_update, view='detailed')
def create( self, trans, parent_folder_id, new_folder_name, new_folder_description='' ): """ Create a new folder under the given folder. :param parent_folder_id: decoded id :type parent_folder_id: int :param new_folder_name: name of the new folder :type new_folder_name: str :param new_folder_description: description of the folder (optional, defaults to empty string) :type new_folder_description: str :returns: the new folder :rtype: LibraryFolder :raises: InsufficientPermissionsException """ parent_folder = self.get( trans, parent_folder_id ) current_user_roles = trans.get_current_user_roles() if not ( trans.user_is_admin or trans.app.security_agent.can_add_library_item( current_user_roles, parent_folder ) ): raise exceptions.InsufficientPermissionsException( 'You do not have proper permission to create folders under given folder.' ) new_folder = trans.app.model.LibraryFolder( name=new_folder_name, description=new_folder_description ) # We are associating the last used genome build with folders, so we will always # initialize a new folder with the first dbkey in genome builds list which is currently # ? unspecified (?) new_folder.genome_build = trans.app.genome_builds.default_value parent_folder.add_folder( new_folder ) trans.sa_session.add( new_folder ) trans.sa_session.flush() # New folders default to having the same permissions as their parent folder trans.app.security_agent.copy_library_permissions( trans, parent_folder, new_folder ) return new_folder
def _get_user(self, trans, id): user = self.get_user(trans, id) if not user: raise exceptions.RequestParameterInvalidException('Invalid user (%s).' % id) if user != trans.user and not trans.user_is_admin: raise exceptions.InsufficientPermissionsException('Access denied.') return user
def raw_tool_source(self, trans: GalaxyWebTransaction, id, **kwds): """Returns tool source. ``language`` is included in the response header.""" if not trans.app.config.enable_tool_source_display and not trans.user_is_admin: raise exceptions.InsufficientPermissionsException("Only administrators may display tool sources on this Galaxy server.") tool = self._get_tool(id, user=trans.user, tool_version=kwds.get('tool_version')) trans.response.headers['language'] = tool.tool_source.language return tool.tool_source.to_string()
def update(self, trans, id, payload, **kwd): """ update( self, trans, id, payload, **kwd ) * PUT /api/users/{id} updates the values for the item with the given ``id`` :type id: str :param id: the encoded id of the item to update :type payload: dict :param payload: a dictionary of new attribute values :rtype: dict :returns: an error object if an error occurred or a dictionary containing the serialized item after any changes """ current_user = trans.user user_to_update = self.user_manager.by_id(self.decode_id(id)) # only allow updating other users if they're admin editing_someone_else = current_user != user_to_update is_admin = trans.api_inherit_admin or self.user_manager.is_admin( current_user) if editing_someone_else and not is_admin: raise exceptions.InsufficientPermissionsException( 'You are not allowed to update that user', id=id) self.user_deserializer.deserialize(user_to_update, payload, user=current_user, trans=trans) return self.user_serializer.serialize_to_view(user_to_update, view='detailed')
def get_permissions( self, trans, id: EncodedDatabaseIdField, scope: Optional[LibraryPermissionScope] = LibraryPermissionScope. current, is_library_access: Optional[bool] = False, page: Optional[int] = 1, page_limit: Optional[int] = 10, query: Optional[str] = None, ) -> Union[LibraryCurrentPermissions, LibraryAvailablePermissions]: """Load all permissions for the given library id and return it. :param id: the encoded id of the library :type id: an encoded id string :param scope: either 'current' or 'available' :type scope: string :param is_library_access: indicates whether the roles available for the library access are requested :type is_library_access: bool :returns: dictionary with all applicable permissions' values :rtype: dictionary :raises: InsufficientPermissionsException """ current_user_roles = trans.get_current_user_roles() is_admin = trans.user_is_admin library = self.library_manager.get( trans, trans.security.decode_id(id, object_name='library')) if not (is_admin or trans.app.security_agent.can_manage_library_item( current_user_roles, library)): raise exceptions.InsufficientPermissionsException( 'You do not have proper permission to access permissions of this library.' ) if scope == LibraryPermissionScope.current or scope is None: roles = self.library_manager.get_current_roles(trans, library) return LibraryCurrentPermissions.parse_obj(roles) # Return roles that are available to select. elif scope == LibraryPermissionScope.available: roles, total_roles = trans.app.security_agent.get_valid_roles( trans, library, query, page, page_limit, is_library_access) return_roles = [] for role in roles: role_id = trans.security.encode_id(role.id) return_roles.append( dict(id=role_id, name=role.name, type=role.type)) return LibraryAvailablePermissions(roles=return_roles, page=page, page_limit=page_limit, total=total_roles) else: raise exceptions.RequestParameterInvalidException( "The value of 'scope' parameter is invalid. Alllowed values: current, available" )
def show_roles( self, trans, encoded_dataset_id, **kwd ): """ show_roles( self, trans, id, **kwd ): * GET /api/libraries/datasets/{encoded_dataset_id}/permissions Displays information about current or available roles for a given dataset permission. :param encoded_dataset_id: the encoded id of the dataset to query :type encoded_dataset_id: an encoded id string :param scope: either 'current' or 'available' :type scope: string :rtype: dictionary :returns: either dict of current roles for all permission types or dict of available roles to choose from (is the same for any permission type) """ current_user_roles = trans.get_current_user_roles() try: library_dataset = self.get_library_dataset( trans, id=encoded_dataset_id, check_ownership=False, check_accessible=False ) except Exception as e: raise exceptions.ObjectNotFound( 'Requested dataset was not found.' + str(e) ) dataset = library_dataset.library_dataset_dataset_association.dataset # User has to have manage permissions permission in order to see the roles. can_manage = trans.app.security_agent.can_manage_dataset( current_user_roles, dataset ) or trans.user_is_admin() if not can_manage: raise exceptions.InsufficientPermissionsException( 'You do not have proper permission to access permissions.' ) scope = kwd.get( 'scope', None ) if scope == 'current' or scope is None: return self._get_current_roles( trans, library_dataset ) # Return roles that are available to select. elif scope == 'available': page = kwd.get( 'page', None ) if page is not None: page = int( page ) else: page = 1 page_limit = kwd.get( 'page_limit', None ) if page_limit is not None: page_limit = int( page_limit ) else: page_limit = 10 query = kwd.get( 'q', None ) roles, total_roles = trans.app.security_agent.get_valid_roles( trans, dataset, query, page, page_limit ) return_roles = [] for role in roles: role_id = trans.security.encode_id( role.id ) return_roles.append( dict( id=role_id, name=role.name, type=role.type ) ) return dict( roles=return_roles, page=page, page_limit=page_limit, total=total_roles ) else: raise exceptions.RequestParameterInvalidException( "The value of 'scope' parameter is invalid. Alllowed values: current, available" )
def get_permissions(self, trans, encoded_library_id, **kwd): """ * GET /api/libraries/{id}/permissions Load all permissions for the given library id and return it. :param encoded_library_id: the encoded id of the library :type encoded_library_id: an encoded id string :param scope: either 'current' or 'available' :type scope: string :param is_library_access: indicates whether the roles available for the library access are requested :type is_library_access: bool :returns: dictionary with all applicable permissions' values :rtype: dictionary :raises: InsufficientPermissionsException """ current_user_roles = trans.get_current_user_roles() is_admin = trans.user_is_admin library = self.library_manager.get(trans, self.__decode_id(trans, encoded_library_id, 'library')) if not (is_admin or trans.app.security_agent.can_manage_library_item(current_user_roles, library)): raise exceptions.InsufficientPermissionsException('You do not have proper permission to access permissions of this library.') scope = kwd.get('scope', None) is_library_access = util.string_as_bool(kwd.get('is_library_access', False)) if scope == 'current' or scope is None: roles = self.library_manager.get_current_roles(trans, library) return roles # Return roles that are available to select. elif scope == 'available': page = kwd.get('page', None) if page is not None: page = int(page) else: page = 1 page_limit = kwd.get('page_limit', None) if page_limit is not None: page_limit = int(page_limit) else: page_limit = 10 query = kwd.get('q', None) roles, total_roles = trans.app.security_agent.get_valid_roles(trans, library, query, page, page_limit, is_library_access) return_roles = [] for role in roles: role_id = trans.security.encode_id(role.id) return_roles.append(dict(id=role_id, name=role.name, type=role.type)) return dict(roles=return_roles, page=page, page_limit=page_limit, total=total_roles) else: raise exceptions.RequestParameterInvalidException("The value of 'scope' parameter is invalid. Alllowed values: current, available")
def create( self, trans, encoded_folder_id, payload, **kwd ): """ * POST /api/folders/{encoded_id}/contents create a new library file from an HDA :param encoded_folder_id: the encoded id of the folder to import dataset(s) to :type encoded_folder_id: an encoded id string :param payload: dictionary structure containing: :param from_hda_id: (optional) the id of an accessible HDA to copy into the library :type from_hda_id: encoded id :param ldda_message: (optional) the new message attribute of the LDDA created :type ldda_message: str :param extended_metadata: (optional) dub-dictionary containing any extended metadata to associate with the item :type extended_metadata: dict :type payload: dict :returns: a dictionary containing the id, name, and 'show' url of the new item :rtype: dict :raises: ObjectAttributeInvalidException, InsufficientPermissionsException, ItemAccessibilityException, InternalServerError """ encoded_folder_id_16 = self.__decode_library_content_id( trans, encoded_folder_id ) from_hda_id, ldda_message = ( payload.pop( 'from_hda_id', None ), payload.pop( 'ldda_message', '' ) ) if ldda_message: ldda_message = util.sanitize_html.sanitize_html( ldda_message, 'utf-8' ) rval = {} try: decoded_hda_id = self.decode_id( from_hda_id ) hda = self.hda_manager.get_owned( decoded_hda_id, trans.user, current_history=trans.history ) hda = self.hda_manager.error_if_uploading( hda ) folder = self.get_library_folder( trans, encoded_folder_id_16, check_accessible=True ) library = folder.parent_library if library.deleted: raise exceptions.ObjectAttributeInvalidException() if not self.can_current_user_add_to_library_item( trans, folder ): raise exceptions.InsufficientPermissionsException() ldda = self.copy_hda_to_library_folder( trans, hda, folder, ldda_message=ldda_message ) update_time = ldda.update_time.strftime( "%Y-%m-%d %I:%M %p" ) ldda_dict = ldda.to_dict() rval = trans.security.encode_dict_ids( ldda_dict ) rval['update_time'] = update_time except exceptions.ObjectAttributeInvalidException: raise exceptions.ObjectAttributeInvalidException( 'You cannot add datasets into deleted library. Undelete it first.' ) except exceptions.InsufficientPermissionsException: raise exceptions.exceptions.InsufficientPermissionsException( 'You do not have proper permissions to add a dataset to a folder with id (%s)' % ( encoded_folder_id ) ) except Exception as exc: # TODO handle exceptions better within the mixins if ( ( 'not accessible to the current user' in str( exc ) ) or ( 'You are not allowed to access this dataset' in str( exc ) ) ): raise exceptions.ItemAccessibilityException( 'You do not have access to the requested item' ) else: log.exception( exc ) raise exceptions.InternalServerError( 'An unknown error ocurred. Please try again.' ) return rval
def update_permissions(self, trans, dataset_assoc, **kwd): action = kwd.get('action', 'set_permissions') if action not in ['remove_restrictions', 'make_private', 'set_permissions']: raise exceptions.RequestParameterInvalidException('The mandatory parameter "action" has an invalid value. ' 'Allowed values are: "remove_restrictions", "make_private", "set_permissions"') if hasattr(dataset_assoc, "library_dataset_dataset_association"): library_dataset = dataset_assoc dataset = library_dataset.library_dataset_dataset_association.dataset else: library_dataset = None dataset = dataset_assoc.dataset current_user_roles = trans.get_current_user_roles() can_manage = trans.app.security_agent.can_manage_dataset(current_user_roles, dataset) or trans.user_is_admin if not can_manage: raise exceptions.InsufficientPermissionsException('You do not have proper permissions to manage permissions on this dataset.') if action == 'remove_restrictions': trans.app.security_agent.make_dataset_public(dataset) if not trans.app.security_agent.dataset_is_public(dataset): raise exceptions.InternalServerError('An error occurred while making dataset public.') elif action == 'make_private': if not trans.app.security_agent.dataset_is_private_to_user(trans, dataset): private_role = trans.app.security_agent.get_private_user_role(trans.user) dp = trans.app.model.DatasetPermissions(trans.app.security_agent.permitted_actions.DATASET_ACCESS.action, dataset, private_role) trans.sa_session.add(dp) trans.sa_session.flush() if not trans.app.security_agent.dataset_is_private_to_user(trans, dataset): # Check again and inform the user if dataset is not private. raise exceptions.InternalServerError('An error occurred and the dataset is NOT private.') elif action == 'set_permissions': def to_role_id(encoded_role_id): role_id = base.decode_id(self.app, encoded_role_id) return role_id def parameters_roles_or_none(role_type): encoded_role_ids = kwd.get(role_type, kwd.get(f"{role_type}_ids[]", None)) if encoded_role_ids is not None: return list(map(to_role_id, encoded_role_ids)) else: return None access_roles = parameters_roles_or_none('access') manage_roles = parameters_roles_or_none('manage') modify_roles = parameters_roles_or_none('modify') role_ids_dict = { 'DATASET_MANAGE_PERMISSIONS': manage_roles, 'DATASET_ACCESS': access_roles, } if library_dataset is not None: role_ids_dict["LIBRARY_MODIFY"] = modify_roles self._set_permissions(trans, dataset_assoc, role_ids_dict)
def detect_datatype(self, trans, dataset_assoc): """Sniff and assign the datatype to a given dataset association (ldda or hda)""" data = trans.sa_session.query(self.model_class).get(dataset_assoc.id) if data.datatype.is_datatype_change_allowed(): if not data.ok_to_edit_metadata(): raise exceptions.ItemAccessibilityException('This dataset is currently being used as input or output. You cannot change datatype until the jobs have completed or you have canceled them.') else: path = data.dataset.file_name is_binary = check_binary(path) datatype = sniff.guess_ext(path, trans.app.datatypes_registry.sniff_order, is_binary=is_binary) trans.app.datatypes_registry.change_datatype(data, datatype) trans.sa_session.flush() self.set_metadata(trans, dataset_assoc) else: raise exceptions.InsufficientPermissionsException(f'Changing datatype "{data.extension}" is not allowed.')
def delete(self, trans, encoded_dataset_id, **kwd): """ delete( self, trans, encoded_dataset_id, **kwd ): * DELETE /api/libraries/datasets/{encoded_dataset_id} Marks the dataset deleted or undeleted based on the value of the undelete flag. If the flag is not present it is considered False and the item is marked deleted. :param encoded_dataset_id: the encoded id of the dataset to change :type encoded_dataset_id: an encoded id string :returns: dict containing information about the dataset :rtype: dictionary """ undelete = util.string_as_bool(kwd.get('undelete', False)) try: dataset = self.get_library_dataset(trans, id=encoded_dataset_id, check_ownership=False, check_accessible=False) except Exception as e: raise exceptions.ObjectNotFound( 'Requested dataset was not found.' + str(e)) current_user_roles = trans.get_current_user_roles() allowed = trans.app.security_agent.can_modify_library_item( current_user_roles, dataset) if (not allowed) and (not trans.user_is_admin()): raise exceptions.InsufficientPermissionsException( 'You do not have proper permissions to delete this dataset.') if undelete: dataset.deleted = False else: dataset.deleted = True trans.sa_session.add(dataset) trans.sa_session.flush() rval = trans.security.encode_all_ids(dataset.to_dict()) nice_size = util.nice_size( int(dataset.library_dataset_dataset_association.get_size())) rval['file_size'] = nice_size rval['update_time'] = dataset.update_time.strftime("%Y-%m-%d %I:%M %p") rval['deleted'] = dataset.deleted rval['folder_id'] = 'F' + rval['folder_id'] return rval
def delete(self, trans, encoded_dataset_id, **kwd): """ DELETE /api/libraries/datasets/{encoded_dataset_id} Mark the dataset deleted or undeleted. :param encoded_dataset_id: the encoded id of the dataset to change :type encoded_dataset_id: an encoded id string :param undelete: flag whether to undeleted instead of deleting :type undelete: bool :returns: dict containing information about the dataset :rtype: dictionary """ undelete = util.string_as_bool(kwd.get('undelete', False)) library_dataset = self.ld_manager.get( trans, managers_base.decode_id(self.app, encoded_dataset_id)) current_user_roles = trans.get_current_user_roles() allowed = trans.app.security_agent.can_modify_library_item( current_user_roles, library_dataset) if (not allowed) and (not trans.user_is_admin): raise exceptions.InsufficientPermissionsException( 'You do not have proper permissions to delete this dataset.') if undelete: library_dataset.deleted = False else: library_dataset.deleted = True trans.sa_session.add(library_dataset) trans.sa_session.flush() rval = trans.security.encode_all_ids(library_dataset.to_dict()) nice_size = util.nice_size( int(library_dataset.library_dataset_dataset_association.get_size()) ) rval['file_size'] = nice_size rval['update_time'] = library_dataset.update_time.strftime( "%Y-%m-%d %I:%M %p") rval['deleted'] = library_dataset.deleted rval['folder_id'] = 'F' + rval['folder_id'] return rval
def check_manageable(self, trans, folder): """ Check whether the user can manage the folder. :returns: the original folder :rtype: LibraryFolder :raises: AuthenticationRequired, InsufficientPermissionsException """ if not trans.user: raise exceptions.AuthenticationRequired( "Must be logged in to manage Galaxy items.", type='error') current_user_roles = trans.get_current_user_roles() if not trans.app.security_agent.can_manage_library_item( current_user_roles, folder): raise exceptions.InsufficientPermissionsException( "You don't have permissions to manage this folder.", type='error') else: return folder
class LibraryDatasetsController(BaseAPIController, UsesVisualizationMixin): @expose_api_anonymous def show(self, trans, id, **kwd): """ show( self, trans, id, **kwd ) * GET /api/libraries/datasets/{encoded_dataset_id}: Displays information about the dataset identified by the encoded ID. :param id: the encoded id of the dataset to query :type id: an encoded id string :rtype: dictionary :returns: detailed dataset information from base controller .. seealso:: :attr:`galaxy.web.base.controller.UsesLibraryMixinItems.get_library_dataset` """ try: dataset = self.get_library_dataset(trans, id=id, check_ownership=False, check_accessible=True) except Exception: raise exceptions.ObjectNotFound('Requested dataset was not found.') # Build the full path for breadcrumb purposes. full_path = self._build_path(trans, dataset.folder) dataset_item = (trans.security.encode_id(dataset.id), dataset.name) full_path.insert(0, dataset_item) full_path = full_path[::-1] nice_size = util.nice_size( int(dataset.library_dataset_dataset_association.get_size())) date_uploaded = dataset.library_dataset_dataset_association.create_time.strftime( "%Y-%m-%d %I:%M %p") rval = trans.security.encode_all_ids(dataset.to_dict()) rval['deleted'] = dataset.deleted rval['folder_id'] = 'F' + rval['folder_id'] rval['full_path'] = full_path rval['file_size'] = nice_size rval['date_uploaded'] = date_uploaded return rval @expose_api def show_roles(self, trans, encoded_dataset_id, **kwd): """ show_roles( self, trans, id, **kwd ): GET /api/libraries/datasets/{encoded_dataset_id}/permissions: Displays information about current and available roles for a given dataset permission. """ current_user_roles = trans.get_current_user_roles() page = kwd.get('page', None) if page is not None: page = int(page) page_limit = kwd.get('page_limit', None) if page_limit is not None: page_limit = int(page_limit) query = kwd.get('q', None) if page is None: page = 1 if page_limit is None: page_limit = 10 try: library_dataset = self.get_library_dataset(trans, id=encoded_dataset_id, check_ownership=False, check_accessible=False) except Exception, e: raise exceptions.ObjectNotFound( 'Requested dataset was not found.' + str(e)) library = library_dataset.folder.parent_library dataset = library_dataset.library_dataset_dataset_association.dataset can_manage = trans.app.security_agent.can_manage_dataset( current_user_roles, dataset) or trans.user_is_admin() if not can_manage: raise exceptions.InsufficientPermissionsException( 'You do not have proper permissions to access permissions.') roles = trans.app.security_agent.get_valid_dataset_roles( trans, dataset, query, page, page_limit) total_roles = len(roles) return_roles = [] for role in roles: return_roles.append( dict(id=role.name, name=role.name, type=role.type)) return dict(roles=return_roles, page=page, page_limit=page_limit, total=total_roles)
of the undelete flag (if present). """ undelete = util.string_as_bool(kwd.get('undelete', False)) try: dataset = self.get_library_dataset(trans, id=encoded_dataset_id, check_ownership=False, check_accessible=False) except Exception, e: raise exceptions.ObjectNotFound( 'Requested dataset was not found.' + str(e)) current_user_roles = trans.get_current_user_roles() allowed = trans.app.security_agent.can_modify_library_item( current_user_roles, dataset) if (not allowed) and (not trans.user_is_admin()): raise exceptions.InsufficientPermissionsException( 'You do not have proper permissions to delete this dataset.') if undelete: dataset.deleted = False else: dataset.deleted = True trans.sa_session.add(dataset) trans.sa_session.flush() rval = trans.security.encode_all_ids(dataset.to_dict()) rval['update_time'] = dataset.update_time.strftime("%Y-%m-%d %I:%M %p") rval['deleted'] = dataset.deleted rval['folder_id'] = 'F' + rval['folder_id'] return rval
def load(self, trans, payload=None, **kwd): """ * POST /api/libraries/datasets Load dataset from the given source into the library. Source can be: user directory - root folder specified in galaxy.ini as "$user_library_import_dir" example path: path/to/galaxy/$user_library_import_dir/[email protected]/{user can browse everything here} the folder with the user login has to be created beforehand (admin)import directory - root folder specified in galaxy ini as "$library_import_dir" example path: path/to/galaxy/$library_import_dir/{admin can browse everything here} (admin)any absolute or relative path - option allowed with "allow_library_path_paste" in galaxy.ini :param payload: dictionary structure containing: :param encoded_folder_id: the encoded id of the folder to import dataset(s) to :type encoded_folder_id: an encoded id string :param source: source the datasets should be loaded from :type source: str :param link_data: flag whether to link the dataset to data or copy it to Galaxy, defaults to copy while linking is set to True all symlinks will be resolved _once_ :type link_data: bool :param preserve_dirs: flag whether to preserve the directory structure when importing dir if False only datasets will be imported :type preserve_dirs: bool :param file_type: file type of the loaded datasets, defaults to 'auto' (autodetect) :type file_type: str :param dbkey: dbkey of the loaded genome, defaults to '?' (unknown) :type dbkey: str :type dictionary :returns: dict containing information about the created upload job :rtype: dictionary :raises: RequestParameterMissingException, AdminRequiredException, ConfigDoesNotAllowException, RequestParameterInvalidException InsufficientPermissionsException, ObjectNotFound """ if payload: kwd.update(payload) kwd['space_to_tab'] = False kwd['to_posix_lines'] = True kwd['dbkey'] = kwd.get('dbkey', '?') kwd['file_type'] = kwd.get('file_type', 'auto') kwd['link_data_only'] = 'link_to_files' if util.string_as_bool( kwd.get('link_data', False)) else 'copy_files' encoded_folder_id = kwd.get('encoded_folder_id', None) if encoded_folder_id is not None: folder_id = self.folder_manager.cut_and_decode( trans, encoded_folder_id) else: raise exceptions.RequestParameterMissingException( 'The required atribute encoded_folder_id is missing.') path = kwd.get('path', None) if path is None: raise exceptions.RequestParameterMissingException( 'The required atribute path is missing.') folder = self.folder_manager.get(trans, folder_id) source = kwd.get('source', None) if source not in [ 'userdir_file', 'userdir_folder', 'importdir_file', 'importdir_folder', 'admin_path' ]: raise exceptions.RequestParameterMissingException( 'You have to specify "source" parameter. Possible values are "userdir_file", "userdir_folder", "admin_path", "importdir_file" and "importdir_folder". ' ) if source in ['importdir_file', 'importdir_folder']: if not trans.user_is_admin: raise exceptions.AdminRequiredException( 'Only admins can import from importdir.') if not trans.app.config.library_import_dir: raise exceptions.ConfigDoesNotAllowException( 'The configuration of this Galaxy instance does not allow admins to import into library from importdir.' ) import_base_dir = trans.app.config.library_import_dir path = os.path.join(import_base_dir, path) if source in ['userdir_file', 'userdir_folder']: user_login = trans.user.email user_base_dir = trans.app.config.user_library_import_dir if user_base_dir is None: raise exceptions.ConfigDoesNotAllowException( 'The configuration of this Galaxy instance does not allow upload from user directories.' ) full_dir = os.path.join(user_base_dir, user_login) if not path.lower().startswith(full_dir.lower()): path = os.path.join(full_dir, path) if not os.path.exists(path): raise exceptions.RequestParameterInvalidException( 'Given path does not exist on the host.') if not self.folder_manager.can_add_item(trans, folder): raise exceptions.InsufficientPermissionsException( 'You do not have proper permission to add items to the given folder.' ) if source == 'admin_path': if not trans.app.config.allow_library_path_paste: raise exceptions.ConfigDoesNotAllowException( 'The configuration of this Galaxy instance does not allow admins to import into library from path.' ) if not trans.user_is_admin: raise exceptions.AdminRequiredException( 'Only admins can import from path.') # Set up the traditional tool state/params tool_id = 'upload1' tool = trans.app.toolbox.get_tool(tool_id) state = tool.new_state(trans) tool.populate_state(trans, tool.inputs, kwd, state.inputs) tool_params = state.inputs dataset_upload_inputs = [] for input in tool.inputs.itervalues(): if input.type == "upload_dataset": dataset_upload_inputs.append(input) library_bunch = upload_common.handle_library_params( trans, {}, trans.security.encode_id(folder.id)) abspath_datasets = [] kwd['filesystem_paths'] = path if source in ['importdir_folder']: kwd['filesystem_paths'] = os.path.join(import_base_dir, path) # user wants to import one file only if source in ["userdir_file", "importdir_file"]: file = os.path.abspath(path) abspath_datasets.append(trans.webapp.controllers['library_common']. make_library_uploaded_dataset( trans, 'api', kwd, os.path.basename(file), file, 'server_dir', library_bunch)) # user wants to import whole folder if source == "userdir_folder": uploaded_datasets_bunch = trans.webapp.controllers[ 'library_common'].get_path_paste_uploaded_datasets( trans, 'api', kwd, library_bunch, 200, '') uploaded_datasets = uploaded_datasets_bunch[0] if uploaded_datasets is None: raise exceptions.ObjectNotFound( 'Given folder does not contain any datasets.') for ud in uploaded_datasets: ud.path = os.path.abspath(ud.path) abspath_datasets.append(ud) # user wants to import from path if source in ["admin_path", "importdir_folder"]: # validate the path is within root uploaded_datasets_bunch = trans.webapp.controllers[ 'library_common'].get_path_paste_uploaded_datasets( trans, 'api', kwd, library_bunch, 200, '') uploaded_datasets = uploaded_datasets_bunch[0] if uploaded_datasets is None: raise exceptions.ObjectNotFound( 'Given folder does not contain any datasets.') for ud in uploaded_datasets: ud.path = os.path.abspath(ud.path) abspath_datasets.append(ud) json_file_path = upload_common.create_paramfile( trans, abspath_datasets) data_list = [ud.data for ud in abspath_datasets] job_params = {} job_params['link_data_only'] = dumps( kwd.get('link_data_only', 'copy_files')) job_params['uuid'] = dumps(kwd.get('uuid', None)) job, output = upload_common.create_job(trans, tool_params, tool, json_file_path, data_list, folder=folder, job_params=job_params) trans.sa_session.add(job) trans.sa_session.flush() job_dict = job.to_dict() job_dict['id'] = trans.security.encode_id(job_dict['id']) return job_dict
def set_permissions(self, trans, encoded_library_id, payload=None, **kwd): """ *POST /api/libraries/{encoded_library_id}/permissions Set permissions of the given library to the given role ids. :param encoded_library_id: the encoded id of the library to set the permissions of :type encoded_library_id: an encoded id string :param payload: dictionary structure containing: :param action: (required) describes what action should be performed available actions: remove_restrictions, set_permissions :type action: str :param access_ids[]: list of Role.id defining roles that should have access permission on the library :type access_ids[]: string or list :param add_ids[]: list of Role.id defining roles that should have add item permission on the library :type add_ids[]: string or list :param manage_ids[]: list of Role.id defining roles that should have manage permission on the library :type manage_ids[]: string or list :param modify_ids[]: list of Role.id defining roles that should have modify permission on the library :type modify_ids[]: string or list :type: dictionary :returns: dict of current roles for all available permission types :rtype: dictionary :raises: RequestParameterInvalidException, InsufficientPermissionsException, InternalServerError RequestParameterMissingException """ if payload: kwd.update(payload) is_admin = trans.user_is_admin() current_user_roles = trans.get_current_user_roles() library = self.library_manager.get( trans, self.__decode_id(trans, encoded_library_id, 'library')) if not (is_admin or trans.app.security_agent.can_manage_library_item( current_user_roles, library)): raise exceptions.InsufficientPermissionsException( 'You do not have proper permission to modify permissions of this library.' ) new_access_roles_ids = util.listify(kwd.get('access_ids[]', None)) new_add_roles_ids = util.listify(kwd.get('add_ids[]', None)) new_manage_roles_ids = util.listify(kwd.get('manage_ids[]', None)) new_modify_roles_ids = util.listify(kwd.get('modify_ids[]', None)) action = kwd.get('action', None) if action is None: if payload is not None: return self.set_permissions_old(trans, library, payload, **kwd) else: raise exceptions.RequestParameterMissingException( 'The mandatory parameter "action" is missing.') elif action == 'remove_restrictions': is_public = self.library_manager.make_public(trans, library) if not is_public: raise exceptions.InternalServerError( 'An error occured while making library public.') elif action == 'set_permissions': # ACCESS LIBRARY ROLES valid_access_roles = [] invalid_access_roles_names = [] for role_id in new_access_roles_ids: role = self.role_manager.get( trans, self.__decode_id(trans, role_id, 'role')) valid_roles, total_roles = trans.app.security_agent.get_valid_roles( trans, library, is_library_access=True) if role in valid_roles: valid_access_roles.append(role) else: invalid_access_roles_names.append(role_id) if len(invalid_access_roles_names) > 0: log.warning( "The following roles could not be added to the library access permission: " + str(invalid_access_roles_names)) # ADD TO LIBRARY ROLES valid_add_roles = [] invalid_add_roles_names = [] for role_id in new_add_roles_ids: role = self.role_manager.get( trans, self.__decode_id(trans, role_id, 'role')) valid_roles, total_roles = trans.app.security_agent.get_valid_roles( trans, library) if role in valid_roles: valid_add_roles.append(role) else: invalid_add_roles_names.append(role_id) if len(invalid_add_roles_names) > 0: log.warning( "The following roles could not be added to the add library item permission: " + str(invalid_add_roles_names)) # MANAGE LIBRARY ROLES valid_manage_roles = [] invalid_manage_roles_names = [] for role_id in new_manage_roles_ids: role = self.role_manager.get( trans, self.__decode_id(trans, role_id, 'role')) valid_roles, total_roles = trans.app.security_agent.get_valid_roles( trans, library) if role in valid_roles: valid_manage_roles.append(role) else: invalid_manage_roles_names.append(role_id) if len(invalid_manage_roles_names) > 0: log.warning( "The following roles could not be added to the manage library permission: " + str(invalid_manage_roles_names)) # MODIFY LIBRARY ROLES valid_modify_roles = [] invalid_modify_roles_names = [] for role_id in new_modify_roles_ids: role = self.role_manager.get( trans, self.__decode_id(trans, role_id, 'role')) valid_roles, total_roles = trans.app.security_agent.get_valid_roles( trans, library) if role in valid_roles: valid_modify_roles.append(role) else: invalid_modify_roles_names.append(role_id) if len(invalid_modify_roles_names) > 0: log.warning( "The following roles could not be added to the modify library permission: " + str(invalid_modify_roles_names)) permissions = { trans.app.security_agent.permitted_actions.LIBRARY_ACCESS: valid_access_roles } permissions.update({ trans.app.security_agent.permitted_actions.LIBRARY_ADD: valid_add_roles }) permissions.update({ trans.app.security_agent.permitted_actions.LIBRARY_MANAGE: valid_manage_roles }) permissions.update({ trans.app.security_agent.permitted_actions.LIBRARY_MODIFY: valid_modify_roles }) trans.app.security_agent.set_all_library_permissions( trans, library, permissions) trans.sa_session.refresh(library) # Copy the permissions to the root folder trans.app.security_agent.copy_library_permissions( trans, library, library.root_folder) else: raise exceptions.RequestParameterInvalidException( 'The mandatory parameter "action" has an invalid value.' 'Allowed values are: "remove_restrictions", set_permissions"') roles = self.library_manager.get_current_roles(trans, library) return roles
current_user_roles = trans.get_current_user_roles() try: library_dataset = self.get_library_dataset(trans, id=encoded_dataset_id, check_ownership=False, check_accessible=False) except Exception, e: raise exceptions.ObjectNotFound( 'Requested dataset was not found.' + str(e)) dataset = library_dataset.library_dataset_dataset_association.dataset # User has to have manage permissions permission in order to see the roles. can_manage = trans.app.security_agent.can_manage_dataset( current_user_roles, dataset) or trans.user_is_admin() if not can_manage: raise exceptions.InsufficientPermissionsException( 'You do not have proper permission to access permissions.') scope = kwd.get('scope', None) if scope == 'current' or scope is None: return self._get_current_roles(trans, library_dataset) # Return roles that are available to select. elif scope == 'available': page = kwd.get('page', None) if page is not None: page = int(page) else: page = 1 page_limit = kwd.get('page_limit', None) if page_limit is not None:
def set_permissions( self, trans, encoded_folder_id, **kwd ): """ def set_permissions( self, trans, encoded_folder_id, **kwd ): *POST /api/folders/{encoded_folder_id}/permissions :param encoded_folder_id: the encoded id of the folder to set the permissions of :type encoded_folder_id: an encoded id string :param action: (required) describes what action should be performed available actions: set_permissions :type action: string :param add_ids[]: list of Role.id defining roles that should have add item permission on the folder :type add_ids[]: string or list :param manage_ids[]: list of Role.id defining roles that should have manage permission on the folder :type manage_ids[]: string or list :param modify_ids[]: list of Role.id defining roles that should have modify permission on the folder :type modify_ids[]: string or list :rtype: dictionary :returns: dict of current roles for all available permission types. :raises: RequestParameterInvalidException, ObjectNotFound, InsufficientPermissionsException, InternalServerError RequestParameterMissingException """ is_admin = trans.user_is_admin() current_user_roles = trans.get_current_user_roles() decoded_folder_id = self.folder_manager.decode_folder_id( trans, self.folder_manager.cut_the_prefix( encoded_folder_id ) ) folder = self.folder_manager.get( trans, decoded_folder_id ) if not ( is_admin or trans.app.security_agent.can_manage_library_item( current_user_roles, folder ) ): raise exceptions.InsufficientPermissionsException( 'You do not have proper permission to modify permissions of this folder.' ) new_add_roles_ids = util.listify( kwd.get( 'add_ids[]', None ) ) new_manage_roles_ids = util.listify( kwd.get( 'manage_ids[]', None ) ) new_modify_roles_ids = util.listify( kwd.get( 'modify_ids[]', None ) ) action = kwd.get( 'action', None ) if action is None: raise exceptions.RequestParameterMissingException( 'The mandatory parameter "action" is missing.' ) elif action == 'set_permissions': # ADD TO LIBRARY ROLES valid_add_roles = [] invalid_add_roles_names = [] for role_id in new_add_roles_ids: role = self._load_role( trans, role_id ) # Check whether role is in the set of allowed roles valid_roles, total_roles = trans.app.security_agent.get_valid_roles( trans, folder ) if role in valid_roles: valid_add_roles.append( role ) else: invalid_add_roles_names.append( role_id ) if len( invalid_add_roles_names ) > 0: log.warning( "The following roles could not be added to the add library item permission: " + str( invalid_add_roles_names ) ) # MANAGE FOLDER ROLES valid_manage_roles = [] invalid_manage_roles_names = [] for role_id in new_manage_roles_ids: role = self._load_role( trans, role_id ) # Check whether role is in the set of allowed roles valid_roles, total_roles = trans.app.security_agent.get_valid_roles( trans, folder ) if role in valid_roles: valid_manage_roles.append( role ) else: invalid_manage_roles_names.append( role_id ) if len( invalid_manage_roles_names ) > 0: log.warning( "The following roles could not be added to the manage folder permission: " + str( invalid_manage_roles_names ) ) # MODIFY FOLDER ROLES valid_modify_roles = [] invalid_modify_roles_names = [] for role_id in new_modify_roles_ids: role = self._load_role( trans, role_id ) # Check whether role is in the set of allowed roles valid_roles, total_roles = trans.app.security_agent.get_valid_roles( trans, folder ) if role in valid_roles: valid_modify_roles.append( role ) else: invalid_modify_roles_names.append( role_id ) if len( invalid_modify_roles_names ) > 0: log.warning( "The following roles could not be added to the modify folder permission: " + str( invalid_modify_roles_names ) ) permissions = { trans.app.security_agent.permitted_actions.LIBRARY_ADD : valid_add_roles } permissions.update( { trans.app.security_agent.permitted_actions.LIBRARY_MANAGE : valid_manage_roles } ) permissions.update( { trans.app.security_agent.permitted_actions.LIBRARY_MODIFY : valid_modify_roles } ) trans.app.security_agent.set_all_library_permissions( trans, folder, permissions ) else: raise exceptions.RequestParameterInvalidException( 'The mandatory parameter "action" has an invalid value.' 'Allowed values are: "set_permissions"' ) return self.folder_manager.get_current_roles( trans, folder )
def update_permissions(self, trans, encoded_dataset_id, payload=None, **kwd): """ POST /api/libraries/datasets/{encoded_dataset_id}/permissions Set permissions of the given library dataset to the given role ids. :param encoded_dataset_id: the encoded id of the dataset to update permissions of :type encoded_dataset_id: an encoded id string :param payload: dictionary structure containing: :param action: (required) describes what action should be performed available actions: make_private, remove_restrictions, set_permissions :type action: string :param access_ids[]: list of Role.id defining roles that should have access permission on the dataset :type access_ids[]: string or list :param manage_ids[]: list of Role.id defining roles that should have manage permission on the dataset :type manage_ids[]: string or list :param modify_ids[]: list of Role.id defining roles that should have modify permission on the library dataset item :type modify_ids[]: string or list :type: dictionary :returns: dict of current roles for all available permission types :rtype: dictionary :raises: RequestParameterInvalidException, ObjectNotFound, InsufficientPermissionsException, InternalServerError RequestParameterMissingException """ if payload: kwd.update(payload) action = kwd.get('action', None) if action not in ['remove_restrictions', 'make_private', 'set_permissions']: raise exceptions.RequestParameterInvalidException('The mandatory parameter "action" has an invalid value. ' 'Allowed values are: "remove_restrictions", "make_private", "set_permissions"') library_dataset = self.ld_manager.get(trans, managers_base.decode_id(self.app, encoded_dataset_id)) # Some permissions are attached directly to the underlying dataset. dataset = library_dataset.library_dataset_dataset_association.dataset current_user_roles = trans.get_current_user_roles() can_manage = trans.app.security_agent.can_manage_dataset(current_user_roles, dataset) or trans.user_is_admin if not can_manage: raise exceptions.InsufficientPermissionsException('You do not have proper permissions to manage permissions on this dataset.') new_access_roles_ids = util.listify(kwd.get('access_ids[]', None)) new_manage_roles_ids = util.listify(kwd.get('manage_ids[]', None)) new_modify_roles_ids = util.listify(kwd.get('modify_ids[]', None)) if action == 'remove_restrictions': trans.app.security_agent.make_dataset_public(dataset) if not trans.app.security_agent.dataset_is_public(dataset): raise exceptions.InternalServerError('An error occurred while making dataset public.') elif action == 'make_private': if not trans.app.security_agent.dataset_is_private_to_user(trans, dataset): private_role = trans.app.security_agent.get_private_user_role(trans.user) dp = trans.app.model.DatasetPermissions(trans.app.security_agent.permitted_actions.DATASET_ACCESS.action, dataset, private_role) trans.sa_session.add(dp) trans.sa_session.flush() if not trans.app.security_agent.dataset_is_private_to_user(trans, dataset): # Check again and inform the user if dataset is not private. raise exceptions.InternalServerError('An error occurred and the dataset is NOT private.') elif action == 'set_permissions': # ACCESS DATASET ROLES valid_access_roles = [] invalid_access_roles_ids = [] valid_roles_for_dataset, total_roles = trans.app.security_agent.get_valid_roles(trans, dataset) if new_access_roles_ids is None: trans.app.security_agent.make_dataset_public(dataset) else: for role_id in new_access_roles_ids: role = self.role_manager.get(trans, managers_base.decode_id(self.app, role_id)) if role in valid_roles_for_dataset: valid_access_roles.append(role) else: invalid_access_roles_ids.append(role_id) if len(invalid_access_roles_ids) > 0: log.warning(f"The following roles could not be added to the dataset access permission: {str(invalid_access_roles_ids)}") access_permission = dict(access=valid_access_roles) trans.app.security_agent.set_dataset_permission(dataset, access_permission) # MANAGE DATASET ROLES valid_manage_roles = [] invalid_manage_roles_ids = [] new_manage_roles_ids = util.listify(new_manage_roles_ids) for role_id in new_manage_roles_ids: role = self.role_manager.get(trans, managers_base.decode_id(self.app, role_id)) if role in valid_roles_for_dataset: valid_manage_roles.append(role) else: invalid_manage_roles_ids.append(role_id) if len(invalid_manage_roles_ids) > 0: log.warning(f"The following roles could not be added to the dataset manage permission: {str(invalid_manage_roles_ids)}") manage_permission = {trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS: valid_manage_roles} trans.app.security_agent.set_dataset_permission(dataset, manage_permission) # MODIFY LIBRARY ITEM ROLES valid_modify_roles = [] invalid_modify_roles_ids = [] new_modify_roles_ids = util.listify(new_modify_roles_ids) for role_id in new_modify_roles_ids: role = self.role_manager.get(trans, managers_base.decode_id(self.app, role_id)) if role in valid_roles_for_dataset: valid_modify_roles.append(role) else: invalid_modify_roles_ids.append(role_id) if len(invalid_modify_roles_ids) > 0: log.warning(f"The following roles could not be added to the dataset modify permission: {str(invalid_modify_roles_ids)}") modify_permission = {trans.app.security_agent.permitted_actions.LIBRARY_MODIFY: valid_modify_roles} trans.app.security_agent.set_library_item_permission(library_dataset, modify_permission) return self._get_current_roles(trans, library_dataset)
def load(self, trans, **kwd): """ Load dataset from the given source into the library. :param encoded_folder_id: the encoded id of the folder to import dataset to :type encoded_folder_id: an encoded id string :param source: source of the dataset to be loaded :type source: str :param link_data: flag whether to link the dataset to data or copy it to Galaxy :type link_data: bool :param preserve_dirs: flag whether to preserver directory structure when importing dir :type preserve_dirs: bool """ kwd['space_to_tab'] = 'False' kwd['to_posix_lines'] = 'True' kwd['dbkey'] = kwd.get('dbkey', '?') kwd['file_type'] = kwd.get('file_type', 'auto') kwd[' link_data_only'] = 'link_to_files' if util.string_as_bool( kwd.get('link_data', False)) else 'copy_files' encoded_folder_id = kwd.get('encoded_folder_id', None) if encoded_folder_id is not None: folder_id = self.folder_manager.cut_and_decode( trans, encoded_folder_id) else: raise exceptions.RequestParameterMissingException( 'The required atribute encoded_folder_id is missing.') path = kwd.get('path', None) if path is None: raise exceptions.RequestParameterMissingException( 'The required atribute path is missing.') folder = self.folder_manager.get(trans, folder_id) source = kwd.get('source', None) if source not in [ 'userdir_file', 'userdir_folder', 'importdir_file', 'importdir_folder', 'admin_path' ]: raise exceptions.RequestParameterMissingException( 'You have to specify "source" parameter. Possible values are "userdir_file", "userdir_folder", "admin_path", "importdir_file" and "importdir_folder". ' ) if source in ['importdir_file', 'importdir_folder']: if not trans.user_is_admin: raise exceptions.AdminRequiredException( 'Only admins can import from importdir.') if not trans.app.config.library_import_dir: raise exceptions.ConfigDoesNotAllowException( 'The configuration of this Galaxy instance does not allow admins to import into library from importdir.' ) user_base_dir = trans.app.config.library_import_dir if source in ['userdir_file', 'userdir_folder']: user_login = trans.user.email user_base_dir = trans.app.config.user_library_import_dir if user_base_dir is None: raise exceptions.ConfigDoesNotAllowException( 'The configuration of this Galaxy instance does not allow upload from user directories.' ) full_dir = os.path.join(user_base_dir, user_login) # path_to_root_import_folder = None if not path.lower().startswith(full_dir.lower()): # path_to_root_import_folder = path path = os.path.join(full_dir, path) if not os.path.exists(path): raise exceptions.RequestParameterInvalidException( 'Given path does not exist on the host.') if not self.folder_manager.can_add_item(trans, folder): raise exceptions.InsufficientPermissionsException( 'You do not have proper permission to add items to the given folder.' ) if source == 'admin_path': if not trans.app.config.allow_library_path_paste: raise exceptions.ConfigDoesNotAllowException( 'The configuration of this Galaxy instance does not allow admins to import into library from path.' ) if not trans.user_is_admin: raise exceptions.AdminRequiredException( 'Only admins can import from path.') # Set up the traditional tool state/params tool_id = 'upload1' tool = trans.app.toolbox.get_tool(tool_id) state = tool.new_state(trans) tool.update_state(trans, tool.inputs_by_page[0], state.inputs, kwd) tool_params = state.inputs dataset_upload_inputs = [] for input_name, input in tool.inputs.iteritems(): if input.type == "upload_dataset": dataset_upload_inputs.append(input) library_bunch = upload_common.handle_library_params( trans, {}, trans.security.encode_id(folder.id)) abspath_datasets = [] kwd['filesystem_paths'] = path params = util.Params(kwd) # user wants to import one file only if source == "userdir_file": file = os.path.abspath(path) abspath_datasets.append(trans.webapp.controllers['library_common']. make_library_uploaded_dataset( trans, 'api', params, os.path.basename(file), file, 'server_dir', library_bunch)) # user wants to import whole folder if source == "userdir_folder": uploaded_datasets_bunch = trans.webapp.controllers[ 'library_common'].get_path_paste_uploaded_datasets( trans, 'api', params, library_bunch, 200, '') uploaded_datasets = uploaded_datasets_bunch[0] if uploaded_datasets is None: raise exceptions.ObjectNotFound( 'Given folder does not contain any datasets.') for ud in uploaded_datasets: ud.path = os.path.abspath(ud.path) abspath_datasets.append(ud) # user wants to import from path (admins only) if source == "admin_path": # validate the path is within root uploaded_datasets_bunch = trans.webapp.controllers[ 'library_common'].get_path_paste_uploaded_datasets( trans, 'api', params, library_bunch, 200, '') uploaded_datasets = uploaded_datasets_bunch[0] if uploaded_datasets is None: raise exceptions.ObjectNotFound( 'Given folder does not contain any datasets.') for ud in uploaded_datasets: ud.path = os.path.abspath(ud.path) abspath_datasets.append(ud) json_file_path = upload_common.create_paramfile( trans, abspath_datasets) data_list = [ud.data for ud in abspath_datasets] job, output = upload_common.create_job(trans, tool_params, tool, json_file_path, data_list, folder=folder) # HACK: Prevent outputs_to_working_directory from overwriting inputs when "linking" job.add_parameter('link_data_only', dumps(kwd.get('link_data_only', 'copy_files'))) job.add_parameter('uuid', dumps(kwd.get('uuid', None))) trans.sa_session.add(job) trans.sa_session.flush() job_dict = job.to_dict() job_dict['id'] = trans.security.encode_id(job_dict['id']) return job_dict
def load(self, trans, payload=None, **kwd): """ POST /api/libraries/datasets Load dataset(s) from the given source into the library. :param payload: dictionary structure containing: :param encoded_folder_id: the encoded id of the folder to import dataset(s) to :type encoded_folder_id: an encoded id string :param source: source the datasets should be loaded from. Source can be: - user directory root folder specified in galaxy.ini as "$user_library_import_dir" example path: path/to/galaxy/$user_library_import_dir/[email protected]/{user can browse everything here} the folder with the user login has to be created beforehand - (admin)import directory root folder specified in galaxy ini as "$library_import_dir" example path: path/to/galaxy/$library_import_dir/{admin can browse everything here} - (admin)any absolute or relative path option allowed with "allow_library_path_paste" in galaxy.ini :type source: str :param link_data: flag whether to link the dataset to data or copy it to Galaxy, defaults to copy while linking is set to True all symlinks will be resolved _once_ :type link_data: bool :param preserve_dirs: flag whether to preserve the directory structure when importing dir if False only datasets will be imported :type preserve_dirs: bool :param file_type: file type of the loaded datasets, defaults to 'auto' (autodetect) :type file_type: str :param dbkey: dbkey of the loaded genome, defaults to '?' (unknown) :type dbkey: str :param tag_using_filenames: flag whether to generate dataset tags from filenames :type tag_using_filenames: bool :type dictionary :returns: dict containing information about the created upload job :rtype: dictionary :raises: RequestParameterMissingException, AdminRequiredException, ConfigDoesNotAllowException, RequestParameterInvalidException InsufficientPermissionsException, ObjectNotFound """ if payload: kwd.update(payload) kwd['space_to_tab'] = False kwd['to_posix_lines'] = True kwd['dbkey'] = kwd.get('dbkey', '?') kwd['file_type'] = kwd.get('file_type', 'auto') kwd['link_data_only'] = 'link_to_files' if util.string_as_bool(kwd.get('link_data', False)) else 'copy_files' kwd['tag_using_filenames'] = util.string_as_bool(kwd.get('tag_using_filenames', None)) encoded_folder_id = kwd.get('encoded_folder_id', None) if encoded_folder_id is not None: folder_id = self.folder_manager.cut_and_decode(trans, encoded_folder_id) else: raise exceptions.RequestParameterMissingException('The required attribute encoded_folder_id is missing.') path = kwd.get('path', None) if path is None: raise exceptions.RequestParameterMissingException('The required attribute path is missing.') if not isinstance(path, str): raise exceptions.RequestParameterInvalidException('The required attribute path is not String.') folder = self.folder_manager.get(trans, folder_id) source = kwd.get('source', None) if source not in ['userdir_file', 'userdir_folder', 'importdir_file', 'importdir_folder', 'admin_path']: raise exceptions.RequestParameterMissingException('You have to specify "source" parameter. Possible values are "userdir_file", "userdir_folder", "admin_path", "importdir_file" and "importdir_folder". ') elif source in ['importdir_file', 'importdir_folder']: if not trans.user_is_admin: raise exceptions.AdminRequiredException('Only admins can import from importdir.') if not trans.app.config.library_import_dir: raise exceptions.ConfigDoesNotAllowException('The configuration of this Galaxy instance does not allow admins to import into library from importdir.') import_base_dir = trans.app.config.library_import_dir if not safe_relpath(path): # admins shouldn't be able to explicitly specify a path outside server_dir, but symlinks are allowed. # the reasoning here is that galaxy admins may not have direct filesystem access or can only access # library_import_dir via FTP (which cannot create symlinks), and may rely on sysadmins to set up the # import directory. if they have filesystem access, all bets are off. raise exceptions.RequestParameterInvalidException('The given path is invalid.') path = os.path.join(import_base_dir, path) elif source in ['userdir_file', 'userdir_folder']: username = trans.user.username if trans.app.config.user_library_import_check_permissions else None user_login = trans.user.email user_base_dir = trans.app.config.user_library_import_dir if user_base_dir is None: raise exceptions.ConfigDoesNotAllowException('The configuration of this Galaxy instance does not allow upload from user directories.') full_dir = os.path.join(user_base_dir, user_login) if not safe_contains(full_dir, path, allowlist=trans.app.config.user_library_import_symlink_allowlist): # the path is a symlink outside the user dir path = os.path.join(full_dir, path) log.error('User attempted to import a path that resolves to a path outside of their import dir: %s -> %s', path, os.path.realpath(path)) raise exceptions.RequestParameterInvalidException('The given path is invalid.') if trans.app.config.user_library_import_check_permissions and not full_path_permission_for_user(full_dir, path, username): log.error('User attempted to import a path that resolves to a path outside of their import dir: ' '%s -> %s and cannot be read by them.', path, os.path.realpath(path)) raise exceptions.RequestParameterInvalidException('The given path is invalid.') path = os.path.join(full_dir, path) if unsafe_walk(path, allowlist=[full_dir] + trans.app.config.user_library_import_symlink_allowlist, username=username): # the path is a dir and contains files that symlink outside the user dir error = 'User attempted to import a path that resolves to a path outside of their import dir: {} -> {}'.format( path, os.path.realpath(path) ) if trans.app.config.user_library_import_check_permissions: error += ' or is not readable for them.' log.error(error) raise exceptions.RequestParameterInvalidException('The given path is invalid.') if not os.path.exists(path): raise exceptions.RequestParameterInvalidException('Given path does not exist on the host.') if not self.folder_manager.can_add_item(trans, folder): raise exceptions.InsufficientPermissionsException('You do not have proper permission to add items to the given folder.') elif source == 'admin_path': if not trans.app.config.allow_library_path_paste: raise exceptions.ConfigDoesNotAllowException('The configuration of this Galaxy instance does not allow admins to import into library from path.') if not trans.user_is_admin: raise exceptions.AdminRequiredException('Only admins can import from path.') # Set up the traditional tool state/params tool_id = 'upload1' tool = trans.app.toolbox.get_tool(tool_id) state = tool.new_state(trans) populate_state(trans, tool.inputs, kwd, state.inputs) tool_params = state.inputs dataset_upload_inputs = [] for input in tool.inputs.values(): if input.type == "upload_dataset": dataset_upload_inputs.append(input) library_bunch = upload_common.handle_library_params(trans, {}, trans.security.encode_id(folder.id)) abspath_datasets = [] kwd['filesystem_paths'] = path if source in ['importdir_folder']: kwd['filesystem_paths'] = os.path.join(import_base_dir, path) # user wants to import one file only elif source in ["userdir_file", "importdir_file"]: file = os.path.abspath(path) abspath_datasets.append(self._make_library_uploaded_dataset( trans, kwd, os.path.basename(file), file, 'server_dir', library_bunch)) # user wants to import whole folder elif source == "userdir_folder": uploaded_datasets_bunch = self._get_path_paste_uploaded_datasets( trans, kwd, library_bunch, 200, '') uploaded_datasets = uploaded_datasets_bunch[0] if uploaded_datasets is None: raise exceptions.ObjectNotFound('Given folder does not contain any datasets.') for ud in uploaded_datasets: ud.path = os.path.abspath(ud.path) abspath_datasets.append(ud) # user wants to import from path if source in ["admin_path", "importdir_folder"]: # validate the path is within root uploaded_datasets_bunch = self._get_path_paste_uploaded_datasets( trans, kwd, library_bunch, 200, '') uploaded_datasets = uploaded_datasets_bunch[0] if uploaded_datasets is None: raise exceptions.ObjectNotFound('Given folder does not contain any datasets.') for ud in uploaded_datasets: ud.path = os.path.abspath(ud.path) abspath_datasets.append(ud) json_file_path = upload_common.create_paramfile(trans, abspath_datasets) data_list = [ud.data for ud in abspath_datasets] job_params = {} job_params['link_data_only'] = dumps(kwd.get('link_data_only', 'copy_files')) job_params['uuid'] = dumps(kwd.get('uuid', None)) job, output = upload_common.create_job(trans, tool_params, tool, json_file_path, data_list, folder=folder, job_params=job_params) trans.app.job_manager.enqueue(job, tool=tool) job_dict = job.to_dict() job_dict['id'] = trans.security.encode_id(job_dict['id']) return job_dict