Пример #1
0
 def form_valid(self, form):
     """Create the request"""
     if self.request.user.is_authenticated:
         user = self.request.user
     else:
         try:
             user = self._handle_anonymous_submitter(form)
         except requests.exceptions.RequestException:
             return self.form_invalid(form)
     if form.cleaned_data["action"] in ("save", "submit"):
         composer = form.save()
         # if a new agency is added while the user is anonymous,
         # we want to associate that agency to the user once they
         # login or register
         composer.agencies.filter(user=None,
                                  status="pending").update(user=user)
     if form.cleaned_data["action"] == "save":
         self.request.session["ga"] = "request_drafted"
         mixpanel_event(
             self.request,
             "Request Saved",
             self._composer_mixpanel_properties(composer),
         )
         messages.success(self.request, "Request saved")
     elif form.cleaned_data["action"] == "submit":
         self._submit_composer(composer, form)
     return redirect(composer)
Пример #2
0
 def form_valid(self, form):
     """Saves relationship and sends action before returning URL"""
     redirection = super(ProjectCrowdfundView, self).form_valid(form)
     crowdfund = self.object
     project = self.get_project()
     relationship = ProjectCrowdfunds.objects.create(
         project=project, crowdfund=crowdfund
     )
     new_action(
         self.request.user,
         "began crowdfunding",
         action_object=relationship.crowdfund,
         target=relationship.project,
     )
     crowdfund.send_intro_email(self.request.user)
     mixpanel_event(
         self.request,
         "Launch Project Crowdfund",
         self._project_mixpanel_properties(
             project,
             {
                 "Name": crowdfund.name,
                 "Payment Capped": crowdfund.payment_capped,
                 "Payment Required": float(crowdfund.payment_required),
                 "Date Due": crowdfund.date_due.isoformat(),
             },
         ),
     )
     return redirection
Пример #3
0
 def _handle_anonymous_submitter(self, form):
     """Handle a submission from an anonymous user"""
     # form validation guarentees we have either registration or login info
     if form.cleaned_data.get('register_full_name'):
         user = self.miniregister(
             form.cleaned_data['register_full_name'],
             form.cleaned_data['register_email'],
             form.cleaned_data.get('register_newsletter'),
         )
         if form.cleaned_data.get('register_pro'):
             try:
                 user.profile.start_pro_subscription(
                     form.cleaned_data.get('stripe_token'), )
             except StripeError:
                 messages.error(
                     self.request, 'There was an error processing your '
                     'payment.  Your account has been created, but you '
                     'have not been subscribed to a professional account.  '
                     'You can subscribe from the settings page.')
             else:
                 mixpanel_event(self.request, 'Pro Subscription Started')
         return user
     else:
         login(self.request, form.user)
         return form.user
Пример #4
0
def follow(request, jurisdiction, jidx, slug, idx):
    """Follow or unfollow a request"""
    foia = get_object_or_404(
        FOIARequest,
        agency__jurisdiction__slug=jurisdiction,
        agency__jurisdiction__pk=jidx,
        slug=slug,
        pk=idx,
    )
    if actstream.actions.is_following(request.user, foia):
        actstream.actions.unfollow(request.user, foia)
        messages.success(request, 'You are no longer following this request.')
        mixpanel_event(
            request,
            'Unfollow',
            foia.mixpanel_data(),
        )
    else:
        actstream.actions.follow(request.user, foia, actor_only=False)
        messages.success(request, 'You are now following this request.')
        mixpanel_event(
            request,
            'Follow',
            foia.mixpanel_data(),
        )
    return redirect(foia)
