示例#1
0
def reviews_submit_notification_moderators(self, timestamp, context):
    # imports moved here to avoid AppRegistryNotReady error
    from osf.models import NotificationSubscription
    from website.profile.utils import get_profile_image_url
    from website.notifications import emails
    from website import settings

    # Get NotificationSubscription instance, which contains reference to all subscribers
    provider_subscription = NotificationSubscription.load('{}_new_pending_submissions'.format(context['reviewable'].provider._id))
    # Set message
    context['message'] = u'submitted {}.'.format(context['reviewable'].node.title)
    # Set url for profile image of the submitter
    context['profile_image_url'] = get_profile_image_url(context['referrer'])
    # Set submission url
    context['reviews_submission_url'] = '{}reviews/preprints/{}/{}'.format(settings.DOMAIN, context['reviewable'].provider._id, context['reviewable']._id)
    # Store emails to be sent to subscribers instantly (at a 5 min interval)
    emails.store_emails(provider_subscription.email_transactional.all().values_list('guids___id', flat=True),
                        'email_transactional',
                        'new_pending_submissions',
                        context['referrer'],
                        context['reviewable'].node,
                        timestamp,
                        abstract_provider=context['reviewable'].provider,
                        **context)

    # Store emails to be sent to subscribers daily
    emails.store_emails(provider_subscription.email_digest.all().values_list('guids___id', flat=True),
                        'email_digest',
                        'new_pending_submissions',
                        context['referrer'],
                        context['reviewable'].node,
                        timestamp,
                        abstract_provider=context['reviewable'].provider,
                        **context)
示例#2
0
文件: listeners.py 项目: jwalz/osf.io
def reviews_submit_notification_moderators(self, timestamp, context):
    # imports moved here to avoid AppRegistryNotReady error
    from osf.models import NotificationSubscription
    from website.profile.utils import get_profile_image_url
    from website.notifications.emails import store_emails

    resource = context['reviewable']
    provider = resource.provider

    # Set submission url
    if provider.type == 'osf.preprintprovider':
        context['reviews_submission_url'] = (
            f'{DOMAIN}reviews/preprints/{provider._id}/{resource._id}')
    elif provider.type == 'osf.registrationprovider':
        context[
            'reviews_submission_url'] = f'{DOMAIN}{resource._id}?mode=moderator'
    else:
        raise NotImplementedError(f'unsupported provider type {provider.type}')

    # Set url for profile image of the submitter
    context['profile_image_url'] = get_profile_image_url(context['referrer'])

    # Set message
    revision_id = context.get('revision_id')
    if revision_id:
        context['message'] = f'submitted updates to "{resource.title}".'
        context['reviews_submission_url'] += f'&revisionId={revision_id}'
    else:
        context['message'] = f'submitted "{resource.title}".'

    # Get NotificationSubscription instance, which contains reference to all subscribers
    provider_subscription, created = NotificationSubscription.objects.get_or_create(
        _id=f'{provider._id}_new_pending_submissions', provider=provider)

    # "transactional" subscribers receive notifications "Immediately" (i.e. at 5 minute intervals)
    # "digest" subscribers receive emails daily
    recipients_per_subscription_type = {
        'email_transactional':
        list(provider_subscription.email_transactional.all().values_list(
            'guids___id', flat=True)),
        'email_digest':
        list(provider_subscription.email_digest.all().values_list('guids___id',
                                                                  flat=True))
    }

    for subscription_type, recipient_ids in recipients_per_subscription_type.items(
    ):
        if not recipient_ids:
            continue

        store_emails(recipient_ids,
                     subscription_type,
                     'new_pending_submissions',
                     context['referrer'],
                     resource,
                     timestamp,
                     abstract_provider=provider,
                     **context)
