def extension_detail(request, addon): """Extensions details page.""" # If current version is incompatible with this app, redirect. comp_apps = addon.compatible_apps if comp_apps and request.APP not in comp_apps: prefixer = urlresolvers.get_url_prefix() prefixer.app = comp_apps.keys()[0].short return redirect('addons.detail', addon.slug, permanent=True) # Popular collections this addon is part of. collections = Collection.objects.listed().filter( addons=addon, application=request.APP.id) ctx = { 'addon': addon, 'src': request.GET.get('src', 'dp-btn-primary'), 'version_src': request.GET.get('src', 'dp-btn-version'), 'tags': addon.tags.not_blacklisted(), 'grouped_ratings': GroupedRating.get(addon.id), 'review_form': ReviewForm(), 'reviews': Review.without_replies.all().filter( addon=addon, is_latest=True), 'get_replies': Review.get_replies, 'collections': collections.order_by('-subscribers')[:3], 'abuse_form': AbuseForm(request=request), } # details.html just returns the top half of the page for speed. The bottom # does a lot more queries we don't want on the initial page load. if request.is_ajax(): # Other add-ons/apps from the same author(s). ctx['author_addons'] = addon.authors_other_addons(app=request.APP)[:6] return render(request, 'addons/impala/details-more.html', ctx) else: return render(request, 'addons/impala/details.html', ctx)
def extension_detail(request, addon): """Extensions details page.""" # If current version is incompatible with this app, redirect. comp_apps = addon.compatible_apps if comp_apps and request.APP not in comp_apps: prefixer = get_url_prefix() prefixer.app = list(comp_apps.keys())[0].short return redirect('addons.detail', addon.slug, permanent=True) ctx = { 'addon': addon, 'src': request.GET.get('src', 'dp-btn-primary'), 'version_src': request.GET.get('src', 'dp-btn-version'), 'tags': addon.tags.not_denied(), 'grouped_ratings': GroupedRating.get(addon.id), 'review_form': RatingForm(), 'reviews': Rating.without_replies.all().filter( addon=addon, is_latest=True).exclude(body=None), 'get_replies': Rating.get_replies, 'abuse_form': AbuseForm(request=request), } # details.html just returns the top half of the page for speed. The bottom # does a lot more queries we don't want on the initial page load. if request.is_ajax(): # Other add-ons/apps from the same author(s). ctx['author_addons'] = addon.authors_other_addons(app=request.APP)[:6] return render(request, 'addons/impala/details-more.html', ctx) else: return render(request, 'addons/impala/details.html', ctx)
def test_app_in_fragment_cache_key(cache_mock): cache_mock.return_value = "" request = mock.Mock() request.APP.id = "<app>" request.user.is_authenticated.return_value = False template = jingo.get_env().from_string("{% cache 1 %}{% endcache %}") render(request, template) assert cache_mock.call_args[0][0].endswith("<app>")
def handler404(request, exception=None, **kwargs): if request.is_api: # It's a v3+ api request return JsonResponse( {'detail': six.text_type(NotFound.default_detail)}, status=404) # X_IS_MOBILE_AGENTS is set by nginx as an env variable when it detects # a mobile User Agent or when the mamo cookie is present. if request.META.get('X_IS_MOBILE_AGENTS') == '1': return render(request, 'amo/404-responsive.html', status=404) else: return render(request, 'amo/404.html', status=404)
def handler404(request): if request.path_info.startswith('/api/v3/'): return JsonResponse( {'detail': unicode(NotFound.default_detail)}, status=404) elif request.path_info.startswith('/api/'): # Pass over to handler404 view in api if api was targeted. return legacy_api.views.handler404(request) if request.MOBILE: return render(request, 'amo/404-responsive.html', status=404) else: return render(request, 'amo/404.html', status=404)
def handler404(request): if re.match(settings.DRF_API_REGEX, request.path_info): return JsonResponse( {'detail': unicode(NotFound.default_detail)}, status=404) elif request.path_info.startswith('/api/'): # Pass over to handler404 view in api if api was targeted. return legacy_api.views.handler404(request) # X_IS_MOBILE_AGENTS is set by nginx as an env variable when it detects # a mobile User Agent or when the mamo cookie is present. if request.META.get('X_IS_MOBILE_AGENTS') == '1': return render(request, 'amo/404-responsive.html', status=404) else: return render(request, 'amo/404.html', status=404)
def handler404(request): if request.is_api: # It's a v3+ api request return JsonResponse( {'detail': unicode(NotFound.default_detail)}, status=404) elif request.is_legacy_api: # It's a legacy api request - pass over to legacy api handler404. return legacy_api.views.handler404(request) # X_IS_MOBILE_AGENTS is set by nginx as an env variable when it detects # a mobile User Agent or when the mamo cookie is present. if request.META.get('X_IS_MOBILE_AGENTS') == '1': return render(request, 'amo/404-responsive.html', status=404) else: return render(request, 'amo/404.html', status=404)
def addon_manage(request, addon): form = AddonStatusForm(request.POST or None, instance=addon) pager = amo.utils.paginate( request, Version.unfiltered.filter(addon=addon), 30) # A list coercion so this doesn't result in a subquery with a LIMIT which # MySQL doesn't support (at this time). versions = list(pager.object_list) files = File.objects.filter(version__in=versions).select_related('version') formset = FileFormSet(request.POST or None, queryset=files) if form.is_valid() and formset.is_valid(): if 'status' in form.changed_data: ActivityLog.create(amo.LOG.CHANGE_STATUS, addon, form.cleaned_data['status']) log.info('Addon "%s" status changed to: %s' % ( addon.slug, form.cleaned_data['status'])) form.save() for form in formset: if 'status' in form.changed_data: log.info('Addon "%s" file (ID:%d) status changed to: %s' % ( addon.slug, form.instance.id, form.cleaned_data['status'])) form.save() return redirect('zadmin.addon_manage', addon.slug) # Build a map from file.id to form in formset for precise form display form_map = dict((form.instance.id, form) for form in formset.forms) # A version to file map to avoid an extra query in the template file_map = {} for file in files: file_map.setdefault(file.version_id, []).append(file) return render(request, 'zadmin/addon_manage.html', { 'addon': addon, 'pager': pager, 'versions': versions, 'form': form, 'formset': formset, 'form_map': form_map, 'file_map': file_map})
def add(request, addon, template=None): if addon.has_author(request.user): raise PermissionDenied form = forms.ReviewForm(request.POST or None) if (request.method == 'POST' and form.is_valid() and not request.POST.get('detailed')): details = _review_details(request, addon, form) review = Review.objects.create(**details) if 'flag' in form.cleaned_data and form.cleaned_data['flag']: rf = ReviewFlag(review=review, user_id=request.user.id, flag=ReviewFlag.OTHER, note='URLs') rf.save() amo.log(amo.LOG.ADD_REVIEW, addon, review) log.debug('New review: %s' % review.id) reply_url = helpers.url('addons.reviews.reply', addon.slug, review.id, add_prefix=False) data = {'name': addon.name, 'rating': '%s out of 5 stars' % details['rating'], 'review': details['body'], 'reply_url': helpers.absolutify(reply_url)} emails = [a.email for a in addon.authors.all()] send_mail('reviews/emails/add_review.ltxt', u'Mozilla Add-on User Review: %s' % addon.name, emails, Context(data), 'new_review') return redirect(helpers.url('addons.reviews.list', addon.slug)) return render(request, template, dict(addon=addon, form=form))
def unsubscribe(request, hash=None, token=None, perm_setting=None): """ Pulled from django contrib so that we can add user into the form so then we can show relevant messages about the user. """ assert hash is not None and token is not None user = None try: email = UnsubscribeCode.parse(token, hash) user = UserProfile.objects.get(email=email) except (ValueError, UserProfile.DoesNotExist): pass perm_settings = [] if user is not None and perm_setting is not None: unsubscribed = True perm_setting = notifications.NOTIFICATIONS_BY_SHORT[perm_setting] UserNotification.objects.update_or_create( user=user, notification_id=perm_setting.id, defaults={'enabled': False}) perm_settings = [perm_setting] else: unsubscribed = False email = '' return render(request, 'users/unsubscribe.html', {'unsubscribed': unsubscribed, 'email': email, 'perm_settings': perm_settings})
def monthly_pick(request): form = MonthlyPickFormSet(request.POST or None) if request.method == 'POST' and form.is_valid(): form.save() messages.success(request, 'Changes successfully saved.') return redirect('zadmin.monthly_pick') return render(request, 'zadmin/monthly_pick.html', dict(form=form))
def stats_report(request, addon, report): check_stats_permission(request, addon) stats_base_url = reverse('stats.overview', args=[addon.slug]) view = get_report_view(request) return render(request, 'stats/reports/%s.html' % report, {'addon': addon, 'report': report, 'view': view, 'stats_base_url': stats_base_url})
def addon_detail(request, addon): """Add-ons details page dispatcher.""" if addon.is_deleted or (addon.is_pending() and not addon.is_persona()): # Allow pending themes to be listed. raise http.Http404 if addon.is_disabled: return render(request, 'addons/impala/disabled.html', {'addon': addon}, status=404) # addon needs to have a version and be valid for this app. if addon.type in request.APP.types: if addon.type == amo.ADDON_PERSONA: return persona_detail(request, addon) else: if not addon.current_version: raise http.Http404 return extension_detail(request, addon) else: # Redirect to an app that supports this type. try: new_app = [a for a in amo.APP_USAGE if addon.type in a.types][0] except IndexError: raise http.Http404 else: prefixer = urlresolvers.get_url_prefix() prefixer.app = new_app.short return http.HttpResponsePermanentRedirect(reverse( 'addons.detail', args=[addon.slug]))
def themes(request, user, category=None): cats = Category.objects.filter(type=amo.ADDON_PERSONA) ctx = { 'profile': user, 'categories': sorted(cats, key=attrgetter('weight', 'name')), 'search_cat': 'themes' } if user.is_artist: base = user.addons.public().filter( type=amo.ADDON_PERSONA, addonuser__user=user, addonuser__listed=True) if category: qs = cats.filter(slug=category) ctx['category'] = cat = get_list_or_404(qs)[0] base = base.filter(categories__id=cat.id) else: base = Addon.objects.none() filter_ = PersonasFilter(request, base, key='sort', default='popular') addons = amo.utils.paginate(request, filter_.qs, 30, count=base.count()) ctx.update({ 'addons': addons, 'filter': filter_, 'sorting': filter_.field, 'sort_opts': filter_.opts }) return render(request, 'browse/personas/grid.html', ctx)
def promos(request, context, version, platform, compat_mode='strict'): if platform: platform = platform.lower() platform = amo.PLATFORM_DICT.get(platform, amo.PLATFORM_ALL) modules = get_modules(request, platform.api_name, version) return render(request, 'addons/impala/homepage_promos.html', {'modules': modules, 'module_context': context})
def home(request): # Add-ons. base = Addon.objects.listed(request.APP).filter(type=amo.ADDON_EXTENSION) # This is lame for performance. Kill it with ES. frozen = list(FrozenAddon.objects.values_list('addon', flat=True)) # We want to display 6 Featured Extensions, Up & Coming Extensions and # Featured Themes. featured = Addon.objects.featured(request.APP, request.LANG, amo.ADDON_EXTENSION)[:6] hotness = base.exclude(id__in=frozen).order_by('-hotness')[:6] personas = Addon.objects.featured(request.APP, request.LANG, amo.ADDON_PERSONA)[:6] # Most Popular extensions is a simple links list, we display slightly more. popular = base.exclude(id__in=frozen).order_by('-average_daily_users')[:10] # We want a maximum of 6 Featured Collections as well (though we may get # fewer than that). collections = Collection.objects.filter(listed=True, application=request.APP.id, type=amo.COLLECTION_FEATURED)[:6] return render(request, 'addons/home.html', {'popular': popular, 'featured': featured, 'hotness': hotness, 'personas': personas, 'src': 'homepage', 'collections': collections})
def compare(request, diff, key=None, type='file'): form = forms.FileCompareForm(request.POST or None, addon=diff.addon, initial={'left': diff.left.file, 'right': diff.right.file}, request=request) response = check_compare_form(request, form) if response: return response data = setup_viewer(request, diff.left.file) data['diff'] = diff data['poll_url'] = reverse('files.compare.poll', args=[diff.left.file.id, diff.right.file.id]) data['form'] = form if not diff.is_extracted(): extract_file(diff.left) extract_file(diff.right) if diff.is_extracted(): data.update({'status': True, 'files': diff.get_files(), 'files_deleted': diff.get_deleted_files()}) key = diff.left.get_default(key) if key not in data['files'] and key not in data['files_deleted']: raise http.Http404 diff.select(key) data['key'] = key if diff.is_diffable(): data['left'], data['right'] = diff.read_file() tmpl = 'files/content.html' if type == 'fragment' else 'files/viewer.html' return render(request, tmpl, data)
def home(request): # Shuffle the list and get 3 items. def rand(xs): return random.shuffle(xs) or xs[:3] # Get some featured add-ons with randomness. featured = Addon.featured_random(request.APP, request.LANG)[:3] # Get 10 popular add-ons, then pick 3 at random. qs = list(Addon.objects.listed(request.APP) .filter(type=amo.ADDON_EXTENSION) .order_by('-average_daily_users') .values_list('id', flat=True)[:10]) popular = rand(qs) # Do one query and split up the add-ons. addons = (Addon.objects.filter(id__in=featured + popular) .filter(type=amo.ADDON_EXTENSION)) featured = [a for a in addons if a.id in featured] popular = sorted([a for a in addons if a.id in popular], key=attrgetter('average_daily_users'), reverse=True) if not request.META.get('HTTP_USER_AGENT'): ios_user = False else: ios_user = '******' in request.META.get('HTTP_USER_AGENT') return render(request, 'addons/mobile/home.html', {'featured': featured, 'popular': popular, 'ios_user': ios_user})
def browse(request, viewer, key=None, type='file'): form = forms.FileCompareForm(request.POST or None, addon=viewer.addon, initial={'left': viewer.file}, request=request) response = check_compare_form(request, form) if response: return response data = setup_viewer(request, viewer.file) data['viewer'] = viewer data['poll_url'] = reverse('files.poll', args=[viewer.file.id]) data['form'] = form if not viewer.is_extracted(): extract_file(viewer) if viewer.is_extracted(): data.update({'status': True, 'files': viewer.get_files()}) key = viewer.get_default(key) if key not in data['files']: raise http.Http404 viewer.select(key) data['key'] = key if (not viewer.is_directory() and not viewer.is_binary()): data['content'] = viewer.read_file() tmpl = 'files/content.html' if type == 'fragment' else 'files/viewer.html' return render(request, tmpl, data)
def deleted_themes(request): data = request.GET.copy() deleted = Addon.unfiltered.filter(type=amo.ADDON_PERSONA, status=amo.STATUS_DELETED) if not data.get('start') and not data.get('end'): today = datetime.date.today() data['start'] = datetime.date(today.year, today.month, 1) form = forms.DeletedThemeLogForm(data) if form.is_valid(): data = form.cleaned_data if data.get('start'): deleted = deleted.filter(modified__gte=data['start']) if data.get('end'): deleted = deleted.filter(modified__lte=data['end']) if data.get('search'): term = data['search'] deleted = deleted.filter( Q(name__localized_string__icontains=term)) return render(request, 'reviewers/themes/deleted.html', { 'form': form, 'pager': paginate(request, deleted.order_by('-modified'), 30), 'tab': 'deleted' })
def add_view(self, request, form_url='', extra_context=None): """Override the default admin add view for bulk add.""" form = self.model_add_form() if request.method == 'POST': form = self.model_add_form(request.POST) if form.is_valid(): inserted = 0 duplicates = 0 for x in form.cleaned_data[self.add_form_field].splitlines(): # check with the cache if self.deny_list_model.blocked(x): duplicates += 1 continue try: self.deny_list_model.objects.create( **{self.model_field: x.lower()}) inserted += 1 except IntegrityError: # although unlikely, someone else could have added # the same value. # note: unless we manage the transactions manually, # we do lose a primary id here. duplicates += 1 msg = '%s new values added to the deny list.' % (inserted) if duplicates: msg += ' %s duplicates were ignored.' % (duplicates) messages.success(request, msg) form = self.model_add_form() return render(request, self.template_path, {'form': form})
def themes_list(request, flagged=False, rereview=False): """Themes queue in list format.""" themes = [] if flagged: # TODO (ngoke): rename to STATUS_FLAGGED. themes = Addon.objects.filter(status=amo.STATUS_REVIEW_PENDING, type=amo.ADDON_PERSONA, persona__isnull=False) elif rereview: themes = [ rqt.theme.addon for rqt in RereviewQueueTheme.objects.select_related('theme__addon')] else: themes = Addon.objects.filter(status=amo.STATUS_PENDING, type=amo.ADDON_PERSONA, persona__isnull=False) search_form = forms.ThemeSearchForm(request.GET) per_page = request.GET.get('per_page', QUEUE_PER_PAGE) pager = paginate(request, themes, per_page) return render(request, 'reviewers/themes/queue_list.html', context( **{'addons': pager.object_list, 'flagged': flagged, 'pager': pager, 'rereview': rereview, 'theme_search_form': search_form, 'statuses': dict((k, unicode(v)) for k, v in amo.STATUS_CHOICES_API.items()), 'tab': ('rereview_themes' if rereview else 'flagged_themes' if flagged else 'pending_themes')}))
def themes_logs(request): data = request.GET.copy() if not data.get('start') and not data.get('end'): today = datetime.date.today() data['start'] = datetime.date(today.year, today.month, 1) form = forms.ReviewThemeLogForm(data) theme_logs = ActivityLog.objects.filter(action=amo.LOG.THEME_REVIEW.id) if form.is_valid(): data = form.cleaned_data if data.get('start'): theme_logs = theme_logs.filter(created__gte=data['start']) if data.get('end'): theme_logs = theme_logs.filter(created__lte=data['end']) if data.get('search'): term = data['search'] theme_logs = theme_logs.filter( Q(_details__icontains=term) | Q(user__display_name__icontains=term) | Q(user__username__icontains=term)).distinct() pager = paginate(request, theme_logs, 30) data = context(form=form, pager=pager, ACTION_DICT=amo.REVIEW_ACTIONS, REJECT_REASONS=amo.THEME_REJECT_REASONS, tab='themes') return render(request, 'reviewers/themes/logs.html', data)
def eventlog_detail(request, id): log = get_object_or_404(ActivityLog.objects.editor_events(), pk=id) review = None # I really cannot express the depth of the insanity incarnate in # our logging code... if len(log.arguments) > 1 and isinstance(log.arguments[1], Review): review = log.arguments[1] is_admin = acl.action_allowed(request, 'ReviewerAdminTools', 'View') can_undelete = review and review.deleted and ( is_admin or request.user.pk == log.user.pk) if request.method == 'POST': # A Form seems overkill for this. if request.POST['action'] == 'undelete': if not can_undelete: raise PermissionDenied ReviewerScore.award_moderation_points( log.user, review.addon, review.id, undo=True) review.undelete() return redirect('editors.eventlog.detail', id) data = context(request, log=log, can_undelete=can_undelete) return render(request, 'editors/eventlog_detail.html', data)
def extension_detail(request, addon): if not request.META.get('HTTP_USER_AGENT'): ios_user = False else: ios_user = '******' in request.META.get('HTTP_USER_AGENT') return render(request, 'addons/mobile/details.html', {'addon': addon, 'ios_user': ios_user})
def extensions(request, category=None): TYPE = amo.ADDON_EXTENSION if category is not None: q = Category.objects.filter(application=request.APP.id, type=TYPE) category = get_object_or_404(q, slug=category) sort = request.GET.get('sort') if not sort and category and category.count > 4: return category_landing(request, category) addons, filter = addon_listing(request, [TYPE]) sorting = filter.field src = 'cb-btn-%s' % sorting dl_src = 'cb-dl-%s' % sorting if category: addons = addons.filter(categories__id=category.id) addons = amo.utils.paginate(request, addons, count=addons.count()) return render(request, 'browse/extensions.html', {'section': 'extensions', 'addon_type': TYPE, 'category': category, 'addons': addons, 'filter': filter, 'sorting': sorting, 'sort_opts': filter.opts, 'src': src, 'dl_src': dl_src, 'search_cat': '%s,0' % TYPE})
def queue_moderated(request): qs = Review.objects.all().to_moderate().order_by('reviewflag__created') page = paginate(request, qs, per_page=20) motd_editable = acl.action_allowed(request, 'AddonReviewerMOTD', 'Edit') flags = dict(ReviewFlag.FLAGS) reviews_formset = ReviewFlagFormSet(request.POST or None, queryset=page.object_list, request=request) if request.method == 'POST': if reviews_formset.is_valid(): reviews_formset.save() else: amo.messages.error( request, ' '.join(e.as_text() or _('An unknown error occurred') for e in reviews_formset.errors)) return redirect(reverse('editors.queue_moderated')) return render(request, 'editors/queue.html', context(request, reviews_formset=reviews_formset, tab='moderated', page=page, flags=flags, search_form=None, point_types=amo.REVIEWED_AMO, motd_editable=motd_editable))
def home(request): data = context( reviews_total=ActivityLog.objects.total_reviews(theme=True)[:5], reviews_monthly=ActivityLog.objects.monthly_reviews(theme=True)[:5], queue_counts=queue_counts_themes(request) ) return render(request, 'editors/themes/home.html', data)
def compat(request): minimum = 10 ratio = .8 binary = None # Expected usage: # For Firefox 8.0 reports: ?appver=1-8.0 # For over 70% incompatibility: ?appver=1-8.0&ratio=0.7 # For binary-only add-ons: ?appver=1-8.0&type=binary data = {'appver': '%s' % FIREFOX_COMPAT[0]['main'], 'minimum': minimum, 'ratio': ratio, 'type': 'all'} version = data['appver'] data.update(request.GET.items()) form = CompatForm(data) if request.GET and form.is_valid(): version = form.cleaned_data['appver'] if form.cleaned_data['ratio'] is not None: ratio = float(form.cleaned_data['ratio']) if form.cleaned_data['minimum'] is not None: minimum = int(form.cleaned_data['minimum']) if form.cleaned_data['type'] == 'binary': binary = True usage_addons, usage_total = compat_stats( request, version, minimum, ratio, binary) return render(request, 'zadmin/compat.html', { 'form': form, 'usage_addons': usage_addons, 'usage_total': usage_total})
def render_cat(request, template, data=None, extra=None): if extra is None: extra = {} if data is None: data = {} data.update(dict(search_cat='collections')) return render(request, template, data, **extra)
def mail(request): backend = DevEmailBackend() if request.method == 'POST': backend.clear() return redirect('zadmin.mail') return render(request, 'zadmin/mail.html', dict(mail=backend.view_all()))
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 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.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 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, 'action_dict': rvw.REVIEW_ACTIONS, 'tab': ('flagged' if theme.addon.status == amo.STATUS_REVIEW_PENDING else 'rereview' if rereview else 'pending') }))
def review(request, addon, channel=None): # channel is passed in as text, but we want the constant. channel = amo.CHANNEL_CHOICES_LOOKUP.get( channel, amo.RELEASE_CHANNEL_LISTED) unlisted_only = (channel == amo.RELEASE_CHANNEL_UNLISTED or not addon.has_listed_versions()) if unlisted_only and not acl.check_unlisted_addons_reviewer(request): raise PermissionDenied version = addon.find_latest_version( channel=channel, exclude=(amo.STATUS_BETA,)) if not settings.ALLOW_SELF_REVIEWS and addon.has_author(request.user): amo.messages.warning( request, ugettext('Self-reviews are not allowed.')) return redirect(reverse('editors.queue')) form_helper = ReviewHelper(request=request, addon=addon, version=version) form = forms.ReviewForm(request.POST if request.method == 'POST' else None, helper=form_helper) if channel == amo.RELEASE_CHANNEL_LISTED: queue_type = form.helper.handler.review_type redirect_url = reverse('editors.queue_%s' % queue_type) else: redirect_url = reverse('editors.unlisted_queue_all') is_admin = acl.action_allowed(request, amo.permissions.ADDONS_EDIT) is_post_reviewer = acl.action_allowed(request, amo.permissions.ADDONS_POST_REVIEW) approvals_info = None reports = None user_reviews = None was_auto_approved = False if channel == amo.RELEASE_CHANNEL_LISTED: if addon.current_version: was_auto_approved = addon.current_version.was_auto_approved if is_post_reviewer and version and version.is_webextension: try: approvals_info = addon.addonapprovalscounter except AddonApprovalsCounter.DoesNotExist: pass developers = addon.listed_authors reports = Paginator( (AbuseReport.objects .filter(Q(addon=addon) | Q(user__in=developers)) .order_by('-created')), 5).page(1) user_reviews = Paginator( (Review.without_replies .filter(addon=addon, rating__lte=3, body__isnull=False) .order_by('-created')), 5).page(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.user, addon=addon) if form.cleaned_data.get('adminflag') and is_admin: addon.update(admin_review=False) amo.messages.success( request, ugettext('Review successfully processed.')) clear_reviewing_cache(addon.id) 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 version and not getattr(settings, 'CELERY_ALWAYS_EAGER', False): for file_ in version.all_files: if not file_.has_been_validated: devhub_tasks.validate(file_) canned = AddonCannedResponse.objects.all() actions = form.helper.actions.items() try: show_diff = version and ( addon.versions.exclude(id=version.id).filter( channel=channel, 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 for. actions_minimal = [k for (k, a) in actions if not a.get('minimal')] # The actions we should show the comments form for (contrary to minimal # form above, it defaults to True, because most actions do need to have # the comments form). actions_comments = [k for (k, a) in actions if a.get('comments', True)] versions = (Version.unfiltered.filter(addon=addon, channel=channel) .select_related('autoapprovalsummary') .exclude(files__status=amo.STATUS_BETA) .order_by('-created') .transform(Version.transformer_activity) .transform(Version.transformer)) # We assume comments on old deleted versions are for listed versions. # See _get_comments_for_hard_deleted_versions above for more detail. all_versions = (_get_comments_for_hard_deleted_versions(addon) if channel == amo.RELEASE_CHANNEL_LISTED else []) 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 max_average_daily_users = int( get_config('AUTO_APPROVAL_MAX_AVERAGE_DAILY_USERS') or 0), min_approved_updates = int( get_config('AUTO_APPROVAL_MIN_APPROVED_UPDATES') or 0) auto_approval_info = {} # Now that we've paginated the versions queryset, iterate on them to # generate auto approvals info. Note that the variable should not clash # the already existing 'version'. for a_version in pager.object_list: if not is_post_reviewer or not a_version.is_ready_for_auto_approval: continue try: summary = a_version.autoapprovalsummary except AutoApprovalSummary.DoesNotExist: auto_approval_info[a_version.pk] = None continue # Call calculate_verdict() again, it will use the data already stored. # Need to pass max_average_daily_users and min_approved_updates current # values. verdict_info = summary.calculate_verdict( max_average_daily_users=max_average_daily_users, min_approved_updates=min_approved_updates, pretty=True) auto_approval_info[a_version.pk] = verdict_info if version: flags = get_flags(version) else: 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, actions_comments=actions_comments, whiteboard_form=forms.WhiteboardForm(instance=addon), user_changes=user_changes_log, unlisted=(channel == amo.RELEASE_CHANNEL_UNLISTED), approvals_info=approvals_info, is_post_reviewer=is_post_reviewer, auto_approval_info=auto_approval_info, reports=reports, user_reviews=user_reviews, was_auto_approved=was_auto_approved) return render(request, 'editors/review.html', ctx)
def js(request): return render(request, 'addons/popups.html', content_type='text/javascript')
def _queue(request, TableObj, tab, qs=None, unlisted=False, SearchForm=QueueSearchForm): if qs is None: qs = TableObj.Meta.model.objects.all() if SearchForm: if request.GET: search_form = SearchForm(request.GET) if search_form.is_valid(): qs = search_form.filter_qs(qs) else: search_form = SearchForm() is_searching = search_form.data.get('searching') else: search_form = None is_searching = False admin_reviewer = is_admin_reviewer(request) # Those restrictions will only work with our RawSQLModel, so we need to # make sure we're not dealing with a regular Django ORM queryset first. if hasattr(qs, 'sql_model'): if not is_searching and not admin_reviewer: qs = filter_admin_review_for_legacy_queue(qs) if not unlisted: if is_limited_reviewer(request): qs = qs.having('waiting_time_hours >=', amo.REVIEW_LIMITED_DELAY_HOURS) qs = filter_static_themes( qs, acl.action_allowed(request, amo.permissions.ADDONS_REVIEW), acl.action_allowed(request, amo.permissions.STATIC_THEMES_REVIEW)) # Most WebExtensions are picked up by auto_approve cronjob, they # don't need to appear in the queues, unless auto approvals have # been disabled for them. Webextension static themes aren't auto # approved. qs = qs.filter( Q(addon_type_id=amo.ADDON_STATICTHEME) | Q(**{'files.is_webextension': False}) | Q(**{'addons_addonreviewerflags.auto_approval_disabled': True}) ) order_by = request.GET.get('sort', TableObj.default_order_by()) if hasattr(TableObj, 'translate_sort_cols'): order_by = TableObj.translate_sort_cols(order_by) table = TableObj(data=qs, order_by=order_by) per_page = request.GET.get('per_page', REVIEWS_PER_PAGE) try: per_page = int(per_page) except ValueError: per_page = REVIEWS_PER_PAGE if per_page <= 0 or per_page > REVIEWS_PER_PAGE_MAX: per_page = REVIEWS_PER_PAGE page = paginate(request, table.rows, per_page=per_page) table.set_page(page) return render( request, 'reviewers/queue.html', context(request, table=table, page=page, tab=tab, search_form=search_form, point_types=amo.REVIEWED_AMO, unlisted=unlisted))
def credits(request): developers = (UserProfile.objects .exclude(display_name=None) .filter(groupuser__group__name='Developers Credits') .order_by('display_name') .distinct()) past_developers = (UserProfile.objects .exclude(display_name=None) .filter( groupuser__group__name='Past Developers Credits') .order_by('display_name') .distinct()) other_contribs = (UserProfile.objects .exclude(display_name=None) .filter( groupuser__group__name='Other Contributors Credits') .order_by('display_name') .distinct()) languages = sorted(list(set(settings.AMO_LANGUAGES) - set(['en-US']))) localizers = [] for lang in languages: users = (UserProfile.objects .exclude(display_name=None) .filter(groupuser__group__name='%s Localizers' % lang) .order_by('display_name') .distinct()) if users: localizers.append((lang, users)) total_reviews = (ActivityLog.objects.total_reviews() .filter(approval_count__gt=10)) reviewers = defaultdict(list) for total in total_reviews: cnt = total.get('approval_count', 0) if cnt > 10000: reviewers[10000].append(total) elif cnt > 5000: reviewers[5000].append(total) elif cnt > 2000: reviewers[2000].append(total) elif cnt > 1000: reviewers[1000].append(total) elif cnt > 500: reviewers[500].append(total) elif cnt > 100: reviewers[100].append(total) elif cnt > 10: reviewers[10].append(total) context = { 'developers': developers, 'past_developers': past_developers, 'other_contribs': other_contribs, 'localizers': localizers, 'reviewers': reviewers, } return render(request, 'pages/credits.html', context)
def appversions(request): apps, versions = get_versions() return render(request, 'applications/appversions.html', { 'apps': apps, 'versions': versions })
def privacy(request, addon): if not addon.privacy_policy: return http.HttpResponseRedirect(addon.get_url_path()) return render(request, 'addons/privacy.html', {'addon': addon})
def login(request): return render(request, 'users/login.html')
def leaderboard(request): return render(request, 'editors/leaderboard.html', context( request, scores=ReviewerScore.all_users_by_score()))
def find_replacement_addon(request): guid = request.GET.get('guid') if not guid: raise http.Http404 return render(request, 'addons/replacement_addons.html')
def performance(request, user_id=False): user = request.user editors = _recent_editors() is_admin = (acl.action_allowed(request, amo.permissions.ADMIN) or acl.action_allowed(request, amo.permissions.REVIEWER_ADMIN_TOOLS_VIEW)) if is_admin and user_id: try: user = UserProfile.objects.get(pk=user_id) except UserProfile.DoesNotExist: pass # Use request.user from above. motd_editable = acl.action_allowed( request, amo.permissions.ADDON_REVIEWER_MOTD_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.user.id == user.id), motd_editable=motd_editable) return render(request, 'editors/performance.html', data)
def handler500(request): if request.is_legacy_api: # Pass over to handler500 view in api if api was targeted. return legacy_api.views.handler500(request) else: return render(request, 'amo/500.html', status=500)
def search(request, tag_name=None): APP = request.APP types = (amo.ADDON_EXTENSION, amo.ADDON_THEME, amo.ADDON_DICT, amo.ADDON_SEARCH, amo.ADDON_LPAPP) category = request.GET.get('cat') if category == 'collections': extra_params = {'sort': {'newest': 'created'}} else: extra_params = None fixed = fix_search_query(request.GET, extra_params=extra_params) if fixed is not request.GET: # We generally want a 301, except if it's a "type", because that's only # here to support the new frontend, so a permanent redirect could mess # things up when the user is going back and forth between the old and # new frontend. https://github.com/mozilla/addons-server/issues/6846 status = 302 if 'type' in request.GET else 301 return http.HttpResponseRedirect( urlparams(request.path, **fixed), status=status) facets = request.GET.copy() # In order to differentiate between "all versions" and an undefined value, # we use "any" instead of "" in the frontend. if 'appver' in facets and facets['appver'] == 'any': facets['appver'] = '' form = ESSearchForm(facets or {}) form.is_valid() # Let the form try to clean data. form_data = form.cleaned_data if tag_name: form_data['tag'] = tag_name if category == 'themes' or form_data.get('atype') == amo.ADDON_PERSONA: return _personas(request) sort, extra_sort = split_choices(form.sort_choices, 'created') if form_data.get('atype') == amo.ADDON_SEARCH: # Search add-ons should not be searched by ADU, so replace 'Users' # sort with 'Weekly Downloads'. sort, extra_sort = list(sort), list(extra_sort) sort[1] = extra_sort[1] del extra_sort[1] # Perform search, using aggregation so that we can build the facets UI. # Note that we don't need to aggregate on platforms, that facet it built # from our constants directly, using the current application for this # request (request.APP). appversion_field = 'current_version.compatible_apps.%s.max' % APP.id qs = (Addon.search_public().filter(app=APP.id) .aggregate(tags={'terms': {'field': 'tags'}}, appversions={'terms': {'field': appversion_field}}, categories={'terms': {'field': 'category', 'size': 200}}) ) filters = ['atype', 'appver', 'cat', 'sort', 'tag', 'platform'] mapping = {'users': '-average_daily_users', 'rating': '-bayesian_rating', 'created': '-created', 'name': 'name.raw', 'downloads': '-weekly_downloads', 'updated': '-last_updated', 'hotness': '-hotness'} qs = _filter_search(request, qs, form_data, filters, mapping, types=types) pager = amo.utils.paginate(request, qs) ctx = { 'is_pjax': request.META.get('HTTP_X_PJAX'), 'pager': pager, 'query': form_data, 'form': form, 'sort_opts': sort, 'extra_sort_opts': extra_sort, 'sorting': sort_sidebar(request, form_data, form), 'sort': form_data.get('sort'), } if not ctx['is_pjax']: aggregations = pager.object_list.aggregations ctx.update({ 'tag': tag_name, 'categories': category_sidebar(request, form_data, aggregations), 'platforms': platform_sidebar(request, form_data), 'versions': version_sidebar(request, form_data, aggregations), 'tags': tag_sidebar(request, form_data, aggregations), }) return render(request, 'search/results.html', ctx)
def _queue(request, TableObj, tab, qs=None, unlisted=False, SearchForm=forms.QueueSearchForm): if qs is None: qs = TableObj.Meta.model.objects.all() if SearchForm: if request.GET: search_form = SearchForm(request.GET) if search_form.is_valid(): qs = search_form.filter_qs(qs) else: search_form = SearchForm() is_searching = search_form.data.get('searching') else: search_form = None is_searching = False admin_reviewer = is_admin_reviewer(request) if hasattr(qs, 'filter'): if not is_searching and not admin_reviewer: qs = exclude_admin_only_addons(qs) # Those additional restrictions will only work with our RawSQLModel, # so we need to make sure we're not dealing with a regular Django ORM # queryset first. if hasattr(qs, 'sql_model') and not unlisted: if is_limited_reviewer(request): qs = qs.having('waiting_time_hours >=', REVIEW_LIMITED_DELAY_HOURS) if waffle.switch_is_active('post-review'): # Hide webextensions from the queues so that human reviewers # don't pick them up: auto-approve cron should take care of # them. qs = qs.filter(**{'files.is_webextension': False}) motd_editable = acl.action_allowed( request, amo.permissions.ADDON_REVIEWER_MOTD_EDIT) order_by = request.GET.get('sort', TableObj.default_order_by()) if hasattr(TableObj, 'translate_sort_cols'): order_by = TableObj.translate_sort_cols(order_by) table = TableObj(data=qs, order_by=order_by) per_page = request.GET.get('per_page', REVIEWS_PER_PAGE) try: per_page = int(per_page) except ValueError: per_page = REVIEWS_PER_PAGE if per_page <= 0 or per_page > REVIEWS_PER_PAGE_MAX: per_page = REVIEWS_PER_PAGE page = paginate(request, table.rows, per_page=per_page) table.set_page(page) return render( request, 'editors/queue.html', context(request, table=table, page=page, tab=tab, search_form=search_form, point_types=amo.REVIEWED_AMO, unlisted=unlisted, motd_editable=motd_editable))
def handler403(request, exception=None, **kwargs): return render(request, 'amo/403.html', status=403)
def dashboard(request): stats_base_url = reverse('stats.dashboard') view = get_report_view(request) return render(request, 'stats/dashboard.html', {'report': 'site', 'view': view, 'stats_base_url': stats_base_url})
def export_email_addresses(request): return render(request, 'zadmin/export_button.html', {})
def review(request, addon, channel=None): whiteboard_url = reverse('reviewers.whiteboard', args=(channel or 'listed', addon.slug if addon.slug else addon.pk)) channel, content_review_only = determine_channel(channel) was_auto_approved = (channel == amo.RELEASE_CHANNEL_LISTED and addon.current_version and addon.current_version.was_auto_approved) is_static_theme = addon.type == amo.ADDON_STATICTHEME # If we're just looking (GET) we can bypass the specific permissions checks # if we have ReviewerTools:View. bypass_more_specific_permissions_because_read_only = ( request.method == 'GET' and acl.action_allowed(request, amo.permissions.REVIEWER_TOOLS_VIEW)) if not bypass_more_specific_permissions_because_read_only: perform_review_permission_checks( request, addon, channel, content_review_only=content_review_only) version = addon.find_latest_version(channel=channel, exclude=()) if not settings.ALLOW_SELF_REVIEWS and addon.has_author(request.user): amo.messages.warning(request, ugettext('Self-reviews are not allowed.')) return redirect(reverse('reviewers.queue')) # Get the current info request state to set as the default. form_initial = {'info_request': addon.pending_info_request} form_helper = ReviewHelper(request=request, addon=addon, version=version, content_review_only=content_review_only) form = ReviewForm(request.POST if request.method == 'POST' else None, helper=form_helper, initial=form_initial) is_admin = acl.action_allowed(request, amo.permissions.REVIEWS_ADMIN) approvals_info = None reports = None user_ratings = None if channel == amo.RELEASE_CHANNEL_LISTED: if was_auto_approved: try: approvals_info = addon.addonapprovalscounter except AddonApprovalsCounter.DoesNotExist: pass developers = addon.listed_authors reports = Paginator((AbuseReport.objects.filter( Q(addon=addon) | Q(user__in=developers)).order_by('-created')), 5).page(1) user_ratings = Paginator((Rating.without_replies.filter( addon=addon, rating__lte=3, body__isnull=False).order_by('-created')), 5).page(1) if content_review_only: queue_type = 'content_review' elif was_auto_approved: queue_type = 'auto_approved' else: queue_type = form.helper.handler.review_type redirect_url = reverse('reviewers.queue_%s' % queue_type) else: redirect_url = reverse('reviewers.unlisted_queue_all') if request.method == 'POST' and form.is_valid(): form.helper.process() amo.messages.success(request, ugettext('Review successfully processed.')) clear_reviewing_cache(addon.id) return redirect(redirect_url) # Kick off validation tasks for any files in this version which don't have # cached validation, since reviewers 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 version and not getattr(settings, 'CELERY_ALWAYS_EAGER', False): for file_ in version.all_files: if not file_.has_been_validated: devhub_tasks.validate(file_) actions = form.helper.actions.items() try: # Find the previously approved version to compare to. show_diff = version and (addon.versions.exclude(id=version.id).filter( # We're looking for a version that was either manually approved # (either it has no auto approval summary, or it has one but # with a negative verdict because it was locked by a reviewer # who then approved it themselves), or auto-approved but then # confirmed. Q(autoapprovalsummary__isnull=True) | Q(autoapprovalsummary__verdict=amo.NOT_AUTO_APPROVED) | Q(autoapprovalsummary__verdict=amo.AUTO_APPROVED, autoapprovalsummary__confirmed=True)).filter( channel=channel, files__isnull=False, created__lt=version.created, files__status=amo.STATUS_PUBLIC).latest()) except Version.DoesNotExist: show_diff = None # The actions we shouldn't show a minimal form for. actions_full = [ k for (k, a) in actions if not (is_static_theme or a.get('minimal')) ] # The actions we should show the comments form for (contrary to minimal # form above, it defaults to True, because most actions do need to have # the comments form). actions_comments = [k for (k, a) in actions if a.get('comments', True)] versions = (Version.unfiltered.filter( addon=addon, channel=channel).select_related( 'autoapprovalsummary').order_by('-created').transform( Version.transformer_activity).transform(Version.transformer)) # We assume comments on old deleted versions are for listed versions. # See _get_comments_for_hard_deleted_versions above for more detail. all_versions = (_get_comments_for_hard_deleted_versions(addon) if channel == amo.RELEASE_CHANNEL_LISTED else []) 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 auto_approval_info = {} # Now that we've paginated the versions queryset, iterate on them to # generate auto approvals info. Note that the variable should not clash # the already existing 'version'. for a_version in pager.object_list: if not a_version.is_ready_for_auto_approval: continue try: summary = a_version.autoapprovalsummary except AutoApprovalSummary.DoesNotExist: auto_approval_info[a_version.pk] = None continue # Call calculate_verdict() again, it will use the data already stored. verdict_info = summary.calculate_verdict(pretty=True) auto_approval_info[a_version.pk] = verdict_info flags = get_flags(addon, version) if version else [] if not is_static_theme: try: whiteboard = Whiteboard.objects.get(pk=addon.pk) except Whiteboard.DoesNotExist: whiteboard = Whiteboard(pk=addon.pk) whiteboard_form = WhiteboardForm(instance=whiteboard, prefix='whiteboard') else: whiteboard_form = None backgrounds = version.get_background_image_urls() if version else [] 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, actions=actions, actions_comments=actions_comments, actions_full=actions_full, addon=addon, api_token=request.COOKIES.get(API_TOKEN_COOKIE, None), approvals_info=approvals_info, auto_approval_info=auto_approval_info, backgrounds=backgrounds, content_review_only=content_review_only, count=count, flags=flags, form=form, is_admin=is_admin, num_pages=num_pages, pager=pager, reports=reports, show_diff=show_diff, subscribed=ReviewerSubscription.objects.filter( user=request.user, addon=addon).exists(), unlisted=(channel == amo.RELEASE_CHANNEL_UNLISTED), user_changes=user_changes_log, user_ratings=user_ratings, version=version, was_auto_approved=was_auto_approved, whiteboard_form=whiteboard_form, whiteboard_url=whiteboard_url) return render(request, 'reviewers/review.html', ctx)
def home(request): data = context( reviews_total=ActivityLog.objects.total_reviews(theme=True)[:5], reviews_monthly=ActivityLog.objects.monthly_reviews(theme=True)[:5], queue_counts=queue_counts_themes(request)) return render(request, 'editors/themes/home.html', data)
def blocked_detail(request, id): bltypes = dict((m._type, m) for m in (BlocklistItem, BlocklistPlugin)) item = get_object_or_404(bltypes[id[0]], details=id[1:]) return render(request, 'blocklist/blocked_detail.html', {'item': item})
def index(request): log = ActivityLog.objects.admin_events()[:5] return render(request, 'zadmin/index.html', {'log': log})
def site_stats_report(request, report): stats_base_url = reverse('stats.dashboard') view = get_report_view(request) return render(request, 'stats/reports/%s.html' % report, {'report': report, 'view': view, 'stats_base_url': stats_base_url})
def show_settings(request): settings_dict = debug.get_safe_settings() return render(request, 'zadmin/settings.html', { 'settings_dict': settings_dict, 'title': 'Settings!' })
def handler404(request, exception=None, **kwargs): if getattr(request, 'is_api', False): # It's a v3+ api request return JsonResponse({'detail': str(NotFound.default_detail)}, status=404) return render(request, 'amo/404.html', status=404)
def login(request, template=None): return render(request, template)
def blocked_list(request, apiver=3): app = request.APP.guid objs = get_items(apiver, app)[1].values() + get_plugins(apiver, app) items = sorted(objs, key=attrgetter('created'), reverse=True) return render(request, 'blocklist/blocked_list.html', {'items': items})
def search(request, tag_name=None): APP = request.APP types = (amo.ADDON_EXTENSION, amo.ADDON_THEME, amo.ADDON_DICT, amo.ADDON_SEARCH, amo.ADDON_LPAPP) category = request.GET.get('cat') if category == 'collections': extra_params = {'sort': {'newest': 'created'}} else: extra_params = None fixed = fix_search_query(request.GET, extra_params=extra_params) if fixed is not request.GET: return http.HttpResponsePermanentRedirect(urlparams(request.path, **fixed)) facets = request.GET.copy() # In order to differentiate between "all versions" and an undefined value, # we use "any" instead of "" in the frontend. if 'appver' in facets and facets['appver'] == 'any': facets['appver'] = '' form = ESSearchForm(facets or {}) form.is_valid() # Let the form try to clean data. form_data = form.cleaned_data if tag_name: form_data['tag'] = tag_name if category == 'collections': return _collections(request) elif category == 'themes' or form_data.get('atype') == amo.ADDON_PERSONA: return _personas(request) sort, extra_sort = split_choices(form.sort_choices, 'created') if form_data.get('atype') == amo.ADDON_SEARCH: # Search add-ons should not be searched by ADU, so replace 'Users' # sort with 'Weekly Downloads'. sort, extra_sort = list(sort), list(extra_sort) sort[1] = extra_sort[1] del extra_sort[1] # Perform search, using aggregation so that we can build the facets UI. # Note that we don't need to aggregate on platforms, that facet it built # from our constants directly, using the current application for this # request (request.APP). appversion_field = 'current_version.compatible_apps.%s.max' % APP.id qs = (Addon.search_public().filter(app=APP.id) .aggregate(tags={'terms': {'field': 'tags'}}, appversions={'terms': {'field': appversion_field}}, categories={'terms': {'field': 'category', 'size': 200}}) ) if waffle.switch_is_active('boost-webextensions-in-search'): qs = qs.score({ # Boost webextensions if the waffle switch is enabled. 'weight': WEBEXTENSIONS_WEIGHT, 'filter': {'term': {'current_version.files.is_webextension': True}} }) filters = ['atype', 'appver', 'cat', 'sort', 'tag', 'platform'] mapping = {'users': '-average_daily_users', 'rating': '-bayesian_rating', 'created': '-created', 'name': 'name_sort', 'downloads': '-weekly_downloads', 'updated': '-last_updated', 'hotness': '-hotness'} qs = _filter_search(request, qs, form_data, filters, mapping, types=types) pager = amo.utils.paginate(request, qs) ctx = { 'is_pjax': request.META.get('HTTP_X_PJAX'), 'pager': pager, 'query': form_data, 'form': form, 'sort_opts': sort, 'extra_sort_opts': extra_sort, 'sorting': sort_sidebar(request, form_data, form), 'sort': form_data.get('sort'), } if not ctx['is_pjax']: aggregations = pager.object_list.aggregations ctx.update({ 'tag': tag_name, 'categories': category_sidebar(request, form_data, aggregations), 'platforms': platform_sidebar(request, form_data), 'versions': version_sidebar(request, form_data, aggregations), 'tags': tag_sidebar(request, form_data, aggregations), }) return render(request, 'search/results.html', ctx)
def motd(request): form = None form = MOTDForm(initial={'motd': get_config('reviewers_review_motd')}) data = context(request, form=form) return render(request, 'reviewers/motd.html', data)
def env(request): env = {} for k in request.META.keys(): env[k] = debug.cleanse_setting(k, request.META[k]) return render(request, 'zadmin/settings.html', {'settings_dict': env, 'title': 'Env!'})