Esempio n. 1
0
def check_stats_permission(request, addon, for_contributions=False,
                           no_raise=False):
    """
    Check if user is allowed to view stats for ``addon``.

    no_raise -- if enabled function returns true or false
                else function raises PermissionDenied
                if user is not allowed.
    """
    # If public, non-contributions: everybody can view.
    if addon.public_stats and not for_contributions:
        return True

    # Everything else requires an authenticated user.
    if not request.user.is_authenticated():
        if no_raise:
            return False
        raise PermissionDenied

    if not for_contributions:
        # Only authors and Stats Viewers allowed.
        if (addon.has_author(request.amo_user) or
            acl.action_allowed(request, 'Stats', 'View')):
            return True

    else:  # For contribution stats.
        # Only authors and Contribution Stats Viewers.
        if (addon.has_author(request.amo_user) or
            acl.action_allowed(request, 'RevenueStats', 'View')):
            return True

    if no_raise:
        return False
    raise PermissionDenied
Esempio n. 2
0
    def get_list(self, request=None, **kwargs):
        form = ApiSearchForm(request.GET if request else None)
        if not form.is_valid():
            raise self.form_errors(form)

        # Pluck out status first since it forms part of the base query, but
        # only for privileged users.
        status = form.cleaned_data['status']
        if status != amo.STATUS_PUBLIC and not (
            acl.action_allowed(request, 'Apps', 'Review') or
            acl.action_allowed(request, 'Admin', '%')):
            return http.HttpUnauthorized(
                content=json.dumps(
                    {'reason': 'Unauthorized to filter by status.'}))

        # Search specific processing of the results.
        region = getattr(request, 'REGION', mkt.regions.WORLDWIDE)
        qs = _get_query(region, gaia=request.GAIA, mobile=request.MOBILE,
                        tablet=request.TABLET, status=status)
        qs = _filter_search(request, qs, form.cleaned_data, region=region)
        paginator = self._meta.paginator_class(request.GET, qs,
            resource_uri=self.get_resource_list_uri(),
            limit=self._meta.limit)
        page = paginator.page()

        # Rehydrate the results as per tastypie.
        objs = [self.build_bundle(obj=obj, request=request)
                for obj in page['objects']]
        page['objects'] = [self.full_dehydrate(bundle) for bundle in objs]
        # This isn't as quite a full as a full TastyPie meta object,
        # but at least it's namespaced that way and ready to expand.
        return self.create_response(request, page)
Esempio n. 3
0
 def wrapper(request, *args, **kw):
     from access import acl
     if (acl.action_allowed(request, '*', '*')
         or not acl.action_allowed(request, 'Restricted', 'UGC')):
         return f(request, *args, **kw)
     else:
         return http.HttpResponseForbidden()
Esempio n. 4
0
    def test_tools_developer_and_admin(self):
        # Make them a developer.
        user = self.login('admin')
        AddonUser.objects.create(user=user, addon=Addon.objects.all()[0])

        r = self.client.get(self.url, follow=True)
        request = r.context['request']
        eq_(request.amo_user.is_developer, True)
        eq_(acl.action_allowed(request, 'Editors', '%'), True)
        eq_(acl.action_allowed(request, 'Localizer', '%'), True)
        eq_(acl.action_allowed(request, 'Admin', '%'), True)

        expected = [
            ('Tools', '#'),
            ('Manage My Add-ons', reverse('devhub.addons')),
            ('Submit a New Add-on', reverse('devhub.submit.1')),
            ('Manage My Apps', reverse('devhub.apps')),
            ('Submit a New App', reverse('devhub.submit_apps.1')),
            ('Submit a New Persona', reverse('devhub.personas.submit')),
            ('Developer Hub', reverse('devhub.index')),
            ('Editor Tools', reverse('editors.home')),
            ('Localizer Tools', '/localizers'),
            ('Admin Tools', reverse('zadmin.home')),
        ]
        check_links(expected, pq(r.content)('#aux-nav .tools a'))
Esempio n. 5
0
def setup_viewer(request, file_obj):
    data = {'file': file_obj,
            'version': file_obj.version,
            'addon': file_obj.version.addon,
            'status': False,
            'selected': {},
            'validate_url': ''}


    if (acl.action_allowed(request, 'Editors', '%') or
        acl.check_addon_ownership(request, file_obj.version.addon,
                                  viewer=True, ignore_disabled=True)):
        data['validate_url'] = reverse('devhub.json_file_validation',
                                       args=[file_obj.version.addon.slug,
                                             file_obj.id])

    if acl.action_allowed(request, 'Editors', '%'):
        data['file_link'] = {'text': _('Back to review'),
                             'url': reverse('editors.review',
                                            args=[data['addon'].slug])}
    else:
        data['file_link'] = {'text': _('Back to addon'),
                             'url': reverse('addons.detail',
                                            args=[data['addon'].pk])}
    return data
Esempio n. 6
0
 def wrapper(request, *args, **kw):
     from access import acl
     if (acl.action_allowed(request, '*', '*')
             or not acl.action_allowed(request, 'Restricted', 'UGC')):
         return f(request, *args, **kw)
     else:
         raise PermissionDenied
Esempio n. 7
0
def global_settings(request):
    """
    Storing standard AMO-wide information used in global headers, such as
    account links and settings.
    """
    account_links = []
    tools_links = []
    context = {}

    tools_title = _('Tools')
    is_reviewer = False

    if request.user.is_authenticated():
        amo_user = request.amo_user
        profile = request.user
        is_reviewer = acl.check_reviewer(request)

        account_links.append({'text': _('My Profile'),
                              'href': profile.get_url_path()})

        if not settings.APP_PREVIEW:
            account_links.append({
                'text': _('My Collections'),
                'href': reverse('collections.user', args=[amo_user.username])})

        account_links.append({
            'text': _('Log out'),
            'href': remora_url('/users/logout?to=' + urlquote(request.path)),
        })

        if request.amo_user.is_developer:
            tools_links.append({'text': _('Manage My Submissions'),
                                'href': reverse('devhub.addons')})
        tools_links += [
            {'text': _('Submit a New Add-on'),
             'href': reverse('devhub.submit.1')},
            {'text': _('Developer Hub'),
             'href': reverse('devhub.index')},
        ]

        if is_reviewer:
            tools_links.append({'text': _('Editor Tools'),
                                'href': reverse('editors.home')})
        if (acl.action_allowed(request, 'Admin', '%') or
            acl.action_allowed(request, 'AdminTools', 'View')):
            tools_links.append({'text': _('Admin Tools'),
                                'href': reverse('zadmin.home')})

        context['amo_user'] = request.amo_user
    else:
        context['amo_user'] = AnonymousUser()

    context.update({'account_links': account_links,
                    'settings': settings, 'amo': amo,
                    'tools_links': tools_links,
                    'tools_title': tools_title,
                    'ADMIN_MESSAGE': get_config('site_notice'),
                    'collect_timings_percent': get_collect_timings(),
                    'is_reviewer': is_reviewer})
    return context
Esempio n. 8
0
def check_stats_permission(request, addon, for_contributions=False):
    """
    Check if user is allowed to view stats for ``addon``.

    Raises PermissionDenied if user is not allowed.
    """
    # If public, non-contributions: everybody can view.
    if addon.public_stats and not for_contributions:
        return

    # Everything else requires an authenticated user.
    if not request.user.is_authenticated():
        raise PermissionDenied

    if not for_contributions:
        # Only authors and Stats Viewers allowed.
        if addon.has_author(request.amo_user) or acl.action_allowed(request, "Stats", "View"):
            return

    else:  # For contribution stats.
        # Only authors and Contribution Stats Viewers.
        if addon.has_author(request.amo_user) or acl.action_allowed(request, "RevenueStats", "View"):
            return

    raise PermissionDenied
Esempio n. 9
0
def profile(request, user_id):
    webapp = settings.APP_PREVIEW
    user = get_object_or_404(UserProfile, id=user_id)

    # Get user's own and favorite collections, if they allowed that.
    own_coll = fav_coll = []
    if not webapp:
        if user.display_collections:
            own_coll = (Collection.objects.listed().filter(author=user).order_by("-created"))[:10]
        if user.display_collections_fav:
            fav_coll = (Collection.objects.listed().filter(following__user=user).order_by("-following__created"))[:10]

    edit_any_user = acl.action_allowed(request, "Admin", "EditAnyUser")
    own_profile = request.user.is_authenticated() and request.amo_user.id == user.id

    personas = []
    if user.is_developer:
        if webapp:
            items = user.apps_listed
        else:
            items = user.addons_listed.exclude(type=amo.ADDON_PERSONA)
            personas = user.addons_listed.filter(type=amo.ADDON_PERSONA)
        addons = amo.utils.paginate(request, items.order_by("-weekly_downloads"))
    else:
        addons = []

    def get_addons(reviews):
        if not reviews:
            return
        qs = Addon.objects.filter(id__in=set(r.addon_id for r in reviews))
        addons = dict((addon.id, addon) for addon in qs)
        for review in reviews:
            review.addon = addons.get(review.addon_id)

    reviews = user.reviews.transform(get_addons)

    data = {
        "profile": user,
        "own_coll": own_coll,
        "reviews": reviews,
        "fav_coll": fav_coll,
        "edit_any_user": edit_any_user,
        "addons": addons,
        "own_profile": own_profile,
        "webapp": webapp,
        "personas": personas,
    }
    if not own_profile:
        data["abuse_form"] = AbuseForm(request=request)

    data["review_perms"] = {}  # See reviews.views.review_list for more
    if (
        own_profile
        or acl.action_allowed(request, "Reviews", "Edit")
        or acl.action_allowed(request, "Admin", "EditAnyUser")
    ):
        data["review_perms"] = dict(can_delete=True)

    return jingo.render(request, "users/profile.html", data)
Esempio n. 10
0
def app_header(context, app, page_type=''):
    t = env.get_template('lookup/helpers/app_header.html')
    is_admin = acl.action_allowed(context['request'], 'Users', 'Edit')
    is_staff = acl.action_allowed(context['request'], 'Apps', 'Configure')
    is_reviewer = acl.check_reviewer(context['request'])
    return jinja2.Markup(t.render(app=app, page_type=page_type,
                                  is_admin=is_admin, is_staff=is_staff,
                                  is_reviewer=is_reviewer))
Esempio n. 11
0
def motd(request):
    form = None
    if acl.action_allowed(request, 'AddonReviewerMOTD', 'Edit'):
        form = forms.MOTDForm(
            initial={'motd': get_config('editors_review_motd')})
    motd_editable = acl.action_allowed(request, 'AddonReviewerMOTD', 'Edit')
    data = context(request, form=form, motd_editable=motd_editable)
    return render(request, 'editors/motd.html', data)
Esempio n. 12
0
def global_settings(request):
    """Store global Marketplace-wide info. used in the header."""
    account_links = []
    tools_links = []
    context = {}

    tools_title = _('Tools')

    if request.user.is_authenticated() and hasattr(request, 'amo_user'):
        amo_user = request.amo_user
        account_links = []
        context['is_reviewer'] = acl.check_reviewer(request)
        if getattr(request, 'can_view_consumer', True):
            account_links = [
                {'text': _('Account History'),
                 'href': reverse('account.purchases')},
                {'text': _('Account Settings'),
                 'href': reverse('account.settings')},
            ]
        account_links += [
            {'text': _('Change Password'),
             'href': 'https://browserid.org/signin'},
            {'text': _('Log out'), 'href': reverse('users.logout')},
        ]
        if '/developers/' not in request.path:
            if amo_user.is_app_developer:
                tools_links.append({'text': _('My Submissions'),
                                    'href': reverse('mkt.developers.apps')})
            else:
                tools_links.append({'text': _('Developers'),
                                    'href': reverse('ecosystem.landing')})
        if '/reviewers/' not in request.path and context['is_reviewer']:
            tools_links.append({'text': _('Reviewer Tools'),
                                'href': reverse('reviewers.home')})
        if acl.action_allowed(request, 'Localizers', '%'):
            tools_links.append({'text': _('Localizer Tools'),
                                'href': '/localizers'})
        if acl.action_allowed(request, 'AccountLookup', '%'):
            tools_links.append({'text': _('Lookup Tool'),
                                'href': reverse('lookup.home')})
        if acl.action_allowed(request, 'Admin', '%'):
            tools_links.append({'text': _('Admin Tools'),
                                'href': reverse('zadmin.home')})

        context['amo_user'] = amo_user
    else:
        context['amo_user'] = AnonymousUser()

    context.update(account_links=account_links,
                   settings=settings,
                   amo=amo, mkt=mkt,
                   APP=amo.FIREFOX,
                   tools_links=tools_links,
                   tools_title=tools_title,
                   ADMIN_MESSAGE=get_config('site_notice'),
                   collect_timings_percent=get_collect_timings(),
                   is_admin=acl.action_allowed(request, 'Addons', 'Edit'))
    return context
Esempio n. 13
0
def global_settings(request):
    """
    Storing standard AMO-wide information used in global headers, such as
    account links and settings.
    """
    account_links = []
    tools_links = []
    context = {}

    if request.user.is_authenticated():
        # TODO(jbalogh): reverse links
        amo_user = request.amo_user
        account_links.append({
            'text': _('View Profile'),
            'href': request.user.get_profile().get_url_path(),
        })
        account_links.append({'text': _('Edit Profile'),
                              'href': reverse('users.edit')})
        if request.amo_user.is_developer:
            account_links.append({'text': _('My Add-ons'),
                                  'href': '/developers/addons'})

        account_links.append({
            'text': _('My Collections'),
            'href': reverse('collections.user', args=[amo_user.username])})
        if amo_user.favorite_addons:
            account_links.append(
                {'text': _('My Favorites'),
                 'href': reverse('collections.detail',
                                 args=[amo_user.username, 'favorites'])})

        account_links.append({
            'text': _('Log out'),
            'href': remora_url('/users/logout?to=' + urlquote(request.path)),
        })

        tools_links.append({'text': _('Developer Hub'),
                            'href': '/developers'})
        if acl.action_allowed(request, 'Editors', '%'):
            tools_links.append({'text': _('Editor Tools'),
                                'href': '/editors'})
        if acl.action_allowed(request, 'Localizers', '%'):
            tools_links.append({'text': _('Localizer Tools'),
                                'href': '/localizers'})
        if acl.action_allowed(request, 'Admin', '%'):
            tools_links.append({'text': _('Admin Tools'),
                                'href': reverse('zadmin.home')})

        context['amo_user'] = request.amo_user
    else:
        context['amo_user'] = AnonymousUser()

    context.update({'account_links': account_links,
                    'settings': settings, 'amo': amo,
                    'tools_links': tools_links,
                    'ADMIN_MESSAGE': get_config('site_notice')})
    return context
Esempio n. 14
0
def queue_tabnav_themes(context):
    """Similar to queue_tabnav, but for themes."""
    tabs = []
    if acl.action_allowed(context["request"], "Personas", "Review"):
        tabs.append(("editors.themes.list", "pending_themes", _("Pending")))
    if acl.action_allowed(context["request"], "SeniorPersonasTools", "View"):
        tabs.append(("editors.themes.list_flagged", "flagged_themes", _("Flagged")))
        tabs.append(("editors.themes.list_rereview", "rereview_themes", _("Updates")))
    return tabs
Esempio n. 15
0
 def wrapper(request, *args, **kw):
     admin = (action_allowed(request, 'Admin', '%') or
              action_allowed(request, 'AdminTools', 'View'))
     if reviewers == True:
         admin = (admin or
                  action_allowed(request, 'ReviewerAdminTools', 'View'))
     if admin:
         return f(request, *args, **kw)
     raise PermissionDenied
Esempio n. 16
0
def queue_tabnav_themes_interactive(context):
    """Tabnav for the interactive shiny theme queues."""
    tabs = []
    if acl.action_allowed(context["request"], "Personas", "Review"):
        tabs.append(("editors.themes.queue_themes", "pending", _("Pending")))
    if acl.action_allowed(context["request"], "SeniorPersonasTools", "View"):
        tabs.append(("editors.themes.queue_flagged", "flagged", _("Flagged")))
        tabs.append(("editors.themes.queue_rereview", "rereview", _("Updates")))
    return tabs
Esempio n. 17
0
 def wrapper(request, *args, **kw):
     admin = (action_allowed(request, 'Admin', '%') or
              action_allowed(request, 'AdminTools', 'View'))
     if reviewers == True:
         admin = (admin or
                  action_allowed(request, 'ReviewerAdminTools', 'View'))
     if admin:
         return f(request, *args, **kw)
     return http.HttpResponseForbidden()
Esempio n. 18
0
 def wrapper(request, *args, **kw):
     admin = action_allowed(request, "Admin", "%") or action_allowed(request, "AdminTools", "View")
     if reviewers == True:
         admin = admin or action_allowed(request, "ReviewerAdminTools", "View")
     if theme_reviewers == True:
         admin = admin or action_allowed(request, "SeniorPersonasTools", "View")
     if admin:
         return f(request, *args, **kw)
     raise PermissionDenied
Esempio n. 19
0
def _permission_to_edit_locale(request, locale=''):
    """If locale is empty, it checks global permissions."""

    if acl.action_allowed(request, 'Admin', 'EditAnyLocale'):
        return True

    if locale and acl.action_allowed(request, 'Localizers', locale):
        return True

    return False
Esempio n. 20
0
def _permission_to_edit_locale(request, locale=''):
    """If locale is empty, it checks global permissions."""

    if acl.action_allowed(request, 'Locales', 'Edit'):
        return True

    if locale and acl.action_allowed(request, 'Locale.%s' % locale, 'Edit'):
        return True

    return False
Esempio n. 21
0
def home(request):
    if (not acl.action_allowed(request, 'Addons', 'Review') and
            acl.action_allowed(request, 'Personas', 'Review')):
        return http.HttpResponseRedirect(reverse('editors.themes.home'))

    motd_editable = acl.action_allowed(request, 'AddonReviewerMOTD', 'Edit')
    durations = (('new', _('New Add-ons (Under 5 days)')),
                 ('med', _('Passable (5 to 10 days)')),
                 ('old', _('Overdue (Over 10 days)')))

    progress, percentage = _editor_progress()
    unlisted_progress, unlisted_percentage = _editor_progress(unlisted=True)
    reviews_max_display = getattr(settings, 'EDITOR_REVIEWS_MAX_DISPLAY', 5)
    reviews_total = ActivityLog.objects.total_reviews()[:reviews_max_display]
    reviews_monthly = (
        ActivityLog.objects.monthly_reviews()[:reviews_max_display])
    reviews_total_count = ActivityLog.objects.user_approve_reviews(
        request.user).count()
    reviews_monthly_count = (
        ActivityLog.objects.current_month_user_approve_reviews(
            request.user).count())

    # Try to read user position from retrieved reviews.
    # If not available, query for it.
    reviews_total_position = (
        ActivityLog.objects.user_position(reviews_total, request.user)
        or ActivityLog.objects.total_reviews_user_position(request.user))

    reviews_monthly_position = (
        ActivityLog.objects.user_position(reviews_monthly, request.user)
        or ActivityLog.objects.monthly_reviews_user_position(request.user))

    data = context(
        request,
        reviews_total=reviews_total,
        reviews_monthly=reviews_monthly,
        reviews_total_count=reviews_total_count,
        reviews_monthly_count=reviews_monthly_count,
        reviews_total_position=reviews_total_position,
        reviews_monthly_position=reviews_monthly_position,
        new_editors=EventLog.new_editors(),
        eventlog=ActivityLog.objects.editor_events()[:6],
        progress=progress,
        unlisted_progress=unlisted_progress,
        percentage=percentage,
        unlisted_percentage=unlisted_percentage,
        durations=durations,
        reviews_max_display=reviews_max_display,
        motd_editable=motd_editable,
        queue_counts_total=queue_counts(admin_reviewer=True),
        unlisted_queue_counts_total=queue_counts(admin_reviewer=True,
                                                 unlisted=True),
    )

    return render(request, 'editors/home.html', data)
Esempio n. 22
0
 def check_acls(self, request, obj, acl_type):
     if acl_type == 'moz_contact':
         return request.user.email == obj.addon.mozilla_contact
     elif acl_type == 'admin':
         return acl.action_allowed(request, 'Admin', '%')
     elif acl_type == 'reviewer':
         return acl.action_allowed(request, 'Apps', 'Review')
     elif acl_type == 'senior_reviewer':
         return acl.action_allowed(request, 'Apps', 'ReviewEscalated')
     else:
         raise 'Invalid ACL lookup.'
