Esempio n. 1
0
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, "profile": profile, "roles": roles, "form": f}
    )
Esempio n. 2
0
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})
Esempio n. 3
0
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})
Esempio n. 4
0
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})
Esempio n. 5
0
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 waffle.switch_is_active("currencies") and 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)
Esempio n. 6
0
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})
Esempio n. 7
0
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))
Esempio n. 8
0
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."))
Esempio n. 9
0
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},
    )
Esempio n. 10
0
def landing(request):
    """Developer Hub landing page."""
    _refresh_mdn(request)

    videos = [
        {"name": "airbnb", "path": "FirefoxMarketplace-airbnb-BR-RC-SD1%20640"},
        {"name": "evernote", "path": "FirefoxMarketplace-Evernote_BR-RC-SD1%20640"},
        {"name": "uken", "path": "FirefoxMarketplace-uken-BR-RC-SD1%20640"},
        {"name": "soundcloud", "path": "FirefoxMarketplace-Soundcloud-BR-RC-SD1%20640"},
        {"name": "box", "path": "FirefoxMarketplace_box-BR-RC-SD1%20640"},
    ]

    form = DevNewsletterForm(request.POST or None)

    if request.method == "POST" and form.is_valid():
        data = form.cleaned_data

        try:
            basket.subscribe(data["email"], "app-dev", source_url=settings.SITE_URL)
            messages.success(request, _("Thank you for subscribing!"))
            return redirect("ecosystem.landing")
        except basket.BasketException:
            messages.error(request, _("We apologize, but an error " "occurred in our system. Please try again later."))

    return jingo.render(request, "ecosystem/landing.html", {"videos": videos, "newsletter_form": form})
Esempio n. 11
0
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})
Esempio n. 12
0
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
    })
Esempio n. 13
0
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})
Esempio n. 14
0
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))
Esempio n. 15
0
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)
Esempio n. 16
0
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})
Esempio n. 17
0
 def inner(request, addon_id, addon, *args, **kwargs):
     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]))
     else:
         return render_view(request, addon_id, addon, *args, **kwargs)
Esempio n. 18
0
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})
Esempio n. 19
0
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))
Esempio n. 20
0
def in_app_keys(request):
    """
    Allows developers to get a simulation-only key for in-app payments.

    This key cannot be used for real payments.
    """
    keys = UserInappKey.objects.no_cache().filter(
        solitude_seller__user=request.amo_user
    )

    # TODO(Kumar) support multiple test keys. For now there's only one.
    key = None
    key_public_id = None

    if keys.exists():
        key = keys.get()

        # Attempt to retrieve the public id from solitude
        try:
            key_public_id = key.public_id()
        except HttpClientError, e:
            messages.error(request,
                           _('A server error occurred '
                             'when retrieving the application key.'))
            log.exception('Solitude connection error: {0}'.format(e.message))
Esempio n. 21
0
def langpacks(request):
    if request.method == 'POST':
        try:
            tasks.fetch_langpacks.delay(request.POST['path'])
        except ValueError, e:
            messages.error(request, "Invalid language pack sub-path provided.")

        return redirect('zadmin.langpacks')
Esempio n. 22
0
 def inner(request, addon_id, addon, *args, **kwargs):
     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]))
     else:
         return render_view(request, addon_id, addon, *args, **kwargs)
Esempio n. 23
0
def app_review(request, addon):
    resp = None
    try:
        resp = _review(request, addon)
    except SigningError, exc:
        transaction.rollback()
        messages.error(request, "Signing Error: %s" % exc.message)
        transaction.commit()
        return redirect(reverse("reviewers.apps.review", args=[addon.app_slug]))
Esempio n. 24
0
def register(request):
    if waffle.switch_is_active('fxa-auth'):
        return login(request)

    if request.user.is_authenticated():
        messages.info(request, _('You are already logged in to an account.'))
        form = None

    elif request.method == 'POST':

        form = forms.UserRegisterForm(request.POST)
        mkt_user = UserProfile.objects.filter(email=form.data['email'],
                                              password='')
        if form.is_valid():
            try:
                u = form.save(commit=False)
                u.set_password(form.cleaned_data['password'])
                u.generate_confirmationcode()
                u.lang = request.LANG
                u.save()
                log.info(u'Registered new account for user (%s)', u)
                log_cef('New Account', 5, request, username=u.username,
                        signature='AUTHNOTICE',
                        msg='User created a new account')

                u.email_confirmation_code()

                msg = _('Congratulations! Your user account was '
                        'successfully created.')
                messages.success(request, msg)

                msg = _(u'An email has been sent to your address {0} to '
                        'confirm your account. Before you can log in, you '
                        'have to activate your account by clicking on the '
                        'link provided in this email.').format(u.email)
                messages.info(request, _('Confirmation Email Sent'), msg)

            except IntegrityError, e:
                # I was unable to reproduce this, but I suspect it happens
                # when they POST twice quickly and the slaves don't have the
                # new info yet (total guess).  Anyway, I'm assuming the
                # first one worked properly, so this is still a success
                # case to the end user so we just log it...
                log.error('Failed to register new user (%s): %s' % (u, e))

            return http.HttpResponseRedirect(reverse('users.login'))

        elif mkt_user.exists():
            f = PasswordResetForm()
            f.users_cache = [mkt_user[0]]
            f.save(use_https=request.is_secure(),
                   email_template_name='users/email/pwreset.ltxt',
                   request=request)
            return render(request, 'users/newpw_sent.html', {})
        else:
            messages.error(request, _('There are errors in this form'),
                           _('Please correct them and resubmit.'))