Пример #5
0
 def _handle_cancel_payments(self, attr, arg):
     """Handle cancelling recurring donations or crowdfunds"""
     payments = (
         getattr(self.request.user, attr)
         .filter(pk__in=self.request.POST.getlist(arg))
     )
     attr_type = {
         'donations': 'Donation',
         'recurring_crowdfund_payments': 'Recurring Crowdfund',
     }
     for payment in payments:
         payment.cancel()
         mixpanel_event(
             self.request,
             'Cancel {}'.format(attr_type[attr]),
             {'Amount': payment.amount},
         )
     msg = attr.replace('_', ' ')
     if payments:
         messages.success(
             self.request,
             'The selected {} have been cancelled.'.format(msg),
         )
     else:
         messages.warning(
             self.request,
             'No {} were selected to be cancelled.'.format(msg),
         )
Пример #6
0
 def form_valid(self, form):
     """Create the request"""
     if self.request.user.is_authenticated:
         user = self.request.user
     else:
         user = self._handle_anonymous_submitter(form)
     if form.cleaned_data['action'] in ('save', 'submit'):
         composer = form.save(commit=False)
         composer.user = user
         composer.save()
         form.save_m2m()
         # if a new agency is added while the user is anonymous,
         # we want to associate that agency to the user once they
         # login or register
         composer.agencies.filter(user=None,
                                  status='pending').update(user=user)
     if form.cleaned_data['action'] == 'save':
         self.request.session['ga'] = 'request_drafted'
         mixpanel_event(
             self.request,
             'Request Saved',
             self._composer_mixpanel_properties(composer),
         )
         messages.success(self.request, 'Request saved')
     elif form.cleaned_data['action'] == 'submit':
         self._submit_composer(composer, form)
     return redirect(composer)
Пример #7
0
 def form_valid(self, form):
     """When form is valid, create the user and begin their professional subscription."""
     new_user = create_new_user(self.request, form)
     welcome.delay(new_user)
     try:
         new_user.profile.start_pro_subscription(
             self.request.POST['stripe_token'])
         success_msg = 'Your professional account was successfully created. Welcome to MuckRock!'
         messages.success(self.request, success_msg)
         mixpanel_event(
             self.request,
             'Pro Subscription Started',
         )
     except (KeyError, AttributeError):
         # no payment information provided
         logger.warn('No payment information provided.')
         error_msg = ('Your account was successfully created, '
                      'but you did not provide payment information. '
                      'You can subscribe from the account management page.')
         messages.error(self.request, error_msg)
     except stripe.error.CardError:
         # card declined
         logger.warn('Card was declined.')
         error_msg = (
             'Your account was successfully created, but your card was declined. '
             'You can subscribe from the account management page.')
         messages.error(self.request, error_msg)
     except (stripe.error.InvalidRequestError, stripe.error.APIError):
         # invalid request made to stripe
         logger.warn('No payment information provided.')
         error_msg = ('Your account was successfully created, '
                      'but we could not contact our payment provider. '
                      'You can subscribe from the account management page.')
         messages.error(self.request, error_msg)
     return super(ProfessionalSignupView, self).form_valid(form)
Пример #8
0
 def _user_follow_up(self, request, foia):
     """Handle follow ups for non-admins"""
     has_perm = foia.has_perm(request.user, 'followup')
     contact_info_form = ContactInfoForm(request.POST,
                                         foia=foia,
                                         prefix='followup')
     has_contact_perm = request.user.has_perm('foia.set_info_foiarequest')
     contact_valid = contact_info_form.is_valid()
     use_contact_info = (
         has_contact_perm
         and contact_info_form.cleaned_data.get('use_contact_information'))
     comm_sent = self._new_comm(
         request,
         foia,
         has_perm and (not use_contact_info or contact_valid),
         'Your follow up has been sent.',
         contact_info=contact_info_form.cleaned_data
         if use_contact_info else None,
     )
     if use_contact_info:
         foia.add_contact_info_note(
             request.user,
             contact_info_form.cleaned_data,
         )
     if comm_sent:
         new_action(request.user, 'followed up on', target=foia)
         mixpanel_event(
             request,
             'Follow Up',
             foia.mixpanel_data({
                 'Use Contact Info': use_contact_info,
             }),
         )
     return redirect(foia.get_absolute_url() + '#')
