def has_read_developer_agreement(self): from olympia.zadmin.models import get_config # Fallback date in case the config date value is invalid or set to the # future. The current fallback date is when we enabled post-review. dev_agreement_change_fallback = datetime(2017, 9, 22, 17, 36) if self.read_dev_agreement is None: return False try: last_agreement_change_config = get_config( 'last_dev_agreement_change_date') change_config_date = datetime.strptime( last_agreement_change_config, '%Y-%m-%d %H:%M') # If the config date is in the future, instead check against the # fallback date if change_config_date > datetime.now(): return self.read_dev_agreement > dev_agreement_change_fallback return self.read_dev_agreement > change_config_date except (ValueError, TypeError): log.exception('last_developer_agreement_change misconfigured, ' '"%s" is not a ' 'datetime' % last_agreement_change_config) return self.read_dev_agreement > dev_agreement_change_fallback
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)
def motd(request): form = None motd_editable = acl.action_allowed( request, amo.permissions.ADDON_REVIEWER_MOTD_EDIT) if motd_editable: form = forms.MOTDForm( initial={'motd': get_config('editors_review_motd')}) data = context(request, form=form, motd_editable=motd_editable) return render(request, 'editors/motd.html', data)
def handle(self, *args, **options): """Command entry point.""" self.post_review = waffle.switch_is_active('post-review') self.dry_run = options.get('dry_run', False) self.max_average_daily_users = int( get_config('AUTO_APPROVAL_MAX_AVERAGE_DAILY_USERS') or 0) self.min_approved_updates = int( get_config('AUTO_APPROVAL_MIN_APPROVED_UPDATES') or 0) if self.min_approved_updates <= 0 or self.max_average_daily_users <= 0: # Auto approval are shut down if one of those values is not present # or <= 0. url = '%s%s' % ( settings.SITE_URL, reverse('admin:zadmin_config_changelist')) raise CommandError( 'Auto-approvals are deactivated because either ' 'AUTO_APPROVAL_MAX_AVERAGE_DAILY_USERS or ' 'AUTO_APPROVAL_MIN_APPROVED_UPDATES have not been ' 'set or were set to 0. Use the admin tools Config model to ' 'set them by going to %s.' % url) self.successful_verdict = ( amo.WOULD_HAVE_BEEN_AUTO_APPROVED if self.dry_run else amo.AUTO_APPROVED) self.stats = Counter() # Get a lock before doing anything, we don't want to have multiple # instances of the command running in parallel. lock = atomic_lock(settings.TMP_PATH, LOCK_NAME, lifetime=15 * 60) with lock as lock_attained: if lock_attained: qs = self.fetch_candidates() self.stats['total'] = len(qs) for version in qs: self.process(version) self.log_final_summary(self.stats) else: # We didn't get the lock... log.error('auto-approve lock present, aborting.')
def base_context(**kw): ctx = {'motd': get_config('editors_review_motd')} ctx.update(kw) return 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 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 = ugettext('Tools') is_reviewer = False if request.user.is_authenticated(): is_reviewer = acl.is_user_any_kind_of_reviewer(request.user) account_links.append({'text': ugettext('My Profile'), 'href': request.user.get_url_path()}) if request.user.is_artist: account_links.append({'text': ugettext('My Themes'), 'href': request.user.get_themes_url_path()}) account_links.append({'text': ugettext('Account Settings'), 'href': reverse('users.edit')}) account_links.append({ 'text': ugettext('My Collections'), 'href': reverse('collections.user', args=[request.user.username])}) if request.user.favorite_addons: account_links.append( {'text': ugettext('My Favorites'), 'href': reverse('collections.detail', args=[request.user.username, 'favorites'])}) account_links.append({ 'text': ugettext('Log out'), 'href': reverse('users.logout') + '?to=' + urlquote(request.path), }) if request.user.is_developer: tools_links.append({'text': ugettext('Manage My Submissions'), 'href': reverse('devhub.addons')}) tools_links.append( {'text': ugettext('Submit a New Add-on'), 'href': reverse('devhub.submit.agreement')}) no_more_lwt = waffle.switch_is_active('disable-lwt-uploads') tools_links.append( {'text': ugettext('Submit a New Theme'), 'href': reverse('devhub.submit.agreement' if no_more_lwt else 'devhub.themes.submit')}) tools_links.append( {'text': ugettext('Developer Hub'), 'href': reverse('devhub.index')}) tools_links.append( {'text': ugettext('Manage API Keys'), 'href': reverse('devhub.api_key')} ) if is_reviewer: tools_links.append({'text': ugettext('Reviewer Tools'), 'href': reverse('reviewers.dashboard')}) if acl.action_allowed(request, amo.permissions.ANY_ADMIN): tools_links.append({'text': ugettext('Admin Tools'), 'href': reverse('zadmin.index')}) context['user'] = request.user else: context['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'), 'is_reviewer': is_reviewer}) return context
def handle(self, *args, **options): dry_run = options.get('dry_run', False) 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) if min_approved_updates <= 0 or max_average_daily_users <= 0: # Auto approval are shut down if one of those values is not present # or <= 0. url = '%s%s' % (settings.SITE_URL, reverse('admin:zadmin_config_changelist')) raise CommandError( 'Auto-approvals are deactivated because either ' 'AUTO_APPROVAL_MAX_AVERAGE_DAILY_USERS or ' 'AUTO_APPROVAL_MIN_APPROVED_UPDATES have not been ' 'set or were set to 0. Use the admin tools Config model to ' 'set them by going to %s.' % url) stats = Counter() qs = self.fetch_candidates() stats['total'] = len(qs) successful_verdict = (amo.WOULD_HAVE_BEEN_AUTO_APPROVED if dry_run else amo.AUTO_APPROVED) for version in qs: # Is the addon already locked by a reviewer ? if get_reviewing_cache(version.addon.pk): stats['locked'] += 1 continue # If admin review or more information was requested, skip this # version, let a human handle it. if version.addon.admin_review or version.has_info_request: stats['flagged'] += 1 continue # Lock the addon for ourselves, no reviewer should touch it. set_reviewing_cache(version.addon.pk, settings.TASK_USER_ID) try: log.info('Processing %s version %s...', unicode(version.addon.name), unicode(version.version)) summary, info = AutoApprovalSummary.create_summary_for_version( version, max_average_daily_users=max_average_daily_users, min_approved_updates=min_approved_updates, dry_run=dry_run) log.info('Auto Approval for %s version %s: %s', unicode(version.addon.name), unicode(version.version), summary.get_verdict_display()) stats.update({k: int(v) for k, v in info.items()}) if summary.verdict == successful_verdict: stats['auto_approved'] += 1 # FIXME: implement auto-approve if verdict is amo.AUTO_APPROVED except (AutoApprovalNotEnoughFilesError, AutoApprovalNoValidationResultError): log.info( 'Version %s was skipped either because it had no ' 'file or because it had no validation attached.', version) stats['error'] += 1 finally: clear_reviewing_cache(version.addon.pk) self.log_final_summary(stats, dry_run=dry_run)
def _upload_mlbf_to_remote_settings(*, force_base=False): last_generation_time = get_config(MLBF_TIME_CONFIG_KEY, 0, json_value=True) log.info('Starting Upload MLBF to remote settings cron job.') # This timestamp represents the point in time when all previous addon # guid + versions and blocks were used to generate the bloomfilter. # An add-on version/file from before this time will definitely be accounted # for in the bloomfilter so we can reliably assert if it's blocked or not. # An add-on version/file from after this time can't be reliably asserted - # there may be false positives or false negatives. # https://github.com/mozilla/addons-server/issues/13695 generation_time = int(time.time() * 1000) mlbf = MLBF(generation_time) previous_filter = MLBF(last_generation_time) changes_count = mlbf.blocks_changed_since_previous(previous_filter) statsd.incr( 'blocklist.cron.upload_mlbf_to_remote_settings.blocked_changed', changes_count) need_update = ( force_base or last_generation_time < get_blocklist_last_modified_time() or changes_count) if not need_update: log.info( 'No new/modified/deleted Blocks in database; ' 'skipping MLBF generation') return mlbf.generate_and_write_mlbf() statsd.incr( 'blocklist.cron.upload_mlbf_to_remote_settings.blocked_count', len(mlbf.fetch_blocked_json())) statsd.incr( 'blocklist.cron.upload_mlbf_to_remote_settings.not_blocked_count', len(mlbf.fetch_not_blocked_json())) base_filter_id = get_config(MLBF_BASE_ID_CONFIG_KEY, 0, json_value=True) # optimize for when the base_filter was the previous generation so # we don't have to load the blocked JSON file twice. base_filter = ( MLBF(base_filter_id) if last_generation_time != base_filter_id else previous_filter) make_base_filter = ( force_base or not base_filter or mlbf.should_reset_base_filter(base_filter)) if last_generation_time and not make_base_filter: try: mlbf.write_stash(previous_filter) except FileNotFoundError: log.info('No previous blocked.json so we can\'t create a stash.') # fallback to creating a new base if stash fails make_base_filter = True upload_filter.delay( generation_time, is_base=make_base_filter, upload_stash=not make_base_filter)
def test_waffle_off_disables_publishing(self): upload_mlbf_to_kinto() self.publish_attachment_mock.assert_not_called() self.publish_record_mock.assert_not_called() assert not get_config(MLBF_TIME_CONFIG_KEY)
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(): user = request.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 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=[user.username]) }) if user.favorite_addons: account_links.append({ 'text': _('My Favorites'), 'href': reverse('collections.detail', args=[user.username, 'favorites']) }) account_links.append({ 'text': _('Log out'), 'href': reverse('users.logout') + '?to=' + urlquote(request.path), }) if request.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') }, ] 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, 'Admin', '%') or acl.action_allowed(request, 'AdminTools', 'View')): tools_links.append({ 'text': _('Admin Tools'), 'href': reverse('zadmin.home') }) context['user'] = request.user else: context['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'), 'is_reviewer': is_reviewer }) return context
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')) # Get the current info request state to set as the default. form_initial = {'info_request': version and version.has_info_request} form_helper = ReviewHelper(request=request, addon=addon, version=version) form = forms.ReviewForm(request.POST if request.method == 'POST' else None, helper=form_helper, initial=form_initial) 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 was_auto_approved and is_post_reviewer: queue_type = 'auto_approved' else: queue_type = form.helper.handler.review_type redirect_url = reverse('editors.queue_%s' % queue_type) else: redirect_url = reverse('editors.unlisted_queue_all') 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: # 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 # or auto-approved but then confirmed. Q(autoapprovalsummary__isnull=True) | 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 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)] # The actions we should show the 'info request' checkbox for. actions_info_request = [k for (k, a) in actions if a.get('info_request', False)] 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, actions_info_request=actions_info_request, 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 to_representation(self, obj): return { 'read_only': settings.READ_ONLY, 'notice': get_config('site_notice'), }
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 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(): user = request.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 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=[user.username])}) if user.favorite_addons: account_links.append( {'text': _('My Favorites'), 'href': reverse('collections.detail', args=[user.username, 'favorites'])}) account_links.append({ 'text': _('Log out'), 'href': reverse('users.logout') + '?to=' + urlquote(request.path), }) if request.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, 'Admin', '%') or acl.action_allowed(request, 'AdminTools', 'View')): tools_links.append({'text': _('Admin Tools'), 'href': reverse('zadmin.home')}) context['user'] = request.user else: context['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'), 'is_reviewer': is_reviewer}) return context
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 = ugettext('Tools') is_reviewer = False if request.user.is_authenticated(): is_reviewer = acl.is_user_any_kind_of_reviewer(request.user) account_links.append({'text': ugettext('My Profile'), 'href': request.user.get_url_path()}) if request.user.is_artist: account_links.append({'text': ugettext('My Themes'), 'href': request.user.get_themes_url_path()}) account_links.append({'text': ugettext('Account Settings'), 'href': reverse('users.edit')}) account_links.append({ 'text': ugettext('My Collections'), 'href': reverse('collections.user', args=[request.user.username])}) if request.user.favorite_addons: account_links.append( {'text': ugettext('My Favorites'), 'href': reverse('collections.detail', args=[request.user.username, 'favorites'])}) account_links.append({ 'text': ugettext('Log out'), 'href': reverse('users.logout') + '?to=' + urlquote(request.path), }) if request.user.is_developer: tools_links.append({'text': ugettext('Manage My Submissions'), 'href': reverse('devhub.addons')}) links = [ {'text': ugettext('Submit a New Add-on'), 'href': reverse('devhub.submit.agreement')}, {'text': ugettext('Submit a New Theme'), 'href': reverse('devhub.themes.submit')}, {'text': ugettext('Developer Hub'), 'href': reverse('devhub.index')}, ] links.append({'text': ugettext('Manage API Keys'), 'href': reverse('devhub.api_key')}) tools_links += links if is_reviewer: tools_links.append({'text': ugettext('Reviewer Tools'), 'href': reverse('reviewers.dashboard')}) if (acl.action_allowed(request, amo.permissions.ADMIN) or acl.action_allowed(request, amo.permissions.ADMIN_TOOLS_VIEW)): tools_links.append({'text': ugettext('Admin Tools'), 'href': reverse('zadmin.index')}) context['user'] = request.user else: context['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'), 'is_reviewer': is_reviewer}) return context