def test_mfr_url(self): user = UserFactory() project = ProjectFactory(creator=user) comment = CommentFactory() assert get_mfr_url(project, 'github') == MFR_SERVER_URL assert get_mfr_url(project, 'osfstorage') == project.osfstorage_region.mfr_url assert get_mfr_url(comment, 'osfstorage') == MFR_SERVER_URL
def test_serialize_preprint_file(self, preprint, primary_file): req = make_drf_request_with_version(version='2.2') data = FileSerializer(primary_file, context={ 'request': req }).data['data'] mfr_url = get_mfr_url(preprint, 'osfstorage') # Check render file link with path download_link = data['links']['download'] assert data['links']['render'] == build_expected_render_link( mfr_url, download_link, with_version=False) # Check render file link with guid primary_file.get_guid(create=True)._id req = make_drf_request_with_version() data = FileSerializer(primary_file, context={ 'request': req }).data['data'] download_link = data['links']['download'] assert data['links']['render'] == build_expected_render_link( mfr_url, download_link, with_version=False) # Check html link assert data['links']['html'] == '{}{}/files/osfstorage/{}'.format( settings.DOMAIN, preprint._id, primary_file._id)
def get_render_link(self, obj): file = self.context['file'] mfr_url = get_mfr_url(file.target, file.provider) download_url = self.get_download_link(obj) return get_file_render_link(mfr_url, download_url, version=obj.identifier)
def test_load_and_property(self, app, user, file): # test_by_id res = app.get( '/{}files/{}/versions/1/'.format(API_BASE, file._id), auth=user.auth, ) assert res.status_code == 200 assert res.json['data']['id'] == '1' mfr_url = get_mfr_url(file, 'osfstorage') render_link = res.json['data']['links']['render'] download_link = res.json['data']['links']['download'] assert mfr_url in render_link assert download_link in render_link assert 'revision=1' in render_link guid = file.get_guid(create=True)._id res = app.get( '/{}files/{}/versions/1/'.format(API_BASE, file._id), auth=user.auth, ) render_link = res.json['data']['links']['render'] download_link = res.json['data']['links']['download'] assert mfr_url in render_link assert download_link in render_link assert guid in render_link assert 'revision=1' in render_link # test_read_only assert app.put( '/{}files/{}/versions/1/'.format(API_BASE, file._id), expect_errors=True, auth=user.auth, ).status_code == 405 assert app.post( '/{}files/{}/versions/1/'.format(API_BASE, file._id), expect_errors=True, auth=user.auth, ).status_code == 405 assert app.delete( '/{}files/{}/versions/1/'.format(API_BASE, file._id), expect_errors=True, auth=user.auth, ).status_code == 405
def test_get_file_download_and_render_links(self, file_one, node): mfr_link = get_mfr_url(file_one.target, 'osfstorage') # file links with path download_link = get_file_download_link(file_one) assert download_link == '{}download/{}/'.format( settings.DOMAIN, file_one._id) assert get_file_render_link( mfr_link, download_link) == build_expected_render_link(mfr_link, download_link, with_version=False) # file versions link with path download_link = get_file_download_link(file_one, version=2) assert download_link == '{}download/{}/?revision=2'.format( settings.DOMAIN, file_one._id) assert get_file_render_link(mfr_link, download_link, version=2) == build_expected_render_link( mfr_link, download_link) # file links with guid file_one.get_guid(create=True) download_link = get_file_download_link(file_one) assert download_link == '{}download/{}/'.format( settings.DOMAIN, file_one.get_guid()._id) assert get_file_render_link( mfr_link, download_link) == build_expected_render_link(mfr_link, download_link, with_version=False) # file version links with guid download_link = get_file_download_link(file_one, version=2) assert download_link == '{}download/{}/?revision=2'.format( settings.DOMAIN, file_one.get_guid()._id) assert get_file_render_link(mfr_link, download_link, version=2) == build_expected_render_link( mfr_link, download_link)
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, deleted = None, 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' deleted = deleted_on 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), deleted=markupsafe.escape(deleted)) 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 get_render_link(self, obj): if obj.is_file: mfr_url = get_mfr_url(obj.target, obj.provider) download_url = self.get_download_link(obj) return get_file_render_link(mfr_url, download_url)
def test_file_serializer(self, file_one, node): created = file_one.versions.last().created modified = file_one.versions.first().created created_tz_aware = created.replace(tzinfo=utc) modified_tz_aware = modified.replace(tzinfo=utc) new_format = '%Y-%m-%dT%H:%M:%S.%fZ' download_base = '/download/{}' path = file_one._id mfr_url = get_mfr_url(file_one, 'osfstorage') # test_date_modified_formats_to_old_format req = make_drf_request_with_version(version='2.0') data = FileSerializer(file_one, context={'request': req}).data['data'] assert modified_tz_aware == data['attributes']['date_modified'] # test_date_modified_formats_to_new_format req = make_drf_request_with_version(version='2.2') data = FileSerializer(file_one, context={'request': req}).data['data'] assert datetime.strftime( modified, new_format) == data['attributes']['date_modified'] # test_date_created_formats_to_old_format req = make_drf_request_with_version(version='2.0') data = FileSerializer(file_one, context={'request': req}).data['data'] assert created_tz_aware == data['attributes']['date_created'] # test_date_created_formats_to_new_format req = make_drf_request_with_version(version='2.2') data = FileSerializer(file_one, context={'request': req}).data['data'] assert datetime.strftime( created, new_format) == data['attributes']['date_created'] # check download file link with path assert download_base.format(path) in data['links']['download'] # check render file link with path assert download_base.format(path) in data['links']['render'] assert mfr_url in data['links']['render'] # check download file link with guid guid = file_one.get_guid(create=True)._id req = make_drf_request_with_version() data = FileSerializer(file_one, context={'request': req}).data['data'] assert download_base.format(guid) in data['links']['download'] # check render file link with guid assert download_base.format(guid) in data['links']['render'] assert mfr_url in data['links']['render'] # check html link in file serializer assert data['links']['html'] == '{}{}/files/osfstorage/{}'.format( settings.DOMAIN, node._id, file_one._id) # check download/render/html link for folder folder = node.get_addon('osfstorage').get_root().append_folder( 'Test_folder') folder.save() req = make_drf_request_with_version(version='2.2') data = FileSerializer(folder, context={'request': req}).data['data'] assert 'render' not in data['links'] assert 'download' not in data['links'] assert 'html' not in data['links']
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 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_view_file(auth, node, file_node, version): # TODO: resolve circular import issue from addons.wiki import settings as wiki_settings if isinstance(version, tuple): version, error = version error = error.replace('\n', '').strip() else: error = None ret = serialize_node(node, auth, primary=True) if file_node._id + '-' + version._id not in node.file_guid_to_share_uuids: node.file_guid_to_share_uuids[file_node._id + '-' + version._id] = uuid.uuid4() node.save() if ret['user']['can_edit']: sharejs_uuid = str(node.file_guid_to_share_uuids[file_node._id + '-' + version._id]) else: sharejs_uuid = None internal_furl = furl.furl(settings.INTERNAL_DOMAIN) download_url = furl.furl(request.url.encode('utf-8')).set( netloc=internal_furl.netloc, args=dict( request.args, **{ 'direct': None, 'mode': 'render', 'action': 'download', 'public_file': node.is_public, })) # Verify file verify_result = {'verify_result': '', 'verify_result_title': ''} cookie = auth.user.get_or_create_cookie() headers = {'content-type': 'application/json'} file_data_request = requests.get(file_node.generate_waterbutler_url( version=version.identifier, meta='', _internal=True), headers=headers, cookies={settings.COOKIE_NAME: cookie}) if file_data_request.status_code == 200: file_data = file_data_request.json().get('data') file_info = { 'provider': file_node.provider, 'file_id': file_node._id, 'file_name': file_data['attributes'].get('name'), 'file_path': file_data['attributes'].get('materialized'), 'size': file_data['attributes'].get('size'), 'created': file_data['attributes'].get('created_utc'), 'modified': file_data['attributes'].get('modified_utc'), 'version': '' } if file_node.provider == 'osfstorage': file_info['version'] = file_data['attributes']['extra'].get( 'version') verify_result = timestamp.check_file_timestamp(auth.user.id, node, file_info) mfr_url = get_mfr_url(node, file_node.provider) render_url = furl.furl(mfr_url).set(path=['render'], args={'url': download_url.url}) ret.update({ 'urls': { 'render': render_url.url, 'mfr': mfr_url, 'sharejs': wiki_settings.SHAREJS_URL, 'profile_image': get_profile_image_url(auth.user, 25), 'files': node.web_url_for('collect_file_trees'), 'archived_from': get_archived_from_url(node, file_node) if node.is_registration else None, }, 'error': error, 'file_name': file_node.name, 'file_name_title': os.path.splitext(file_node.name)[0], 'file_name_ext': os.path.splitext(file_node.name)[1], 'version_id': version.identifier, 'file_path': file_node.path, 'sharejs_uuid': sharejs_uuid, 'provider': file_node.provider, 'materialized_path': file_node.materialized_path, 'extra': version.metadata.get('extra', {}), 'size': version.size if version.size is not None else 9966699, 'private': getattr(node.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 'file_guid': file_node.get_guid()._id, 'file_id': file_node._id, 'allow_comments': file_node.provider in settings.ADDONS_COMMENTABLE, 'checkout_user': file_node.checkout._id if file_node.checkout else None, 'pre_reg_checkout': is_pre_reg_checkout(node, file_node), 'timestamp_verify_result': verify_result['verify_result'], 'timestamp_verify_result_title': verify_result['verify_result_title'], }) ret.update(rubeus.collect_addon_assets(node)) return ret
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 addon_view_file(auth, node, file_node, version): # TODO: resolve circular import issue from addons.wiki import settings as wiki_settings if isinstance(version, tuple): version, error = version error = error.replace('\n', '').strip() else: error = None ret = serialize_node(node, auth, primary=True) if file_node._id + '-' + version._id not in node.file_guid_to_share_uuids: node.file_guid_to_share_uuids[file_node._id + '-' + version._id] = uuid.uuid4() node.save() if ret['user']['can_edit']: sharejs_uuid = str(node.file_guid_to_share_uuids[file_node._id + '-' + version._id]) else: sharejs_uuid = None internal_furl = furl.furl(settings.INTERNAL_DOMAIN) download_url = furl.furl(request.url).set(netloc=internal_furl.netloc, args=dict( request.args, **{ 'direct': None, 'mode': 'render', 'action': 'download', 'public_file': node.is_public, })) mfr_url = get_mfr_url(node, file_node.provider) render_url = furl.furl(mfr_url).set(path=['render'], args={'url': download_url.url}) version_names = BaseFileVersionsThrough.objects.filter( basefilenode_id=file_node.id).order_by('-fileversion_id').values_list( 'version_name', flat=True) ret.update({ 'urls': { 'render': render_url.url, 'mfr': mfr_url, 'sharejs': wiki_settings.SHAREJS_URL, 'profile_image': get_profile_image_url(auth.user, 25), 'files': node.web_url_for('collect_file_trees'), 'archived_from': get_archived_from_url(node, file_node) if node.is_registration else None, }, 'error': error, 'file_name': file_node.name, 'file_name_title': os.path.splitext(file_node.name)[0], 'file_name_ext': os.path.splitext(file_node.name)[1], 'version_id': version.identifier, 'file_path': file_node.path, 'sharejs_uuid': sharejs_uuid, 'provider': file_node.provider, 'materialized_path': file_node.materialized_path, 'extra': version.metadata.get('extra', {}), 'size': version.size if version.size is not None else 9966699, 'private': getattr(node.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 'file_guid': file_node.get_guid()._id, 'file_id': file_node._id, 'allow_comments': file_node.provider in settings.ADDONS_COMMENTABLE, 'checkout_user': file_node.checkout._id if file_node.checkout else None, 'version_names': list(version_names) }) ret.update(rubeus.collect_addon_assets(node)) return ret
def addon_view_file(auth, node, file_node, version): # TODO: resolve circular import issue from addons.wiki import settings as wiki_settings if isinstance(version, tuple): version, error = version error = error.replace('\n', '').strip() else: error = None ret = serialize_node(node, auth, primary=True) if file_node._id + '-' + version._id not in node.file_guid_to_share_uuids: node.file_guid_to_share_uuids[file_node._id + '-' + version._id] = uuid.uuid4() node.save() if ret['user']['can_edit']: sharejs_uuid = str(node.file_guid_to_share_uuids[file_node._id + '-' + version._id]) else: sharejs_uuid = None internal_furl = furl.furl(settings.INTERNAL_DOMAIN) download_url = furl.furl(request.url.encode('utf-8')).set( netloc=internal_furl.netloc, args=dict(request.args, **{ 'direct': None, 'mode': 'render', 'action': 'download', 'public_file': node.is_public, }) ) mfr_url = get_mfr_url(node, file_node.provider) render_url = furl.furl(mfr_url).set( path=['render'], args={'url': download_url.url} ) ret.update({ 'urls': { 'render': render_url.url, 'mfr': mfr_url, 'sharejs': wiki_settings.SHAREJS_URL, 'profile_image': get_profile_image_url(auth.user, 25), 'files': node.web_url_for('collect_file_trees'), 'archived_from': get_archived_from_url(node, file_node) if node.is_registration else None, }, 'error': error, 'file_name': file_node.name, 'file_name_title': os.path.splitext(file_node.name)[0], 'file_name_ext': os.path.splitext(file_node.name)[1], 'version_id': version.identifier, 'file_path': file_node.path, 'sharejs_uuid': sharejs_uuid, 'provider': file_node.provider, 'materialized_path': file_node.materialized_path, 'extra': version.metadata.get('extra', {}), 'size': version.size if version.size is not None else 9966699, 'private': getattr(node.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 'file_guid': file_node.get_guid()._id, 'file_id': file_node._id, 'allow_comments': file_node.provider in settings.ADDONS_COMMENTABLE, 'checkout_user': file_node.checkout._id if file_node.checkout else None, 'pre_reg_checkout': is_pre_reg_checkout(node, file_node), }) ret.update(rubeus.collect_addon_assets(node)) return ret