Skip to content
Snippets Groups Projects
Commit 87c0578b authored by Dan Braghis's avatar Dan Braghis Committed by Todd Dembrey
Browse files

Handle account activation

parent 90274d96
No related branches found
No related tags found
No related merge requests found
{% load wagtailadmin_tags %}{% base_url_setting as base_url %}
Dear {{ name|default:username }},
An account on Open Technology Fund has been created. Activate your account by clicking this link or copying and pasting it to your browser:
{% if base_url %}{{ base_url }}{% else %}{{ protocol }}://{{ domain }}{% endif %}{% url 'users:activate' uidb64=uid token=token %}
This link can be used once to log in and will lead you to a page where you can set your password.
After setting your password, you will be able to log in at {% if base_url %}{{ base_url }}{% else %}{{ protocol }}://{{ domain }}{% endif %} in the future using:
username: {{ username }}
password: Your chosen password
Thanks,
The OTF Team
--
Open Technology Fund
https://www.opentech.fund/
Account details for {{ username }} at Open Technology Fund
{% extends 'base.html' %}
{% block title %}Invalid activation{% endblock %}
{% block content %}
<h2>Invalid activation URL</h2>
{% endblock %}
......@@ -2,7 +2,7 @@ from django.conf.urls import url
from django.contrib.auth import views as auth_views
from django.urls import reverse_lazy
from opentech.apply.users.views import account, oauth
from opentech.apply.users.views import account, oauth, ActivationView
urlpatterns = [
url(r'^$', account, name='account'),
......@@ -53,5 +53,10 @@ urlpatterns = [
auth_views.PasswordResetCompleteView.as_view(template_name='users/password_reset/complete.html'),
name='password_reset_complete'
),
url(
r'^activate/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
ActivationView.as_view(),
name='activate'
),
url(r'^oauth$', oauth, name='oauth'),
]
from django.conf import settings
from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.template.loader import render_to_string
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode
def can_use_oauth_check(user):
......@@ -14,3 +18,24 @@ def can_use_oauth_check(user):
# Anonymous user or setting not defined
pass
return False
def send_activation_email(user):
"""
Send the activation email. The activation key is the username,
signed using TimestampSigner.
"""
token_generator = PasswordResetTokenGenerator()
context = {
'user': user,
'name': user.get_full_name(),
'username': user.get_username(),
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': token_generator.make_token(user),
}
subject = render_to_string('users/activation/email_subject.txt', context)
# Force subject to a single line to avoid header-injection issues.
subject = ''.join(subject.splitlines())
message = render_to_string('users/activation/email.txt', context)
user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
from django.contrib.auth import get_user_model, login
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.shortcuts import redirect, render
from django.template.response import TemplateResponse
from django.urls import reverse_lazy
from django.utils.encoding import force_text
from django.utils.http import urlsafe_base64_decode
from django.views.generic.base import TemplateView
from wagtail.wagtailadmin.views.account import password_management_enabled
......@@ -10,7 +15,7 @@ from .decorators import require_oauth_whitelist
@login_required(login_url=reverse_lazy('users:login'))
def account(request):
"Account page placeholder view"
"""Account page placeholder view"""
return render(request, 'users/account.html', {
'show_change_password': password_management_enabled() and request.user.has_usable_password(),
......@@ -20,8 +25,62 @@ def account(request):
@login_required(login_url=reverse_lazy('users:login'))
@require_oauth_whitelist
def oauth(request):
"""Generic, empty view for the OAuth associations."""
return TemplateResponse(request, 'users/oauth.html', {})
class ActivationView(TemplateView):
"""
Generic, empty view for the OAuth associations.
Inspired by https://github.com/ubernostrum/django-registration
"""
return TemplateResponse(request, 'users/oauth.html', {})
def get(self, request, *args, **kwargs):
user = self.activate(*args, **kwargs)
if user:
user.backend = 'django.contrib.auth.backends.ModelBackend'
login(request, user)
return redirect('users:password_change')
return render(request, 'users/activation/invalid.html')
def activate(self, *args, **kwargs):
user = self.validate_token(kwargs.get('uidb64'), kwargs.get('token'))
if user:
user.is_active = True
user.save()
return user
return False
def validate_token(self, uidb64, token):
"""
Verify that the activation key is valid and within the
permitted activation time window, returning the username if
valid or ``None`` if not.
"""
uid = force_text(urlsafe_base64_decode(uidb64))
user = self.get_user(uid)
token_generator = PasswordResetTokenGenerator()
if user is not None and token_generator.check_token(user, token):
return user
return False
def get_user(self, uid):
"""
Given the verified uid, look up and return the
corresponding user account if it exists, or ``None`` if it
doesn't.
"""
User = get_user_model()
try:
user = User.objects.get(**{
'pk': uid,
'is_active': False
})
return user
except (TypeError, ValueError, OverflowError, User.DoesNotExist):
return None
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment