def addon_delete_file_node(self, node, user, event_type, payload): """ Get addon BaseFileNode(s), move it into the TrashedFileNode collection and remove it from StoredFileNode. Required so that the guids of deleted addon files are not re-pointed when an addon file or folder is moved or renamed. """ if event_type == 'file_removed' and payload.get('provider', None) != 'osfstorage': provider = payload['provider'] path = payload['metadata']['path'] materialized_path = payload['metadata']['materialized'] if path.endswith('/'): folder_children = BaseFileNode.resolve_class(provider, BaseFileNode.ANY).objects.filter( provider=provider, node=node, _materialized_path__startswith=materialized_path ) for item in folder_children: if item.kind == 'file' and not TrashedFileNode.load(item._id): item.delete(user=user) elif item.kind == 'folder': BaseFileNode.remove_one(item) else: try: file_node = BaseFileNode.resolve_class(provider, BaseFileNode.FILE).objects.get( node=node, _materialized_path=materialized_path ) except BaseFileNode.DoesNotExist: file_node = None if file_node and not TrashedFileNode.load(file_node._id): file_node.delete(user=user)
def get_file_guids(cls, materialized_path, provider, node=None): guids = [] path = materialized_path.strip('/') file_obj = cls.load(path) if not file_obj: file_obj = TrashedFileNode.load(path) # At this point, file_obj may be an OsfStorageFile, an OsfStorageFolder, or a # TrashedFileNode. TrashedFileNodes do not have *File and *Folder subclasses, since # only osfstorage trashes folders. To search for children of TrashFileNodes # representing ex-OsfStorageFolders, we will reimplement the `children` method of the # Folder class here. if not file_obj.is_file: children = [] if isinstance(file_obj, TrashedFileNode): children = file_obj.trashed_children.all() else: children = file_obj.children for item in children: guids.extend(cls.get_file_guids(item.path, provider, node=node)) else: guid = file_obj.get_guid() if guid: guids.append(guid._id) return sorted(guids)
def update_file_guid_referent(self, node, event_type, payload, user=None): if event_type not in ('addon_file_moved', 'addon_file_renamed'): return # Nothing to do source, destination = payload['source'], payload['destination'] source_node, destination_node = Node.load(source['node']['_id']), Node.load(destination['node']['_id']) if source['provider'] in settings.ADDONS_BASED_ON_IDS: if event_type == 'addon_file_renamed': return # Node has not changed and provider has not changed # Must be a move if source['provider'] == destination['provider'] and source_node == destination_node: return # Node has not changed and provider has not changed file_guids = BaseFileNode.resolve_class(source['provider'], BaseFileNode.ANY).get_file_guids( materialized_path=source['materialized'] if source['provider'] != 'osfstorage' else source['path'], provider=source['provider'], node=source_node ) for guid in file_guids: obj = Guid.load(guid) if source_node != destination_node and Comment.find(Q('root_target._id', 'eq', guid)).count() != 0: update_comment_node(guid, source_node, destination_node) if source['provider'] != destination['provider'] or source['provider'] != 'osfstorage': old_file = BaseFileNode.load(obj.referent._id) obj.referent = create_new_file(obj, source, destination, destination_node) obj.save() if old_file and not TrashedFileNode.load(old_file._id): old_file.delete()
def get_archived_from_url(node, file_node): if file_node.copied_from: trashed = TrashedFileNode.load(file_node.copied_from._id) if not trashed: return node.registered_from.web_url_for('addon_view_or_download_file', provider=file_node.provider, path=file_node.copied_from._id) return None
def addon_deleted_file(auth, target, error_type='BLAME_PROVIDER', **kwargs): """Shows a nice error message to users when they try to view a deleted file """ # Allow file_node to be passed in so other views can delegate to this one file_node = kwargs.get('file_node') or TrashedFileNode.load(kwargs.get('trashed_id')) deleted_by, deleted_on = None, None if isinstance(file_node, TrashedFileNode): deleted_by = file_node.deleted_by deleted_by_guid = file_node.deleted_by._id if deleted_by else None deleted_on = file_node.deleted_on.strftime('%c') + ' UTC' if getattr(file_node, 'suspended', False): error_type = 'FILE_SUSPENDED' elif file_node.deleted_by is None or (auth.private_key and auth.private_link.anonymous): if file_node.provider == 'osfstorage': error_type = 'FILE_GONE_ACTOR_UNKNOWN' else: error_type = 'BLAME_PROVIDER' else: error_type = 'FILE_GONE' else: error_type = 'DONT_KNOW' file_path = kwargs.get('path', file_node.path) file_name = file_node.name or os.path.basename(file_path) file_name_title, file_name_ext = os.path.splitext(file_name) provider_full = settings.ADDONS_AVAILABLE_DICT[file_node.provider].full_name try: file_guid = file_node.get_guid()._id except AttributeError: file_guid = None format_params = dict( file_name=markupsafe.escape(file_name), deleted_by=markupsafe.escape(getattr(deleted_by, 'fullname', None)), deleted_on=markupsafe.escape(deleted_on), provider=markupsafe.escape(provider_full) ) if deleted_by: format_params['deleted_by_guid'] = markupsafe.escape(deleted_by_guid) error_msg = ERROR_MESSAGES[error_type].format(**format_params) if isinstance(target, AbstractNode): error_msg += format_last_known_metadata(auth, target, file_node, error_type) ret = serialize_node(target, auth, primary=True) ret.update(rubeus.collect_addon_assets(target)) ret.update({ 'error': error_msg, 'urls': { 'render': None, 'sharejs': None, 'mfr': get_mfr_url(target, file_node.provider), 'profile_image': get_profile_image_url(auth.user, 25), 'files': target.web_url_for('collect_file_trees'), }, 'extra': {}, 'size': 9966699, # Prevent file from being edited, just in case 'sharejs_uuid': None, 'file_name': file_name, 'file_path': file_path, 'file_name_title': file_name_title, 'file_name_ext': file_name_ext, 'target_deleted': getattr(target, 'is_deleted', False), 'version_id': None, 'file_guid': file_guid, 'file_id': file_node._id, 'provider': file_node.provider, 'materialized_path': file_node.materialized_path or file_path, 'private': getattr(target.get_addon(file_node.provider), 'is_private', False), 'file_tags': list(file_node.tags.filter(system=False).values_list('name', flat=True)) if not file_node._state.adding else [], # Only access ManyRelatedManager if saved 'allow_comments': file_node.provider in settings.ADDONS_COMMENTABLE, }) else: # TODO - serialize deleted metadata for future types of deleted file targets ret = {'error': error_msg} return ret, httplib.GONE
def addon_deleted_file(auth, target, error_type='BLAME_PROVIDER', **kwargs): """Shows a nice error message to users when they try to view a deleted file """ # Allow file_node to be passed in so other views can delegate to this one file_node = kwargs.get('file_node') or TrashedFileNode.load( kwargs.get('trashed_id')) deleted_by, deleted_on = None, None if isinstance(file_node, TrashedFileNode): deleted_by = file_node.deleted_by deleted_by_guid = file_node.deleted_by._id if deleted_by else None deleted_on = file_node.deleted_on.strftime('%c') + ' UTC' if getattr(file_node, 'suspended', False): error_type = 'FILE_SUSPENDED' elif file_node.deleted_by is None or (auth.private_key and auth.private_link.anonymous): if file_node.provider == 'osfstorage': error_type = 'FILE_GONE_ACTOR_UNKNOWN' else: error_type = 'BLAME_PROVIDER' else: error_type = 'FILE_GONE' else: error_type = 'DONT_KNOW' file_path = kwargs.get('path', file_node.path) file_name = file_node.name or os.path.basename(file_path) file_name_title, file_name_ext = os.path.splitext(file_name) provider_full = settings.ADDONS_AVAILABLE_DICT[ file_node.provider].full_name try: file_guid = file_node.get_guid()._id except AttributeError: file_guid = None format_params = dict(file_name=markupsafe.escape(file_name), deleted_by=markupsafe.escape( getattr(deleted_by, 'fullname', None)), deleted_on=markupsafe.escape(deleted_on), provider=markupsafe.escape(provider_full)) if deleted_by: format_params['deleted_by_guid'] = markupsafe.escape(deleted_by_guid) error_msg = ERROR_MESSAGES[error_type].format(**format_params) if isinstance(target, AbstractNode): error_msg += format_last_known_metadata(auth, target, file_node, error_type) ret = serialize_node(target, auth, primary=True) ret.update(rubeus.collect_addon_assets(target)) ret.update({ 'error': error_msg, 'urls': { 'render': None, 'sharejs': None, 'mfr': get_mfr_url(target, file_node.provider), 'profile_image': get_profile_image_url(auth.user, 25), 'files': target.web_url_for('collect_file_trees'), }, 'extra': {}, 'size': 9966699, # Prevent file from being edited, just in case 'sharejs_uuid': None, 'file_name': file_name, 'file_path': file_path, 'file_name_title': file_name_title, 'file_name_ext': file_name_ext, 'target_deleted': getattr(target, 'is_deleted', False), 'version_id': None, 'file_guid': file_guid, 'file_id': file_node._id, 'provider': file_node.provider, 'materialized_path': file_node.materialized_path or file_path, 'private': getattr(target.get_addon(file_node.provider), 'is_private', False), 'file_tags': list( file_node.tags.filter(system=False).values_list( 'name', flat=True)) if not file_node._state.adding else [], # Only access ManyRelatedManager if saved 'allow_comments': file_node.provider in settings.ADDONS_COMMENTABLE, }) else: # TODO - serialize deleted metadata for future types of deleted file targets ret = {'error': error_msg} return ret, http_status.HTTP_410_GONE
def addon_deleted_file(auth, node, error_type='BLAME_PROVIDER', **kwargs): """Shows a nice error message to users when they try to view a deleted file """ # Allow file_node to be passed in so other views can delegate to this one file_node = kwargs.get('file_node') or TrashedFileNode.load( kwargs.get('trashed_id')) deleted_by, deleted_on = None, None if isinstance(file_node, TrashedFileNode): deleted_by = file_node.deleted_by deleted_by_guid = file_node.deleted_by._id if deleted_by else None deleted_on = file_node.deleted_on.strftime('%c') + ' UTC' if file_node.suspended: error_type = 'FILE_SUSPENDED' elif file_node.deleted_by is None: if file_node.provider == 'osfstorage': error_type = 'FILE_GONE_ACTOR_UNKNOWN' else: error_type = 'BLAME_PROVIDER' else: error_type = 'FILE_GONE' else: error_type = 'DONT_KNOW' file_path = kwargs.get('path', file_node.path) file_name = file_node.name or os.path.basename(file_path) file_name_title, file_name_ext = os.path.splitext(file_name) provider_full = settings.ADDONS_AVAILABLE_DICT[ file_node.provider].full_name try: file_guid = file_node.get_guid()._id except AttributeError: file_guid = None format_params = dict(file_name=markupsafe.escape(file_name), deleted_by=markupsafe.escape(deleted_by), deleted_on=markupsafe.escape(deleted_on), provider=markupsafe.escape(provider_full)) if deleted_by: format_params['deleted_by_guid'] = markupsafe.escape(deleted_by_guid) ret = serialize_node(node, auth, primary=True) ret.update(rubeus.collect_addon_assets(node)) ret.update({ 'error': ERROR_MESSAGES[error_type].format(**format_params), 'urls': { 'render': None, 'sharejs': None, 'mfr': settings.MFR_SERVER_URL, 'gravatar': get_gravatar(auth.user, 25), 'files': node.web_url_for('collect_file_trees'), }, 'extra': {}, 'size': 9966699, # Prevent file from being edited, just in case 'sharejs_uuid': None, 'file_name': file_name, 'file_path': file_path, 'file_name_title': file_name_title, 'file_name_ext': file_name_ext, 'version_id': None, 'file_guid': file_guid, 'file_id': file_node._id, 'provider': file_node.provider, 'materialized_path': file_node.materialized_path or file_path, 'private': getattr(node.get_addon(file_node.provider), 'is_private', False), 'file_tags': file_node.tags.filter(system=False).values_list('name', flat=True), 'allow_comments': file_node.provider in settings.ADDONS_COMMENTABLE, }) return ret, httplib.GONE