Пример #9
0
 def _submit_composer(self, composer, form):
     """Submit a composer"""
     # pylint: disable=not-an-iterable
     if form.cleaned_data.get('num_requests', 0) > 0:
         self.buy_requests(form)
     if (form.cleaned_data.get('use_contact_information')
             and self.request.user.profile.is_advanced()
             and len(composer.agencies.all()) == 1):
         contact_info = {
             k: form.cleaned_data.get(k)
             for k in ContactInfoForm.base_fields
         }
     else:
         contact_info = None
     try:
         composer.submit(contact_info)
     except InsufficientRequestsError:
         messages.warning(self.request,
                          'You need to purchase more requests')
     else:
         messages.success(self.request, 'Request submitted')
         self.request.session['ga'] = 'request_submitted'
         mixpanel_event(
             self.request,
             'Request Submitted',
             self._composer_mixpanel_properties(composer),
         )
         warning = self._proxy_warnings(composer)
         if warning:
             messages.warning(self.request, warning)
Пример #10
0
    def miniregister(self, form, full_name, email, newsletter=False):
        """Create a new user from their full name and email"""
        full_name = full_name.strip()

        user_json = self._create_squarelet_user(form, {
            "name": full_name,
            "preferred_username": full_name,
            "email": email
        })

        user, _ = Profile.objects.squarelet_update_or_create(
            user_json["uuid"], user_json)
        login(self.request,
              user,
              backend="muckrock.accounts.backends.SquareletBackend")

        if newsletter:
            mailchimp_subscribe(
                self.request,
                user.email,
                source="Mini-Register: {}".format(self.minireg_source),
                url="{}{}".format(settings.MUCKROCK_URL, self.request.path),
            )

        mixpanel_event(
            self.request,
            "Sign Up",
            {
                "Source": "Mini-Register: {}".format(self.minireg_source),
                "Newsletter": newsletter,
            },
            signup=True,
        )
        return user
Пример #11
0
def _user_follow_up(request, foia):
    """Handle follow ups for non-admins"""
    has_perm = foia.has_perm(request.user, "followup")
    contact_info_form = ContactInfoForm(request.POST, foia=foia, prefix="followup")
    has_contact_perm = request.user.has_perm("foia.set_info_foiarequest")
    contact_valid = contact_info_form.is_valid()
    use_contact_info = has_contact_perm and contact_info_form.cleaned_data.get(
        "use_contact_information"
    )
    comm_sent = _new_comm(
        request,
        foia,
        has_perm and (not use_contact_info or contact_valid),
        "Your follow up has been sent.",
        contact_info=contact_info_form.cleaned_data if use_contact_info else None,
    )
    if use_contact_info:
        foia.add_contact_info_note(request.user, contact_info_form.cleaned_data)
    if comm_sent:
        new_action(request.user, "followed up on", target=foia)
        mixpanel_event(
            request,
            "Follow Up",
            foia.mixpanel_data({"Use Contact Info": use_contact_info}),
        )
    return _get_redirect(request, foia)
Пример #12
0
 def get(self, request, *args, **kwargs):
     response = super(ProjectCrowdfundView, self).get(request, *args, **kwargs)
     mixpanel_event(
         request,
         "Start Project Crowdfund",
         self._project_mixpanel_properties(self.get_project()),
     )
     return response
