Example #1
0
        def wrapper(request, addon, *args, **kw):
            if theme:
                kw['theme'] = addon.is_persona()
            elif addon.is_persona():
                # Don't allow theme views if theme not passed in.
                raise http.Http404

            def fun():
                return f(request, addon_id=addon.id, addon=addon, *args, **kw)

            if allow_reviewers:
                if acl.is_reviewer(request, addon):
                    return fun()
            # Require an owner or dev for POST requests.
            if request.method == 'POST':
                if acl.check_addon_ownership(request, addon,
                                             dev=not owner_for_post):
                    return fun()
            # Ignore disabled so they can view their add-on.
            elif acl.check_addon_ownership(request, addon, dev=True,
                                           ignore_disabled=True):
                # Redirect to the submit flow if they're not done.
                if (not submitting and addon.should_redirect_to_submit_flow()):
                    return redirect('devhub.submit.details', addon.slug)
                return fun()
            raise PermissionDenied
Example #2
0
        def wrapper(request, addon, *args, **kw):
            def fun():
                return f(request, addon_id=addon.id, addon=addon, *args, **kw)

            if request.method in ('HEAD', 'GET'):
                # Allow reviewers for read operations.
                if allow_reviewers_for_read and (acl.is_reviewer(
                        request, addon) or acl.action_allowed(
                            request, permissions.REVIEWER_TOOLS_VIEW)):
                    return fun()
                # On read-only requests, ignore disabled so developers can
                # still view their add-on.
                if acl.check_addon_ownership(request,
                                             addon,
                                             dev=not owner_for_get,
                                             ignore_disabled=True):
                    # Redirect to the submit flow if they're not done.
                    if (not submitting
                            and addon.should_redirect_to_submit_flow()):
                        return redirect('devhub.submit.details', addon.slug)
                    return fun()
            # Require an owner or dev for POST requests (if the add-on status
            # is disabled that check will return False).
            elif request.method == 'POST':
                if acl.check_addon_ownership(request,
                                             addon,
                                             dev=not owner_for_post):
                    return fun()
            raise PermissionDenied
Example #3
0
def setup_viewer(request, file_obj):
    addon = file_obj.version.addon
    data = {
        'file': file_obj,
        'version': file_obj.version,
        'addon': addon,
        'status': False,
        'selected': {},
        'validate_url': ''
    }
    is_user_a_reviewer = acl.is_reviewer(request, addon)

    if (is_user_a_reviewer or acl.check_addon_ownership(
            request, addon, dev=True, ignore_disabled=True)):

        data['validate_url'] = reverse('devhub.json_file_validation',
                                       args=[addon.slug, file_obj.id])
        data['automated_signing'] = file_obj.automated_signing

        if file_obj.has_been_validated:
            data['validation_data'] = file_obj.validation.processed_validation

    if is_user_a_reviewer:
        data['file_link'] = {
            'text': ugettext('Back to review'),
            'url': reverse('reviewers.review', args=[addon.slug])
        }
    else:
        data['file_link'] = {
            'text': ugettext('Back to add-on'),
            'url': reverse('addons.detail', args=[addon.pk])
        }
    return data
Example #4
0
        def wrapper(request, addon, *args, **kw):
            if theme:
                kw['theme'] = addon.is_persona()
            elif addon.is_persona():
                # Don't allow theme views if theme not passed in.
                raise http.Http404

            def fun():
                return f(request, addon_id=addon.id, addon=addon, *args, **kw)

            if allow_reviewers:
                if acl.is_reviewer(request, addon):
                    return fun()
            # Require an owner or dev for POST requests.
            if request.method == 'POST':
                if acl.check_addon_ownership(request,
                                             addon,
                                             dev=not owner_for_post):
                    return fun()
            # Ignore disabled so they can view their add-on.
            elif acl.check_addon_ownership(request,
                                           addon,
                                           viewer=True,
                                           ignore_disabled=True):
                # Redirect to the submit flow if they're not done.
                if (not submitting and addon.should_redirect_to_submit_flow()):
                    return redirect('devhub.submit.details', addon.slug)
                return fun()
            raise PermissionDenied