Esempio n. 23
0
def performance(request, user_id=False):
    user = request.amo_user
    editors = _recent_editors()

    is_admin = (acl.action_allowed(request, 'Admin', '%') or
                acl.action_allowed(request, 'ReviewerAdminTools', 'View'))

    if is_admin and user_id:
        try:
            user = UserProfile.objects.get(pk=user_id)
        except UserProfile.DoesNotExist:
            pass  # Use request.amo_user from above.

    monthly_data = _performance_by_month(user.id)
    performance_total = _performance_total(monthly_data)

    # Incentive point breakdown.
    today = date.today()
    month_ago = today - timedelta(days=30)
    year_ago = today - timedelta(days=365)
    point_total = ReviewerScore.get_total(user)
    totals = ReviewerScore.get_breakdown(user)
    months = ReviewerScore.get_breakdown_since(user, month_ago)
    years = ReviewerScore.get_breakdown_since(user, year_ago)

    def _sum(iter, types):
        return sum(s.total for s in iter if s.atype in types)

    breakdown = {
        'month': {
            'addons': _sum(months, amo.GROUP_TYPE_ADDON),
            'apps': _sum(months, amo.GROUP_TYPE_WEBAPP),
            'themes': _sum(months, amo.GROUP_TYPE_THEME),
        },
        'year': {
            'addons': _sum(years, amo.GROUP_TYPE_ADDON),
            'apps': _sum(years, amo.GROUP_TYPE_WEBAPP),
            'themes': _sum(years, amo.GROUP_TYPE_THEME),
        },
        'total': {
            'addons': _sum(totals, amo.GROUP_TYPE_ADDON),
            'apps': _sum(totals, amo.GROUP_TYPE_WEBAPP),
            'themes': _sum(totals, amo.GROUP_TYPE_THEME),
        }
    }

    data = context(monthly_data=json.dumps(monthly_data),
                   performance_month=performance_total['month'],
                   performance_year=performance_total['year'],
                   breakdown=breakdown, point_total=point_total,
                   editors=editors, current_user=user, is_admin=is_admin,
                   is_user=(request.amo_user.id == user.id))

    return render(request, 'editors/performance.html', data)
Esempio n. 24
0
def queue_tabnav_themes(context):
    """Similar to queue_tabnav, but for themes."""
    tabs = []
    if acl.action_allowed(context['request'], 'Personas', 'Review'):
        tabs.append((
            'themes', 'pending', 'queue_themes', _('Pending'),
        ))
    if acl.action_allowed(context['request'], 'ReviewerAdminTools', 'View'):
        tabs.append((
            'themes', 'flagged', 'queue_flagged', _('Flagged'),
        ))
    return tabs
Esempio n. 25
0
def app_header(context, app, page_type=''):
    t = env.get_template('lookup/helpers/app_header.html')

    is_author = acl.check_ownership(context['request'], app)
    is_operator = any(g.name == 'Operators' for g in context['request'].groups)
    is_admin = acl.action_allowed(context['request'], 'Users', 'Edit')
    is_staff = acl.action_allowed(context['request'], 'Apps', 'Configure')
    is_reviewer = acl.check_reviewer(context['request'])
    return jinja2.Markup(t.render(app=app, page_type=page_type,
                                  is_admin=is_admin, is_staff=is_staff,
                                  is_reviewer=is_reviewer, is_author=is_author,
                                  is_operator=is_operator))
Esempio n. 26
0
def home(request):
    if not acl.action_allowed(request, "Addons", "Review") and acl.action_allowed(request, "Personas", "Review"):
        return http.HttpResponseRedirect(reverse("editors.themes.home"))

    motd_editable = acl.action_allowed(request, "AddonReviewerMOTD", "Edit")
    durations = (
        ("new", _("New Add-ons (Under 5 days)")),
        ("med", _("Passable (5 to 10 days)")),
        ("old", _("Overdue (Over 10 days)")),
    )

    progress, percentage = _editor_progress()
    unlisted_progress, unlisted_percentage = _editor_progress(unlisted=True)
    reviews_max_display = getattr(settings, "EDITOR_REVIEWS_MAX_DISPLAY", 5)
    reviews_total = ActivityLog.objects.total_reviews()[:reviews_max_display]
    reviews_monthly = ActivityLog.objects.monthly_reviews()[:reviews_max_display]
    reviews_total_count = ActivityLog.objects.user_approve_reviews(request.user).count()
    reviews_monthly_count = ActivityLog.objects.current_month_user_approve_reviews(request.user).count()

    # Try to read user position from retrieved reviews.
    # If not available, query for it.
    reviews_total_position = ActivityLog.objects.user_position(
        reviews_total, request.user
    ) or ActivityLog.objects.total_reviews_user_position(request.user)

    reviews_monthly_position = ActivityLog.objects.user_position(
        reviews_monthly, request.user
    ) or ActivityLog.objects.monthly_reviews_user_position(request.user)

    data = context(
        request,
        reviews_total=reviews_total,
        reviews_monthly=reviews_monthly,
        reviews_total_count=reviews_total_count,
        reviews_monthly_count=reviews_monthly_count,
        reviews_total_position=reviews_total_position,
        reviews_monthly_position=reviews_monthly_position,
        new_editors=EventLog.new_editors(),
        eventlog=ActivityLog.objects.editor_events()[:6],
        progress=progress,
        unlisted_progress=unlisted_progress,
        percentage=percentage,
        unlisted_percentage=unlisted_percentage,
        durations=durations,
        reviews_max_display=reviews_max_display,
        motd_editable=motd_editable,
        queue_counts_total=queue_counts(admin_reviewer=True),
        unlisted_queue_counts_total=queue_counts(admin_reviewer=True, unlisted=True),
    )

    return render(request, "editors/home.html", data)
Esempio n. 27
0
def queue_tabnav(context):
    """
    Returns tuple of tab navigation for the queue pages.

    Each tuple contains three elements: (named_url. tab_code, tab_text)
    """
    request = context['request']
    counts = context['queue_counts']
    apps_reviewing = AppsReviewing(request).get_apps()

    # Apps.
    if acl.action_allowed(request, 'Apps', 'Review'):
        rv = [
            ('reviewers.apps.queue_pending', 'pending',
             _('Apps ({0})', counts['pending']).format(counts['pending'])),

            ('reviewers.apps.queue_rereview', 'rereview',
             _('Re-reviews ({0})', counts['rereview']).format(
             counts['rereview'])),

            ('reviewers.apps.queue_updates', 'updates',
             _('Updates ({0})', counts['updates']).format(counts['updates'])),
        ]
        if acl.action_allowed(request, 'Apps', 'ReviewEscalated'):
            rv.append(('reviewers.apps.queue_escalated', 'escalated',
                       _('Escalations ({0})', counts['escalated']).format(
                       counts['escalated'])))
        rv.extend([
            ('reviewers.apps.queue_moderated', 'moderated',
             _('Moderated Reviews ({0})', counts['moderated'])
             .format(counts['moderated'])),

            ('reviewers.apps.apps_reviewing', 'reviewing',
             _('Reviewing ({0})').format(len(apps_reviewing))),
        ])
    else:
        rv = []

    # Themes.
    if (acl.action_allowed(request, 'Personas', 'Review') and
        waffle.switch_is_active('mkt-themes')):
        rv.append(('reviewers.themes.list', 'themes',
                  _('Themes ({0})').format(counts['themes']),))

    if waffle.switch_is_active('buchets') and 'pro' in request.GET:
        device_srch = device_queue_search(request)
        rv.append(('reviewers.apps.queue_device', 'device',
                  _('Device ({0})').format(device_srch.count()),))

    return rv
Esempio n. 28
0
def queue_tabnav(context):
    """
    Returns tuple of tab navigation for the queue pages.

    Each tuple contains three elements: (url, tab_code, tab_text)

    """
    request = context['request']
    counts = context['queue_counts']
    apps_reviewing = AppsReviewing(request).get_apps()

    # Apps.
    if acl.action_allowed(request, 'Apps', 'Review'):
        rv = [
            (reverse('reviewers.apps.queue_pending'), 'pending',
             _('Apps ({0})', counts['pending']).format(counts['pending'])),

            (reverse('reviewers.apps.queue_rereview'), 'rereview',
             _('Re-reviews ({0})', counts['rereview']).format(
             counts['rereview'])),

            (reverse('reviewers.apps.queue_updates'), 'updates',
             _('Updates ({0})', counts['updates']).format(counts['updates'])),
        ]
        if acl.action_allowed(request, 'Apps', 'ReviewEscalated'):
            rv.append((reverse('reviewers.apps.queue_escalated'), 'escalated',
                       _('Escalations ({0})', counts['escalated']).format(
                       counts['escalated'])))
        rv.extend([
            (reverse('reviewers.apps.queue_moderated'), 'moderated',
             _('Moderated Reviews ({0})', counts['moderated'])
             .format(counts['moderated'])),

            (reverse('reviewers.apps.apps_reviewing'), 'reviewing',
             _('Reviewing ({0})').format(len(apps_reviewing))),
        ])
        if acl.action_allowed(request, 'Apps', 'ReviewRegionCN'):
            url_ = reverse('reviewers.apps.queue_region',
                           args=[mkt.regions.CN.slug])
            rv.append((url_, 'region',
                      _('China ({0})').format(counts['region_cn'])))
    else:
        rv = []

    if waffle.switch_is_active('buchets') and 'pro' in request.GET:
        device_srch = device_queue_search(request)
        rv.append((reverse('reviewers.apps.queue_device'), 'device',
                  _('Device ({0})').format(device_srch.count()),))

    return rv
Esempio n. 29
0
def queue_tabnav(context):
    """
    Returns tuple of tab navigation for the queue pages.

    Each tuple contains three elements: (named_url. tab_code, tab_text)
    """
    counts = context["queue_counts"]
    apps_reviewing = AppsReviewing(context["request"]).get_apps()

    # Apps.
    if acl.action_allowed(context["request"], "Apps", "Review"):
        rv = [
            ("reviewers.apps.queue_pending", "pending", _("Apps ({0})", counts["pending"]).format(counts["pending"])),
            (
                "reviewers.apps.queue_rereview",
                "rereview",
                _("Re-reviews ({0})", counts["rereview"]).format(counts["rereview"]),
            ),
            (
                "reviewers.apps.queue_updates",
                "updates",
                _("Updates ({0})", counts["updates"]).format(counts["updates"]),
            ),
        ]
        if acl.action_allowed(context["request"], "Apps", "ReviewEscalated"):
            rv.append(
                (
                    "reviewers.apps.queue_escalated",
                    "escalated",
                    _("Escalations ({0})", counts["escalated"]).format(counts["escalated"]),
                )
            )
        rv.extend(
            [
                (
                    "reviewers.apps.queue_moderated",
                    "moderated",
                    _("Moderated Reviews ({0})", counts["moderated"]).format(counts["moderated"]),
                ),
                ("reviewers.apps.apps_reviewing", "reviewing", _("Reviewing ({0})").format(len(apps_reviewing))),
            ]
        )
    else:
        rv = []

    # Themes.
    if acl.action_allowed(context["request"], "Personas", "Review") and waffle.switch_is_active("mkt-themes"):
        rv.append(("reviewers.themes.list", "themes", _("Themes ({0})").format(counts["themes"])))
    return rv