Esempio n. 25
0
def _login(request, template=None, data=None, dont_redirect=False):
    data = data or {}
    data['webapp'] = True
    # In case we need it later.  See below.
    get_copy = request.GET.copy()

    if 'to' in request.GET:
        request = _clean_next_url(request)

    if request.user.is_authenticated():
        return http.HttpResponseRedirect(
            request.GET.get('to', settings.LOGIN_REDIRECT_URL))

    user = None
    login_status = None
    r = auth_login(request, template_name=template, redirect_field_name='to',
                   extra_context=data)

    if isinstance(r, http.HttpResponseRedirect):
        # Django's auth.views.login has security checks to prevent someone from
        # redirecting to another domain.  Since we want to allow this in
        # certain cases, we have to make a new response object here to replace
        # the above.

        if 'domain' in request.GET:
            request.GET = get_copy
            request = _clean_next_url(request)
            r = http.HttpResponseRedirect(request.GET['to'])

        # Succsesful log in according to django.  Now we do our checks.  I do
        # the checks here instead of the form's clean() because I want to use
        # the messages framework and it's not available in the request there.
        if user.deleted:
            logout(request)
            log.warning(u'Attempt to log in with deleted account (%s)' % user)
            messages.error(request, _('Wrong email address or password!'))
            user.log_login_attempt(False)
            log_cef('Authentication Failure', 5, request,
                    username=request.user, signature='AUTHFAIL',
                    msg='Account is deactivated')
            return render(request, template, data)

        login_status = True

        if dont_redirect:
            # We're recalling the middleware to re-initialize amo_user
            ACLMiddleware().process_request(request)
            r = render(request, template, data)

    if login_status is not None:
        user.log_login_attempt(login_status)
        log_cef('Authentication Failure', 5, request,
                username=request.POST['username'],
                signature='AUTHFAIL',
                msg='The password was incorrect')

    return r
Esempio n. 26
0
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)
Esempio n. 27
0
def login(request):
    logout(request)

    if 'to' in request.GET:
        request = _clean_next_url(request)

    r = auth.views.login(request,
                         template_name='users/login.html',
                         redirect_field_name='to',
                         authentication_form=forms.AuthenticationForm)

    if isinstance(r, http.HttpResponseRedirect):
        # Succsesful log in according to django.  Now we do our checks.  I do
        # the checks here instead of the form's clean() because I want to use
        # the messages framework and it's not available in the request there
        user = request.user.get_profile()

        if user.deleted:
            logout(request)
            log.warning(u'Attempt to log in with deleted account (%s)' % user)
            messages.error(request, _('Wrong email address or password!'))
            return jingo.render(request, 'users/login.html',
                                {'form': forms.AuthenticationForm()})

        if user.confirmationcode:
            logout(request)
            log.info(u'Attempt to log in with unconfirmed account (%s)' % user)
            msg1 = _(('A link to activate your user account was sent by email '
                      'to your address {0}. You have to click it before you '
                      'can log in.').format(user.email))
            url = "%s%s" % (settings.SITE_URL,
                            reverse('users.confirm.resend', args=[user.id]))
            msg2 = _(('If you did not receive the confirmation email, make '
                      'sure your email service did not mark it as "junk '
                      'mail" or "spam". If you need to, you can have us '
                      '<a href="%s">resend the confirmation message</a> '
                      'to your email address mentioned above.') % url)
            messages.error(request, _('Activation Email Sent'), msg1)
            messages.info(request, _('Having Trouble?'), msg2, title_safe=True)
            return jingo.render(request, 'users/login.html',
                                {'form': forms.AuthenticationForm()})

        rememberme = request.POST.get('rememberme', None)
        if rememberme:
            request.session.set_expiry(settings.SESSION_COOKIE_AGE)
            log.debug((u'User (%s) logged in successfully with '
                       '"remember me" set') % user)
        else:
            user.log_login_attempt(request, True)
    elif 'username' in request.POST:
        # Hitting POST directly because cleaned_data doesn't exist
        user = UserProfile.objects.filter(email=request.POST['username'])
        if user:
            user.get().log_login_attempt(request, False)

    return r