Example #5
0
def setup_viewer(request, file_obj):
    addon = file_obj.version.addon
    data = {
        'file': file_obj,
        'version': file_obj.version,
        'addon': addon,
        'status': False,
        'selected': {},
        'validate_url': ''
    }
    is_user_a_reviewer = acl.is_reviewer(request, addon)

    if (is_user_a_reviewer or acl.check_addon_ownership(
            request, addon, dev=True, ignore_disabled=True)):

        data['validate_url'] = reverse('devhub.json_file_validation',
                                       args=[addon.slug, file_obj.id])
        data['automated_signing'] = file_obj.automated_signing

        if file_obj.has_been_validated:
            data['validation_data'] = file_obj.validation.processed_validation

    if is_user_a_reviewer:
        data['file_link'] = {
            'text': ugettext('Back to review'),
            'url': reverse('reviewers.review', args=[addon.slug])
        }
    else:
        data['file_link'] = {
            'text': ugettext('Back to add-on'),
            'url': reverse('addons.detail', args=[addon.pk])
        }
    return data
    def has_object_permission(self, request, view, obj):
        can_access_because_viewer = (
            request.method in SAFE_METHODS
            and acl.action_allowed(request, permissions.REVIEWER_TOOLS_VIEW))
        can_access_because_listed_reviewer = obj.has_listed_versions(
            include_deleted=True) and acl.is_reviewer(request, obj)

        return can_access_because_viewer or can_access_because_listed_reviewer
Example #7
0
    def has_object_permission(self, request, view, obj):
        can_access_because_viewer = (
            request.method in SAFE_METHODS and
            acl.action_allowed(request, permissions.REVIEWER_TOOLS_VIEW))
        can_access_because_listed_reviewer = (
            obj.has_listed_versions() and acl.is_reviewer(request, obj))

        return can_access_because_viewer or can_access_because_listed_reviewer
Example #8
0
def review_list(request, addon, review_id=None, user_id=None):
    qs = Review.without_replies.all().filter(addon=addon).order_by('-created')

    ctx = {'addon': addon, 'grouped_ratings': GroupedRating.get(addon.id)}

    ctx['form'] = forms.ReviewForm(None)
    is_admin = acl.action_allowed(request, amo.permissions.ADDONS_EDIT)

    if review_id is not None:
        ctx['page'] = 'detail'
        # If this is a dev reply, find the first msg for context.
        review = get_object_or_404(Review.objects.all(), pk=review_id)
        if review.reply_to_id:
            review_id = review.reply_to_id
            ctx['reply'] = review
        qs = qs.filter(pk=review_id)
    elif user_id is not None:
        ctx['page'] = 'user'
        qs = qs.filter(user=user_id)
        if not qs:
            raise http.Http404()
    else:
        ctx['page'] = 'list'
        qs = qs.filter(is_latest=True)
        # Don't filter out empty reviews for admins.
        if not is_admin:
            # But otherwise, filter out everyone elses empty reviews.
            user_filter = (Q(user=request.user.pk)
                           if request.user.is_authenticated() else Q())
            qs = qs.filter(~Q(body=None) | user_filter)

    ctx['reviews'] = reviews = paginate(request, qs)
    ctx['replies'] = Review.get_replies(reviews.object_list)
    if request.user.is_authenticated():
        ctx['review_perms'] = {
            'is_admin':
            is_admin,
            'is_reviewer':
            acl.is_reviewer(request, addon),
            'is_author':
            acl.check_addon_ownership(request,
                                      addon,
                                      viewer=True,
                                      dev=True,
                                      support=True),
        }
        ctx['flags'] = get_flags(request, reviews.object_list)
    else:
        ctx['review_perms'] = {}
    return render(request, 'reviews/review_list.html', ctx)