Esempio n. 30
0
def queue_tabnav_themes_interactive(context):
    """Tabnav for the interactive shiny theme queues."""
    tabs = []
    if acl.action_allowed(context['request'], 'Personas', 'Review'):
        tabs.append((
            'editors.themes.queue_themes', 'pending', _('Pending'),
        ))
    if acl.action_allowed(context['request'], 'SeniorPersonasTools', 'View'):
        tabs.append((
            'editors.themes.queue_flagged', 'flagged', _('Flagged'),
        ))
        tabs.append((
            'editors.themes.queue_rereview', 'rereview', _('Updates'),
        ))
    return tabs
Esempio n. 31
0
def _review(request, addon):
    version = addon.latest_version

    if (not settings.DEBUG
            and addon.authors.filter(user=request.user).exists()):
        amo.messages.warning(request, _('Self-reviews are not allowed.'))
        return redirect(reverse('editors.queue'))

    form = forms.get_review_form(request.POST or None,
                                 request=request,
                                 addon=addon,
                                 version=version)

    queue_type = (form.helper.review_type
                  if form.helper.review_type != 'preliminary' else 'prelim')
    redirect_url = reverse('editors.queue_%s' % queue_type)

    num = request.GET.get('num')
    paging = {}
    if num:
        try:
            num = int(num)
        except (ValueError, TypeError):
            raise http.Http404
        total = queue_counts(queue_type)
        paging = {
            'current': num,
            'total': total,
            'prev': num > 1,
            'next': num < total,
            'prev_url': '%s?num=%s' % (redirect_url, num - 1),
            'next_url': '%s?num=%s' % (redirect_url, num + 1)
        }

    if request.method == 'POST' and form.is_valid():
        form.helper.process()
        if form.cleaned_data.get('notify'):
            EditorSubscription.objects.get_or_create(user=request.amo_user,
                                                     addon=addon)
        amo.messages.success(request, _('Review successfully processed.'))
        return redirect(redirect_url)

    canned = CannedResponse.objects.all()
    is_admin = acl.action_allowed(request, 'Admin', 'EditAnyAddon')
    actions = form.helper.actions.items()

    statuses = [
        amo.STATUS_PUBLIC, amo.STATUS_LITE, amo.STATUS_LITE_AND_NOMINATED
    ]

    try:
        show_diff = (addon.versions.exclude(id=version.id).filter(
            files__isnull=False,
            created__lt=version.created,
            files__status__in=statuses).latest())
    except Version.DoesNotExist:
        show_diff = None

    # The actions we should show a minimal form from.
    actions_minimal = [k for (k, a) in actions if not a.get('minimal')]

    # We only allow the user to check/uncheck files for "pending"
    allow_unchecking_files = form.helper.review_type == "pending"

    versions = (Version.objects.filter(addon=addon).exclude(
        files__status=amo.STATUS_BETA).order_by('-created').transform(
            Version.transformer_activity).transform(Version.transformer))

    pager = amo.utils.paginate(request, versions, 10)

    num_pages = pager.paginator.num_pages
    count = pager.paginator.count

    ctx = context(version=version,
                  addon=addon,
                  pager=pager,
                  num_pages=num_pages,
                  count=count,
                  flags=Review.objects.filter(addon=addon, flag=True),
                  form=form,
                  paging=paging,
                  canned=canned,
                  is_admin=is_admin,
                  status_types=amo.STATUS_CHOICES,
                  show_diff=show_diff,
                  allow_unchecking_files=allow_unchecking_files,
                  actions=actions,
                  actions_minimal=actions_minimal)

    return jingo.render(request, 'editors/review.html', ctx)
Esempio n. 32
0
 def has_curate_permission(self, request):
     return acl.action_allowed(request, 'Collections', 'Curate')
Esempio n. 33
0
def addons_section(request,
                   addon_id,
                   addon,
                   section,
                   editable=False,
                   webapp=False):
    basic = AppFormBasic if webapp else addon_forms.AddonFormBasic
    models = {
        'basic': basic,
        'media': AppFormMedia,
        'details': AppFormDetails,
        'support': AppFormSupport,
        'technical': AppFormTechnical,
        'admin': forms.AdminSettingsForm
    }

    is_dev = acl.check_addon_ownership(request, addon, dev=True)

    if section not in models:
        raise http.Http404()

    version = addon.current_version or addon.latest_version

    tags, previews, restricted_tags = [], [], []
    cat_form = appfeatures = appfeatures_form = None

    # Permissions checks.
    # Only app owners can edit any of the details of their apps.
    # Users with 'Apps:Configure' can edit the admin settings.
    if (section != 'admin' and not is_dev) or (
            section == 'admin'
            and not acl.action_allowed(request, 'Apps', 'Configure')
            and not acl.action_allowed(request, 'Apps', 'ViewConfiguration')):
        raise PermissionDenied

    if section == 'basic':
        cat_form = CategoryForm(request.POST or None,
                                product=addon,
                                request=request)

    elif section == 'media':
        previews = PreviewFormSet(request.POST or None,
                                  prefix='files',
                                  queryset=addon.get_previews())

    elif section == 'technical':
        # Only show the list of features if app isn't packaged.
        if (waffle.switch_is_active('buchets') and not addon.is_packaged
                and section == 'technical'):
            appfeatures = version.features
            formdata = request.POST if request.method == 'POST' else None
            appfeatures_form = AppFeaturesForm(formdata, instance=appfeatures)

    elif section == 'admin':
        tags = addon.tags.not_blacklisted().values_list('tag_text', flat=True)
        restricted_tags = addon.tags.filter(restricted=True)

    # Get the slug before the form alters it to the form data.
    valid_slug = addon.app_slug
    if editable:
        if request.method == 'POST':

            if (section == 'admin'
                    and not acl.action_allowed(request, 'Apps', 'Configure')):
                raise PermissionDenied

            form = models[section](request.POST,
                                   request.FILES,
                                   instance=addon,
                                   request=request)

            all_forms = [form, previews]
            if appfeatures_form:
                all_forms.append(appfeatures_form)
            if cat_form:
                all_forms.append(cat_form)
            if all(not f or f.is_valid() for f in all_forms):
                if cat_form:
                    cat_form.save()

                addon = form.save(addon)

                if appfeatures_form:
                    appfeatures_form.save()

                if 'manifest_url' in form.changed_data:
                    addon.update(
                        app_domain=addon.domain_from_url(addon.manifest_url))
                    update_manifests([addon.pk])

                if previews:
                    for preview in previews.forms:
                        preview.save(addon)

                editable = False
                if section == 'media':
                    amo.log(amo.LOG.CHANGE_ICON, addon)
                else:
                    amo.log(amo.LOG.EDIT_PROPERTIES, addon)

                valid_slug = addon.app_slug
        else:
            form = models[section](instance=addon, request=request)
    else:
        form = False

    data = {
        'addon': addon,
        'webapp': webapp,
        'version': version,
        'form': form,
        'editable': editable,
        'tags': tags,
        'restricted_tags': restricted_tags,
        'cat_form': cat_form,
        'preview_form': previews,
        'valid_slug': valid_slug,
    }

    if appfeatures_form and appfeatures:
        data.update({
            'appfeatures': appfeatures,
            'feature_list': [unicode(f) for f in appfeatures.to_list()],
            'appfeatures_form': appfeatures_form
        })

    return jingo.render(request, 'developers/apps/edit/%s.html' % section,
                        data)
Esempio n. 34
0
    def get_actions(self):
        public = {
            'method':
            self.handler.process_public,
            'minimal':
            False,
            'label':
            _lazy(u'Push to public'),
            'details':
            _lazy(u'This will approve the sandboxed app so it '
                  u'appears on the public side.')
        }
        reject = {
            'method':
            self.handler.process_sandbox,
            'label':
            _lazy(u'Reject'),
            'minimal':
            False,
            'details':
            _lazy(u'This will reject the app and remove it from '
                  u'the review queue.')
        }
        info = {
            'method':
            self.handler.request_information,
            'label':
            _lazy(u'Request more information'),
            'minimal':
            True,
            'details':
            _lazy(u'This will send the author(s) an email '
                  u'requesting more information.')
        }
        escalate = {
            'method': self.handler.process_escalate,
            'label': _lazy(u'Escalate'),
            'minimal': True,
            'details': _lazy(u'Flag this app for an admin to review.')
        }
        comment = {
            'method':
            self.handler.process_comment,
            'label':
            _lazy(u'Comment'),
            'minimal':
            True,
            'details':
            _lazy(u'Make a comment on this app.  The author won\'t '
                  u'be able to see this.')
        }
        clear_escalation = {
            'method':
            self.handler.process_clear_escalation,
            'label':
            _lazy(u'Clear Escalation'),
            'minimal':
            True,
            'details':
            _lazy(u'Clear this app from the escalation queue. The '
                  u'author will get no email or see comments '
                  u'here.')
        }
        clear_rereview = {
            'method':
            self.handler.process_clear_rereview,
            'label':
            _lazy(u'Clear Re-review'),
            'minimal':
            True,
            'details':
            _lazy(u'Clear this app from the re-review queue. The '
                  u'author will get no email or see comments '
                  u'here.')
        }
        disable = {
            'method':
            self.handler.process_disable,
            'label':
            _lazy(u'Disable app'),
            'minimal':
            True,
            'details':
            _lazy(u'Disable the app, removing it from public '
                  u'results. Sends comments to author.')
        }

        actions = SortedDict()

        if not self.version:
            # Return early if there is no version, this app is incomplete.
            actions['info'] = info
            actions['comment'] = comment
            return actions

        file_status = self.version.files.values_list('status', flat=True)
        multiple_versions = (File.objects.exclude(version=self.version).filter(
            version__addon=self.addon,
            status__in=amo.REVIEWED_STATUSES).exists())

        # Public.
        if ((self.addon.is_packaged and amo.STATUS_PUBLIC not in file_status)
                or (not self.addon.is_packaged
                    and self.addon.status != amo.STATUS_PUBLIC)):
            actions['public'] = public

        # Reject.
        if self.addon.is_packaged:
            # Packaged apps reject the file only, or the app itself if there's
            # only a single version.
            if (not multiple_versions and self.addon.status
                    not in [amo.STATUS_REJECTED, amo.STATUS_DISABLED]):
                actions['reject'] = reject
            elif multiple_versions and amo.STATUS_DISABLED not in file_status:
                actions['reject'] = reject
        else:
            # Hosted apps reject the app itself.
            if self.addon.status not in [
                    amo.STATUS_REJECTED, amo.STATUS_DISABLED
            ]:
                actions['reject'] = reject

        # Disable.
        if (acl.action_allowed(self.handler.request, 'Addons', 'Edit')
                and (self.addon.status != amo.STATUS_DISABLED
                     or amo.STATUS_DISABLED not in file_status)):
            actions['disable'] = disable

        # Clear escalation.
        if self.handler.in_escalate:
            actions['clear_escalation'] = clear_escalation

        # Clear re-review.
        if self.handler.in_rereview:
            actions['clear_rereview'] = clear_rereview

        # Escalate.
        if not self.handler.in_escalate:
            actions['escalate'] = escalate

        # Request info and comment are always shown.
        actions['info'] = info
        actions['comment'] = comment

        return actions