Esempio n. 28
0
def login(request):
    logout(request)

    if 'to' in request.GET:
        request = _clean_next_url(request)

    r = auth.views.login(request, template_name='users/login.html',
                         redirect_field_name='to',
                         authentication_form=forms.AuthenticationForm)

    if isinstance(r, http.HttpResponseRedirect):
        # Succsesful log in according to django.  Now we do our checks.  I do
        # the checks here instead of the form's clean() because I want to use
        # the messages framework and it's not available in the request there
        user = request.user.get_profile()

        if user.deleted:
            logout(request)
            log.warning(u'Attempt to log in with deleted account (%s)' % user)
            messages.error(request, _('Wrong email address or password!'))
            return jingo.render(request, 'users/login.html',
                                {'form': forms.AuthenticationForm()})

        if user.confirmationcode:
            logout(request)
            log.info(u'Attempt to log in with unconfirmed account (%s)' % user)
            msg1 = _(('A link to activate your user account was sent by email '
                      'to your address {0}. You have to click it before you '
                      'can log in.').format(user.email))
            url = "%s%s" % (settings.SITE_URL,
                            reverse('users.confirm.resend', args=[user.id]))
            msg2 = _(('If you did not receive the confirmation email, make '
                      'sure your email service did not mark it as "junk '
                      'mail" or "spam". If you need to, you can have us '
                      '<a href="%s">resend the confirmation message</a> '
                      'to your email address mentioned above.') % url)
            messages.error(request, _('Activation Email Sent'),  msg1)
            messages.info(request, _('Having Trouble?'), msg2,
                          title_safe=True)
            return jingo.render(request, 'users/login.html',
                                {'form': forms.AuthenticationForm()})

        rememberme = request.POST.get('rememberme', None)
        if rememberme:
            request.session.set_expiry(settings.SESSION_COOKIE_AGE)
            log.debug((u'User (%s) logged in successfully with '
                                        '"remember me" set') % user)
        else:
            user.log_login_attempt(request, True)
    elif 'username' in request.POST:
        # Hitting POST directly because cleaned_data doesn't exist
        user = UserProfile.objects.filter(email=request.POST['username'])
        if user:
            user.get().log_login_attempt(request, False)

    return r
Esempio n. 29
0
def delete(request, addon_id, addon):
    form = forms.DeleteForm(request)
    if form.is_valid():
        addon.delete('Removed via devhub')
        messages.success(request, _('Add-on deleted.'))
        return redirect('devhub.addons')
    else:
        messages.error(request,
                       _('Password was incorrect.  Add-on was not deleted.'))
        return redirect('devhub.versions', addon.slug)
Esempio n. 30
0
def delete(request, addon_id, addon):
    form = forms.DeleteForm(request)
    if form.is_valid():
        addon.delete('Removed via devhub')
        messages.success(request, _('Add-on deleted.'))
        return redirect('devhub.addons')
    else:
        messages.error(request,
                       _('Password was incorrect.  Add-on was not deleted.'))
        return redirect('devhub.versions', addon.slug)
Esempio n. 31
0
def notify(request, job):
    job = get_object_or_404(ValidationJob, pk=job)
    notify_form = NotifyForm(request.POST, text='validation')

    if not notify_form.is_valid():
        messages.error(request, notify_form)
    else:
        tasks.notify_compatibility.delay(job, notify_form.cleaned_data)

    return redirect(reverse('zadmin.validation'))
Esempio n. 32
0
def notify(request, job):
    job = get_object_or_404(ValidationJob, pk=job)
    notify_form = NotifyForm(request.POST, text='validation')

    if not notify_form.is_valid():
        messages.error(request, notify_form)
    else:
        tasks.notify_compatibility.delay(job, notify_form.cleaned_data)

    return redirect(reverse('zadmin.validation'))
Esempio n. 33
0
def app_review(request, addon):
    resp = None
    try:
        resp = _review(request, addon)
    except SigningError, exc:
        transaction.rollback()
        messages.error(request, 'Signing Error: %s' % exc)
        transaction.commit()
        return redirect(reverse('reviewers.apps.review',
                                args=[addon.app_slug]))