示例#3
0
def reviews_submit_notification_moderators(self, timestamp, context):
    # imports moved here to avoid AppRegistryNotReady error
    from osf.models import NotificationSubscription
    from website.profile.utils import get_profile_image_url
    from website.notifications.emails import store_emails

    resource = context['reviewable']
    provider = resource.provider

    # Get NotificationSubscription instance, which contains reference to all subscribers
    provider_subscription, created = NotificationSubscription.objects.get_or_create(
        _id=f'{provider._id}_new_pending_submissions', provider=provider)

    # Set message
    context['message'] = f'submitted "{resource.title}".'
    # Set url for profile image of the submitter
    context['profile_image_url'] = get_profile_image_url(context['referrer'])
    # Set submission url
    if provider.type == 'osf.preprintprovider':
        url_segment = 'preprints'
        flag_suffix = ''
    elif provider.type == 'osf.registrationprovider':
        url_segment = 'registries'
        flag_suffix = '?mode=moderator'
    else:
        raise NotImplementedError(f'unsupported provider type {provider.type}')

    context[
        'reviews_submission_url'] = f'{DOMAIN}reviews/{url_segment}/{provider._id}/{resource._id}{flag_suffix}'

    email_transactional_ids = list(
        provider_subscription.email_transactional.all().values_list(
            'guids___id', flat=True))
    email_digest_ids = list(
        provider_subscription.email_digest.all().values_list('guids___id',
                                                             flat=True))

    # Store emails to be sent to subscribers instantly (at a 5 min interval)
    store_emails(email_transactional_ids,
                 'email_transactional',
                 'new_pending_submissions',
                 context['referrer'],
                 resource,
                 timestamp,
                 abstract_provider=provider,
                 **context)

    # Store emails to be sent to subscribers daily
    store_emails(email_digest_ids,
                 'email_digest',
                 'new_pending_submissions',
                 context['referrer'],
                 resource,
                 timestamp,
                 abstract_provider=provider,
                 **context)
示例#4
0
def reviews_withdraw_requests_notification_moderators(self, timestamp,
                                                      context):
    # imports moved here to avoid AppRegistryNotReady error
    from osf.models import NotificationSubscription
    from website.profile.utils import get_profile_image_url
    from website.notifications.emails import store_emails

    resource = context['reviewable']
    provider = resource.provider

    # Get NotificationSubscription instance, which contains reference to all subscribers
    provider_subscription, created = NotificationSubscription.objects.get_or_create(
        _id=f'{provider._id}_new_pending_withdraw_requests', provider=provider)

    # Set message
    context['message'] = f'has requested withdrawal of "{resource.title}".'
    # Set url for profile image of the submitter
    context['profile_image_url'] = get_profile_image_url(context['referrer'])
    # Set submission url
    context[
        'reviews_submission_url'] = f'{DOMAIN}reviews/registries/{provider._id}/{resource._id}'

    email_transactional_ids = list(
        provider_subscription.email_transactional.all().values_list(
            'guids___id', flat=True))
    email_digest_ids = list(
        provider_subscription.email_digest.all().values_list('guids___id',
                                                             flat=True))

    # Store emails to be sent to subscribers instantly (at a 5 min interval)
    store_emails(email_transactional_ids,
                 'email_transactional',
                 'new_pending_withdraw_requests',
                 context['referrer'],
                 resource,
                 timestamp,
                 abstract_provider=provider,
                 template='new_pending_submissions',
                 **context)

    # Store emails to be sent to subscribers daily
    store_emails(email_digest_ids,
                 'email_digest',
                 'new_pending_withdraw_requests',
                 context['referrer'],
                 resource,
                 timestamp,
                 abstract_provider=provider,
                 template='new_pending_submissions',
                 **context)