Esempio n. 35
0
def global_settings(request):
    """
    Storing standard AMO-wide information used in global headers, such as
    account links and settings.
    """
    account_links = []
    tools_links = []
    context = {}

    tools_title = _('Tools')

    if request.user.is_authenticated() and hasattr(request, 'amo_user'):
        amo_user = request.amo_user
        account_links.append({
            'text': _('My Profile'),
            'href': request.user.get_profile().get_url_path(),
        })
        account_links.append({
            'text': _('Account Settings'),
            'href': reverse('users.edit')
        })
        if not settings.APP_PREVIEW:
            account_links.append({
                'text':
                _('My Collections'),
                'href':
                reverse('collections.user', args=[amo_user.username])
            })

            if amo_user.favorite_addons:
                account_links.append({
                    'text':
                    _('My Favorites'),
                    'href':
                    reverse('collections.detail',
                            args=[amo_user.username, 'favorites'])
                })

        if waffle.switch_is_active('marketplace'):
            account_links.append({
                'text': _('My Purchases'),
                'href': reverse('users.purchases')
            })

        if waffle.flag_is_active(request, 'allow-pre-auth'):
            account_links.append({
                'text': loc('Payment Profile'),
                'href': reverse('users.payments')
            })

        account_links.append({
            'text':
            _('Log out'),
            'href':
            remora_url('/users/logout?to=' + urlquote(request.path)),
        })

        if not settings.APP_PREVIEW:
            if request.amo_user.is_developer:
                tools_links.append({
                    'text': _('Manage My Add-ons'),
                    'href': reverse('devhub.addons')
                })
            tools_links.append({
                'text': _('Submit a New Add-on'),
                'href': reverse('devhub.submit.1')
            })

        if waffle.flag_is_active(request, 'accept-webapps'):
            if settings.APP_PREVIEW or request.amo_user.is_developer:
                tools_links.append({
                    'text': _('Manage My Apps'),
                    'href': reverse('devhub.apps')
                })
            tools_links.append({
                'text': _('Submit a New App'),
                'href': reverse('devhub.submit_apps.1')
            })

        if waffle.flag_is_active(request, 'submit-personas'):
            # TODO(cvan)(fligtar): Do we want this here?
            tools_links.append({
                'text': 'Submit a New Persona',
                'href': reverse('devhub.personas.submit')
            })

        if not settings.APP_PREVIEW:
            tools_links.append({
                'text': _('Developer Hub'),
                'href': reverse('devhub.index')
            })

        if acl.action_allowed(request, 'Editors', '%'):
            tools_links.append({
                'text': _('Editor Tools'),
                'href': reverse('editors.home')
            })
        if acl.action_allowed(request, 'Localizers', '%'):
            tools_links.append({
                'text': _('Localizer Tools'),
                'href': '/localizers'
            })
        if acl.action_allowed(request, 'Admin', '%'):
            tools_links.append({
                'text': _('Admin Tools'),
                'href': reverse('zadmin.home')
            })

        context['amo_user'] = request.amo_user
    else:
        context['amo_user'] = AnonymousUser()

    # The flag has to be enabled for everyone and then we'll use that
    # percentage in the pages.
    percent = 0
    try:
        flag = waffle.models.Flag.objects.get(name='collect-timings')
        if flag.everyone and flag.percent:
            percent = float(flag.percent) / 100.0
    except waffle.models.Flag.DoesNotExist:
        pass

    context.update({
        'account_links': account_links,
        'settings': settings,
        'amo': amo,
        'tools_links': tools_links,
        'tools_title': tools_title,
        'ADMIN_MESSAGE': get_config('site_notice'),
        'collect_timings_percent': percent
    })
    return context
Esempio n. 36
0
def performance(request, user_id=False):
    user = request.amo_user
    editors = _recent_editors()

    is_admin = (acl.action_allowed(request, 'Admin', '%')
                or acl.action_allowed(request, 'ReviewerAdminTools', 'View'))

    if is_admin and user_id:
        try:
            user = UserProfile.objects.get(pk=user_id)
        except UserProfile.DoesNotExist:
            pass  # Use request.amo_user from above.

    motd_editable = acl.action_allowed(request, 'AddonReviewerMOTD', 'Edit')

    monthly_data = _performance_by_month(user.id)
    performance_total = _performance_total(monthly_data)

    # Incentive point breakdown.
    today = date.today()
    month_ago = today - timedelta(days=30)
    year_ago = today - timedelta(days=365)
    point_total = ReviewerScore.get_total(user)
    totals = ReviewerScore.get_breakdown(user)
    months = ReviewerScore.get_breakdown_since(user, month_ago)
    years = ReviewerScore.get_breakdown_since(user, year_ago)

    def _sum(iter, types, exclude=False):
        """Sum the `total` property for items in `iter` that have an `atype`
        that is included in `types` when `exclude` is False (default) or not in
        `types` when `exclude` is True."""
        return sum(s.total for s in iter
                   if (s.atype in types) == (not exclude))

    breakdown = {
        'month': {
            'addons':
            _sum(months, amo.GROUP_TYPE_ADDON),
            'themes':
            _sum(months, amo.GROUP_TYPE_THEME),
            'other':
            _sum(months,
                 amo.GROUP_TYPE_ADDON + amo.GROUP_TYPE_THEME,
                 exclude=True)
        },
        'year': {
            'addons':
            _sum(years, amo.GROUP_TYPE_ADDON),
            'themes':
            _sum(years, amo.GROUP_TYPE_THEME),
            'other':
            _sum(years,
                 amo.GROUP_TYPE_ADDON + amo.GROUP_TYPE_THEME,
                 exclude=True)
        },
        'total': {
            'addons':
            _sum(totals, amo.GROUP_TYPE_ADDON),
            'themes':
            _sum(totals, amo.GROUP_TYPE_THEME),
            'other':
            _sum(totals,
                 amo.GROUP_TYPE_ADDON + amo.GROUP_TYPE_THEME,
                 exclude=True)
        }
    }

    data = context(request,
                   monthly_data=json.dumps(monthly_data),
                   performance_month=performance_total['month'],
                   performance_year=performance_total['year'],
                   breakdown=breakdown,
                   point_total=point_total,
                   editors=editors,
                   current_user=user,
                   is_admin=is_admin,
                   is_user=(request.amo_user.id == user.id),
                   motd_editable=motd_editable)

    return render(request, 'editors/performance.html', data)
Esempio n. 37
0
 def get_tags(self, addon):
     if acl.action_allowed(self.request, 'Apps', 'Edit'):
         return list(addon.tags.values_list('tag_text', flat=True))
     else:
         return list(addon.tags.filter(restricted=False)
                     .values_list('tag_text', flat=True))
Esempio n. 38
0
 def is_authorized(self, request, object=None):
     if acl.action_allowed(request, self.app, self.action):
         return True
     log.info('Permission authorization failed')
     return False
Esempio n. 39
0
 def has_permission(self, request, view):
     return request.method in SAFE_METHODS and acl.action_allowed(
         request, 'Apps', 'Review')
Esempio n. 40
0
 def has_permission(self, request, view):
     return acl.action_allowed(request, self.app, self.action)
Esempio n. 41
0
 def can_view_stats(self, request):
     if request and request.amo_user:
         return (self.publishable_by(request.amo_user)
                 or acl.action_allowed(request, 'CollectionStats', 'View'))
     return False
Esempio n. 42
0
 def wrapper(request, *args, **kw):
     if acl.action_allowed(request, 'Editors', '%'):
         return func(request, *args, **kw)
     else:
         return http.HttpResponseForbidden()
Esempio n. 43
0
File: forms.py Progetto: vdt/zamboni
 def get_tags(self, addon):
     if acl.action_allowed(self.request, 'Addons', 'Edit'):
         return [t.tag_text for t in addon.tags.all()]
     else:
         return [t.tag_text for t in addon.tags.filter(restricted=False)]
