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'^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'))
|
||||||
]
|
]
|
||||||
|
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.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-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
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.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('/')
|
||||||
|
Loading…
Reference in New Issue
Block a user