123 lines
4.1 KiB
Python
123 lines
4.1 KiB
Python
import hashlib
|
|
from django.conf import settings
|
|
from django.contrib.sites.models import Site
|
|
from django.core.mail import send_mail
|
|
from django.shortcuts import render, redirect
|
|
from django.template import loader
|
|
from django.views.generic import View
|
|
from django.http import HttpResponseBadRequest
|
|
|
|
from .forms import KeyRegistrationForm, KeyConfirmationForm
|
|
from .models import Tier, Key
|
|
|
|
|
|
def _get_confirm_hash(key, email):
|
|
value = '{}{}{}'.format(key, email, settings.SECRET_KEY)
|
|
return hashlib.sha256(value.encode()).hexdigest()
|
|
|
|
|
|
class RegistrationView(View):
|
|
"""
|
|
present user with a form to fill out to get a key
|
|
|
|
upon submission, send an email sending user to confirmation page
|
|
"""
|
|
template_name = "simplekeys/register.html"
|
|
email_subject = 'API Key Registration'
|
|
email_message_template = 'simplekeys/confirmation_email.txt'
|
|
from_email = settings.DEFAULT_FROM_EMAIL
|
|
tier = 'default'
|
|
redirect = '/'
|
|
confirmation_url = '/confirm/'
|
|
|
|
def get(self, request):
|
|
return render(request, self.template_name,
|
|
{'form': KeyRegistrationForm()})
|
|
|
|
def post(self, request):
|
|
form = KeyRegistrationForm(request.POST)
|
|
|
|
if not form.is_valid():
|
|
return render(request, self.template_name,
|
|
{'form': form})
|
|
|
|
# go ahead w/ creation
|
|
key = form.instance
|
|
key.tier = Tier.objects.get(slug=self.tier)
|
|
# TODO: option to override this and avoid sending email?
|
|
key.status = 'u'
|
|
key.save()
|
|
|
|
# send email & redirect user
|
|
confirm_hash = _get_confirm_hash(key.key, key.email)
|
|
|
|
# if URL is relative, make absolute
|
|
if not self.confirmation_url.startswith(('http:', 'https:')):
|
|
confirmation_url = '{protocol}://{site}{confirmation_url}'.format(
|
|
protocol='https' if request.is_secure else 'http',
|
|
site=Site.objects.get_current().domain,
|
|
confirmation_url=self.confirmation_url
|
|
)
|
|
else:
|
|
confirmation_url = self.confirmation_url
|
|
|
|
confirmation_url = (
|
|
'{base}?key={key}&email={email}&confirm_hash={confirm_hash}'
|
|
).format(
|
|
base=confirmation_url,
|
|
key=key.key,
|
|
email=key.email,
|
|
confirm_hash=confirm_hash
|
|
)
|
|
message = loader.render_to_string(
|
|
self.email_message_template,
|
|
{'key': key, 'confirmation_url': confirmation_url}
|
|
)
|
|
|
|
send_mail(self.email_subject,
|
|
message,
|
|
self.from_email,
|
|
[key.email])
|
|
|
|
return redirect(self.redirect)
|
|
|
|
|
|
class ConfirmationView(View):
|
|
"""
|
|
present user with a simple form that just needs to be submitted
|
|
to activate the key (don't do activation on GET to prevent
|
|
email clients from clicking link)
|
|
"""
|
|
|
|
confirmation_template_name = "simplekeys/confirmation.html"
|
|
confirmed_template_name = "simplekeys/confirmed.html"
|
|
|
|
def get(self, request):
|
|
form = KeyConfirmationForm(request.GET)
|
|
if form.is_valid():
|
|
return render(request, self.confirmation_template_name,
|
|
{'form': form})
|
|
else:
|
|
return HttpResponseBadRequest('invalid request')
|
|
|
|
def post(self, request):
|
|
form = KeyConfirmationForm(request.POST)
|
|
if form.is_valid():
|
|
hash = _get_confirm_hash(form.cleaned_data['key'],
|
|
form.cleaned_data['email'])
|
|
if hash != form.cleaned_data['confirm_hash']:
|
|
return HttpResponseBadRequest('invalid request - bad hash')
|
|
|
|
# update the key
|
|
try:
|
|
key = Key.objects.get(key=form.cleaned_data['key'],
|
|
status__in=('u', 'a'))
|
|
except Key.DoesNotExist:
|
|
return HttpResponseBadRequest('invalid request - no key')
|
|
|
|
key.status = 'a'
|
|
key.save()
|
|
return render(request, self.confirmed_template_name, {'key': key})
|
|
else:
|
|
return HttpResponseBadRequest('invalid request - invalid form')
|