From 3f6d6da389ad79ce7bf44a713104a2dfcb691453 Mon Sep 17 00:00:00 2001 From: Nick Sergeant Date: Tue, 10 May 2016 12:35:15 -0400 Subject: [PATCH] This is the only idea I have for stopping the spam. --- accounts/templates/activate.html | 103 ++++++++++++++++++ accounts/urls.py | 2 + accounts/views.py | 52 +++++++++ media/js/src/modules/site.js | 80 ++++++++++++++ snipts/templates/snipts/list.html | 8 +- templates/homepage.html | 2 +- templates/registration/activation_email.txt | 4 - templates/registration/registration_form.html | 3 + urls.py | 4 +- utils/views.py | 2 +- 10 files changed, 250 insertions(+), 10 deletions(-) create mode 100644 accounts/templates/activate.html diff --git a/accounts/templates/activate.html b/accounts/templates/activate.html new file mode 100644 index 0000000..d4411ca --- /dev/null +++ b/accounts/templates/activate.html @@ -0,0 +1,103 @@ +{% extends "base.html" %} + +{% block page-title %}Activate account{% endblock %} + +{% block body-class %}{{ block.super }} static signup pro pro-signup{% endblock %} + +{% block extra-scripts %} + +{% endblock %} + +{% block js %} + {{ block.super }} + {% if debug %} + Stripe.setPublishableKey('pk_test_cgknmaWRMQeJt2adEdvH3T9l'); + {% else %} + Stripe.setPublishableKey('pk_live_gUO2nCl7dhx6j0posz6gnbhA'); + {% endif %} +{% endblock %} + +{% block breadcrumb %} +
  • Activate
  • +{% endblock %} + +{% block content %} + {% if request.GET.declined %} +
    + {{ request.GET.declined }} You have not been charged. Please try again. +
    + {% endif %} +
    +
    +
    + Activate for a one-time fee of $9. +
    +
    +
    Please wait…
    +
    +
    + +
    + + Visa + MasterCard + Discover + American Express +
    +
    +
    + +
    + + +
    +
    +
    + +
    + +
    +
    +
    +
    + {% csrf_token %} + +
    + Secure by default. Every Snipt page is secure. +
    +
    + Your credit card is stored securely with Stripe and we use Stripe.js for maximum security. +
    +
    +
    + Prefer to pay with PayPal? Email support@snipt.net. +
    +
    +
    +{% endblock %} diff --git a/accounts/urls.py b/accounts/urls.py index 1fcae22..9b42775 100644 --- a/accounts/urls.py +++ b/accounts/urls.py @@ -3,5 +3,7 @@ from django.conf.urls import * urlpatterns = \ patterns('', + url(r'^activate/$', views.activate, + name='account-activate'), url(r'^stats/$', views.stats, name='account-stats'), url(r'^', views.account, name='account-detail')) diff --git a/accounts/views.py b/accounts/views.py index ef5fc85..a48b37c 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -1,5 +1,12 @@ +import datetime +import os +import stripe + from annoying.decorators import render_to +from django.conf import settings from django.contrib.auth.decorators import login_required +from django.core.mail import send_mail +from django.http import HttpResponseRedirect from snipts.models import Snipt @@ -9,6 +16,51 @@ def account(request): return {} +@login_required +@render_to('activate.html') +def activate(request): + + if request.method == 'POST': + + token = request.POST['token'] + stripe.api_key = os.environ.get('STRIPE_SECRET_KEY', + settings.STRIPE_SECRET_KEY) + + try: + customer = stripe.Customer.create(card=token, + email=request.user.email) + stripe.Charge.create(amount=900, + currency='usd', + customer=customer.id, + description='Snipt.net') + except stripe.CardError as e: + error_message = e.json_body['error']['message'] + return HttpResponseRedirect('/account/activate/?declined=%s' % error_message or + 'Your card was declined.') + + profile = request.user.profile + profile.pro_date = datetime.datetime.now() + profile.stripe_id = customer.id + profile.save() + + request.user.is_active = True + request.user.save() + + send_mail('[Snipt] New signup: {}'.format(request.user.username), + """ + User: https://snipt.net/{} + Email: {} + """.format(request.user.username, request.user.email), + 'support@snipt.net', + ['nick@snipt.net'], + fail_silently=False) + + return HttpResponseRedirect('/login-redirect/') + + else: + return {} + + @login_required @render_to('stats.html') def stats(request): diff --git a/media/js/src/modules/site.js b/media/js/src/modules/site.js index 075cec3..9f30229 100644 --- a/media/js/src/modules/site.js +++ b/media/js/src/modules/site.js @@ -96,6 +96,62 @@ window.ui_halted = false; }); + if (this.$body.hasClass('pro-signup')) { + var $form = $('form#pro-signup'); + var $submit = $('button[type="submit"]', $form); + + var $cardNumber = $('input#number'); + var $expMonth = $('select#exp-month'); + var $expYear = $('select#exp-year'); + var $cvc = $('input#cvc'); + + $form.submit(function() { + + $submit.attr('disabled', 'disabled'); + + var errors = false; + + if (!Stripe.validateCardNumber($cardNumber.val())) { + $cardNumber.parents('div.control-group').addClass('error'); + errors = true; + } else { + $cardNumber.parents('div.control-group').removeClass('error'); + } + + if (!Stripe.validateExpiry($expMonth.val(), $expYear.val())) { + $expMonth.parents('div.control-group').addClass('error'); + errors = true; + } else { + $expMonth.parents('div.control-group').removeClass('error'); + } + + if (!Stripe.validateCVC($cvc.val())) { + $cvc.parents('div.control-group').addClass('error'); + errors = true; + } else { + $cvc.parents('div.control-group').removeClass('error'); + } + + if (!errors) { + + $('.payment-errors').hide(); + $('.payment-loading').show(); + + Stripe.createToken({ + number: $cardNumber.val(), + cvc: $cvc.val(), + exp_month: $expMonth.val(), + exp_year: $expYear.val() + }, that.stripeResponseHandler); + + } else { + $submit.removeAttr('disabled'); + } + + return false; + }); + } + if (this.$body.hasClass('login')) { $('input#id_username').focus(); } @@ -192,6 +248,30 @@ $('div.infield label', this.$body).inFieldLabels({ fadeDuration: 200 }); + }, + stripeResponseHandler: function(status, response) { + + var $form = $('form#pro-signup'); + + if (response.error) { + $('button[type="submit"]', $form).removeAttr('disabled'); + $('.payment-loading').hide(); + $('.payment-errors').text(response.error.message).show(); + } else { + var token = response.id; + + // Kill all of the form details so none of it touches our server. + // Note, this is unnecessary, because the inputs themselves do not + // have a name attr, meaning they'll never get sent to begin with. + $('input#name').val(''); + $('input#number').val(''); + $('select#exp-month').val(''); + $('select#exp-year').val(''); + $('input#cvc').val(''); + + $form.append(""); + $form.get(0).submit(); + } } }); diff --git a/snipts/templates/snipts/list.html b/snipts/templates/snipts/list.html index 20f47b0..2c7f044 100644 --- a/snipts/templates/snipts/list.html +++ b/snipts/templates/snipts/list.html @@ -27,9 +27,13 @@ {% empty %}
    {% if request.user == user and not request.user.is_active %} - Welcome! Please click the activation link in your email in order to create your first snipt. + Welcome! Please activate your account to create your first snipt. {% else %} - No snipts to show here. Sorry! + {% if request.user == user %} + Welcome! Create your first snipt by clicking "Add Snipt" above. + {% else %} + No snipts to show here. Sorry! + {% endif %} {% endif %}
    {% endfor %} diff --git a/templates/homepage.html b/templates/homepage.html index 60a8ae5..0ae955b 100644 --- a/templates/homepage.html +++ b/templates/homepage.html @@ -97,7 +97,7 @@

    Personal accounts

    - Individuals can post public and private snippets for free, making them perfect + Individuals can post public and private snippets, making them perfect for storing and organizing code you never want to forget.

    diff --git a/templates/registration/activation_email.txt b/templates/registration/activation_email.txt index baed765..40f90b4 100644 --- a/templates/registration/activation_email.txt +++ b/templates/registration/activation_email.txt @@ -2,10 +2,6 @@ Hey there, Welcome to Snipt. If you ever have any thoughts or issues with the site whatsoever, please feel free to contact me directly. -To complete your registration, please activate your account here: - -https://{{site.domain}}{% url 'registration_activate' activation_key %} - Thanks! Nick Sergeant diff --git a/templates/registration/registration_form.html b/templates/registration/registration_form.html index e9d863d..1763917 100644 --- a/templates/registration/registration_form.html +++ b/templates/registration/registration_form.html @@ -21,6 +21,9 @@ {% endif %} {% endif %}
    +
    + Create an account for a one-time fee of $9. +
    diff --git a/urls.py b/urls.py index 5b16f6e..cb7ddaf 100644 --- a/urls.py +++ b/urls.py @@ -11,8 +11,8 @@ from snipts.api import (PublicSniptResource, from snipts.views import search from tastypie.api import Api from utils.views import SniptRegistrationView -from views import (homepage, lexers, login_redirect, sitemap, tags, - user_api_key) +from views import (homepage, lexers, login_redirect, sitemap, + tags, user_api_key) public_api = Api(api_name='public') public_api.register(PublicSniptResource()) diff --git a/utils/views.py b/utils/views.py index c95cad6..547a971 100644 --- a/utils/views.py +++ b/utils/views.py @@ -12,4 +12,4 @@ class SniptRegistrationView(RegistrationView): return super(RegistrationView, self).dispatch(request, *args, **kwargs) def get_success_url(self, request, user): - return '/{}/'.format(user.username) + return '/account/activate/'