Added password reset system

This commit is contained in:
Zakary Timson 2018-01-25 14:49:47 -05:00
parent 96e6b4cecb
commit 728ff00997
6 changed files with 121 additions and 5 deletions

View File

@ -48,5 +48,7 @@ urlpatterns = [
url(r'^members', charter_members.views.all, name='members'), url(r'^members', charter_members.views.all, name='members'),
url(r'^newsletter/unsubscribe', newsletters.views.unsubscribe, name='unsubscribe'), url(r'^newsletter/unsubscribe', newsletters.views.unsubscribe, name='unsubscribe'),
url(r'^newsletter/', newsletters.views.newsletters, name='newsletters'), url(r'^newsletter/', newsletters.views.newsletters, name='newsletters'),
url(r'^resetToken', main.views.reset_token, name='reset token'),
url(r'^reset/', main.views.reset, name='reset'),
url(r'^tinymce/', include('tinymce.urls')) url(r'^tinymce/', include('tinymce.urls'))
] ]

View File

@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.5 on 2018-01-25 06:51
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='ResetToken',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('token', models.CharField(max_length=8)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]

View File

@ -1 +1,7 @@
from django.db import models from django.db import models
from django.contrib.auth.models import User
class ResetToken(models.Model):
token = models.CharField(max_length=8)
user = models.ForeignKey(User)

View File

@ -39,6 +39,16 @@
$('#reset-form').collapse('show'); $('#reset-form').collapse('show');
}); });
$('#reset').click(function() {
$.ajax({
type: 'POST',
url: '{% url 'reset token' %}',
data: {email: $('#reset-email').val()}
});
$('#reset-form').collapse('hide');
$('#reset-confirm').collapse('show');
});
{% if failed %} {% if failed %}
$('#login-form input[name="username"]').css('border-color', '#ff0000').effect('shake'); $('#login-form input[name="username"]').css('border-color', '#ff0000').effect('shake');
$('#login-form input[name="password"]').css('border-color', '#ff0000').effect('shake'); $('#login-form input[name="password"]').css('border-color', '#ff0000').effect('shake');
@ -161,11 +171,12 @@
<p class="d-inline-block text-muted curs-pointer"><a id="login-mode">Login</a></p> <p class="d-inline-block text-muted curs-pointer"><a id="login-mode">Login</a></p>
</form> </form>
<form id="reset-form" class="collapse" method="post"> <div id="reset-form" class="collapse">
{% csrf_token %} <input id="reset-email" type="text" class="form-control mb-2 p-2" placeholder="Email"/>
<input type="text" class="form-control mb-2 p-2" name="email" placeholder="Email"/> <button id="reset" class="btn btn-primary col-12 mb-2 p-2">Reset</button>
<button class="btn btn-primary col-12 mb-2 p-2">Reset</button> </div>
</form>
<div id="reset-confirm" class="alert alert-success collapse">Instructions have been sent to your email.</div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

42
main/templates/reset.html Normal file
View File

@ -0,0 +1,42 @@
{% extends 'base.html' %}
{% load static %}
{% block head %}
<style>
body {
background-color: #0F4C85;
}
.login {
background-color: #F7F7F7;
border-radius: 2px;
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3)
}
.btn, .form-control {
border-radius: 0;
}
</style>
{% endblock %}
{% block body %}
<div class="col-11 col-md-8 col-lg-6 col-xl-4 mx-auto mt-5 p-5 login">
<form method="post">
{% csrf_token %}
<div class="mb-4">
<img src="{% static 'main/img/logo.png' %}" height="30px" width="auto">
<a class="navbar-brand text-dark-primary" href="{% url 'home' %}" style="vertical-align: sub">
OACPL
<div class="d-inline-block d-sm-none">
OACPL
</div>
</a>
</div>
<p>Please enter new password</p>
<input class="form-control mb-3" name="token" value="{% if token %}{{ token }}{% endif %}" type="{% if token %}hidden{% else %}text{% endif %}" placeholder="Code">
<input class="form-control mb-3" name="password1" type="password" placeholder="Password">
<input class="form-control mb-3" name="password2" type="password" placeholder="Confirm Password">
<button id="reset" class="btn btn-primary col-12 mb-2 p-2">Reset</button>
</form>
</div>
{% endblock %}

View File

@ -1,8 +1,13 @@
import random
from django.http import JsonResponse from django.http import JsonResponse
from django.contrib import auth from django.contrib import auth
from django.core import mail from django.core import mail
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.contrib.auth.models import User
from OACPL.utils import render_to_string
from .models import ResetToken
from charter_members.forms import RegisterForm from charter_members.forms import RegisterForm
from OACPL.utils import url_fix_render_to_string from OACPL.utils import url_fix_render_to_string
from charter_members.models import Attorney from charter_members.models import Attorney
@ -49,6 +54,29 @@ def login(request):
return render(request, 'login.html', {'navbar': False, 'footer': False, 'register': register_form}) return render(request, 'login.html', {'navbar': False, 'footer': False, 'register': register_form})
def reset(request):
if request.method == 'POST':
if request.POST.get('password1') == request.POST.get('password2'):
reset_req = ResetToken.objects.filter(token=request.POST.get('token')).first()
reset_req.user.set_password(request.POST.get('password1'))
reset_req.user.save()
auth.login(request, reset_req.user)
reset_req.delete()
return redirect('/')
return render(request, 'reset.html', {'navbar': False, 'footer': False, 'token': request.GET.get('token')})
def reset_token(request):
user = User.objects.filter(email=request.POST.get('email')).first()
if user:
token = ''.join([chr(random.randrange(97, 122)) for i in range(8)])
reset = ResetToken.objects.create(token=token, user=user)
reset.save()
mail.send_mail('OACPL Password Recovery', 'To reset your password navigate to https://oacpl.org/reset and enter code: ' + token, settings.EMAIL_HOST_USER, [user.email], html_message=render_to_string('email.html', {'content': 'To reset your password click <a href="/reset?token={}">here</a>.<br><br>If the link does not work, please navigate to {}/reset and enter the following code: '.format(token, settings.BASE_URL, token), 'name': user.first_name + ' ' + user.last_name, 'base_url': settings.BASE_URL}))
return JsonResponse({'success': True})
def logout(request): def logout(request):
auth.logout(request) auth.logout(request)
return redirect('/') return redirect('/')