Added password reset system
This commit is contained in:
parent
96e6b4cecb
commit
728ff00997
@ -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'))
|
||||
]
|
||||
|
27
main/migrations/0001_initial.py
Normal file
27
main/migrations/0001_initial.py
Normal 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)),
|
||||
],
|
||||
),
|
||||
]
|
@ -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)
|
||||
|
@ -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
42
main/templates/reset.html
Normal 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 %}
|
@ -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('/')
|
||||
|
Loading…
Reference in New Issue
Block a user