Пример #13
0
 def post(self, request, **kwargs):
     """
     First we validate the payment form, so we don't charge someone's card by accident.
     Next, we charge their card. Finally, use the validated payment form to create and
     return a CrowdfundRequestPayment object.
     """
     # pylint: disable=too-many-locals
     token = request.POST.get('stripe_token')
     email = request.POST.get('stripe_email')
     email = validate_stripe_email(email)
     payment_form = CrowdfundPaymentForm(request.POST)
     if payment_form.is_valid() and token and email:
         amount = payment_form.cleaned_data['stripe_amount']
         # If there is no user but the show and full_name fields are filled in,
         # and a user with that email does not already exists,
         # create the user with our "miniregistration" functionality and then log them in
         user = request.user if request.user.is_authenticated else None
         registered = False
         show = payment_form.cleaned_data['show']
         full_name = payment_form.cleaned_data['full_name']
         email_exists = User.objects.filter(email__iexact=email).exists()
         if user is None and show and full_name and not email_exists:
             user = self.miniregister(full_name, email)
             registered = True
         crowdfund = payment_form.cleaned_data['crowdfund']
         try:
             if (crowdfund.can_recur()
                     and payment_form.cleaned_data['recurring']):
                 crowdfund.make_recurring_payment(token, email, amount,
                                                  show, user)
                 event = 'Recurring Crowdfund Payment'
                 kwargs = {}
             else:
                 crowdfund.make_payment(token, email, amount, show, user)
                 event = 'Crowdfund Payment'
                 kwargs = {'charge': float(amount)}
         except stripe.StripeError as payment_error:
             logging.warn(payment_error)
             return self.return_error(request, payment_error)
         else:
             mixpanel_event(
                 request, event, {
                     'Amount': float(amount),
                     'Crowdfund': crowdfund.name,
                     'Crowdfund ID': crowdfund.pk,
                     'Show': show,
                 }, **kwargs)
         if request.is_ajax():
             data = {
                 'authenticated':
                 user.is_authenticated() if user else False,
                 'registered': registered,
             }
             return JsonResponse(data, status=200)
         else:
             messages.success(request, 'Thank you for your contribution!')
             return redirect(self.get_redirect_url())
     return self.return_error(request)
Пример #14
0
def downgrade(request):
    """Downgrades the user from a Professional to a Basic account."""
    if not request.user.is_authenticated():
        raise AttributeError('Cannot downgrade an anonymous user.')
    if request.user.profile.acct_type != 'pro':
        raise ValueError(
            'Cannot downgrade this account, it is not Professional.')
    request.user.profile.cancel_pro_subscription()
    mixpanel_event(request, 'Pro Subscription Cancelled')
Пример #15
0
def crowdfund_request(request, idx, **kwargs):
    """Crowdfund a request"""
    # pylint: disable=unused-argument
    # select for update locks this request in order to prevent a race condition
    # allowing multiple crowdfunds to be created for it
    foia = get_object_or_404(
        FOIARequest.objects.select_for_update().select_related(
            "agency__jurisdiction", "composer"
        ),
        pk=idx,
    )
    # check for unauthorized access
    if not foia.has_perm(request.user, "crowdfund"):
        messages.error(request, "You may not crowdfund this request.")
        return redirect(foia)
    if request.method == "POST":
        # save crowdfund object
        form = CrowdfundForm(request.POST)
        if form.is_valid():
            crowdfund = form.save()
            foia.crowdfund = crowdfund
            foia.save(comment="added a crowdfund")
            messages.success(request, "Your crowdfund has started, spread the word!")
            new_action(
                request.user, "began crowdfunding", action_object=crowdfund, target=foia
            )
            crowdfund.send_intro_email(request.user)
            mixpanel_event(
                request,
                "Launch Request Crowdfund",
                foia.mixpanel_data(
                    {
                        "Name": crowdfund.name,
                        "Payment Capped": crowdfund.payment_capped,
                        "Payment Required": float(crowdfund.payment_required),
                        "Date Due": crowdfund.date_due.isoformat(),
                    }
                ),
            )
            return redirect(foia)

    elif request.method == "GET":
        # create crowdfund form
        default_crowdfund_duration = 30
        date_due = timezone.now() + timedelta(default_crowdfund_duration)
        initial = {
            "name": "Crowdfund Request: %s" % str(foia),
            "description": "Help cover the request fees needed to free these docs!",
            "payment_required": foia.get_stripe_amount(),
            "date_due": date_due,
            "foia": foia,
        }
        form = CrowdfundForm(initial=initial)
        mixpanel_event(request, "Start Request Crowdfund", foia.mixpanel_data())

    return render(request, "forms/foia/crowdfund.html", {"form": form})
