def get_metadata_files(draft): data = draft.registration_metadata for q, question in get_file_questions('prereg-prize.json'): if not isinstance(data[q]['value'], dict): for i, file_info in enumerate(data[q]['extra']): provider = file_info['data']['provider'] if provider != 'osfstorage': raise Http404( 'File does not exist in OSFStorage ({}: {})'.format( q, question )) file_guid = file_info.get('fileId') if not file_guid: node = Node.load(file_info.get('nodeId')) path = file_info['data'].get('path') item = BaseFileNode.resolve_class( provider, BaseFileNode.FILE ).get_or_create(node, path) file_guid = item.get_guid(create=True)._id data[q]['extra'][i]['fileId'] = file_guid draft.update_metadata(data) draft.save() else: item = BaseFileNode.load(file_info['data']['path'].replace('/', '')) if item is None: raise Http404( 'File with guid "{}" in "{}" does not exist'.format( file_guid, question )) yield item continue for i, file_info in enumerate(data[q]['value']['uploader']['extra']): provider = file_info['data']['provider'] if provider != 'osfstorage': raise Http404( 'File does not exist in OSFStorage ({}: {})'.format( q, question )) file_guid = file_info.get('fileId') if not file_guid: node = Node.load(file_info.get('nodeId')) path = file_info['data'].get('path') item = BaseFileNode.resolve_class( provider, BaseFileNode.FILE ).get_or_create(node, path) file_guid = item.get_guid(create=True)._id data[q]['value']['uploader']['extra'][i]['fileId'] = file_guid draft.update_metadata(data) draft.save() else: item = BaseFileNode.load(file_info['data']['path'].replace('/', '')) if item is None: raise Http404( 'File with guid "{}" in "{}" does not exist'.format( file_guid, question )) yield item
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.objects.filter(root_target___id=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 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 addon_view_or_download_file(auth, path, provider, **kwargs): extras = request.args.to_dict() extras.pop('_', None) # Clean up our url params a bit action = extras.get('action', 'view') guid = kwargs.get('guid') guid_target = getattr(Guid.load(guid), 'referent', None) target = guid_target or kwargs.get('node') or kwargs['project'] provider_safe = markupsafe.escape(provider) path_safe = markupsafe.escape(path) if not path: raise HTTPError(http_status.HTTP_400_BAD_REQUEST) if hasattr(target, 'get_addon'): node_addon = target.get_addon(provider) if not isinstance(node_addon, BaseStorageAddon): object_text = markupsafe.escape( getattr(target, 'project_or_component', 'this object')) raise HTTPError( http_status.HTTP_400_BAD_REQUEST, data={ 'message_short': 'Bad Request', 'message_long': 'The {} add-on containing {} is no longer connected to {}.' .format(provider_safe, path_safe, object_text) }) if not node_addon.has_auth: raise HTTPError( http_status.HTTP_401_UNAUTHORIZED, data={ 'message_short': 'Unauthorized', 'message_long': 'The {} add-on containing {} is no longer authorized.'. format(provider_safe, path_safe) }) if not node_addon.complete: raise HTTPError( http_status.HTTP_400_BAD_REQUEST, data={ 'message_short': 'Bad Request', 'message_long': 'The {} add-on containing {} is no longer configured.'. format(provider_safe, path_safe) }) savepoint_id = transaction.savepoint() file_node = BaseFileNode.resolve_class(provider, BaseFileNode.FILE).get_or_create( target, path) # Note: Cookie is provided for authentication to waterbutler # it is overriden to force authentication as the current user # the auth header is also pass to support basic auth version = file_node.touch( request.headers.get('Authorization'), **dict(extras, cookie=request.cookies.get(settings.COOKIE_NAME))) if version is None: # File is either deleted or unable to be found in the provider location # Rollback the insertion of the file_node transaction.savepoint_rollback(savepoint_id) if not file_node.pk: file_node = BaseFileNode.load(path) if not file_node: raise HTTPError(http_status.HTTP_404_NOT_FOUND, data={ 'message_short': 'File Not Found', 'message_long': 'The requested file could not be found.' }) if file_node.kind == 'folder': raise HTTPError( http_status.HTTP_400_BAD_REQUEST, data={ 'message_short': 'Bad Request', 'message_long': 'You cannot request a folder from this endpoint.' }) # Allow osfstorage to redirect if the deep url can be used to find a valid file_node if file_node.provider == 'osfstorage' and not file_node.is_deleted: return redirect( file_node.target.web_url_for('addon_view_or_download_file', path=file_node._id, provider=file_node.provider)) return addon_deleted_file(target=target, file_node=file_node, path=path, **kwargs) else: transaction.savepoint_commit(savepoint_id) # TODO clean up these urls and unify what is used as a version identifier if request.method == 'HEAD': return make_response(('', http_status.HTTP_302_FOUND, { 'Location': file_node.generate_waterbutler_url( **dict(extras, direct=None, version=version.identifier, _internal=extras.get('mode') == 'render')) })) if action == 'download': format = extras.get('format') _, extension = os.path.splitext(file_node.name) # avoid rendering files with the same format type. if format and '.{}'.format(format.lower()) != extension.lower(): return redirect('{}/export?format={}&url={}'.format( get_mfr_url(target, provider), format, quote( file_node.generate_waterbutler_url( **dict(extras, direct=None, version=version.identifier, _internal=extras.get('mode') == 'render'))))) return redirect( file_node.generate_waterbutler_url( **dict(extras, direct=None, version=version.identifier, _internal=extras.get('mode') == 'render'))) if action == 'get_guid': draft_id = extras.get('draft') draft = DraftRegistration.load(draft_id) if draft is None or draft.is_approved: raise HTTPError(http_status.HTTP_400_BAD_REQUEST, data={ 'message_short': 'Bad Request', 'message_long': 'File not associated with required object.' }) guid = file_node.get_guid(create=True) guid.referent.save() return dict(guid=guid._id) if len(request.path.strip('/').split('/')) > 1: guid = file_node.get_guid(create=True) return redirect( furl.furl('/{}/'.format(guid._id)).set(args=extras).url) if isinstance(target, Preprint): # Redirecting preprint file guids to the preprint detail page return redirect('/{}/'.format(target._id)) return addon_view_file(auth, target, file_node, version)
def get_object(self, file_id): return BaseFileNode.load(file_id)
def addon_view_or_download_file(auth, path, provider, **kwargs): extras = request.args.to_dict() extras.pop('_', None) # Clean up our url params a bit action = extras.get('action', 'view') guid = kwargs.get('guid') guid_target = getattr(Guid.load(guid), 'referent', None) target = guid_target or kwargs.get('node') or kwargs['project'] provider_safe = markupsafe.escape(provider) path_safe = markupsafe.escape(path) if not path: raise HTTPError(httplib.BAD_REQUEST) if hasattr(target, 'get_addon'): node_addon = target.get_addon(provider) if not isinstance(node_addon, BaseStorageAddon): object_text = markupsafe.escape(getattr(target, 'project_or_component', 'this object')) raise HTTPError(httplib.BAD_REQUEST, data={ 'message_short': 'Bad Request', 'message_long': 'The {} add-on containing {} is no longer connected to {}.'.format(provider_safe, path_safe, object_text) }) if not node_addon.has_auth: raise HTTPError(httplib.UNAUTHORIZED, data={ 'message_short': 'Unauthorized', 'message_long': 'The {} add-on containing {} is no longer authorized.'.format(provider_safe, path_safe) }) if not node_addon.complete: raise HTTPError(httplib.BAD_REQUEST, data={ 'message_short': 'Bad Request', 'message_long': 'The {} add-on containing {} is no longer configured.'.format(provider_safe, path_safe) }) savepoint_id = transaction.savepoint() file_node = BaseFileNode.resolve_class(provider, BaseFileNode.FILE).get_or_create(target, path) # Note: Cookie is provided for authentication to waterbutler # it is overriden to force authentication as the current user # the auth header is also pass to support basic auth version = file_node.touch( request.headers.get('Authorization'), **dict( extras, cookie=request.cookies.get(settings.COOKIE_NAME) ) ) if version is None: # File is either deleted or unable to be found in the provider location # Rollback the insertion of the file_node transaction.savepoint_rollback(savepoint_id) if not file_node.pk: file_node = BaseFileNode.load(path) if file_node.kind == 'folder': raise HTTPError(httplib.BAD_REQUEST, data={ 'message_short': 'Bad Request', 'message_long': 'You cannot request a folder from this endpoint.' }) # Allow osfstorage to redirect if the deep url can be used to find a valid file_node if file_node and file_node.provider == 'osfstorage' and not file_node.is_deleted: return redirect( file_node.target.web_url_for('addon_view_or_download_file', path=file_node._id, provider=file_node.provider) ) return addon_deleted_file(target=target, file_node=file_node, path=path, **kwargs) else: transaction.savepoint_commit(savepoint_id) # TODO clean up these urls and unify what is used as a version identifier if request.method == 'HEAD': return make_response(('', httplib.FOUND, { 'Location': file_node.generate_waterbutler_url(**dict(extras, direct=None, version=version.identifier, _internal=extras.get('mode') == 'render')) })) if action == 'download': format = extras.get('format') _, extension = os.path.splitext(file_node.name) # avoid rendering files with the same format type. if format and '.{}'.format(format.lower()) != extension.lower(): return redirect('{}/export?format={}&url={}'.format(get_mfr_url(target, provider), format, urllib.quote(file_node.generate_waterbutler_url( **dict(extras, direct=None, version=version.identifier, _internal=extras.get('mode') == 'render') )))) return redirect(file_node.generate_waterbutler_url(**dict(extras, direct=None, version=version.identifier, _internal=extras.get('mode') == 'render'))) if action == 'get_guid': draft_id = extras.get('draft') draft = DraftRegistration.load(draft_id) if draft is None or draft.is_approved: raise HTTPError(httplib.BAD_REQUEST, data={ 'message_short': 'Bad Request', 'message_long': 'File not associated with required object.' }) guid = file_node.get_guid(create=True) guid.referent.save() return dict(guid=guid._id) if len(request.path.strip('/').split('/')) > 1: guid = file_node.get_guid(create=True) return redirect(furl.furl('/{}/'.format(guid._id)).set(args=extras).url) if isinstance(target, Preprint): # Redirecting preprint file guids to the preprint detail page return redirect('/{}/'.format(target._id)) return addon_view_file(auth, target, file_node, version)
def view_file(request, node_id, provider, file_id): fp = BaseFileNode.load(file_id) wb_url = fp.generate_waterbutler_url() return redirect(wb_url)