Example #9
0
def user_can_delete_review(request, review):
    """Return whether or not the request.user can delete reviews.

    People who can delete reviews:
      * The original review author.
      * Reviewers, but only if they aren't listed as an author of the add-on
        and the add-on is flagged for moderation
      * Users in a group with "Users:Edit" privileges.
      * Users in a group with "Addons:Edit" privileges.

    Persona reviewers can't delete addons reviews.

    """
    is_author = review.addon.has_author(request.user)
    return (
        review.user_id == request.user.id or
        not is_author and (
            (acl.is_reviewer(request, review.addon) and review.editorreview) or
            acl.action_allowed(request, amo.permissions.USERS_EDIT) or
            acl.action_allowed(request, amo.permissions.ADDONS_EDIT)))
Example #10
0
def allowed(request, file):
    try:
        version = file.version
        addon = version.addon
    except ObjectDoesNotExist:
        raise http.Http404

    # General case: addon is listed.
    if version.channel == amo.RELEASE_CHANNEL_LISTED:
        # We don't show the file-browser publicly because of potential DOS
        # issues, we're working on a fix but for now, let's not do this.
        # (cgrebs, 06042017)
        is_owner = acl.check_addon_ownership(request, addon, dev=True)
        if (acl.is_reviewer(request, addon) or is_owner):
            return True  # Public and sources are visible, or reviewer.
        raise PermissionDenied  # Listed but not allowed.
    # Not listed? Needs an owner or an "unlisted" admin.
    else:
        if owner_or_unlisted_reviewer(request, addon):
            return True
    raise http.Http404  # Not listed, not owner or admin.
def allowed(request, file):
    try:
        version = file.version
        addon = version.addon
    except ObjectDoesNotExist:
        raise http.Http404

    # General case: addon is listed.
    if version.channel == amo.RELEASE_CHANNEL_LISTED:
        # We don't show the file-browser publicly because of potential DOS
        # issues, we're working on a fix but for now, let's not do this.
        # (cgrebs, 06042017)
        is_owner = acl.check_addon_ownership(request, addon, dev=True)
        if (acl.is_reviewer(request, addon) or is_owner):
            return True  # Public and sources are visible, or reviewer.
        raise PermissionDenied  # Listed but not allowed.
    # Not listed? Needs an owner or an "unlisted" admin.
    else:
        if owner_or_unlisted_reviewer(request, addon):
            return True
    raise http.Http404  # Not listed, not owner or admin.