Esempio n. 34
0
def register(request):

    if request.user.is_authenticated():
        messages.info(request, _('You are already logged in to an account.'))
        form = None

    elif request.method == 'POST':

        form = forms.UserRegisterForm(request.POST)
        mkt_user = UserProfile.objects.filter(email=form.data['email'],
                                              password='')
        if form.is_valid():
            try:
                u = form.save(commit=False)
                u.set_password(form.cleaned_data['password'])
                u.generate_confirmationcode()
                u.lang = request.LANG
                u.save()
                log.info(u'Registered new account for user (%s)', u)
                log_cef('New Account', 5, request, username=u.username,
                        signature='AUTHNOTICE',
                        msg='User created a new account')

                u.email_confirmation_code()

                msg = _('Congratulations! Your user account was '
                        'successfully created.')
                messages.success(request, msg)

                msg = _(u'An email has been sent to your address {0} to '
                        'confirm your account. Before you can log in, you '
                        'have to activate your account by clicking on the '
                        'link provided in this email.').format(u.email)
                messages.info(request, _('Confirmation Email Sent'), msg)

            except IntegrityError, e:
                # I was unable to reproduce this, but I suspect it happens
                # when they POST twice quickly and the slaves don't have the
                # new info yet (total guess).  Anyway, I'm assuming the
                # first one worked properly, so this is still a success
                # case to the end user so we just log it...
                log.error('Failed to register new user (%s): %s' % (u, e))

            return http.HttpResponseRedirect(reverse('users.login'))

        elif mkt_user.exists():
            f = PasswordResetForm()
            f.users_cache = [mkt_user[0]]
            f.save(use_https=request.is_secure(),
                   email_template_name='users/email/pwreset.ltxt',
                   request=request)
            return render(request, 'users/newpw_sent.html', {})
        else:
            messages.error(request, _('There are errors in this form'),
                           _('Please correct them and resubmit.'))
Esempio n. 35
0
def edit(request):
    # Don't use request.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)
        if form.is_valid():
            messages.success(request, _('Profile Updated'))
            if amouser.email != original_email:

                l = {'user': amouser,
                     'mail1': original_email,
                     'mail2': amouser.email}
                log.info(u"User (%(user)s) has requested email change from "
                         u"(%(mail1)s) to (%(mail2)s)" % l)
                messages.info(
                    request, _('Email Confirmation Sent'),
                    _(u'An email has been sent to {0} to confirm your new '
                      u'email address. For the change to take effect, you '
                      u'need to click on the link provided in this email. '
                      u'Until then, you can keep logging in with your '
                      u'current email address.').format(amouser.email))

                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': settings.DOMAIN, 'url': url}
                send_mail(
                    _('Please confirm your email address '
                      'change at %s' % settings.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, request=request)
    return render(request, 'users/edit.html',
                  {'form': form, 'amouser': amouser})
Esempio n. 36
0
def jetpack(request):
    upgrader = files.utils.JetpackUpgrader()
    minver, maxver = upgrader.jetpack_versions()
    form = JetpackUpgradeForm(request.POST)
    if request.method == "POST":
        if form.is_valid():
            if "minver" in request.POST:
                data = form.cleaned_data
                upgrader.jetpack_versions(data["minver"], data["maxver"])
            elif "upgrade" in request.POST:
                if upgrader.version(maxver):
                    start_upgrade(minver, maxver)
            elif "cancel" in request.POST:
                upgrader.cancel()
            return redirect("zadmin.jetpack")
        else:
            messages.error(request, form.errors.as_text())

    jetpacks = files.utils.find_jetpacks(minver, maxver, from_builder_only=True)

    upgrading = upgrader.version()  # Current Jetpack version upgrading to.
    repack_status = upgrader.files()  # The files being repacked.

    show = request.GET.get("show", upgrading or minver)
    subset = filter(lambda f: not f.needs_upgrade and f.jetpack_version == show, jetpacks)
    need_upgrade = filter(lambda f: f.needs_upgrade, jetpacks)
    repacked = []

    if upgrading:
        # Group the repacked files by status for this Jetpack upgrade.
        grouped_files = sorted_groupby(repack_status.values(), key=lambda f: f["status"])
        for group, rows in grouped_files:
            rows = sorted(list(rows), key=lambda f: f["file"])
            for idx, row in enumerate(rows):
                rows[idx]["file"] = File.objects.get(id=row["file"])
            repacked.append((group, rows))

    groups = sorted_groupby(jetpacks, "jetpack_version")
    by_version = dict((version, len(list(files))) for version, files in groups)
    return jingo.render(
        request,
        "zadmin/jetpack.html",
        dict(
            form=form,
            upgrader=upgrader,
            by_version=by_version,
            upgrading=upgrading,
            need_upgrade=need_upgrade,
            subset=subset,
            show=show,
            repacked=repacked,
            repack_status=repack_status,
        ),
    )
Esempio n. 37
0
def jetpack(request):
    upgrader = files.utils.JetpackUpgrader()
    minver, maxver = upgrader.jetpack_versions()
    form = JetpackUpgradeForm(request.POST)
    if request.method == 'POST':
        if form.is_valid():
            if 'minver' in request.POST:
                data = form.cleaned_data
                upgrader.jetpack_versions(data['minver'], data['maxver'])
            elif 'upgrade' in request.POST:
                if upgrader.version(maxver):
                    start_upgrade(minver, maxver)
            elif 'cancel' in request.POST:
                upgrader.cancel()
            return redirect('zadmin.jetpack')
        else:
            messages.error(request, form.errors.as_text())

    jetpacks = files.utils.find_jetpacks(minver,
                                         maxver,
                                         from_builder_only=True)

    upgrading = upgrader.version()  # Current Jetpack version upgrading to.
    repack_status = upgrader.files()  # The files being repacked.

    show = request.GET.get('show', upgrading or minver)
    subset = filter(
        lambda f: not f.needs_upgrade and f.jetpack_version == show, jetpacks)
    need_upgrade = filter(lambda f: f.needs_upgrade, jetpacks)
    repacked = []

    if upgrading:
        # Group the repacked files by status for this Jetpack upgrade.
        grouped_files = sorted_groupby(repack_status.values(),
                                       key=lambda f: f['status'])
        for group, rows in grouped_files:
            rows = sorted(list(rows), key=lambda f: f['file'])
            for idx, row in enumerate(rows):
                rows[idx]['file'] = File.objects.get(id=row['file'])
            repacked.append((group, rows))

    groups = sorted_groupby(jetpacks, 'jetpack_version')
    by_version = dict((version, len(list(files))) for version, files in groups)
    return jingo.render(
        request, 'zadmin/jetpack.html',
        dict(form=form,
             upgrader=upgrader,
             by_version=by_version,
             upgrading=upgrading,
             need_upgrade=need_upgrade,
             subset=subset,
             show=show,
             repacked=repacked,
             repack_status=repack_status))
Esempio n. 38
0
def app_review(request, addon):
    version = addon.latest_version
    resp = None
    try:
        resp = _review(request, addon, version)
    except SigningError, exc:
        transaction.rollback()
        messages.error(request, 'Signing Error: %s' % exc)
        transaction.commit()
        return redirect(
            reverse('reviewers.apps.review', args=[addon.app_slug]))
Esempio n. 39
0
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)
Esempio n. 40
0
    def inner(request, addon_id, addon, *args, **kwargs):
        setup_url = reverse('mkt.developers.apps.payments',
                            args=[addon.app_slug])
        if addon.premium_type not in amo.ADDON_INAPPS:
            messages.error(
                request, _('Your app is not configured for in-app payments.'))
            return redirect(setup_url)
        if not addon.has_payment_account():
            messages.error(request, _('No payment account for this app.'))
            return redirect(setup_url)

        # App is set up for payments; render the view.
        return render_view(request, addon_id, addon, *args, **kwargs)