示例#5
0
def reviews_withdrawal_requests_notification(self, timestamp, context):
    # imports moved here to avoid AppRegistryNotReady error
    from osf.models import NotificationSubscription
    from website.notifications.emails import store_emails
    from website.profile.utils import get_profile_image_url
    from website import settings

    # Get NotificationSubscription instance, which contains reference to all subscribers
    provider_subscription = NotificationSubscription.load(
        '{}_new_pending_submissions'.format(
            context['reviewable'].provider._id))
    preprint = context['reviewable']
    preprint_word = preprint.provider.preprint_word

    # Set message
    context['message'] = u'has requested withdrawal of the {} "{}".'.format(
        preprint_word, preprint.title)
    # Set url for profile image of the submitter
    context['profile_image_url'] = get_profile_image_url(context['requester'])
    # Set submission url
    context['reviews_submission_url'] = '{}reviews/preprints/{}/{}'.format(
        settings.DOMAIN, preprint.provider._id, preprint._id)

    email_transactional_ids = list(
        provider_subscription.email_transactional.all().values_list(
            'guids___id', flat=True))
    email_digest_ids = list(
        provider_subscription.email_digest.all().values_list('guids___id',
                                                             flat=True))

    # Store emails to be sent to subscribers instantly (at a 5 min interval)
    store_emails(email_transactional_ids,
                 'email_transactional',
                 'new_pending_submissions',
                 context['requester'],
                 preprint,
                 timestamp,
                 abstract_provider=preprint.provider,
                 **context)

    # Store emails to be sent to subscribers daily
    store_emails(email_digest_ids,
                 'email_digest',
                 'new_pending_submissions',
                 context['requester'],
                 preprint,
                 timestamp,
                 abstract_provider=preprint.provider,
                 **context)
示例#6
0
def reviews_submit_notification_moderators(self, timestamp, context):
    # imports moved here to avoid AppRegistryNotReady error
    from osf.models import NotificationSubscription
    from website.profile.utils import get_profile_image_url
    from website.notifications import emails
    from website import settings

    # Get NotificationSubscription instance, which contains reference to all subscribers
    provider_subscription = NotificationSubscription.load(
        '{}_new_pending_submissions'.format(
            context['reviewable'].provider._id))
    # Set message
    context['message'] = u'submitted {}.'.format(
        context['reviewable'].node.title)
    # Set url for profile image of the submitter
    context['profile_image_url'] = get_profile_image_url(context['referrer'])
    # Set submission url
    context['reviews_submission_url'] = '{}reviews/preprints/{}/{}'.format(
        settings.DOMAIN, context['reviewable'].provider._id,
        context['reviewable']._id)
    # Store emails to be sent to subscribers instantly (at a 5 min interval)
    emails.store_emails(
        provider_subscription.email_transactional.all().values_list(
            'guids___id', flat=True),
        'email_transactional',
        'new_pending_submissions',
        context['referrer'],
        context['reviewable'].node,
        timestamp,
        abstract_provider=context['reviewable'].provider,
        **context)

    # Store emails to be sent to subscribers daily
    emails.store_emails(provider_subscription.email_digest.all().values_list(
        'guids___id', flat=True),
                        'email_digest',
                        'new_pending_submissions',
                        context['referrer'],
                        context['reviewable'].node,
                        timestamp,
                        abstract_provider=context['reviewable'].provider,
                        **context)
示例#7
0
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
示例#8
0
文件: views.py 项目: aaxelb/osf.io
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
示例#9
0
文件: views.py 项目: aaxelb/osf.io
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
示例#10
0
 def test_get_other_user_profile_image(self):
     profile_image = profile_utils.get_profile_image_url(self.user, size=25)
     assert_true(profile_image)
示例#11
0
 def test_get_other_user_profile_image_default_size(self):
     profile_image = profile_utils.get_profile_image_url(self.user)
     assert_true(profile_image)