Esempio n. 44
0
def review(request, addon):
    if not addon.is_listed and not acl.check_unlisted_addons_reviewer(request):
        raise http.Http404

    version = addon.latest_version

    if not settings.ALLOW_SELF_REVIEWS and addon.has_author(request.amo_user):
        amo.messages.warning(request, _('Self-reviews are not allowed.'))
        return redirect(reverse('editors.queue'))

    form = forms.get_review_form(request.POST or None,
                                 request=request,
                                 addon=addon,
                                 version=version)

    queue_type = (form.helper.review_type
                  if form.helper.review_type != 'preliminary' else 'prelim')
    if addon.is_listed:
        redirect_url = reverse('editors.queue_%s' % queue_type)
    else:
        redirect_url = reverse('editors.unlisted_queue_%s' % queue_type)

    is_admin = acl.action_allowed(request, 'Addons', 'Edit')

    if request.method == 'POST' and form.is_valid():
        form.helper.process()
        if form.cleaned_data.get('notify'):
            EditorSubscription.objects.get_or_create(user=request.amo_user,
                                                     addon=addon)
        if form.cleaned_data.get('adminflag') and is_admin:
            addon.update(admin_review=False)
        amo.messages.success(request, _('Review successfully processed.'))
        return redirect(redirect_url)

    # Kick off validation tasks for any files in this version which don't have
    # cached validation, since editors will almost certainly need to access
    # them. But only if we're not running in eager mode, since that could mean
    # blocking page load for several minutes.
    if not getattr(settings, 'CELERY_ALWAYS_EAGER', False):
        for file_ in version.files.all():
            if not file_.has_been_validated:
                devhub.tasks.validate(file_)

    canned = AddonCannedResponse.objects.all()
    actions = form.helper.actions.items()

    statuses = [
        amo.STATUS_PUBLIC, amo.STATUS_LITE, amo.STATUS_LITE_AND_NOMINATED
    ]

    try:
        show_diff = (addon.versions.exclude(id=version.id).filter(
            files__isnull=False,
            created__lt=version.created,
            files__status__in=statuses).latest())
    except Version.DoesNotExist:
        show_diff = None

    # The actions we should show a minimal form from.
    actions_minimal = [k for (k, a) in actions if not a.get('minimal')]

    versions = (Version.objects.filter(addon=addon).exclude(
        files__status=amo.STATUS_BETA).order_by('-created').transform(
            Version.transformer_activity).transform(Version.transformer))

    class PseudoVersion(object):
        def __init__(self):
            self.all_activity = []

        all_files = ()
        approvalnotes = None
        compatible_apps_ordered = ()
        releasenotes = None
        status = 'Deleted',

        @property
        def created(self):
            return self.all_activity[0].created

        @property
        def version(self):
            return (self.all_activity[0].activity_log.details.get(
                'version', '[deleted]'))

    # Grab review history for deleted versions of this add-on
    comments = (CommentLog.objects.filter(
        activity_log__action__in=amo.LOG_REVIEW_QUEUE,
        activity_log__versionlog=None,
        activity_log__addonlog__addon=addon).order_by(
            'created').select_related('activity_log'))

    comment_versions = defaultdict(PseudoVersion)
    for c in comments:
        c.version = c.activity_log.details.get('version', c.created)
        comment_versions[c.version].all_activity.append(c)

    all_versions = comment_versions.values()
    all_versions.extend(versions)
    all_versions.sort(key=lambda v: v.created, reverse=True)

    pager = amo.utils.paginate(request, all_versions, 10)

    num_pages = pager.paginator.num_pages
    count = pager.paginator.count

    try:
        flags = ViewQueue.objects.get(id=addon.id).flags
    except ViewQueue.DoesNotExist:
        flags = []

    user_changes_actions = [
        amo.LOG.ADD_USER_WITH_ROLE.id, amo.LOG.CHANGE_USER_WITH_ROLE.id,
        amo.LOG.REMOVE_USER_WITH_ROLE.id
    ]
    user_changes_log = AddonLog.objects.filter(
        activity_log__action__in=user_changes_actions,
        addon=addon).order_by('id')
    ctx = context(request,
                  version=version,
                  addon=addon,
                  pager=pager,
                  num_pages=num_pages,
                  count=count,
                  flags=flags,
                  form=form,
                  canned=canned,
                  is_admin=is_admin,
                  show_diff=show_diff,
                  actions=actions,
                  actions_minimal=actions_minimal,
                  whiteboard_form=forms.WhiteboardForm(instance=addon),
                  user_changes=user_changes_log,
                  unlisted=not addon.is_listed)

    return render(request, 'editors/review.html', ctx)
Esempio n. 45
0
def global_settings(request):
    """
    Storing standard AMO-wide information used in global headers, such as
    account links and settings.
    """
    account_links = []
    tools_links = []
    context = {}

    tools_title = _('Tools')
    is_reviewer = False

    if request.user.is_authenticated():
        amo_user = request.amo_user
        profile = request.user
        is_reviewer = (acl.check_addons_reviewer(request)
                       or acl.check_personas_reviewer(request))

        account_links.append({
            'text': _('My Profile'),
            'href': profile.get_url_path()
        })
        if amo_user.is_artist:
            account_links.append({
                'text': _('My Themes'),
                'href': profile.get_user_url('themes')
            })

        account_links.append({
            'text': _('Account Settings'),
            'href': reverse('users.edit')
        })
        account_links.append({
            'text':
            _('My Collections'),
            'href':
            reverse('collections.user', args=[amo_user.username])
        })

        if amo_user.favorite_addons:
            account_links.append({
                'text':
                _('My Favorites'),
                'href':
                reverse('collections.detail',
                        args=[amo_user.username, 'favorites'])
            })

        account_links.append({
            'text':
            _('Log out'),
            'href':
            remora_url('/users/logout?to=' + urlquote(request.path)),
        })

        if request.amo_user.is_developer:
            tools_links.append({
                'text': _('Manage My Submissions'),
                'href': reverse('devhub.addons')
            })
        links = [
            {
                'text': _('Submit a New Add-on'),
                'href': reverse('devhub.submit.1')
            },
            {
                'text': _('Submit a New Theme'),
                'href': reverse('devhub.themes.submit')
            },
            {
                'text': _('Developer Hub'),
                'href': reverse('devhub.index')
            },
        ]
        if waffle.switch_is_active('signing-api'):
            links.append({
                'text': _('Manage API Keys'),
                'href': reverse('devhub.api_key')
            })

        tools_links += links
        if is_reviewer:
            tools_links.append({
                'text': _('Editor Tools'),
                'href': reverse('editors.home')
            })
        if acl.action_allowed(request, 'L10nTools', 'View'):
            tools_links.append({
                'text': _('Localizer Tools'),
                'href': '/localizers'
            })
        if (acl.action_allowed(request, 'Admin', '%')
                or acl.action_allowed(request, 'AdminTools', 'View')):
            tools_links.append({
                'text': _('Admin Tools'),
                'href': reverse('zadmin.home')
            })

        context['amo_user'] = request.amo_user
    else:
        context['amo_user'] = AnonymousUser()

    context.update({
        'account_links': account_links,
        'settings': settings,
        'amo': amo,
        'tools_links': tools_links,
        'tools_title': tools_title,
        'ADMIN_MESSAGE': get_config('site_notice'),
        'collect_timings_percent': get_collect_timings(),
        'is_reviewer': is_reviewer
    })
    return context
Esempio n. 46
0
def motd(request):
    form = None
    if acl.action_allowed(request, 'AddonReviewerMOTD', 'Edit'):
        form = forms.MOTDForm()
    data = context(form=form)
    return render(request, 'editors/motd.html', data)
Esempio n. 47
0
def _review(request, addon, version):

    if (not settings.ALLOW_SELF_REVIEWS and
        not acl.action_allowed(request, 'Admin', '%') and
        addon.has_author(request.amo_user)):
        messages.warning(request, _('Self-reviews are not allowed.'))
        return redirect(reverse('reviewers.home'))

    if (addon.status == amo.STATUS_BLOCKED and
        not acl.action_allowed(request, 'Apps', 'ReviewEscalated')):
        messages.warning(
            request, _('Only senior reviewers can review blocklisted apps.'))
        return redirect(reverse('reviewers.home'))

    attachment_formset = forms.AttachmentFormSet(data=request.POST or None,
                                                 files=request.FILES or None,
                                                 prefix='attachment')
    form = forms.get_review_form(data=request.POST or None,
                                 files=request.FILES or None, request=request,
                                 addon=addon, version=version,
                                 attachment_formset=attachment_formset)
    postdata = request.POST if request.method == 'POST' else None
    all_forms = [form, attachment_formset]

    if waffle.switch_is_active('buchets') and version:
        features_list = [unicode(f) for f in version.features.to_list()]
        appfeatures_form = AppFeaturesForm(data=postdata,
                                           instance=version.features)
        all_forms.append(appfeatures_form)
    else:
        appfeatures_form = None
        features_list = None

    queue_type = form.helper.review_type
    redirect_url = reverse('reviewers.apps.queue_%s' % queue_type)
    is_admin = acl.action_allowed(request, 'Addons', 'Edit')

    if request.method == 'POST' and all(f.is_valid() for f in all_forms):

        old_types = set(o.id for o in addon.device_types)
        new_types = set(form.cleaned_data.get('device_override'))

        if waffle.switch_is_active('buchets'):
            old_features = set(features_list)
            new_features = set(unicode(f) for f
                               in appfeatures_form.instance.to_list())

        if form.cleaned_data.get('action') == 'public':
            if old_types != new_types:
                # The reviewer overrode the device types. We need to not
                # publish this app immediately.
                if addon.make_public == amo.PUBLIC_IMMEDIATELY:
                    addon.update(make_public=amo.PUBLIC_WAIT)

                # And update the device types to what the reviewer set.
                AddonDeviceType.objects.filter(addon=addon).delete()
                for device in form.cleaned_data.get('device_override'):
                    addon.addondevicetype_set.create(device_type=device)

                # Log that the reviewer changed the device types.
                added_devices = new_types - old_types
                removed_devices = old_types - new_types
                msg = _(u'Device(s) changed by '
                         'reviewer: {0}').format(', '.join(
                    [_(u'Added {0}').format(unicode(amo.DEVICE_TYPES[d].name))
                     for d in added_devices] +
                    [_(u'Removed {0}').format(
                     unicode(amo.DEVICE_TYPES[d].name))
                     for d in removed_devices]))
                amo.log(amo.LOG.REVIEW_DEVICE_OVERRIDE, addon,
                        addon.current_version, details={'comments': msg})

            if (waffle.switch_is_active('buchets') and
                 old_features != new_features):
                # The reviewer overrode the requirements. We need to not
                # publish this app immediately.
                if addon.make_public == amo.PUBLIC_IMMEDIATELY:
                    addon.update(make_public=amo.PUBLIC_WAIT)

                appfeatures_form.save(mark_for_rereview=False)

                # Log that the reviewer changed the minimum requirements.
                added_features = new_features - old_features
                removed_features = old_features - new_features

                fmt = ', '.join(
                      [_(u'Added {0}').format(f) for f in added_features] +
                      [_(u'Removed {0}').format(f) for f in removed_features])
                # L10n: {0} is the list of requirements changes.
                msg = _(u'Requirements changed by reviewer: {0}').format(fmt)
                amo.log(amo.LOG.REVIEW_FEATURES_OVERRIDE, addon,
                        addon.current_version, details={'comments': msg})

        form.helper.process()

        if form.cleaned_data.get('notify'):
            EditorSubscription.objects.get_or_create(user=request.amo_user,
                                                     addon=addon)

        messages.success(request, _('Review successfully processed.'))
        return redirect(redirect_url)

    canned = AppCannedResponse.objects.all()
    actions = form.helper.actions.items()

    try:
        if not version:
            raise Version.DoesNotExist
        show_diff = (addon.versions.exclude(id=version.id)
                                   .filter(files__isnull=False,
                                           created__lt=version.created,
                                           files__status=amo.STATUS_PUBLIC)
                                   .latest())
    except Version.DoesNotExist:
        show_diff = None

    # The actions we should show a minimal form from.
    actions_minimal = [k for (k, a) in actions if not a.get('minimal')]

    # We only allow the user to check/uncheck files for "pending"
    allow_unchecking_files = form.helper.review_type == "pending"

    versions = (Version.with_deleted.filter(addon=addon)
                                    .order_by('-created')
                                    .transform(Version.transformer_activity)
                                    .transform(Version.transformer))

    product_attrs = {
        'product': json.dumps(
            product_as_dict(request, addon, False, 'reviewer'),
            cls=JSONEncoder),
        'manifest_url': addon.manifest_url,
    }

    pager = paginate(request, versions, 10)

    num_pages = pager.paginator.num_pages
    count = pager.paginator.count

    ctx = context(request, version=version, product=addon, pager=pager,
                  num_pages=num_pages, count=count,
                  flags=Review.objects.filter(addon=addon, flag=True),
                  form=form, canned=canned, is_admin=is_admin,
                  status_types=amo.STATUS_CHOICES, show_diff=show_diff,
                  allow_unchecking_files=allow_unchecking_files,
                  actions=actions, actions_minimal=actions_minimal,
                  tab=queue_type, product_attrs=product_attrs,
                  attachment_formset=attachment_formset,
                  appfeatures_form=appfeatures_form,
                  default_visibility=DEFAULT_ACTION_VISIBILITY)

    if features_list is not None:
        ctx['feature_list'] = features_list

    return jingo.render(request, 'reviewers/review.html', ctx)
