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'^newsletter/unsubscribe', newsletters.views.unsubscribe, name='unsubscribe'),
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'))
]

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.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').click(function() {
$.ajax({
type: 'POST',
url: '{% url 'reset token' %}',
data: {email: $('#reset-email').val()}
});
$('#reset-form').collapse('hide');
$('#reset-confirm').collapse('show');
});
{% if failed %}
$('#login-form input[name="username"]').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>
</form>
<form id="reset-form" class="collapse" method="post">
{% csrf_token %}
<input type="text" class="form-control mb-2 p-2" name="email" placeholder="Email"/>
<button class="btn btn-primary col-12 mb-2 p-2">Reset</button>
</form>
<div id="reset-form" class="collapse">
<input id="reset-email" type="text" class="form-control mb-2 p-2" placeholder="Email"/>
<button id="reset" class="btn btn-primary col-12 mb-2 p-2">Reset</button>
</div>
<div id="reset-confirm" class="alert alert-success collapse">Instructions have been sent to your email.</div>
</div>
</div>
{% 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.contrib import auth
from django.core import mail
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 OACPL.utils import url_fix_render_to_string
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})
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):
auth.logout(request)
return redirect('/')