示例#12
0
def project_wiki_view(auth, wname, path=None, **kwargs):
    node = kwargs['node'] or kwargs['project']
    anonymous = has_anonymous_link(node, auth)
    wiki_name = (wname or '').strip()
    wiki_key = to_mongo_key(wiki_name)
    wiki_page = WikiPage.objects.get_for_node(node, wiki_name)
    wiki_version = WikiVersion.objects.get_for_node(node, wiki_name)
    wiki_settings = node.get_addon('wiki')
    can_edit = (
        auth.logged_in and not
        node.is_registration and (
            node.has_permission(auth.user, 'write') or
            wiki_settings.is_publicly_editable
        )
    )
    versions = _get_wiki_versions(node, wiki_name, anonymous=anonymous)

    # Determine panels used in view
    panels = {'view', 'edit', 'compare', 'menu'}
    if request.args and set(request.args).intersection(panels):
        panels_used = [panel for panel in request.args if panel in panels]
        num_columns = len(set(panels_used).intersection({'view', 'edit', 'compare'}))
        if num_columns == 0:
            panels_used.append('view')
            num_columns = 1
    else:
        panels_used = ['view', 'menu']
        num_columns = 1

    try:
        view = wiki_utils.format_wiki_version(
            version=request.args.get('view'),
            num_versions=len(versions),
            allow_preview=True,
        )
        compare = wiki_utils.format_wiki_version(
            version=request.args.get('compare'),
            num_versions=len(versions),
            allow_preview=False,
        )
    except InvalidVersionError:
        raise WIKI_INVALID_VERSION_ERROR

    # ensure home is always lower case since it cannot be renamed
    if wiki_name.lower() == 'home':
        wiki_name = 'home'

    if wiki_version:
        version = wiki_version.identifier
        is_current = wiki_version.is_current
        content = wiki_version.html(node)
        rendered_before_update = wiki_version.rendered_before_update
    else:
        version = 'NA'
        is_current = False
        content = ''
        rendered_before_update = False

    if can_edit:
        if wiki_key not in node.wiki_private_uuids:
            wiki_utils.generate_private_uuid(node, wiki_name)
        sharejs_uuid = wiki_utils.get_sharejs_uuid(node, wiki_name)
    else:
        if not wiki_page and wiki_key != 'home':
            raise WIKI_PAGE_NOT_FOUND_ERROR
        if 'edit' in request.args:
            if wiki_settings.is_publicly_editable:
                raise HTTPError(http.UNAUTHORIZED)
            if node.can_view(auth):
                return redirect(node.web_url_for('project_wiki_view', wname=wname, _guid=True))
            raise HTTPError(http.FORBIDDEN)
        sharejs_uuid = None

    # Opens 'edit' panel when home wiki is empty
    if not content and can_edit and wiki_name == 'home':
        panels_used.append('edit')

    # Default versions for view and compare
    version_settings = {
        'view': view or ('preview' if 'edit' in panels_used else 'current'),
        'compare': compare or 'previous',
    }

    ret = {
        'wiki_id': wiki_page._primary_key if wiki_page else None,
        'wiki_name': wiki_page.page_name if wiki_page else wiki_name,
        'wiki_content': content,
        'rendered_before_update': rendered_before_update,
        'page': wiki_page,
        'version': version,
        'versions': versions,
        'sharejs_uuid': sharejs_uuid or '',
        'sharejs_url': settings.SHAREJS_URL,
        'is_current': is_current,
        'version_settings': version_settings,
        'pages_current': _get_wiki_pages_latest(node),
        'category': node.category,
        'panels_used': panels_used,
        'num_columns': num_columns,
        'urls': {
            'api': _get_wiki_api_urls(node, wiki_name, {
                'content': node.api_url_for('wiki_page_content', wname=wiki_name),
                'draft': node.api_url_for('wiki_page_draft', wname=wiki_name),
            }),
            'web': _get_wiki_web_urls(node, wiki_name),
            'profile_image': get_profile_image_url(auth.user, 25),
        },
    }
    ret.update(_view_project(node, auth, primary=True))
    ret['user']['can_edit_wiki_body'] = can_edit
    return ret
示例#13
0
 def test_get_other_user_profile_image(self):
     profile_image = profile_utils.get_profile_image_url(self.user, size=25)
     assert_true(profile_image)
示例#14
0
 def test_get_other_user_profile_image_default_size(self):
     profile_image = profile_utils.get_profile_image_url(self.user)
     assert_true(profile_image)