Esempio n. 48
0
def _get_themes(request, reviewer, flagged=False, rereview=False):
    """Check out themes.

    :param flagged: Flagged themes (amo.STATUS_REVIEW_PENDING)
    :param rereview: Re-uploaded themes (RereviewQueueTheme)

    """
    num = 0
    themes = []
    locks = []

    status = (amo.STATUS_REVIEW_PENDING if flagged else
              amo.STATUS_PUBLIC if rereview else amo.STATUS_PENDING)

    if rereview:
        # Rereview themes.
        num, themes, locks = _get_rereview_themes(reviewer)
    else:
        # Pending and flagged themes.
        locks = ThemeLock.objects.no_cache().filter(
            reviewer=reviewer, theme__addon__status=status)
        num, themes = _calc_num_themes_checkout(locks)
        if themes:
            return themes
        themes = Persona.objects.no_cache().filter(addon__status=status,
                                                   themelock=None)

    # Don't allow self-reviews.
    if (not settings.ALLOW_SELF_REVIEWS
            and not acl.action_allowed(request, 'Admin', '%')):
        if rereview:
            themes = themes.exclude(theme__addon__addonuser__user=reviewer)
        else:
            themes = themes.exclude(addon__addonuser__user=reviewer)

    # Check out themes by setting lock.
    themes = list(themes)[:num]
    expiry = get_updated_expiry()
    for theme in themes:
        if rereview:
            theme = theme.theme
        ThemeLock.objects.create(theme=theme, reviewer=reviewer, expiry=expiry)

# Empty pool? Go look for some expired locks.
    if not themes:
        expired_locks = ThemeLock.objects.filter(
            expiry__lte=datetime.datetime.now(),
            theme__addon__status=status)[:rvw.THEME_INITIAL_LOCKS]
        # Steal expired locks.
        for lock in expired_locks:
            lock.reviewer = reviewer
            lock.expiry = expiry
            lock.save()
        if expired_locks:
            locks = expired_locks

    if rereview:
        return RereviewQueueTheme.objects.filter(
            theme__themelock__reviewer=reviewer)

    # New theme locks may have been created, grab all reviewer's themes again.
    return [lock.theme for lock in locks]
Esempio n. 49
0
 def wrapper(request, *args, **kw):
     from access import acl
     for app, action in pairs:
         if acl.action_allowed(request, app, action):
             return f(request, *args, **kw)
     return http.HttpResponseForbidden()
Esempio n. 50
0
def themes_single(request, slug):
    """
    Like a detail page, manually review a single theme if it is pending
    and isn't locked.
    """
    reviewer = request.user.get_profile()
    reviewable = True

    # Don't review an already reviewed theme.
    theme = get_object_or_404(Persona, addon__slug=slug)
    if (theme.addon.status != amo.STATUS_PENDING
            and not theme.rereviewqueuetheme_set.all()):
        reviewable = False

    if (not settings.ALLOW_SELF_REVIEWS
            and not acl.action_allowed(request, 'Admin', '%')
            and theme.addon.has_author(request.amo_user)):
        reviewable = False
    else:
        # Don't review a locked theme (that's not locked to self).
        try:
            lock = theme.themelock
            if (lock.reviewer.id != reviewer.id
                    and lock.expiry > datetime.datetime.now()):
                reviewable = False
            elif (lock.reviewer.id != reviewer.id
                  and lock.expiry < datetime.datetime.now()):
                # Steal expired lock.
                lock.reviewer = reviewer
                lock.expiry = get_updated_expiry()
                lock.save()
            else:
                # Update expiry.
                lock.expiry = get_updated_expiry()
                lock.save()
        except ThemeLock.DoesNotExist:
            # Create lock if not created.
            ThemeLock.objects.create(theme=theme,
                                     reviewer=reviewer,
                                     expiry=get_updated_expiry())

    ThemeReviewFormset = formset_factory(forms.ThemeReviewForm)
    formset = ThemeReviewFormset(initial=[{'theme': theme.id}])

    # Since we started the review on the single page, we want to return to the
    # single page rather than get shot back to the queue.
    request.session['theme_redirect_url'] = reverse('editors.themes.single',
                                                    args=[theme.addon.slug])

    rereview = (theme.rereviewqueuetheme_set.all()[0]
                if theme.rereviewqueuetheme_set.exists() else None)
    return jingo.render(
        request, 'editors/themes/single.html',
        context(
            **{
                'formset':
                formset,
                'theme':
                rereview if rereview else theme,
                'theme_formsets':
                zip([rereview if rereview else theme], formset),
                'theme_reviews':
                paginate(
                    request,
                    ActivityLog.objects.filter(
                        action=amo.LOG.THEME_REVIEW.id,
                        _arguments__contains=theme.addon.id)),
                'actions':
                get_actions_json(),
                'theme_count':
                1,
                'rereview':
                rereview,
                'reviewable':
                reviewable,
                'reject_reasons':
                rvw.THEME_REJECT_REASONS.items(),
                'action_dict':
                rvw.REVIEW_ACTIONS,
                'tab':
                ('flagged' if theme.addon.status == amo.STATUS_REVIEW_PENDING
                 else 'rereview' if rereview else 'pending')
            }))
Esempio n. 51
0
def is_admin_reviewer(request):
    return acl.action_allowed(request, 'ReviewerAdminTools', 'View')
Esempio n. 52
0
 def wrapper(request, *args, **kw):
     from access import acl
     for app, action in pairs:
         if acl.action_allowed(request, app, action):
             return f(request, *args, **kw)
     raise PermissionDenied
Esempio n. 53
0
def global_settings(request):
    """
    Storing standard AMO-wide information used in global headers, such as
    account links and settings.
    """
    account_links = []
    tools_links = []
    context = {}

    if request.user.is_authenticated():
        # TODO(jbalogh): reverse links
        amo_user = request.amo_user
        account_links.append({
            'text': _('View Profile'),
            'href': request.user.get_profile().get_url_path(),
        })
        account_links.append({
            'text': _('Edit Profile'),
            'href': reverse('users.edit')
        })
        if request.amo_user.is_developer:
            account_links.append({
                'text': _('My Add-ons'),
                'href': '/developers/addons'
            })

        account_links.append({
            'text':
            _('My Collections'),
            'href':
            reverse('collections.user', args=[amo_user.username])
        })
        if amo_user.favorite_addons:
            account_links.append({
                'text':
                _('My Favorites'),
                'href':
                reverse('collections.detail',
                        args=[amo_user.username, 'favorites'])
            })

        account_links.append({
            'text':
            _('Log out'),
            'href':
            remora_url('/users/logout?to=' + urlquote(request.path)),
        })

        tools_links.append({'text': _('Developer Hub'), 'href': '/developers'})
        if acl.action_allowed(request, 'Editors', '%'):
            tools_links.append({'text': _('Editor Tools'), 'href': '/editors'})
        if acl.action_allowed(request, 'Localizers', '%'):
            tools_links.append({
                'text': _('Localizer Tools'),
                'href': '/localizers'
            })
        if acl.action_allowed(request, 'Admin', '%'):
            tools_links.append({
                'text': _('Admin Tools'),
                'href': reverse('zadmin.home')
            })

        context['amo_user'] = request.amo_user
    else:
        context['amo_user'] = AnonymousUser()

    context.update({
        'account_links': account_links,
        'settings': settings,
        'amo': amo,
        'tools_links': tools_links,
        'ADMIN_MESSAGE': get_config('site_notice')
    })
    return context
Esempio n. 54
0
 def has_permission(self, request, view):
     if (request.method == 'GET'
             or acl.action_allowed(request, 'Apps', 'Publisher')):
         return True
     log.info('Publisher authorization failed')
     return False
Esempio n. 55
0
def check_contrib_stats_perms(context, addon):
    request = context['request']
    if addon.has_author(request.amo_user) or acl.action_allowed(
            request, 'RevenueStats', 'View'):
        return True