Esempio n. 41
0
def paypal_setup_bounce(request, addon_id, addon, webapp):
    if not addon.paypal_id:
        messages.error(request, 'We need a PayPal email before continuing.')
        return redirect(addon.get_dev_url('paypal_setup'))
    paypal_url = paypal.get_permission_url(addon, 'management', [
        'REFUND', 'ACCESS_BASIC_PERSONAL_DATA', 'ACCESS_ADVANCED_PERSONAL_DATA'
    ])

    return jingo.render(request,
                        'developers/payments/paypal-details-request.html', {
                            'paypal_url': paypal_url,
                            'addon': addon
                        })
Esempio n. 42
0
def notify(request, job):
    job = get_object_or_404(ValidationJob, pk=job)
    notify_form = NotifyForm(request.POST, text='validation')

    if not notify_form.is_valid():
        messages.error(request, notify_form)
    else:
        for chunk in chunked(updated_versions(job), 100):
            tasks.update_maxversions.delay(chunk, job.pk,
                                           notify_form.cleaned_data)

        updated_authors = completed_version_authors(job)
        for chunk in chunked(updated_authors, 100):
            # There are times when you want to punch django's ORM in
            # the face. This may be one of those times.
            # TODO: Offload most of this work to the task?
            users_addons = list(
                UserProfile.objects.filter(
                    pk__in=chunk).filter(**_completed_versions(
                        job, 'addons__versions')).values_list(
                            'pk', 'addons__pk').distinct())

            users = list(
                UserProfile.objects.filter(pk__in=set(
                    u for u, a in users_addons)))

            # Annotate fails in tests when using cached results
            addons = (Addon.objects.no_cache().filter(
                **{
                    'pk__in': set(a for u, a in users_addons),
                    'versions__files__'
                    'validation_results__validation_job': job
                }).annotate(
                    errors=Sum('versions__files__validation_results__errors')))
            addons = dict((a.id, a) for a in addons)

            users_addons = dict(
                (u, [addons[a] for u, a in row])
                for u, row in sorted_groupby(users_addons, lambda k: k[0]))

            for u in users:
                addons = users_addons[u.pk]

                u.passing_addons = [a for a in addons if a.errors == 0]
                u.failing_addons = [a for a in addons if a.errors > 0]

            tasks.notify_compatibility.delay(users, job,
                                             notify_form.cleaned_data)

    return redirect(reverse('zadmin.validation'))