Пример #16
0
 def post(self, request, *args, **kwargs):
     """Check for cancel pro before checking form"""
     if (request.user.is_staff
             and request.POST.get('action') == 'cancel-pro'):
         self.user.profile.cancel_pro_subscription()
         mixpanel_event(request, 'Pro Subscription Cancelled')
         messages.success(request, 'Pro account has been cancelled')
         return redirect('acct-profile', username=self.user.username)
     else:
         return super(ProfileView, self).post(request, *args, **kwargs)
Пример #17
0
    def buy_requests(self, form, organization=None, payer=None):
        """Buy requests"""
        if 'organization' in form.cleaned_data:
            organization = payer = form.cleaned_data['organization']
        try:
            num_requests = form.cleaned_data['num_requests']
            price = self.get_price(num_requests)
            payer.pay(
                amount=price,
                description='Purchase {} requests'.format(num_requests),
                token=form.cleaned_data['stripe_token'],
                save_card=form.cleaned_data['save_card'],
            )
            organization.add_requests(num_requests)
        except requests.exceptions.RequestException as exc:
            logger.warn('Payment error: %s', exc, exc_info=sys.exc_info())
            if exc.response.status_code / 100 == 4:
                messages.error(
                    self.request, 'Payment Error: {}'.format(
                        '\n'.join(
                            '{}: {}'.format(k, v)
                            for k, v in exc.response.json().iteritems()
                        )
                    )
                )
            else:
                messages.error(self.request, 'Payment Error')
            return

        self.request.session['ga'] = 'request_purchase'
        mixpanel_event(
            self.request,
            'Requests Purchased',
            {
                'Number': num_requests,
                'Recipient': organization.name,
                'Price': price / 100,
            },
            charge=price / 100,
        )
        if organization.individual:
            msg = (
                'Purchase successful.  {} requests have been added to your '
                'account.'.format(num_requests)
            )
        else:
            msg = (
                'Purchase successful.  {} requests have been added to '
                '{}\'s account.'.format(num_requests, organization.name)
            )
        messages.success(self.request, msg)
Пример #18
0
    def form_valid(self, form):
        """Save the form results"""
        crowdsource = self.get_object()
        has_data = crowdsource.data.exists()
        if self.request.user.is_authenticated:
            user = self.request.user
        else:
            user = self.miniregister(
                form.cleaned_data['full_name'],
                form.cleaned_data['email'],
                form.cleaned_data.get('newsletter'),
            )
        number = (
            self.object.responses.filter(user=user, data=self.data).count() +
            1)
        if not has_data or self.data is not None:
            response = CrowdsourceResponse.objects.create(
                crowdsource=crowdsource,
                user=user,
                data=self.data,
                number=number,
            )
            response.create_values(form.cleaned_data)
            messages.success(self.request, 'Thank you!')
            properties = {
                'Crowdsource': crowdsource.title,
                'Crowdsource ID': crowdsource.pk,
                'Number': number,
            }
            if self.data:
                properties['Data'] = self.data.url
            mixpanel_event(
                self.request,
                'Assignment Completed',
                properties,
            )
            for email in crowdsource.submission_emails.all():
                response.send_email(email.email)

        if self.request.POST['submit'] == 'Submit and Add Another':
            return self.render_to_response(
                self.get_context_data(data=self.data), )

        if has_data:
            return redirect(
                'crowdsource-assignment',
                slug=crowdsource.slug,
                idx=crowdsource.pk,
            )
        else:
            return redirect('crowdsource-list')