Esempio n. 56
0
def global_settings(request):
    """
    Storing standard AMO-wide information used in global headers, such as
    account links and settings.
    """
    account_links = []
    tools_links = []
    context = {}

    tools_title = _('Developer')

    if request.user.is_authenticated() and hasattr(request, 'amo_user'):
        amo_user = request.amo_user
        account_links.append({
            'text': _('View Profile'),
            'href': request.user.get_profile().get_url_path(),
        })
        account_links.append({'text': _('Edit Profile'),
                              'href': reverse('users.edit')})
        account_links.append({
            'text': _('My Collections'),
            'href': reverse('collections.user', args=[amo_user.username])})

        if amo_user.favorite_addons:
            account_links.append(
                {'text': _('My Favorites'),
                 'href': reverse('collections.detail',
                                 args=[amo_user.username, 'favorites'])})

        if waffle.switch_is_active('marketplace'):
            account_links.append({'text': _('My Purchases'),
                                  'href': reverse('users.purchases')})
        account_links.append({
            'text': _('Log out'),
            'href': remora_url('/users/logout?to=' + urlquote(request.path)),
        })

        if request.amo_user.is_developer:
            tools_links.append({'text': _('Manage My Add-ons'),
                                'href': reverse('devhub.addons')})

            tools_links.append({'text': _('Submit a New Add-on'),
                                'href': reverse('devhub.submit.1')})

            if waffle.flag_is_active(request, 'accept-webapps'):
                tools_links.append({'text': _('Submit a New Web App'),
                                    'href': reverse('devhub.submit_apps.1')})

        tools_links.append({'text': _('Developer Hub'),
                            'href': reverse('devhub.index')})

        if acl.action_allowed(request, 'Editors', '%'):
            tools_title = _('Tools')
            tools_links.append({'text': _('Editor Tools'),
                                'href': reverse('editors.home')})
        if acl.action_allowed(request, 'Localizers', '%'):
            tools_title = _('Tools')
            tools_links.append({'text': _('Localizer Tools'),
                                'href': '/localizers'})
        if acl.action_allowed(request, 'Admin', '%'):
            tools_title = _('Tools')
            tools_links.append({'text': _('Admin Tools'),
                                'href': reverse('zadmin.home')})

        context['amo_user'] = request.amo_user
    else:
        context['amo_user'] = AnonymousUser()

    context.update({'account_links': account_links,
                    'settings': settings, 'amo': amo,
                    'tools_links': tools_links,
                    'tools_title': tools_title,
                    'ADMIN_MESSAGE': get_config('site_notice')})
    return context
Esempio n. 57
0
def global_settings(request):
    """Store global Marketplace-wide info. used in the header."""
    account_links = []
    tools_links = []
    footer_links = []
    context = {}

    tools_title = _('Tools')

    if request.user.is_authenticated() and getattr(request, 'amo_user', None):
        amo_user = request.amo_user
        context['is_reviewer'] = acl.check_reviewer(request)
        account_links = [
            # TODO: Coming soon with payments.
            # {'text': _('Account History'),
            #  'href': reverse('account.purchases')},
            {
                'text': _('Account Settings'),
                'href': '/settings'
            },
            {
                'text': _('Change Password'),
                'href': 'https://login.persona.org/signin'
            },
            {
                'text': _('Sign out'),
                'href': reverse('users.logout')
            },
        ]
        if '/developers/' not in request.path:
            tools_links.append({
                'text': _('Developer Hub'),
                'href': reverse('ecosystem.landing')
            })
            if amo_user.is_app_developer:
                tools_links.append({
                    'text': _('My Submissions'),
                    'href': reverse('mkt.developers.apps')
                })
        if '/reviewers/' not in request.path and context['is_reviewer']:
            footer_links.append({
                'text':
                _('Reviewer Tools'),
                'href':
                reverse('reviewers.apps.queue_pending'),
            })
        if acl.action_allowed(request, 'Localizers', '%'):
            footer_links.append({
                'text':
                _('Localizer Tools'),
                'href':
                'https://addons.mozilla.org/localizers/'
            })
        if acl.action_allowed(request, 'AccountLookup', '%'):
            footer_links.append({
                'text': _('Lookup Tool'),
                'href': reverse('lookup.home')
            })
        if acl.action_allowed(request, 'Admin', '%'):
            footer_links.append({
                'text': _('Admin Tools'),
                'href': reverse('zadmin.home')
            })

        tools_links += footer_links

        context['amo_user'] = amo_user
        logged = True
    else:
        context['amo_user'] = AnonymousUser()
        logged = False

    DESKTOP = (getattr(request, 'TABLET', None)
               or not getattr(request, 'MOBILE', None))

    context.update(account_links=account_links,
                   settings=settings,
                   amo=amo,
                   mkt=mkt,
                   APP=amo.FIREFOX,
                   tools_links=tools_links,
                   tools_title=tools_title,
                   footer_links=footer_links,
                   ADMIN_MESSAGE=get_config('site_notice'),
                   collect_timings_percent=get_collect_timings(),
                   is_admin=acl.action_allowed(request, 'Addons', 'Edit'),
                   DESKTOP=DESKTOP,
                   logged=logged)
    return context
Esempio n. 58
0
 def is_authorized(self, request, object=None):
     if request.method == 'GET' and acl.action_allowed(request,
                                                       'Apps', 'Review'):
         return True
Esempio n. 59
0
def _review(request, addon):
    version = addon.latest_version

    if not settings.ALLOW_SELF_REVIEWS and addon.has_author(request.amo_user):
        amo.messages.warning(request, _('Self-reviews are not allowed.'))
        return redirect(reverse('editors.queue'))

    form = forms.get_review_form(request.POST or None,
                                 request=request,
                                 addon=addon,
                                 version=version)

    queue_type = (form.helper.review_type
                  if form.helper.review_type != 'preliminary' else 'prelim')
    redirect_url = reverse('editors.queue_%s' % queue_type)

    num = request.GET.get('num')
    paging = {}
    if num:
        try:
            num = int(num)
        except (ValueError, TypeError):
            raise http.Http404
        total = queue_counts(queue_type)
        paging = {
            'current': num,
            'total': total,
            'prev': num > 1,
            'next': num < total,
            'prev_url': '%s?num=%s' % (redirect_url, num - 1),
            'next_url': '%s?num=%s' % (redirect_url, num + 1)
        }

    is_admin = acl.action_allowed(request, 'Addons', 'Edit')

    if request.method == 'POST' and form.is_valid():
        form.helper.process()
        if form.cleaned_data.get('notify'):
            EditorSubscription.objects.get_or_create(user=request.amo_user,
                                                     addon=addon)
        if form.cleaned_data.get('adminflag') and is_admin:
            addon.update(admin_review=False)
        amo.messages.success(request, _('Review successfully processed.'))
        return redirect(redirect_url)

    canned = AddonCannedResponse.objects.all()
    actions = form.helper.actions.items()

    statuses = [
        amo.STATUS_PUBLIC, amo.STATUS_LITE, amo.STATUS_LITE_AND_NOMINATED
    ]

    try:
        show_diff = (addon.versions.exclude(id=version.id).filter(
            files__isnull=False,
            created__lt=version.created,
            files__status__in=statuses).latest())
    except Version.DoesNotExist:
        show_diff = None

    # The actions we should show a minimal form from.
    actions_minimal = [k for (k, a) in actions if not a.get('minimal')]

    # We only allow the user to check/uncheck files for "pending"
    allow_unchecking_files = form.helper.review_type == "pending"

    versions = (Version.objects.filter(addon=addon).exclude(
        files__status=amo.STATUS_BETA).order_by('-created').transform(
            Version.transformer_activity).transform(Version.transformer))

    class PseudoVersion(object):
        def __init__(self):
            self.all_activity = []

        all_files = ()
        approvalnotes = None
        compatible_apps_ordered = ()
        releasenotes = None
        status = 'Deleted',

        @property
        def created(self):
            return self.all_activity[0].created

        @property
        def version(self):
            return (self.all_activity[0].activity_log.details.get(
                'version', '[deleted]'))

    # Grab review history for deleted versions of this add-on
    comments = (CommentLog.objects.filter(
        activity_log__action__in=amo.LOG_REVIEW_QUEUE,
        activity_log__versionlog=None,
        activity_log__addonlog__addon=addon).order_by(
            'created').select_related('activity_log'))

    comment_versions = defaultdict(PseudoVersion)
    for c in comments:
        c.version = c.activity_log.details.get('version', c.created)
        comment_versions[c.version].all_activity.append(c)

    all_versions = comment_versions.values()
    all_versions.extend(versions)
    all_versions.sort(key=lambda v: v.created, reverse=True)

    pager = amo.utils.paginate(request, all_versions, 10)

    num_pages = pager.paginator.num_pages
    count = pager.paginator.count

    try:
        flags = ViewQueue.objects.get(id=addon.id).flags
    except ViewQueue.DoesNotExist:
        flags = []

    ctx = context(version=version,
                  addon=addon,
                  pager=pager,
                  num_pages=num_pages,
                  count=count,
                  flags=flags,
                  form=form,
                  paging=paging,
                  canned=canned,
                  is_admin=is_admin,
                  show_diff=show_diff,
                  allow_unchecking_files=allow_unchecking_files,
                  actions=actions,
                  actions_minimal=actions_minimal)

    return render(request, 'editors/review.html', ctx)
Esempio n. 60
0
def report_menu(context, request, addon, report):

    report_tree = [
        {
            'name': 'overview',
            'url': '',
            'title': _('Overview'),
        },
        {
            'name':
            'downloads',
            'url':
            'downloads/',
            'title':
            _('Downloads'),
            'children': [
                {
                    'name': 'sources',
                    'url': 'downloads/sources/',
                    'title': _('by Source'),
                },
            ]
        },
        {
            'name':
            'usage',
            'url':
            'usage/',
            'title':
            _('Daily Users'),
            'children': [
                {
                    'name': 'versions',
                    'url': 'usage/versions/',
                    'title': _('by Add-on Version')
                },
                {
                    'name': 'apps',
                    'url': 'usage/applications/',
                    'title': _('by Application')
                },
                {
                    'name': 'locales',
                    'url': 'usage/languages/',
                    'title': _('by Language')
                },
                {
                    'name': 'os',
                    'url': 'usage/os/',
                    'title': _('by Platform')
                },
                {
                    'name': 'statuses',
                    'url': 'usage/status/',
                    'title': _('by Add-on Status')
                },
            ]
        },
    ]

    if (request.user.is_authenticated()
            and (acl.action_allowed(request, 'Admin', 'ViewAnyStats')
                 or addon.has_author(request.amo_user))):
        report_tree.append({
            'name': 'contributions',
            'url': 'contributions/',
            'title': _('Contributions')
        })

    base_url = reverse('stats.overview', args=[addon.slug])
    """Reports Menu. navigation for the various statistic reports."""
    c = {'report': report, 'base_url': base_url, 'report_tree': report_tree}
    return c