Esempio n. 43
0
def notify_failure(request, job):
    job = get_object_or_404(ValidationJob, pk=job)
    notify_form = NotifyForm(request.POST, text='failure')

    if not notify_form.is_valid():
        messages.error(request, notify_form)

    else:
        file_pks = job.result_failing().values_list('file_id', flat=True)
        for chunk in chunked(file_pks, 100):
            tasks.notify_failed.delay(chunk, job.pk, notify_form.cleaned_data)
        messages.success(request, _('Notifying authors task started.'))

    return redirect(reverse('zadmin.validation'))
Esempio n. 44
0
def confirm(request, user, token):
    if not user.confirmationcode:
        return redirect('users.login')

    if user.confirmationcode != token:
        log.info(u"Account confirmation failed for user (%s)", user)
        messages.error(request, _('Invalid confirmation code!'))
        return redirect('users.login')

    user.confirmationcode = ''
    user.save()
    messages.success(request, _('Successfully verified!'))
    log.info(u"Account confirmed for user (%s)", user)
    return redirect('users.login')
Esempio n. 45
0
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.transaction_id is None:
        messages.error(
            request,
            _('A refund cannot be applied for yet. Please try again'
              ' later. If this error persists contact '
              '[email protected].'))
        paypal_log.info('Refund requested for contribution with no '
                        'transaction_id: %r' % (contribution.pk, ))
        return redirect('users.purchases')

    if contribution.is_instant_refund():
        paypal.refund(contribution.paykey)
        # TODO: Consider requiring a refund reason for instant refunds.
        refund = contribution.enqueue_refund(amo.REFUND_APPROVED_INSTANT)
        paypal_log.info('Refund %r issued for contribution %r' %
                        (refund.pk, 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():
        reason = form.cleaned_data['text']
        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': contribution.get_absolute_refund_url(),
                'refund_reason': reason
            })
        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)])
        # Add this refund request to the queue.
        contribution.enqueue_refund(amo.REFUND_PENDING, reason)
        return redirect(
            reverse('users.support', args=[contribution.pk, 'refund-sent']))

    return wizard.render(request, wizard.tpl('refund.html'), {'form': form})
Esempio n. 46
0
def notify_success(request, job):
    job = get_object_or_404(ValidationJob, pk=job)
    notify_form = NotifyForm(request.POST, text='success')

    if not notify_form.is_valid():
        messages.error(request, notify_form.errors)

    else:
        versions = completed_versions_dirty(job)
        for chunk in chunked(versions, 100):
            tasks.notify_success.delay(chunk, job.pk, notify_form.cleaned_data)
        messages.success(request, _('Updating max version task and '
                                    'notifying authors started.'))

    return redirect(reverse('zadmin.validation'))
Esempio n. 47
0
def confirm(request, user_id, token):
    user = get_object_or_404(UserProfile, id=user_id)

    if not user.confirmationcode:
        return http.HttpResponseRedirect(reverse('users.login'))

    if user.confirmationcode != token:
        log.info(u"Account confirmation failed for user (%s)", user)
        messages.error(request, _('Invalid confirmation code!'))
        return http.HttpResponseRedirect(reverse('users.login'))

    user.confirmationcode = ''
    user.save()
    messages.success(request, _('Successfully verified!'))
    log.info(u"Account confirmed for user (%s)", user)
    return http.HttpResponseRedirect(reverse('users.login'))
Esempio n. 48
0
def landing(request):
    """Developer Hub landing page."""
    videos = [
        {
            'name': 'airbnb',
            'path': 'FirefoxMarketplace-airbnb-BR-RC-SD1%20640'
        },
        {
            'name': 'evernote',
            'path': 'FirefoxMarketplace-Evernote_BR-RC-SD1%20640'
        },
        {
            'name': 'uken',
            'path': 'FirefoxMarketplace-uken-BR-RC-SD1%20640'
        },
        {
            'name': 'soundcloud',
            'path': 'FirefoxMarketplace-Soundcloud-BR-RC-SD1%20640'
        },
        {
            'name': 'box',
            'path': 'FirefoxMarketplace_box-BR-RC-SD1%20640'
        }
    ]

    form = DevNewsletterForm(request.LANG, request.POST or None)

    if request.method == 'POST' and form.is_valid():
        data = form.cleaned_data

        try:
            basket.subscribe(data['email'],
                             'app-dev',
                             format=data['email_format'],
                             source_url=settings.SITE_URL)
            messages.success(request, _('Thank you for subscribing!'))
            return redirect('ecosystem.landing')
        except basket.BasketException as e:
            log.error(
                'Basket exception in ecosystem newsletter: %s' % e)
            messages.error(
                request, _('We apologize, but an error occurred in our '
                           'system. Please try again later.'))

    return jingo.render(request, 'ecosystem/landing.html',
        {'videos': videos, 'newsletter_form': form})