Example #12
0
    def get_actions(self, request):
        actions = OrderedDict()
        if request is None:
            # If request is not set, it means we are just (ab)using the
            # ReviewHelper for its `handler` attribute and we don't care about
            # the actions.
            return actions

        # 2 kind of checks are made for the review page.
        # - Base permission checks to access the review page itself, done in
        #   the review() view
        # - A more specific check for each action, done below, restricting
        #   their availability while not affecting whether the user can see
        #   the review page or not.
        permission = None
        version_is_unlisted = (self.version and self.version.channel
                               == amo.RELEASE_CHANNEL_UNLISTED)
        try:
            is_recommendable = self.addon.discoveryitem.recommendable
        except DiscoveryItem.DoesNotExist:
            is_recommendable = False
        current_version_is_listed_and_auto_approved = (
            self.version and self.version.channel == amo.RELEASE_CHANNEL_LISTED
            and self.addon.current_version
            and self.addon.current_version.was_auto_approved)

        if is_recommendable:
            is_admin_needed = (self.addon.needs_admin_content_review
                               or self.addon.needs_admin_code_review)
            permission = amo.permissions.ADDONS_RECOMMENDED_REVIEW
        elif self.content_review:
            is_admin_needed = self.addon.needs_admin_content_review
            permission = amo.permissions.ADDONS_CONTENT_REVIEW
        elif version_is_unlisted:
            is_admin_needed = self.addon.needs_admin_code_review
            permission = amo.permissions.ADDONS_REVIEW_UNLISTED
        elif self.addon.type == amo.ADDON_STATICTHEME:
            is_admin_needed = self.addon.needs_admin_theme_review
            permission = amo.permissions.STATIC_THEMES_REVIEW
        elif current_version_is_listed_and_auto_approved:
            is_admin_needed = (self.addon.needs_admin_content_review
                               or self.addon.needs_admin_code_review)
            permission = amo.permissions.ADDONS_POST_REVIEW
        else:
            is_admin_needed = (self.addon.needs_admin_content_review
                               or self.addon.needs_admin_code_review)
            permission = amo.permissions.ADDONS_REVIEW

        assert permission is not None

        if is_admin_needed:
            permission = amo.permissions.REVIEWS_ADMIN

        # Is the current user a reviewer for this kind of add-on ?
        is_reviewer = acl.is_reviewer(request, self.addon)

        # Is the current user an appropriate reviewer, noy only for this kind
        # of add-on, but also for the state the add-on is in ? (Allows more
        # impactful actions).
        is_appropriate_reviewer = acl.action_allowed_user(
            request.user, permission)

        # Special logic for availability of reject multiple action:
        if (self.content_review or is_recommendable
                or self.addon.type == amo.ADDON_STATICTHEME):
            can_reject_multiple = is_appropriate_reviewer
        else:
            # When doing a code review, this action is also available to
            # users with Addons:PostReview even if the current version hasn't
            # been auto-approved, provided that the add-on isn't marked as
            # needing admin review.
            can_reject_multiple = (
                is_appropriate_reviewer or (acl.action_allowed_user(
                    request.user, amo.permissions.ADDONS_POST_REVIEW)
                                            and not is_admin_needed))

        addon_is_complete = self.addon.status not in (amo.STATUS_NULL,
                                                      amo.STATUS_DELETED)
        version_is_unreviewed = self.version and self.version.is_unreviewed
        addon_is_valid = self.addon.is_public() or self.addon.is_unreviewed()
        addon_is_valid_and_version_is_listed = (addon_is_valid and self.version
                                                and self.version.channel
                                                == amo.RELEASE_CHANNEL_LISTED)

        # Definitions for all actions.
        actions['public'] = {
            'method':
            self.handler.process_public,
            'minimal':
            False,
            'details':
            _('This will approve, sign, and publish this '
              'version. The comments will be sent to the '
              'developer.'),
            'label':
            _('Approve'),
            'available':
            (not self.content_review and addon_is_complete
             and version_is_unreviewed and is_appropriate_reviewer)
        }
        actions['reject'] = {
            'method':
            self.handler.process_sandbox,
            'label':
            _('Reject'),
            'details':
            _('This will reject this version and remove it '
              'from the queue. The comments will be sent '
              'to the developer.'),
            'minimal':
            False,
            'available':
            (not self.content_review and addon_is_complete
             and version_is_unreviewed and is_appropriate_reviewer)
        }
        actions['approve_content'] = {
            'method':
            self.handler.approve_content,
            'label':
            _('Approve Content'),
            'details':
            _('This records your approbation of the '
              'content of the latest public version, '
              'without notifying the developer.'),
            'minimal':
            False,
            'comments':
            False,
            'available':
            (self.content_review and addon_is_valid_and_version_is_listed
             and is_appropriate_reviewer),
        }
        actions['confirm_auto_approved'] = {
            'method':
            self.handler.confirm_auto_approved,
            'label':
            _('Confirm Approval'),
            'details':
            _('The latest public version of this add-on was '
              'automatically approved. This records your '
              'confirmation of the approval of that version, '
              'without notifying the developer.'),
            'minimal':
            True,
            'comments':
            False,
            'available':
            (not self.content_review and addon_is_valid_and_version_is_listed
             and current_version_is_listed_and_auto_approved
             and is_appropriate_reviewer),
        }
        actions['reject_multiple_versions'] = {
            'method':
            self.handler.reject_multiple_versions,
            'label':
            _('Reject Multiple Versions'),
            'minimal':
            True,
            'versions':
            True,
            'details':
            _('This will reject the selected public '
              'versions. The comments will be sent to the '
              'developer.'),
            'available': (addon_is_valid_and_version_is_listed
                          and can_reject_multiple),
        }
        actions['block_multiple_versions'] = {
            'method':
            self.handler.reject_multiple_versions,
            'label':
            _('Block Multiple Versions'),
            'minimal':
            True,
            'versions':
            True,
            'comments':
            False,
            'details':
            _('This will disable the selected approved '
              'versions silently, and open up the block creation '
              'admin page.'),
            'available': (self.addon.type != amo.ADDON_STATICTHEME
                          and version_is_unlisted and is_appropriate_reviewer),
        }
        actions['confirm_multiple_versions'] = {
            'method':
            self.handler.confirm_multiple_versions,
            'label':
            _('Confirm Multiple Versions'),
            'minimal':
            True,
            'versions':
            True,
            'details':
            _('This will confirm approval of the selected '
              'versions without notifying the developer.'),
            'comments':
            False,
            'available': (self.addon.type != amo.ADDON_STATICTHEME
                          and version_is_unlisted and is_appropriate_reviewer),
        }
        actions['reply'] = {
            'method':
            self.handler.reviewer_reply,
            'label':
            _('Reviewer reply'),
            'details':
            _('This will send a message to the developer. '
              'You will be notified when they reply.'),
            'minimal':
            True,
            'available': (self.version is not None and is_reviewer)
        }
        actions['super'] = {
            'method':
            self.handler.process_super_review,
            'label':
            _('Request super-review'),
            'details':
            _('If you have concerns about this add-on that '
              'an admin reviewer should look into, enter '
              'your comments in the area below. They will '
              'not be sent to the developer.'),
            'minimal':
            True,
            'available': (self.version is not None and is_reviewer)
        }
        actions['comment'] = {
            'method':
            self.handler.process_comment,
            'label':
            _('Comment'),
            'details':
            _('Make a comment on this version. The developer '
              'won\'t be able to see this.'),
            'minimal':
            True,
            'available': (is_reviewer)
        }

        return OrderedDict(((key, action) for key, action in actions.items()
                            if action['available']))