Пример #19
0
 def form_valid(self, form):
     """Update the request"""
     if form.cleaned_data['action'] == 'save':
         composer = form.save()
         self.request.session['ga'] = 'request_drafted'
         mixpanel_event(
             self.request,
             'Request Saved',
             self._composer_mixpanel_properties(composer),
         )
         messages.success(self.request, 'Request saved')
     elif form.cleaned_data['action'] == 'submit':
         composer = form.save()
         self._submit_composer(composer, form)
     return redirect(composer)
Пример #20
0
 def form_valid(self, form):
     """Should handle a valid form differently depending on whether the user is staff."""
     organization = self.get_object()
     user = self.request.user
     max_users = form.cleaned_data['max_users']
     if user.is_staff:
         # if staff we want the changes made to the org to be saved before updating
         organization = form.save()
     organization.update_subscription(max_users)
     mixpanel_event(
         self.request,
         'Organization Updated',
         organization.mixpanel_event(),
     )
     return redirect(self.get_success_url())
Пример #21
0
 def form_valid(self, form):
     """Update the request"""
     if form.cleaned_data["action"] == "save":
         composer = form.save()
         self.request.session["ga"] = "request_drafted"
         mixpanel_event(
             self.request,
             "Request Saved",
             self._composer_mixpanel_properties(composer),
         )
         messages.success(self.request, "Request saved")
     elif form.cleaned_data["action"] == "submit":
         composer = form.save()
         self._submit_composer(composer, form)
     return redirect(composer)
Пример #22
0
def create_new_user(request, valid_form):
    """Create a user from the valid form, give them a profile, and log them in."""
    new_user = valid_form.save()
    Profile.objects.create(user=new_user,
                           acct_type='basic',
                           monthly_requests=0,
                           date_update=date.today())
    new_user = authenticate(username=valid_form.cleaned_data['username'],
                            password=valid_form.cleaned_data['password1'])
    login(request, new_user)
    mixpanel_event(
        request,
        'Sign Up',
        {'Source': 'Sign Up Page'},
        signup=True,
    )
    return new_user
Пример #23
0
 def make_charge(self, token, amount, email):
     """Make a Stripe charge and catch any errors."""
     charge = None
     error_msg = None
     try:
         charge = stripe_retry_on_error(
             stripe.Charge.create,
             amount=amount,
             currency='usd',
             source=token,
             description='Donation from %s' % email,
             metadata={'email': email,
                       'action': 'donation'},
             idempotency_key=True,
         )
     except stripe.error.CardError:
         # card declined
         logger.warn('Card was declined.')
         error_msg = 'Your card was declined'
     except (
         stripe.error.InvalidRequestError,
         # Invalid parameters were supplied to Stripe's API
         stripe.error.AuthenticationError,
         # Authentication with Stripe's API failed
         stripe.error.APIConnectionError,
         # Network communication with Stripe failed
         stripe.error.StripeError,  # Generic error
     ) as exception:
         logger.error(exception, exc_info=sys.exc_info())
         error_msg = (
             'Oops, something went wrong on our end.'
             ' Sorry about that!'
         )
     finally:
         if error_msg:
             messages.error(self.request, error_msg)
         else:
             self.request.session['donated'] = amount
             self.request.session['ga'] = 'donation'
             mixpanel_event(
                 self.request,
                 'Donate',
                 {'Amount': amount / 100},
                 charge=amount / 100,
             )
     return charge