Esempio n. 49
0
def register(request):
    if request.user.is_authenticated():
        messages.info(request, _("You are already logged in to an account."))
        form = None
    elif request.method == 'POST':

        form = forms.UserRegisterForm(request.POST)

        if form.is_valid():
            try:
                u = form.save(commit=False)
                u.set_password(form.cleaned_data['password'])
                u.generate_confirmationcode()
                u.save()
                u.create_django_user()
                log.info(u"Registered new account for user (%s)", u)

                u.email_confirmation_code()

                msg = _('Congratulations! Your user account was successfully '
                        'created.')
                messages.success(request, msg)

                msg = _(('An email has been sent to your address {0} to '
                         'confirm your account. Before you can log in, you '
                         'have to activate your account by clicking on the '
                         'link provided in this email.').format(u.email))
                messages.info(request, _('Confirmation Email Sent'), msg)
            except IntegrityError, e:
                # I was unable to reproduce this, but I suspect it happens
                # when they POST twice quickly and the slaves don't have the
                # new info yet (total guess).  Anyway, I'm assuming the
                # first one worked properly, so this is still a success
                # case to tne end user so we just log it...
                log.error("Failed to register new user (%s): %s" % (u, e))

            amo.utils.clear_messages(request)
            return http.HttpResponseRedirect(reverse('users.login') + '?m=3')
            # TODO POSTREMORA Replace the above two lines
            # when remora goes away with this:
            #return http.HttpResponseRedirect(reverse('users.login'))

        else:
            messages.error(request, _('There are errors in this form'),
                           _('Please correct them and resubmit.'))
Esempio n. 50
0
def confirm(request, user_id, token):
    user = get_object_or_404(UserProfile, id=user_id)

    if not user.confirmationcode:
        return redirect('users.login')

    if user.confirmationcode != token:
        log.info(u"Account confirmation failed for user (%s)", user)
        if waffle.switch_is_active('zamboni-login'):
            messages.error(request, _('Invalid confirmation code!'))
        return redirect('users.login')

    user.confirmationcode = ''
    user.save()
    if waffle.switch_is_active('zamboni-login'):
        messages.success(request, _('Successfully verified!'))
    log.info(u"Account confirmed for user (%s)", user)
    return redirect('users.login')
Esempio n. 51
0
def t_shirt(request):
    if not waffle.switch_is_active('t-shirt-orders'):
        raise http.Http404()

    user = request.user
    eligible = tshirt_eligible(user)

    if request.method == 'POST':
        if not eligible:
            messages.error(request,
                           _("We're sorry, but you are not eligible to "
                             "request a t-shirt at this time."))
            return redirect('users.t-shirt')

        if not user.t_shirt_requested:
            user.update(t_shirt_requested=datetime.now())

    return render(request, 'users/t-shirt.html',
                  {'eligible': eligible, 'user': user})
Esempio n. 52
0
def langpacks(request):
    if request.method == 'POST':
        try:
            tasks.fetch_langpacks.delay(request.POST['path'])
        except ValueError:
            messages.error(request, 'Invalid language pack sub-path provided.')

        return redirect('zadmin.langpacks')

    addons = (Addon.objects.no_cache()
                   .filter(addonuser__user__email=settings.LANGPACK_OWNER_EMAIL,
                           type=amo.ADDON_LPAPP)
                   .order_by('name'))

    data = {'addons': addons, 'base_url': settings.LANGPACK_DOWNLOAD_BASE,
            'default_path': settings.LANGPACK_PATH_DEFAULT % (
                'firefox', amo.FIREFOX.latest_version)}

    return jingo.render(request, 'zadmin/langpack_update.html', data)
Esempio n. 53
0
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 (waffle.switch_is_active('currencies')
            and 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)