Example #13
0
 def is_appropriate_reviewer(addon, channel):
     return (acl.is_reviewer(request, addon)
             if channel == amo.RELEASE_CHANNEL_LISTED else
             acl.check_unlisted_addons_reviewer(request))
Example #14
0
    def get_actions(self, request):
        actions = OrderedDict()
        if request is None:
            # If request is not set, it means we are just (ab)using the
            # ReviewHelper for its `handler` attribute and we don't care about
            # the actions.
            return actions

        # 2 kind of checks are made for the review page.
        # - Base permission checks to access the review page itself, done in
        #   the review() view
        # - A more specific check for each action, done below, restricting
        #   their availability while not affecting whether the user can see
        #   the review page or not.
        version_is_unlisted = (self.version and self.version.channel
                               == amo.RELEASE_CHANNEL_UNLISTED)
        promoted_group = self.addon.promoted_group(currently_approved=False)

        # Default permissions / admin needed values if it's just a regular
        # code review, nothing fancy.
        permission = amo.permissions.ADDONS_REVIEW
        permission_post_review = amo.permissions.ADDONS_REVIEW
        is_admin_needed = (self.addon.needs_admin_content_review
                           or self.addon.needs_admin_code_review)
        is_admin_needed_post_review = is_admin_needed

        # More complex/specific cases.
        if promoted_group == RECOMMENDED:
            permission = amo.permissions.ADDONS_RECOMMENDED_REVIEW
            permission_post_review = permission
        elif version_is_unlisted:
            is_admin_needed = self.addon.needs_admin_code_review
            permission = amo.permissions.ADDONS_REVIEW_UNLISTED
            permission_post_review = permission
        elif promoted_group.admin_review:
            is_admin_needed = is_admin_needed_post_review = True
        elif self.content_review:
            is_admin_needed = self.addon.needs_admin_content_review
            permission = amo.permissions.ADDONS_CONTENT_REVIEW
        elif self.addon.type == amo.ADDON_STATICTHEME:
            is_admin_needed = self.addon.needs_admin_theme_review
            permission = amo.permissions.STATIC_THEMES_REVIEW
            permission_post_review = permission

        # In addition, if the latest (or current for post-review) version is
        # pending rejection, an admin is needed.
        if self.version and self.version.pending_rejection:
            is_admin_needed = True
        if (self.addon.current_version
                and self.addon.current_version.pending_rejection):
            is_admin_needed_post_review = True

        # Whatever permission values we set, we override if an admin is needed.
        if is_admin_needed:
            permission = amo.permissions.REVIEWS_ADMIN
        if is_admin_needed_post_review:
            permission_post_review = amo.permissions.REVIEWS_ADMIN

        # Is the current user a reviewer for this kind of add-on ?
        is_reviewer = acl.is_reviewer(request, self.addon)

        # Is the current user an appropriate reviewer, not only for this kind
        # of add-on, but also for the state the add-on is in ? (Allows more
        # impactful actions).
        is_appropriate_reviewer = acl.action_allowed_user(
            request.user, permission)
        is_appropriate_reviewer_post_review = acl.action_allowed_user(
            request.user, permission_post_review)

        addon_is_complete = self.addon.status not in (amo.STATUS_NULL,
                                                      amo.STATUS_DELETED)
        addon_is_incomplete_and_version_is_unlisted = (self.addon.status
                                                       == amo.STATUS_NULL
                                                       and version_is_unlisted)
        addon_is_reviewable = (addon_is_complete
                               or addon_is_incomplete_and_version_is_unlisted)
        version_is_unreviewed = self.version and self.version.is_unreviewed
        addon_is_valid = self.addon.is_public() or self.addon.is_unreviewed()
        addon_is_valid_and_version_is_listed = (addon_is_valid and self.version
                                                and self.version.channel
                                                == amo.RELEASE_CHANNEL_LISTED)
        current_version_is_listed_and_auto_approved = (
            self.version and self.version.channel == amo.RELEASE_CHANNEL_LISTED
            and self.addon.current_version
            and self.addon.current_version.was_auto_approved)
        version_is_blocked = self.version and self.version.is_blocked

        promoted_subscription_okay = (
            not promoted_group
            or not self.addon.promotedaddon.has_pending_subscription)

        # Special logic for availability of reject multiple action:
        if version_is_unlisted:
            can_reject_multiple = is_appropriate_reviewer
        elif (self.content_review or promoted_group.pre_review
              or self.addon.type == amo.ADDON_STATICTHEME):
            can_reject_multiple = (addon_is_valid_and_version_is_listed
                                   and is_appropriate_reviewer)
        else:
            # When doing a code review, this action is also available to
            # users with Addons:PostReview even if the current version hasn't
            # been auto-approved, provided that the add-on isn't marked as
            # needing admin review.
            can_reject_multiple = addon_is_valid_and_version_is_listed and (
                is_appropriate_reviewer or is_appropriate_reviewer_post_review)

        # Definitions for all actions.
        actions['public'] = {
            'method':
            self.handler.approve_latest_version,
            'minimal':
            False,
            'details':
            _('This will approve, sign, and publish this '
              'version. The comments will be sent to the '
              'developer.'),
            'label':
            _('Approve'),
            'available':
            (not self.content_review and addon_is_reviewable
             and version_is_unreviewed and is_appropriate_reviewer
             and not version_is_blocked and promoted_subscription_okay)
        }
        actions['reject'] = {
            'method':
            self.handler.reject_latest_version,
            'label':
            _('Reject'),
            'details':
            _('This will reject this version and remove it '
              'from the queue. The comments will be sent '
              'to the developer.'),
            'minimal':
            False,
            'available': (
                not self.content_review and
                # We specifically don't let the individual reject action be
                # available for unlisted review. `reject_latest_version` isn't
                # currently implemented for unlisted.
                addon_is_valid_and_version_is_listed and
                version_is_unreviewed and is_appropriate_reviewer)
        }
        actions['approve_content'] = {
            'method':
            self.handler.approve_content,
            'label':
            _('Approve Content'),
            'details':
            _('This records your approbation of the '
              'content of the latest public version, '
              'without notifying the developer.'),
            'minimal':
            False,
            'comments':
            False,
            'available':
            (self.content_review and addon_is_valid_and_version_is_listed
             and is_appropriate_reviewer),
        }
        actions['confirm_auto_approved'] = {
            'method':
            self.handler.confirm_auto_approved,
            'label':
            _('Confirm Approval'),
            'details':
            _('The latest public version of this add-on was '
              'automatically approved. This records your '
              'confirmation of the approval of that version, '
              'without notifying the developer.'),
            'minimal':
            True,
            'comments':
            False,
            'available':
            (not self.content_review and addon_is_valid_and_version_is_listed
             and current_version_is_listed_and_auto_approved
             and is_appropriate_reviewer_post_review),
        }
        actions['reject_multiple_versions'] = {
            'method':
            self.handler.reject_multiple_versions,
            'label':
            _('Reject Multiple Versions'),
            'minimal':
            True,
            'delayable':
            not version_is_unlisted,
            'versions':
            True,
            'details':
            _('This will reject the selected versions. '
              'The comments will be sent to the developer.'),
            'available': (can_reject_multiple),
        }
        actions['block_multiple_versions'] = {
            'method':
            self.handler.block_multiple_versions,
            'label':
            _('Block Multiple Versions'),
            'minimal':
            True,
            'versions':
            True,
            'comments':
            False,
            'details':
            _('This will disable the selected approved '
              'versions silently, and open up the block creation '
              'admin page.'),
            'available': (self.addon.type != amo.ADDON_STATICTHEME
                          and version_is_unlisted and is_appropriate_reviewer),
        }
        actions['confirm_multiple_versions'] = {
            'method':
            self.handler.confirm_multiple_versions,
            'label':
            _('Confirm Multiple Versions'),
            'minimal':
            True,
            'versions':
            True,
            'details':
            _('This will confirm approval of the selected '
              'versions without notifying the developer.'),
            'comments':
            False,
            'available': (self.addon.type != amo.ADDON_STATICTHEME
                          and version_is_unlisted and is_appropriate_reviewer),
        }
        actions['reply'] = {
            'method':
            self.handler.reviewer_reply,
            'label':
            _('Reviewer reply'),
            'details':
            _('This will send a message to the developer. '
              'You will be notified when they reply.'),
            'minimal':
            True,
            'available':
            (self.version is not None and is_reviewer
             and (not promoted_group.admin_review or is_appropriate_reviewer))
        }
        actions['super'] = {
            'method':
            self.handler.process_super_review,
            'label':
            _('Request super-review'),
            'details':
            _('If you have concerns about this add-on that '
              'an admin reviewer should look into, enter '
              'your comments in the area below. They will '
              'not be sent to the developer.'),
            'minimal':
            True,
            'available': (self.version is not None and is_reviewer)
        }
        actions['comment'] = {
            'method':
            self.handler.process_comment,
            'label':
            _('Comment'),
            'details':
            _('Make a comment on this version. The developer '
              'won\'t be able to see this.'),
            'minimal':
            True,
            'available': (is_reviewer)
        }

        return OrderedDict(((key, action) for key, action in actions.items()
                            if action['available']))
Example #15
0
 def is_appropriate_reviewer(addon, channel):
     return (acl.is_reviewer(request, addon)
             if channel == amo.RELEASE_CHANNEL_LISTED
             else acl.check_unlisted_addons_reviewer(request))