Пример #24
0
    def buy_requests(self, form, organization=None, payer=None):
        """Buy requests"""
        if "organization" in form.cleaned_data:
            organization = payer = form.cleaned_data["organization"]
        try:
            num_requests = form.cleaned_data["num_requests"]
            price = self.get_price(num_requests)
            payer.pay(
                amount=price,
                description="Purchase {} requests".format(num_requests),
                token=form.cleaned_data["stripe_token"],
                save_card=form.cleaned_data["save_card"],
            )
            organization.add_requests(num_requests)
        except requests.exceptions.RequestException as exc:
            logger.warning("Payment error: %s", exc, exc_info=sys.exc_info())
            if exc.response.status_code // 100 == 4:
                messages.error(
                    self.request,
                    "Payment Error: {}".format("\n".join(
                        "{}: {}".format(k, v)
                        for k, v in exc.response.json().items())),
                )
            else:
                messages.error(self.request, "Payment Error")
            return

        self.request.session["ga"] = "request_purchase"
        mixpanel_event(
            self.request,
            "Requests Purchased",
            {
                "Number": num_requests,
                "Recipient": organization.name,
                "Price": price / 100,
            },
            charge=price / 100,
        )
        if organization.individual:
            msg = ("Purchase successful.  {} requests have been added to your "
                   "account.".format(num_requests))
        else:
            msg = ("Purchase successful.  {} requests have been added to "
                   "{}'s account.".format(num_requests, organization.name))
        messages.success(self.request, msg)
Пример #25
0
 def form_valid(self, form):
     """
     When form is valid, create the user and the organization.
     Then redirect to the organization activation page.
     """
     new_user = create_new_user(self.request, form)
     new_org = form.create_organization(new_user)
     mixpanel_event(
         self.request,
         'Organization Created',
         new_org.mixpanel_event(),
     )
     welcome.delay(new_user)
     messages.success(
         self.request,
         'Your account and organization were successfully created.')
     return HttpResponseRedirect(
         reverse('org-activate', kwargs={'slug': new_org.slug}))
Пример #26
0
def upgrade(request):
    """Upgrades the user from a Basic to a Professional account."""
    if not request.user.is_authenticated():
        raise AttributeError('Cannot upgrade an anonymous user.')
    is_pro_user = request.user.profile.acct_type in ['pro', 'proxy']
    is_org_owner = Organization.objects.filter(owner=request.user).exists()
    if is_pro_user:
        raise ValueError(
            'Cannot upgrade this account, it is already Professional.')
    if is_org_owner:
        raise ValueError(
            'Cannot upgrade this account, it owns an organization.')
    token = request.POST.get('stripe_token')
    if not token:
        raise ValueError(
            'Cannot upgrade this account, no Stripe token provided.')
    request.user.profile.start_pro_subscription(token)
    mixpanel_event(request, 'Pro Subscription Started')
Пример #27
0
    def miniregister(self, full_name, email, newsletter=False):
        """Create a new user from their full name and email and login"""
        password = generate_key(12)
        full_name = full_name.strip()
        username = unique_username(full_name)
        first_name, last_name = split_name(full_name)
        # create a new User
        user = User.objects.create_user(username,
                                        email,
                                        password,
                                        first_name=first_name,
                                        last_name=last_name)
        # create a new Profile
        Profile.objects.create(user=user,
                               acct_type='basic',
                               monthly_requests=settings.MONTHLY_REQUESTS.get(
                                   'basic', 0),
                               date_update=date.today())
        # send the new user a welcome email
        welcome_miniregister.delay(user)
        user = authenticate(
            username=user.username,
            password=password,
        )
        login(self.request, user)
        if newsletter:
            mailchimp_subscribe(
                self.request,
                user.email,
                source='Mini-Register: {}'.format(self.minireg_source),
                url='https://{}{}'.format(settings.MUCKROCK_URL,
                                          self.request.path),
            )

        mixpanel_event(
            self.request,
            'Sign Up',
            {
                'Source': 'Mini-Register: {}'.format(self.minireg_source),
                'Newsletter': newsletter,
            },
            signup=True,
        )
        return user
