def payments(request, addon_id, addon): charity = None if addon.charity_id == amo.FOUNDATION_ORG else addon.charity charity_form = forms.CharityForm(request.POST or None, instance=charity, prefix='charity') contrib_form = forms.ContribForm(request.POST or None, instance=addon, initial=forms.ContribForm.initial(addon)) if request.method == 'POST': if contrib_form.is_valid(): addon, valid = contrib_form.save(commit=False), True addon.wants_contributions = True recipient = contrib_form.cleaned_data['recipient'] if recipient == 'dev': addon.charity = None elif recipient == 'moz': addon.charity_id = amo.FOUNDATION_ORG elif recipient == 'org': valid = charity_form.is_valid() if valid: addon.charity = charity_form.save() if valid: addon.save() messages.success(request, _('Changes successfully saved.')) return redirect('devhub.addons.payments', addon_id) if charity_form.errors or contrib_form.errors: messages.error(request, _('There were errors in your submission.')) return jingo.render(request, 'devhub/addons/payments.html', dict(addon=addon, charity_form=charity_form, contrib_form=contrib_form))
def hera(request): form = FlushForm(initial={'flushprefix': settings.SITE_URL}) boxes = [] configured = False # Default to not showing the form. for i in settings.HERA: hera = get_hera(i) r = {'location': urlparse(i['LOCATION'])[1], 'stats': False} if hera: r['stats'] = hera.getGlobalCacheInfo() configured = True boxes.append(r) if not configured: messages.error(request, "Hera is not (or mis-)configured.") form = None if request.method == 'POST' and hera: form = FlushForm(request.POST) if form.is_valid(): expressions = request.POST['flushlist'].splitlines() for url in expressions: num = flush_urls([url], request.POST['flushprefix'], True) msg = ("Flushed %d objects from front end cache for: %s" % (len(num), url)) log.info("[Hera] (user:%s) %s" % (request.user, msg)) messages.success(request, msg) return jingo.render(request, 'zadmin/hera.html', {'form': form, 'boxes': boxes})
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 jingo.render(request, 'zadmin/monthly_pick.html', dict(form=form))
def edit(request): webapp = settings.APP_PREVIEW # Don't use request.amo_user since it has too much caching. amouser = UserProfile.objects.get(pk=request.user.id) if request.method == 'POST': # ModelForm alters the instance you pass in. We need to keep a copy # around in case we need to use it below (to email the user) original_email = amouser.email form = forms.UserEditForm(request.POST, request.FILES, request=request, instance=amouser, webapp=webapp) if form.is_valid(): messages.success(request, _('Profile Updated')) if amouser.email != original_email: # Temporarily block email changes. if settings.APP_PREVIEW: messages.error(request, 'Error', 'You cannot change your email on the ' 'developer preview site.') return jingo.render(request, 'users/edit.html', {'form': form, 'amouser': amouser}) l = {'user': amouser, 'mail1': original_email, 'mail2': amouser.email} log.info(u"User (%(user)s) has requested email change from" "(%(mail1)s) to (%(mail2)s)" % l) messages.info(request, _('Email Confirmation Sent'), _(u'An email has been sent to {0} to confirm your new ' 'email address. For the change to take effect, you ' 'need to click on the link provided in this email. ' 'Until then, you can keep logging in with your ' 'current email address.').format(amouser.email)) domain = settings.DOMAIN token, hash = EmailResetCode.create(amouser.id, amouser.email) url = "%s%s" % (settings.SITE_URL, reverse('users.emailchange', args=[amouser.id, token, hash])) t = loader.get_template('users/email/emailchange.ltxt') c = {'domain': domain, 'url': url} send_mail(_('Please confirm your email address ' 'change at %s' % domain), t.render(Context(c)), None, [amouser.email], use_blacklist=False, real_email=True) # Reset the original email back. We aren't changing their # address until they confirm the new one amouser.email = original_email form.save() return redirect('users.edit') else: messages.error(request, _('Errors Found'), _('There were errors in the changes ' 'you made. Please correct them and ' 'resubmit.')) else: form = forms.UserEditForm(instance=amouser, webapp=webapp) return jingo.render(request, 'users/edit.html', {'form': form, 'amouser': amouser, 'webapp': webapp})
def api(request): try: access = Access.objects.get(user=request.user) except Access.DoesNotExist: access = None roles = request.amo_user.groups.all() if roles: messages.error(request, _('Users with roles cannot use the API.')) elif not request.amo_user.read_dev_agreement: messages.error(request, _('You must accept the terms of service.')) elif request.method == 'POST': if 'delete' in request.POST: if access: access.delete() messages.success(request, _('API key deleted.')) else: if not access: key = 'mkt:%s:%s' % (request.amo_user.pk, request.amo_user.email) access = Access.objects.create(key=key, user=request.user, secret=generate()) else: access.update(secret=generate()) messages.success(request, _('New API key generated.')) return redirect(reverse('mkt.developers.apps.api')) return jingo.render(request, 'developers/api.html', {'consumer': access, 'profile': profile, 'roles': roles})
def email_devs(request): form = DevMailerForm(request.POST or None) preview = EmailPreviewTopic(topic='email-devs') if preview.filter().count(): preview_csv = reverse('zadmin.email_preview_csv', args=[preview.topic]) else: preview_csv = None if request.method == 'POST' and form.is_valid(): data = form.cleaned_data qs = (AddonUser.objects.filter(role__in=(amo.AUTHOR_ROLE_DEV, amo.AUTHOR_ROLE_OWNER)) .exclude(user__email=None)) if data['recipients'] in ('payments', 'desktop_apps'): qs = qs.exclude(addon__status=amo.STATUS_DELETED) else: qs = qs.filter(addon__status__in=amo.LISTED_STATUSES) if data['recipients'] == 'eula': qs = qs.exclude(addon__eula=None) elif data['recipients'] in ('payments', 'payments_region_enabled', 'payments_region_disabled'): qs = qs.filter(addon__type=amo.ADDON_WEBAPP) qs = qs.exclude(addon__premium_type__in=(amo.ADDON_FREE, amo.ADDON_OTHER_INAPP)) if data['recipients'] == 'payments_region_enabled': qs = qs.filter(addon__enable_new_regions=True) elif data['recipients'] == 'payments_region_disabled': qs = qs.filter(addon__enable_new_regions=False) elif data['recipients'] == 'apps': qs = qs.filter(addon__type=amo.ADDON_WEBAPP) elif data['recipients'] == 'desktop_apps': qs = (qs.filter(addon__type=amo.ADDON_WEBAPP, addon__addondevicetype__device_type=amo.DEVICE_DESKTOP.id)) elif data['recipients'] == 'sdk': qs = qs.exclude(addon__versions__files__jetpack_version=None) elif data['recipients'] == 'all_extensions': qs = qs.filter(addon__type=amo.ADDON_EXTENSION) else: raise NotImplementedError('If you want to support emailing other ' 'types of developers, do it here!') if data['preview_only']: # Clear out the last batch of previewed emails. preview.filter().delete() total = 0 for emails in chunked(set(qs.values_list('user__email', flat=True)), 100): total += len(emails) tasks.admin_email.delay(emails, data['subject'], data['message'], preview_only=data['preview_only'], preview_topic=preview.topic) msg = 'Emails queued for delivery: %s' % total if data['preview_only']: msg = '%s (for preview only, emails not sent!)' % msg messages.success(request, msg) return redirect('zadmin.email_devs') return jingo.render(request, 'zadmin/email-devs.html', dict(form=form, preview_csv=preview_csv))
def in_app_config(request, addon_id, addon, webapp=True): if addon.premium_type not in amo.ADDON_INAPPS: messages.error(request, 'Your app does not use payments.') return redirect(addon.get_dev_url('payments')) try: inapp_config = InappConfig.objects.get(addon=addon, status=amo.INAPP_STATUS_ACTIVE) except models.ObjectDoesNotExist: inapp_config = None inapp_form = InappConfigForm(request.POST or None, instance=inapp_config) if request.method == 'POST' and inapp_form.is_valid(): new_inapp = inapp_form.save(commit=False) new_inapp.addon = addon new_inapp.status = amo.INAPP_STATUS_ACTIVE if not new_inapp.public_key: new_inapp.public_key = InappConfig.generate_public_key() new_inapp.save() if not new_inapp.has_private_key(): new_inapp.set_private_key(InappConfig.generate_private_key()) messages.success(request, _('Changes successfully saved.')) return redirect(addon.get_dev_url('in_app_config')) return jingo.render(request, 'developers/payments/in-app-config.html', dict(addon=addon, inapp_form=inapp_form, inapp_config=inapp_config))
def version_edit(request, addon_id, addon, version_id): show_features = waffle.switch_is_active('buchets') and addon.is_packaged version = get_object_or_404(Version, pk=version_id, addon=addon) form = VersionForm(request.POST or None, instance=version) all_forms = [form] if show_features: appfeatures = version.features appfeatures_form = AppFeaturesForm(request.POST, instance=appfeatures) all_forms.append(appfeatures_form) if request.method == 'POST' and all(f.is_valid() for f in all_forms): [f.save() for f in all_forms] messages.success(request, _('Version successfully edited.')) return redirect(addon.get_dev_url('versions')) context = { 'addon': addon, 'version': version, 'form': form } if show_features: context.update({ 'appfeatures_form': appfeatures_form, 'appfeatures': appfeatures, 'feature_list': [unicode(f) for f in appfeatures.to_list()] }) return jingo.render(request, 'developers/apps/version_edit.html', context)
def edit(request): webapp = settings.APP_PREVIEW # Don't use request.amo_user since it has too much caching. amouser = UserProfile.objects.get(pk=request.user.id) if request.method == "POST": # ModelForm alters the instance you pass in. We need to keep a copy # around in case we need to use it below (to email the user) original_email = amouser.email form = forms.UserEditForm(request.POST, request.FILES, request=request, instance=amouser, webapp=webapp) if form.is_valid(): messages.success(request, _("Profile Updated")) if amouser.email != original_email: # Temporarily block email changes. if settings.APP_PREVIEW: messages.error(request, "Error", "You cannot change your email on the " "developer preview site.") return jingo.render(request, "users/edit.html", {"form": form, "amouser": amouser}) l = {"user": amouser, "mail1": original_email, "mail2": amouser.email} log.info(u"User (%(user)s) has requested email change from" "(%(mail1)s) to (%(mail2)s)" % l) messages.info( request, _("Email Confirmation Sent"), _( u"An email has been sent to {0} to confirm your new " "email address. For the change to take effect, you " "need to click on the link provided in this email. " "Until then, you can keep logging in with your " "current email address." ).format(amouser.email), ) domain = settings.DOMAIN token, hash = EmailResetCode.create(amouser.id, amouser.email) url = "%s%s" % (settings.SITE_URL, reverse("users.emailchange", args=[amouser.id, token, hash])) t = loader.get_template("users/email/emailchange.ltxt") c = {"domain": domain, "url": url} send_mail( _("Please confirm your email address " "change at %s" % domain), t.render(Context(c)), None, [amouser.email], use_blacklist=False, real_email=True, ) # Reset the original email back. We aren't changing their # address until they confirm the new one amouser.email = original_email form.save() return redirect("users.edit") else: messages.error( request, _("Errors Found"), _("There were errors in the changes " "you made. Please correct them and " "resubmit."), ) else: form = forms.UserEditForm(instance=amouser, webapp=webapp) return jingo.render(request, "users/edit.html", {"form": form, "amouser": amouser, "webapp": webapp})
def _refresh_mdn(request): if settings.MDN_LAZY_REFRESH and 'refresh' in request.GET: # If you can delay this, please teach me. I give up. refresh_mdn_cache() messages.success(request, 'Pulling new content from MDN. Please check back in a few minutes.' ' Thanks for all your awesome work! Devs appreciate it!')
def version_delete(request, addon_id, addon): version_id = request.POST.get('version_id') version = get_object_or_404(Version, pk=version_id, addon=addon) version.delete() messages.success(request, _('Version "{0}" deleted.').format(version.version)) return redirect(addon.get_dev_url('versions'))
def preload_submit(request, addon_id, addon): if request.method == "POST": form = PreloadTestPlanForm(request.POST, request.FILES) if form.is_valid(): # Save test plan file. test_plan = request.FILES["test_plan"] # Figure the type to save it as (cleaned as pdf/xls from the form). filetype = mimetypes.guess_type(test_plan.name)[0] if "pdf" in filetype: filename = "test_plan_%s.pdf" else: filename = "test_plan_%s.xls" # Timestamp. filename = filename % str(time.time()).split(".")[0] save_test_plan(request.FILES["test_plan"], filename, addon) # Log test plan. PreloadTestPlan.objects.filter(addon=addon).update(status=amo.STATUS_DISABLED) PreloadTestPlan.objects.create(addon=addon, filename=filename) messages.success(request, _("Application for preload successfully submitted.")) return redirect(addon.get_dev_url("versions")) else: messages.error(request, _("There was an error with the form.")) else: form = PreloadTestPlanForm() return render(request, "developers/apps/preload/submit.html", {"addon": addon, "form": form})
def issue_refund(request, addon_id, addon, webapp=False): txn_id = request.REQUEST.get("transaction_id") if not txn_id: raise http.Http404 form_enabled = True contribution = get_object_or_404( Contribution, transaction_id=txn_id, type__in=[amo.CONTRIB_PURCHASE, amo.CONTRIB_INAPP] ) if hasattr(contribution, "refund") and contribution.refund.status not in (amo.REFUND_PENDING, amo.REFUND_FAILED): # If it's not pending, we've already taken action. messages.error(request, _("Refund already processed.")) form_enabled = False elif request.method == "POST": if "issue" in request.POST: if waffle.flag_is_active(request, "solitude-payments"): try: response = client.post_refund(data={"uuid": contribution.transaction_id}) except client.Error, e: contribution.record_failed_refund(e) paypal_log.error("Refund failed for: %s" % txn_id, exc_info=True) messages.error(request, _("There was an error with " "the refund.")) return redirect(addon.get_dev_url("refunds")) results = response["response"] else: # TODO(solitude): remove this. try: results = paypal.refund(contribution.paykey) except PaypalError, e: contribution.record_failed_refund(e) paypal_log.error("Refund failed for: %s" % txn_id, exc_info=True) messages.error(request, _("There was an error with " "the refund.")) return redirect(addon.get_dev_url("refunds")) for res in results: if res["refundStatus"] == "ALREADY_REVERSED_OR_REFUNDED": paypal_log.debug( "Refund attempt for already-refunded paykey: %s, %s" % (contribution.paykey, res["receiver.email"]) ) messages.error(request, _("Refund was previously issued; " "no action taken.")) return redirect(addon.get_dev_url("refunds")) elif res["refundStatus"] == "NO_API_ACCESS_TO_RECEIVER": paypal_log.debug( "Refund attempt for product %s with no " "refund token: %s, %s" % (contribution.addon.pk, contribution.paykey, res["receiver.email"]) ) messages.error( request, _("A refund can't be issued at this time. We've " "notified an admin; please try again later."), ) return redirect(addon.get_dev_url("refunds")) contribution.mail_approved() amo.log(amo.LOG.REFUND_GRANTED, addon, contribution.user) refund = contribution.enqueue_refund(amo.REFUND_APPROVED) paypal_log.info("Refund %r issued for contribution %r" % (refund.pk, contribution.pk)) messages.success(request, _("Refund issued."))
def refund_reason(request, contribution, wizard): addon = contribution.addon if not 'request' in wizard.get_progress(): return redirect('users.support', contribution.pk, 'request') if contribution.is_instant_refund(): paypal.refund(contribution.paykey) paypal_log.info('Refund issued for contribution %r' % contribution.pk) # Note: we have to wait for PayPal to issue an IPN before it's # completely refunded. messages.success(request, _('Refund is being processed.')) return redirect('users.purchases') form = forms.ContactForm(request.POST or None) if request.method == 'POST' and form.is_valid(): url = absolutify(urlparams(addon.get_dev_url('issue_refund'), transaction_id=contribution.transaction_id)) template = jingo.render_to_string(request, wizard.tpl('emails/refund-request.txt'), context={'addon': addon, 'form': form, 'user': request.amo_user, 'contribution': contribution, 'refund_url': url}) log.info('Refund request sent by user: %s for addon: %s' % (request.amo_user.pk, addon.pk)) # L10n: %s is the addon name. send_mail(_(u'New Refund Request for %s' % addon.name), template, settings.NOBODY_EMAIL, [smart_str(addon.support_email)]) return redirect(reverse('users.support', args=[contribution.pk, 'refund-sent'])) return wizard.render(request, wizard.tpl('refund.html'), {'form': form})
def preload_submit(request, addon_id, addon, webapp): if request.method == 'POST': form = PreloadTestPlanForm(request.POST, request.FILES) if form.is_valid(): # Save test plan file. test_plan = request.FILES['test_plan'] # Figure the type to save it as (cleaned as pdf/xls from the form). if test_plan.content_type == 'application/pdf': filename = 'test_plan_%s.pdf' else: filename = 'test_plan_%s.xls' # Timestamp. filename = filename % str(time.time()).split('.')[0] save_test_plan(request.FILES['test_plan'], filename, addon) # Log test plan. PreloadTestPlan.objects.filter(addon=addon).update( status=amo.STATUS_DISABLED ) PreloadTestPlan.objects.create(addon=addon, filename=filename) messages.success( request, _('Application for preload successfully submitted.')) return redirect(addon.get_dev_url('versions')) else: messages.error(request, _('There was an error with the form.')) else: form = PreloadTestPlanForm() return jingo.render(request, 'developers/apps/preload/submit.html', { 'addon': addon, 'form': form })
def featured_apps_admin(request): home_collection = Webapp.featured_collection('home') category_collection = Webapp.featured_collection('category') if request.POST: if 'home_submit' in request.POST: coll = home_collection rowid = 'home' elif 'category_submit' in request.POST: coll = category_collection rowid = 'category' existing = set(coll.addons.values_list('id', flat=True)) requested = set(int(request.POST[k]) for k in sorted(request.POST.keys()) if k.endswith(rowid + '-webapp')) CollectionAddon.objects.filter(collection=coll, addon__in=(existing - requested)).delete() for id in requested - existing: CollectionAddon.objects.create(collection=coll, addon_id=id) messages.success(request, 'Changes successfully saved.') return redirect(reverse('admin.featured_apps')) return jingo.render(request, 'zadmin/featuredapp.html', { 'home_featured': enumerate(home_collection.addons.all()), 'category_featured': enumerate(category_collection.addons.all()) })
def api(request): roles = request.amo_user.groups.filter(name='Admins').exists() f = APIConsumerForm() if roles: messages.error(request, _('Users with the admin role cannot use the API.')) elif request.method == 'POST': if 'delete' in request.POST: try: consumer = Access.objects.get(pk=request.POST.get('consumer')) consumer.delete() except Access.DoesNotExist: messages.error(request, _('No such API key.')) else: key = 'mkt:%s:%s:%s' % ( request.amo_user.pk, request.amo_user.email, Access.objects.filter(user=request.user).count()) access = Access.objects.create(key=key, user=request.user, secret=generate()) f = APIConsumerForm(request.POST, instance=access) if f.is_valid(): f.save() messages.success(request, _('New API key generated.')) else: access.delete() consumers = list(Access.objects.filter(user=request.user)) return jingo.render(request, 'developers/api.html', {'consumers': consumers, 'roles': roles, 'form': f})
def add(request): "Displays/processes a form to create a collection." data = {} if request.method == 'POST': form = forms.CollectionForm( request.POST, request.FILES, initial=initial_data_from_request(request)) aform = forms.AddonsForm(request.POST) if form.is_valid(): collection = form.save(default_locale=request.LANG) collection.save() if aform.is_valid(): aform.save(collection) title = _("Collection created!") msg = _("""Your new collection is shown below. You can <a href="%(url)s">edit additional settings</a> if you'd like.""") % {'url': collection.edit_url()} messages.success(request, title, msg, extra_tags='collection', message_safe=True) log.info('Created collection %s' % collection.id) return http.HttpResponseRedirect(collection.get_url_path()) else: data['addons'] = Addon.objects.filter(pk__in=aform.clean_addon()) data['comments'] = aform.clean_addon_comment() else: form = forms.CollectionForm() data.update(form=form, filter=get_filter(request)) return render(request, 'bandwagon/add.html', data)
def paypal_setup_confirm(request, addon_id, addon, webapp, source='paypal'): # If you bounce through paypal as you do permissions changes set the # source to paypal. if source == 'paypal': msg = _('PayPal set up complete.') title = _('Confirm Details') button = _('Continue') # If you just hit this page from the Manage Paypal, show some less # wizardy stuff. else: msg = _('Changes saved.') title = _('Contact Details') button = _('Save') adp, created = AddonPaymentData.objects.safer_get_or_create(addon=addon) form = forms.PaypalPaymentData(request.POST or None, instance=adp) if request.method == 'POST' and form.is_valid(): adp.update(**form.cleaned_data) messages.success(request, msg) if source == 'paypal' and addon.is_incomplete() and addon.paypal_id: addon.mark_done() return redirect(addon.get_dev_url('paypal_setup')) return jingo.render(request, 'developers/payments/paypal-details-confirm.html', {'addon': addon, 'button': button, 'form': form, 'title': title})
def status(request, addon_id, addon, webapp=False): form = forms.AppAppealForm(request.POST, product=addon) upload_form = NewWebappForm(request.POST or None, is_packaged=True, addon=addon) if request.method == 'POST': if 'resubmit-app' in request.POST and form.is_valid(): form.save() messages.success(request, _('App successfully resubmitted.')) return redirect(addon.get_dev_url('versions')) elif 'upload-version' in request.POST and upload_form.is_valid(): ver = Version.from_upload(upload_form.cleaned_data['upload'], addon, [amo.PLATFORM_ALL]) log.info('[Webapp:%s] New version created id=%s from upload: %s' % (addon, ver.pk, upload_form.cleaned_data['upload'])) return redirect(addon.get_dev_url('versions.edit', args=[ver.pk])) ctx = {'addon': addon, 'webapp': webapp, 'form': form, 'upload_form': upload_form} if addon.status == amo.STATUS_REJECTED: try: entry = (AppLog.objects .filter(addon=addon, activity_log__action=amo.LOG.REJECT_VERSION.id) .order_by('-created'))[0] except IndexError: entry = None # This contains the rejection reason and timestamp. ctx['rejection'] = entry and entry.activity_log return jingo.render(request, 'developers/apps/status.html', ctx)
def issue_refund(request, addon_id, addon, webapp=False): txn_id = request.REQUEST.get('transaction_id') if not txn_id: raise http.Http404 form_enabled = True contribution = get_object_or_404(Contribution, transaction_id=txn_id, type__in=[amo.CONTRIB_PURCHASE, amo.CONTRIB_INAPP]) if (hasattr(contribution, 'refund') and contribution.refund.status not in (amo.REFUND_PENDING, amo.REFUND_FAILED)): # If it's not pending, we've already taken action. messages.error(request, _('Refund already processed.')) form_enabled = False elif request.method == 'POST': if 'issue' in request.POST: try: results = paypal.refund(contribution.paykey) except PaypalError, e: contribution.record_failed_refund(e) paypal_log.error('Refund failed for: %s' % txn_id, exc_info=True) messages.error(request, _('There was an error with ' 'the refund.')) return redirect(addon.get_dev_url('refunds')) for res in results: if res['refundStatus'] == 'ALREADY_REVERSED_OR_REFUNDED': paypal_log.debug( 'Refund attempt for already-refunded paykey: %s, %s' % (contribution.paykey, res['receiver.email'])) messages.error(request, _('Refund was previously issued; ' 'no action taken.')) return redirect(addon.get_dev_url('refunds')) elif res['refundStatus'] == 'NO_API_ACCESS_TO_RECEIVER': paypal_log.debug('Refund attempt for product %s with no ' 'refund token: %s, %s' % (contribution.addon.pk, contribution.paykey, res['receiver.email'])) messages.error(request, _("A refund can't be issued at this time. We've " "notified an admin; please try again later.")) return redirect(addon.get_dev_url('refunds')) contribution.mail_approved() refund = contribution.enqueue_refund(amo.REFUND_APPROVED) paypal_log.info('Refund %r issued for contribution %r' % (refund.pk, contribution.pk)) messages.success(request, _('Refund issued.')) else: contribution.mail_declined() # TODO: Consider requiring a rejection reason for declined refunds. refund = contribution.enqueue_refund(amo.REFUND_DECLINED) paypal_log.info('Refund %r declined for contribution %r' % (refund.pk, contribution.pk)) messages.success(request, _('Refund declined.')) return redirect(addon.get_dev_url('refunds'))
def hera(request): form = FlushForm(initial={"flushprefix": site_settings.SITE_URL}) boxes = [] configured = False # Default to not showing the form. for i in site_settings.HERA: hera = get_hera(i) r = {"location": urlparse(i["LOCATION"])[1], "stats": False} if hera: r["stats"] = hera.getGlobalCacheInfo() configured = True boxes.append(r) if not configured: messages.error(request, "Hera is not (or mis-)configured.") form = None if request.method == "POST" and hera: form = FlushForm(request.POST) if form.is_valid(): expressions = request.POST["flushlist"].splitlines() for url in expressions: num = flush_urls([url], request.POST["flushprefix"], True) msg = "Flushed %d objects from front end cache for: %s" % (len(num), url) log.info("[Hera] (user:%s) %s" % (request.user, msg)) messages.success(request, msg) return jingo.render(request, "zadmin/hera.html", {"form": form, "boxes": boxes})
def ownership(request, addon_id, addon, webapp=False): # Authors. qs = AddonUser.objects.filter(addon=addon).order_by('position') user_form = forms.AuthorFormSet(request.POST or None, queryset=qs) if request.method == 'POST' and user_form.is_valid(): # Authors. authors = user_form.save(commit=False) for author in authors: action = None if not author.id or author.user_id != author._original_user_id: action = amo.LOG.ADD_USER_WITH_ROLE author.addon = addon elif author.role != author._original_role: action = amo.LOG.CHANGE_USER_WITH_ROLE author.save() if action: amo.log(action, author.user, author.get_role_display(), addon) if (author._original_user_id and author.user_id != author._original_user_id): amo.log(amo.LOG.REMOVE_USER_WITH_ROLE, (UserProfile, author._original_user_id), author.get_role_display(), addon) for author in user_form.deleted_objects: amo.log(amo.LOG.REMOVE_USER_WITH_ROLE, author.user, author.get_role_display(), addon) messages.success(request, _('Changes successfully saved.')) return redirect(addon.get_dev_url('owner')) ctx = dict(addon=addon, webapp=webapp, user_form=user_form) return jingo.render(request, 'developers/apps/owner.html', ctx)
def payments(request, addon_id, addon): charity = None if addon.charity_id == amo.FOUNDATION_ORG else addon.charity charity_form = forms.CharityForm(request.POST or None, instance=charity, prefix='charity') contrib_form = forms.ContribForm(request.POST or None, instance=addon, initial=forms.ContribForm.initial(addon)) profile_form = forms.ProfileForm(request.POST or None, instance=addon, required=True) if request.method == 'POST': if contrib_form.is_valid(): addon = contrib_form.save(commit=False) addon.wants_contributions = True valid = _save_charity(addon, contrib_form, charity_form) if not addon.has_full_profile(): valid &= profile_form.is_valid() if valid: profile_form.save() if valid: addon.save() messages.success(request, _('Changes successfully saved.')) amo.log(amo.LOG.EDIT_CONTRIBUTIONS, addon) return redirect('devhub.addons.payments', addon.slug) errors = charity_form.errors or contrib_form.errors or profile_form.errors if errors: messages.error(request, _('There were errors in your submission.')) return jingo.render(request, 'devhub/addons/payments.html', dict(addon=addon, charity_form=charity_form, errors=errors, contrib_form=contrib_form, profile_form=profile_form))
def emailchange(request, user_id, token, hash): user = get_object_or_404(UserProfile, id=user_id) try: _uid, newemail = EmailResetCode.parse(token, hash) except ValueError: return http.HttpResponse(status=400) if _uid != user.id: # I'm calling this a warning because invalid hashes up to this point # could be any number of things, but this is a targeted attack from # one user account to another log.warning((u"[Tampering] Valid email reset code for UID (%s) " "attempted to change email address for user (%s)") % (_uid, user)) return http.HttpResponse(status=400) user.email = newemail user.save() l = {'user': user, 'newemail': newemail} log.info(u"User (%(user)s) confirmed new email address (%(newemail)s)" % l) messages.success(request, _('Your email address was changed successfully'), _(u'From now on, please use {0} to log in.').format(newemail)) return http.HttpResponseRedirect(reverse('users.edit'))
def paypal_setup(request, addon_id, addon, webapp): if addon.premium_type == amo.ADDON_FREE: messages.error(request, 'Your app does not use payments.') return redirect(addon.get_dev_url('payments')) paypal_form = PaypalSetupForm(request.POST or None) currency_form = CurrencyForm(request.POST or None, initial={'currencies': addon.premium.currencies if addon.premium else {}}) context = {'addon': addon, 'paypal_form': paypal_form, 'currency_form': currency_form} if request.POST.get('form') == 'paypal' and paypal_form.is_valid(): existing = paypal_form.cleaned_data['business_account'] if existing != 'yes': # Go create an account. # TODO: this will either become the API or something some better # URL for the future. return redirect(settings.PAYPAL_CGI_URL) else: # Go setup your details on paypal. addon.update(paypal_id=paypal_form.cleaned_data['email']) if addon.premium and addon.premium.paypal_permissions_token: addon.premium.update(paypal_permissions_token='') return redirect(addon.get_dev_url('paypal_setup_bounce')) if request.POST.get('form') == 'currency' and currency_form.is_valid(): currencies = currency_form.cleaned_data['currencies'] addon.premium.update(currencies=currencies) messages.success(request, _('Currencies updated.')) return redirect(addon.get_dev_url('paypal_setup')) return jingo.render(request, 'developers/payments/paypal-setup.html', context)
def features(request): form = FeaturedCollectionFormSet(request.POST or None) if request.method == 'POST' and form.is_valid(): form.save(commit=False) messages.success(request, 'Changes successfully saved.') return redirect('zadmin.features') return jingo.render(request, 'zadmin/features.html', dict(form=form))
def content_ratings_edit(request, addon_id, addon): initial = {} try: app_info = addon.iarc_info initial['submission_id'] = app_info.submission_id initial['security_code'] = app_info.security_code except IARCInfo.DoesNotExist: pass form = IARCGetAppInfoForm(data=request.POST or None, initial=initial) if request.method == 'POST' and form.is_valid(): try: form.save(addon) messages.success(request, _('Content ratings successfully saved.')) return redirect(addon.get_dev_url('ratings')) except django_forms.ValidationError: pass # Fall through to show the form error. with amo.utils.no_translation(addon.default_locale): addon_delocalized = Addon.objects.get(pk=addon.pk) return jingo.render( request, 'developers/apps/ratings/ratings_edit.html', { 'addon': addon, 'app_name': addon_delocalized.name, 'form': form, 'now': datetime.now().strftime('%Y-%m-%d %H:%M:%S') })
def in_app_config(request, addon_id, addon, webapp=True): inapp = addon.premium_type in amo.ADDON_INAPPS if not inapp: messages.error(request, _('Your app is not configured for in-app payments.')) return redirect(reverse('mkt.developers.apps.payments', args=[addon.app_slug])) try: account = addon.app_payment_account except ObjectDoesNotExist: messages.error(request, _('No payment account for this app.')) return redirect(reverse('mkt.developers.apps.payments', args=[addon.app_slug])) seller_config = get_seller_product(account) owner = acl.check_addon_ownership(request, addon) if request.method == 'POST': # Reset the in-app secret for the app. (client.api.generic .product(seller_config['resource_pk']) .patch(data={'secret': generate_key(48)})) messages.success(request, _('Changes successfully saved.')) return redirect(reverse('mkt.developers.apps.in_app_config', args=[addon.app_slug])) return jingo.render(request, 'developers/payments/in-app-config.html', {'addon': addon, 'owner': owner, 'seller_config': seller_config})
def spam(request): if not acl.action_allowed(request, 'Spam', 'Flag'): raise PermissionDenied spam = Spam() if request.method == 'POST': review = Review.objects.get(pk=request.POST['review']) if 'del_review' in request.POST: log.info('SPAM: %s' % review.id) delete(request, request.POST['addon'], review.id) messages.success(request, 'Deleted that review.') elif 'del_user' in request.POST: user = review.user log.info('SPAMMER: %s deleted %s' % (request.amo_user.username, user.username)) if not user.is_developer: Review.objects.filter(user=user).delete() user.anonymize() messages.success(request, 'Deleted that dirty spammer.') for reason in spam.reasons(): spam.redis.srem(reason, review.id) return http.HttpResponseRedirect(request.path) buckets = {} for reason in spam.reasons(): ids = spam.redis.smembers(reason) key = reason.split(':')[-1] buckets[key] = Review.objects.no_cache().filter(id__in=ids) reviews = dict((review.addon_id, review) for bucket in buckets.values() for review in bucket) for addon in Addon.objects.no_cache().filter(id__in=reviews): reviews[addon.id].addon = addon return render(request, 'reviews/spam.html', dict(buckets=buckets, review_perms=dict(is_admin=True)))