示例#15
0
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
示例#16
0
def project_wiki_view(auth, wname, path=None, **kwargs):
    node = kwargs['node'] or kwargs['project']
    anonymous = has_anonymous_link(node, auth)
    wiki_name = (wname or '').strip()
    wiki_key = to_mongo_key(wiki_name)
    wiki_page = node.get_wiki_page(wiki_name)
    wiki_version = node.get_wiki_version(wiki_name)
    wiki_settings = node.get_addon('wiki')
    can_edit = (auth.logged_in and not node.is_registration
                and (node.has_permission(auth.user, 'write')
                     or wiki_settings.is_publicly_editable))
    versions = _get_wiki_versions(node, wiki_name, anonymous=anonymous)

    # Determine panels used in view
    panels = {'view', 'edit', 'compare', 'menu'}
    if request.args and set(request.args).intersection(panels):
        panels_used = [panel for panel in request.args if panel in panels]
        num_columns = len(
            set(panels_used).intersection({'view', 'edit', 'compare'}))
        if num_columns == 0:
            panels_used.append('view')
            num_columns = 1
    else:
        panels_used = ['view', 'menu']
        num_columns = 1

    try:
        view = wiki_utils.format_wiki_version(
            version=request.args.get('view'),
            num_versions=len(versions),
            allow_preview=True,
        )
        compare = wiki_utils.format_wiki_version(
            version=request.args.get('compare'),
            num_versions=len(versions),
            allow_preview=False,
        )
    except InvalidVersionError:
        raise WIKI_INVALID_VERSION_ERROR

    # ensure home is always lower case since it cannot be renamed
    if wiki_name.lower() == 'home':
        wiki_name = 'home'

    if wiki_version:
        version = wiki_version.identifier
        is_current = wiki_version.is_current
        content = wiki_version.html(node)
        rendered_before_update = wiki_version.rendered_before_update
    else:
        version = 'NA'
        is_current = False
        content = ''
        rendered_before_update = False

    if can_edit:
        if wiki_key not in node.wiki_private_uuids:
            wiki_utils.generate_private_uuid(node, wiki_name)
        sharejs_uuid = wiki_utils.get_sharejs_uuid(node, wiki_name)
    else:
        if not wiki_page and wiki_key != 'home':
            raise WIKI_PAGE_NOT_FOUND_ERROR
        if 'edit' in request.args:
            if wiki_settings.is_publicly_editable:
                raise HTTPError(http.UNAUTHORIZED)
            if node.can_view(auth):
                return redirect(
                    node.web_url_for('project_wiki_view',
                                     wname=wname,
                                     _guid=True))
            raise HTTPError(http.FORBIDDEN)
        sharejs_uuid = None

    # Opens 'edit' panel when home wiki is empty
    if not content and can_edit and wiki_name == 'home':
        panels_used.append('edit')

    # Default versions for view and compare
    version_settings = {
        'view': view or ('preview' if 'edit' in panels_used else 'current'),
        'compare': compare or 'previous',
    }

    ret = {
        'wiki_id': wiki_page._primary_key if wiki_page else None,
        'wiki_name': wiki_page.page_name if wiki_page else wiki_name,
        'wiki_content': content,
        'rendered_before_update': rendered_before_update,
        'page': wiki_page,
        'version': version,
        'versions': versions,
        'sharejs_uuid': sharejs_uuid or '',
        'sharejs_url': settings.SHAREJS_URL,
        'is_current': is_current,
        'version_settings': version_settings,
        'pages_current': _get_wiki_pages_latest(node),
        'category': node.category,
        'panels_used': panels_used,
        'num_columns': num_columns,
        'urls': {
            'api':
            _get_wiki_api_urls(
                node, wiki_name, {
                    'content':
                    node.api_url_for('wiki_page_content', wname=wiki_name),
                    'draft':
                    node.api_url_for('wiki_page_draft', wname=wiki_name),
                }),
            'web':
            _get_wiki_web_urls(node, wiki_name),
            'profile_image':
            get_profile_image_url(auth.user, 25),
        },
    }
    ret.update(_view_project(node, auth, primary=True))
    ret['user']['can_edit_wiki_body'] = can_edit
    return ret
示例#17
0
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