Пример #28
0
 def make_subscription(self, token, amount, email):
     """Start a subscription for recurring donations"""
     subscription = None
     quantity = amount / 100
     customer = stripe_get_customer(
         self.request.user,
         email,
         'Donation for {}'.format(email),
     )
     if self.request.user.is_authenticated:
         user = self.request.user
     else:
         user = None
     try:
         subscription = stripe_retry_on_error(
             customer.subscriptions.create,
             plan='donate',
             source=token,
             quantity=quantity,
             idempotency_key=True,
         )
     except stripe.error.CardError:
         logger.warn('Card was declined.')
         messages.error(self.request, 'Your card was declined')
     except stripe.error.StripeError as exception:
         logger.error(exception, exc_info=sys.exc_info())
         messages.error(
             self.request,
             'Oops, something went wrong on our end. Sorry about that!',
         )
     else:
         RecurringDonation.objects.create(
             user=user,
             email=email,
             amount=quantity,
             customer_id=customer.id,
             subscription_id=subscription.id,
         )
         mixpanel_event(
             self.request,
             'Recurring Donation',
             {'Amount': quantity},
         )
     return subscription
Пример #29
0
 def _pay_fee(self, request, foia):
     """A user pays the fee for a request"""
     form = RequestFeeForm(request.POST, user=self.request.user)
     if not self.request.user.is_authenticated:
         messages.error(self.request, 'Must be logged in to pay')
         return redirect(foia.get_absolute_url() + '#')
     if form.is_valid():
         try:
             form.cleaned_data['organization'].pay(
                 amount=int(form.cleaned_data['amount'] * 1.05),
                 fee_amount=5,
                 description='Pay ${:.2f} fee for request #{}'.format(
                     form.cleaned_data['amount'] / 100.0, foia.pk),
                 token=form.cleaned_data['stripe_token'],
                 save_card=form.cleaned_data['save_card'],
             )
         except requests.exceptions.RequestException as exc:
             logger.warn('Payment error: %s', exc, exc_info=sys.exc_info())
             if exc.response.status_code / 100 == 4:
                 messages.error(
                     self.request, 'Payment Error: {}'.format('\n'.join(
                         '{}: {}'.format(k, v)
                         for k, v in exc.response.json().iteritems())))
             else:
                 messages.error(self.request, 'Payment Error')
             return redirect(foia.get_absolute_url() + '#')
         else:
             messages.success(
                 self.request, 'Your payment was successful. '
                 'We will get this to the agency right away!')
             amount = form.cleaned_data['amount'] / 100.0
             foia.pay(self.request.user, amount)
             mixpanel_event(
                 request,
                 'Request Fee Paid',
                 foia.mixpanel_data({'Price': amount}),
                 charge=amount,
             )
             return redirect(foia.get_absolute_url() + '#')
     else:
         self.fee_form = form
         raise FoiaFormError
Пример #30
0
 def form_valid(self, form):
     """When the form is valid, activate the organization."""
     # should expect a token from Stripe
     token = self.request.POST.get('stripe_token')
     organization = self.get_object()
     # Do not save the form! The activate_subscription method needs to compare the
     # new number of seats to the existing number of seats. If the UpdateForm is saved,
     # it will automatically save the new number of seats to the model since it is a ModelForm.
     num_seats = form.cleaned_data['max_users']
     an_error = False
     if token:
         try:
             organization.activate_subscription(token, num_seats)
             messages.success(self.request,
                              'Your organization subscription is active.')
             logging.info('%s activated %s', self.request.user,
                          organization)
             mixpanel_event(
                 self.request,
                 'Organization Activated',
                 organization.mixpanel_event(),
             )
         except (AttributeError, ValueError) as exception:
             messages.error(self.request, exception)
             an_error = True
         except stripe.CardError as exception:
             messages.error(self.request, exception)
             an_error = True
         except (stripe.AuthenticationError, stripe.InvalidRequestError,
                 stripe.StripeError):
             messages.error(
                 self.request,
                 'Payment error. Your card has not been charged.')
             an_error = True
     else:
         messages.error(self.request, 'No payment information provided!')
         an_error = True
     if an_error:
         return self.form_invalid(form)
     else:
         return redirect(self.get_success_url())