def acquire_refund_permission(request, addon_id, addon, webapp=False): """This is the callback from Paypal.""" # Set up our redirects. if request.GET.get('dest', '') == 'submission': on_good = reverse('submit.app.payments.confirm', args=[addon.app_slug]) on_error = reverse('submit.app.payments.paypal', args=[addon.app_slug]) show_good_msgs = False else: # The management pages are the default. on_good = addon.get_dev_url('paypal_setup_confirm') on_error = addon.get_dev_url('paypal_setup_bounce') show_good_msgs = True if 'request_token' not in request.GET: paypal_log.debug('User did not approve permissions for' ' addon: %s' % addon_id) messages.error( request, 'You will need to accept the permissions ' 'to continue.') return redirect(on_error) paypal_log.debug('User approved permissions for addon: %s' % addon_id) token = paypal.get_permissions_token(request.GET['request_token'], request.GET['verification_code']) paypal_log.debug('Getting personal data for token: %s' % addon_id) data = paypal.get_personal_data(token) email = data.get('email') # If the email from paypal is different, something has gone wrong. if email != addon.paypal_id: paypal_log.debug('Addon paypal_id and personal data differ: ' '%s vs %s' % (email, addon.paypal_id)) messages.warning( request, _('The email returned by Paypal, ' 'did not match the PayPal email you ' 'entered. Please login using %s.') % email) return redirect(on_error) # Set the permissions token that we have just successfully used # in get_personal_data. addonpremium, created = (AddonPremium.objects.safer_get_or_create( addon=addon)) addonpremium.update(paypal_permissions_token=token) # Finally update the data returned from PayPal for this addon. paypal_log.debug('Updating personal data for: %s' % addon_id) apd, created = AddonPaymentData.objects.safer_get_or_create(addon=addon) apd.update(**data) amo.log(amo.LOG.EDIT_PROPERTIES, addon) if show_good_msgs: messages.success(request, 'Please confirm the data we ' 'received from PayPal.') return redirect(on_good)
def acquire_refund_permission(request, addon_id, addon, webapp=False): """This is the callback from Paypal.""" # Set up our redirects. if request.GET.get('dest', '') == 'submission': on_good = reverse('submit.app.payments.confirm', args=[addon.app_slug]) on_error = reverse('submit.app.payments.paypal', args=[addon.app_slug]) show_good_msgs = False else: # The management pages are the default. on_good = addon.get_dev_url('paypal_setup_confirm') on_error = addon.get_dev_url('paypal_setup_bounce') show_good_msgs = True if 'request_token' not in request.GET: paypal_log.debug('User did not approve permissions for' ' addon: %s' % addon_id) messages.error(request, 'You will need to accept the permissions ' 'to continue.') return redirect(on_error) paypal_log.debug('User approved permissions for addon: %s' % addon_id) token = paypal.get_permissions_token(request.GET['request_token'], request.GET['verification_code']) paypal_log.debug('Getting personal data for token: %s' % addon_id) data = paypal.get_personal_data(token) email = data.get('email') # If the email from paypal is different, something has gone wrong. if email != addon.paypal_id: paypal_log.debug('Addon paypal_id and personal data differ: ' '%s vs %s' % (email, addon.paypal_id)) messages.warning(request, _('The email returned by Paypal, ' 'did not match the PayPal email you ' 'entered. Please login using %s.') % email) return redirect(on_error) # Set the permissions token that we have just successfully used # in get_personal_data. addonpremium, created = (AddonPremium.objects .safer_get_or_create(addon=addon)) addonpremium.update(paypal_permissions_token=token) # Finally update the data returned from PayPal for this addon. paypal_log.debug('Updating personal data for: %s' % addon_id) apd, created = AddonPaymentData.objects.safer_get_or_create(addon=addon) apd.update(**data) amo.log(amo.LOG.EDIT_PROPERTIES, addon) if show_good_msgs: messages.success(request, 'Please confirm the data we ' 'received from PayPal.') return redirect(on_good)
def acquire_refund_permission(request, addon_id, addon, webapp=False): """This is the callback from Paypal.""" # Set up our redirects. if request.GET.get("dest", "") == "submission": on_good = reverse("submit.app.payments.confirm", args=[addon.app_slug]) on_error = reverse("submit.app.payments.paypal", args=[addon.app_slug]) show_good_msgs = False else: # The management pages are the default. on_good = addon.get_dev_url("paypal_setup_confirm") on_error = addon.get_dev_url("paypal_setup_bounce") show_good_msgs = True if "request_token" not in request.GET: paypal_log.debug("User did not approve permissions for" " addon: %s" % addon_id) messages.error(request, "You will need to accept the permissions " "to continue.") return redirect(on_error) paypal_log.debug("User approved permissions for addon: %s" % addon_id) token = paypal.get_permissions_token(request.GET["request_token"], request.GET["verification_code"]) paypal_log.debug("Getting personal data for token: %s" % addon_id) data = paypal.get_personal_data(token) email = data.get("email") # If the email from paypal is different, something has gone wrong. if email != addon.paypal_id: paypal_log.debug("Addon paypal_id and personal data differ: " "%s vs %s" % (email, addon.paypal_id)) messages.warning( request, _("The email returned by Paypal, " "did not match the PayPal email you " "entered. Please login using %s.") % email, ) return redirect(on_error) # Set the permissions token that we have just successfully used # in get_personal_data. addonpremium, created = AddonPremium.objects.safer_get_or_create(addon=addon) addonpremium.update(paypal_permissions_token=token) # Finally update the data returned from PayPal for this addon. paypal_log.debug("Updating personal data for: %s" % addon_id) apd, created = AddonPaymentData.objects.safer_get_or_create(addon=addon) apd.update(**data) amo.log(amo.LOG.EDIT_PROPERTIES, addon) if show_good_msgs: messages.success(request, "Please confirm the data we " "received from PayPal.") return redirect(on_good)
def _review(request, addon): version = addon.latest_version if not settings.ALLOW_SELF_REVIEWS and addon.has_author(request.amo_user): messages.warning(request, _('Self-reviews are not allowed.')) return redirect(reverse('reviewers.home')) form = forms.get_review_form(request.POST or None, request=request, addon=addon, version=version) 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 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) messages.success(request, _('Review successfully processed.')) return redirect(redirect_url) canned = AppCannedResponse.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)) product_attrs = { 'product': json.dumps(product_as_dict(request, addon, False, 'developer'), cls=JSONEncoder), 'manifest_url': addon.manifest_url, } pager = paginate(request, versions, 10) num_pages = pager.paginator.num_pages count = pager.paginator.count ctx = context(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) return jingo.render(request, 'reviewers/review.html', ctx)
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'): 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 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: 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) if waffle.switch_is_active('buchets'): ctx['feature_list'] = features_list return jingo.render(request, 'reviewers/review.html', ctx)
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) queue_type = form.helper.review_type redirect_url = reverse('reviewers.apps.queue_%s' % queue_type) is_admin = acl.action_allowed(request, 'Addons', 'Edit') forms_valid = lambda: form.is_valid() and attachment_formset.is_valid() if request.method == 'POST' and forms_valid(): old_types = set(o.id for o in addon.device_types) new_types = set(form.cleaned_data.get('device_override')) if (form.cleaned_data.get('action') == 'public' and 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}) 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: 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(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) return jingo.render(request, 'reviewers/review.html', ctx)
def _review(request, addon): version = addon.latest_version if (not settings.DEBUG and addon.authors.filter(user=request.user).exists()): messages.warning(request, _('Self-reviews are not allowed.')) return redirect(reverse('reviewers.home')) form = forms.get_review_form(request.POST or None, request=request, addon=addon, version=version) 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 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) messages.success(request, _('Review successfully processed.')) return redirect(redirect_url) canned = AppCannedResponse.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)) pager = paginate(request, versions, 10) num_pages = pager.paginator.num_pages count = pager.paginator.count ctx = context(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) return jingo.render(request, 'reviewers/review.html', ctx)
def _review(request, addon): version = addon.latest_version if (not settings.DEBUG and addon.authors.filter(user=request.user).exists()): messages.warning(request, _('Self-reviews are not allowed.')) return redirect(reverse('reviewers.home')) 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('reviewers.apps.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) messages.success(request, _('Review successfully processed.')) return redirect(redirect_url) canned = AppCannedResponse.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)) pager = paginate(request, versions, 10) num_pages = pager.paginator.num_pages count = pager.paginator.count ctx = context(version=version, product=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, 'reviewers/review.html', ctx)
def acquire_refund_permission(request, addon_id, addon, webapp=False): """This is the callback from Paypal.""" # Set up our redirects. if request.GET.get('dest', '') == 'submission': on_good = reverse('submit.app.payments.confirm', args=[addon.app_slug]) on_error = reverse('submit.app.payments.paypal', args=[addon.app_slug]) show_good_msgs = False else: # The management pages are the default. on_good = addon.get_dev_url('paypal_setup_confirm') on_error = addon.get_dev_url('paypal_setup_bounce') show_good_msgs = True if 'request_token' not in request.GET: paypal_log.debug('User did not approve permissions for' ' addon: %s' % addon_id) messages.error(request, 'You will need to accept the permissions ' 'to continue.') return redirect(on_error) paypal_log.debug('User approved permissions for addon: %s' % addon_id) if waffle.flag_is_active(request, 'solitude-payments'): client.post_permission_token(data={ 'seller': addon, 'token': request.GET['request_token'], 'verifier': request.GET['verification_code'], }) try: data = client.post_personal_basic(data={'seller': addon}) except client.Error as err: paypal_log.debug('%s for addon %s' % (err.message, addon.id)) messages.warning(request, err.message) return redirect(on_error) data.update(client.post_personal_advanced(data={'seller': addon})) # TODO(solitude): remove these. else: token = paypal.get_permissions_token(request.GET['request_token'], request.GET['verification_code']) data = paypal.get_personal_data(token) # TODO(solitude): remove this. email = data.get('email') # If the email from paypal is different, something has gone wrong. if email != addon.paypal_id: paypal_log.debug('Addon paypal_id and personal data differ: ' '%s vs %s' % (email, addon.paypal_id)) messages.warning(request, _('The email returned by Paypal, ' 'did not match the PayPal email you ' 'entered. Please login using %s.') % email) return redirect(on_error) # TODO(solitude): remove this. Sadly because the permissions tokens # are never being traversed back we have a disconnect between what is # happening in solitude and here and this will not easily survive flipping # on and off the flag. if not waffle.flag_is_active(request, 'solitude-payments'): # Set the permissions token that we have just successfully used # in get_personal_data. addonpremium, created = (AddonPremium.objects .safer_get_or_create(addon=addon)) addonpremium.update(paypal_permissions_token=token) # Finally update the data returned from PayPal for this addon. paypal_log.debug('Updating personal data for: %s' % addon_id) # TODO(solitude): delete this, as the data was pulled through solitude # it was saved. apd, created = AddonPaymentData.objects.safer_get_or_create(addon=addon) # This can be deleted with solitude, but this needs to change because # data will contain more than the fields on the object, this is a quick # workaround. for k, v in data.items(): setattr(apd, k, v) apd.save() amo.log(amo.LOG.EDIT_PROPERTIES, addon) if show_good_msgs: messages.success(request, 'Please confirm the data we ' 'received from PayPal.') return redirect(on_good)
def _review(request, addon): version = addon.latest_version if not settings.ALLOW_SELF_REVIEWS 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")) form = forms.get_review_form(request.POST or None, request=request, addon=addon, version=version) 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 form.is_valid(): old_types = set(o.id for o in addon.device_types) new_types = set(form.cleaned_data.get("device_override")) if form.cleaned_data.get("action") == "public" and 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}) 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: 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.objects.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( 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, ) return jingo.render(request, "reviewers/review.html", ctx)