Esempio n. 54
0
def register(request):
    if request.user.is_authenticated():
        messages.info(request, _("You are already logged in to an account."))
        form = None
    elif request.method == 'POST':

        form = forms.UserRegisterForm(request.POST)

        if form.is_valid():
            u = form.save(commit=False)
            u.set_password(form.cleaned_data['password'])
            u.generate_confirmationcode()
            u.save()
            u.create_django_user()
            log.info(u"Registered new account for user (%s)", u)

            u.email_confirmation_code()

            messages.success(
                request,
                _('Congratulations! Your user account '
                  'was successfully created.'))
            msg = _(('An email has been sent to your address {0} to confirm '
                     'your account. Before you can log in, you have to '
                     'activate your account by clicking on the link provided '
                     ' in this email.').format(u.email))
            messages.info(request, _('Confirmation Email Sent'), msg)

            amo.utils.clear_messages(request)
            return http.HttpResponseRedirect(reverse('users.login') + '?m=3')
            # TODO POSTREMORA Replace the above with this line
            # when remora goes away
            #return http.HttpResponseRedirect(reverse('users.login'))

        else:
            messages.error(request, _('There are errors in this form'),
                           _('Please correct them and resubmit.'))
    else:
        form = forms.UserRegisterForm()
    return jingo.render(request, 'users/register.html', {
        'form': form,
    })
Esempio n. 55
0
def in_app_keys(request):
    keys = UserInappKey.objects.no_cache().filter(
        solitude_seller__user=request.amo_user
    )

    # TODO(Kumar) support multiple test keys. For now there's only one.
    key = None
    key_public_id = None

    if keys.exists():
        key = keys.get()

        # Attempt to retrieve the public id from solitude
        try:
            key_public_id = key.public_id()
        except HttpClientError, e:
            messages.error(request,
                           _('A server error occurred '
                             'when retrieving the application key.'))
            log.exception('Solitude connection error: {0}'.format(e.message))
Esempio n. 56
0
def delete(request, addon_id, addon, webapp=False):
    # Database deletes only allowed for free or incomplete addons.
    if not addon.can_be_deleted():
        msg = _('Paid apps cannot be deleted. Disable this app instead.')
        messages.error(request, msg)
        return redirect(addon.get_dev_url('versions'))

    # TODO: This short circuits the delete form which checks the password. When
    # BrowserID adds re-auth support, update the form to check with BrowserID
    # and remove the short circuit.
    form = forms.DeleteForm(request)
    if True or form.is_valid():
        addon.delete('Removed via devhub')
        messages.success(request, _('App deleted.'))
        # Preserve query-string parameters if we were directed from Dashboard.
        return redirect(
            request.GET.get('to') or reverse('mkt.developers.apps'))
    else:
        msg = _('Password was incorrect.  App was not deleted.')
        messages.error(request, msg)
        return redirect(addon.get_dev_url('versions'))
Esempio n. 57
0
def marketplace_confirm(request, addon_id, addon, webapp=False):
    if request.method == 'POST':
        if (addon.premium and addon.premium.is_complete()
                and addon.premium.has_permissions_token()):
            if addon.status == amo.STATUS_UNREVIEWED:
                addon.status = amo.STATUS_NOMINATED
            addon.premium_type = amo.ADDON_PREMIUM
            addon.save()
            amo.log(amo.LOG.MAKE_PREMIUM, addon)
            return redirect(addon.get_dev_url('payments'))

        messages.error(request, 'Some required details are missing.')
        return redirect(addon.get_dev_url('market.1'))

    return jingo.render(
        request, 'developers/payments/second-confirm.html', {
            'addon': addon,
            'webapp': webapp,
            'upsell': addon.upsold,
            'premium': addon.premium
        })
Esempio n. 58
0
def delete(request, addon_id, addon, webapp=False):
    # Database deletes only allowed for free or incomplete addons.
    if not addon.can_be_deleted():
        msg = _('Paid apps cannot be deleted. Disable this app instead.')
        messages.error(request, msg)
        return redirect(addon.get_dev_url('versions'))

    # TODO: Force the user to re-auth with BrowserID (this DeleteForm doesn't
    # ask the user for his password)
    form = forms.DeleteForm(request)
    if form.is_valid():
        reason = form.cleaned_data.get('reason', '')
        addon.delete(msg='Removed via devhub', reason=reason)
        messages.success(request, _('App deleted.'))
        # Preserve query-string parameters if we were directed from Dashboard.
        return redirect(
            request.GET.get('to') or reverse('mkt.developers.apps'))
    else:
        msg = _('Password was incorrect.  App was not deleted.')
        messages.error(request, msg)
        return redirect(addon.get_dev_url('versions'))
Esempio n. 59
0
def api(request):
    try:
        access = Access.objects.get(user=request.user)
    except Access.DoesNotExist:
        access = None

    roles = request.amo_user.groups.filter(name='Admins').exists()
    if roles:
        messages.error(request,
                       _('Users with the admin role 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
    })