From 1ea6cb0c0b1a8705c943a59fe28e541e15ef6e3d Mon Sep 17 00:00:00 2001 From: Zambom Date: Mon, 26 Dec 2016 17:15:52 -0200 Subject: [PATCH] Adding password recovering --- amadeus/settings.py | 2 +- amadeus/templates/recover_pass_email_template.html | 27 +++++++++++++++++++++++++++ users/forms.py | 29 ++++++++++++++++++++++++++++- users/templates/users/forgot_password.html | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ users/templates/users/login.html | 2 +- users/urls.py | 2 ++ users/views.py | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 7 files changed, 203 insertions(+), 8 deletions(-) create mode 100644 amadeus/templates/recover_pass_email_template.html create mode 100644 users/templates/users/forgot_password.html diff --git a/amadeus/settings.py b/amadeus/settings.py index 1375de7..bea5236 100644 --- a/amadeus/settings.py +++ b/amadeus/settings.py @@ -180,7 +180,7 @@ LOGS_URL = 'logs/' # E-mail EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' -DEFAULT_FROM_EMAIL = 'admin@admin.com' +DEFAULT_FROM_EMAIL = 'admin@amadeus.com.br' # Messages from django.contrib.messages import constants as messages_constants diff --git a/amadeus/templates/recover_pass_email_template.html b/amadeus/templates/recover_pass_email_template.html new file mode 100644 index 0000000..9b99948 --- /dev/null +++ b/amadeus/templates/recover_pass_email_template.html @@ -0,0 +1,27 @@ +{% extends 'base.html' %} + +{% load i18n %} + +{% block nav %} +{% endblock %} + +{% block breadcrumbs %} +{% endblock %} + +{% block sidebar %} +{% endblock sidebar %} + +{% autoescape off %} + +{% blocktrans %}You're receiving this email because you requested a password reset for your user account at {{ site_name }}.{% endblocktrans %} + +{% trans "Please go to the following page and choose a new password:" %} + +{% block reset_link %} + {{ domain }}{% url 'users:reset_password_confirm' uidb64=uid token=token %} + +{% endblock %} + +{% blocktrans %}The {{ site_name }} team{% endblocktrans %} + +{% endautoescape %} \ No newline at end of file diff --git a/users/forms.py b/users/forms.py index 8aa0c87..23b8658 100644 --- a/users/forms.py +++ b/users/forms.py @@ -3,12 +3,25 @@ from django import forms from django.utils.translation import ugettext_lazy as _ from rolepermissions.shortcuts import assign_role from django.contrib.auth import update_session_auth_hash +from django.core.validators import validate_email +from django.core.exceptions import ValidationError from .models import User class Validation(forms.ModelForm): MIN_PASS_LENGTH = 8 MAX_UPLOAD_SIZE = 2*1024*1024 + def clean_email(self): + email = self.cleaned_data.get('email', '') + + try: + validate_email( email ) + return email + except ValidationError: + self._errors['email'] = [_('You must insert an email address')] + + return ValueError + def clean_image(self): image = self.cleaned_data.get('image', False) @@ -170,4 +183,18 @@ class ChangePassForm(Validation): } widgets = { 'password': forms.PasswordInput - } \ No newline at end of file + } + +class PassResetRequest(forms.Form): + email = forms.CharField(label = _('Email'), max_length = 254) + + def clean_email(self): + email = self.cleaned_data.get('email', '') + + try: + validate_email( email ) + return email + except ValidationError: + self._errors['email'] = [_('You must insert an email address')] + + return ValueError \ No newline at end of file diff --git a/users/templates/users/forgot_password.html b/users/templates/users/forgot_password.html new file mode 100644 index 0000000..6b1a9f6 --- /dev/null +++ b/users/templates/users/forgot_password.html @@ -0,0 +1,84 @@ +{% extends 'base.html' %} + +{% load static i18n %} +{% load widget_tweaks %} + +{% block nav %} +{% endblock %} + +{% block breadcrumbs %} +{% endblock %} + +{% block sidebar %} +{% endblock sidebar %} + +{% block content %} +
+
+
+ +
+
+
+
+
+ {% if messages %} + {% for message in messages %} + + {% endfor %} + {% endif %} +
+
+
+
+

{% trans 'Forgot Password' %}

+

{% trans 'Enter your email below (the one used to access the platform) to recover your password' %}

+
+
+ +
+ {% csrf_token %} + {% for field in form %} +
+
+ {% if field.field.required %} + + {% else %} + + {% endif %} + {% render_field field class='form-control' %} + {{ field.help_text }} + {% if field.errors %} + + {% endif %} +
+
+ {% endfor %} +
+
+
+ +
+ +
+
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/users/templates/users/login.html b/users/templates/users/login.html index 178d7f3..b794965 100644 --- a/users/templates/users/login.html +++ b/users/templates/users/login.html @@ -65,7 +65,7 @@
diff --git a/users/urls.py b/users/urls.py index 01b8252..41f05f6 100644 --- a/users/urls.py +++ b/users/urls.py @@ -7,6 +7,8 @@ urlpatterns = [ url(r'^login/$', views.login, name='login'), url(r'^logout/$', auth_views.logout, {'next_page': 'users:login'}, name='logout'), url(r'^signup/$', views.RegisterUser.as_view(), name = 'signup'), + url(r'^forgot_password/$', views.ForgotPassword.as_view(), name = 'forgot_pass'), + url(r'^reset_password_confirm/(?P[0-9A-Za-z]+)-(?P.+)/$', views.ForgotPassword.as_view(), name = 'reset_password_confirm'), url(r'^$', views.UsersListView.as_view(), name = 'manage'), url(r'^create/$', views.CreateView.as_view(), name = 'create'), url(r'^edit/(?P[\w.%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4})/$', views.UpdateView.as_view(), name='update'), diff --git a/users/views.py b/users/views.py index aea0707..e05f3d7 100644 --- a/users/views.py +++ b/users/views.py @@ -1,6 +1,4 @@ -from django.http import Http404 from django.shortcuts import get_object_or_404,redirect, render -from django.db.models import Q from django.views import generic from django.contrib import messages from rolepermissions.mixins import HasRoleMixin @@ -10,11 +8,17 @@ from django.core.urlresolvers import reverse, reverse_lazy from django.utils.translation import ugettext_lazy as _ from rolepermissions.shortcuts import assign_role from rolepermissions.verifications import has_role -from itertools import chain -from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from .models import User -from .forms import RegisterUserForm, ProfileForm, UserForm, ChangePassForm +from .forms import RegisterUserForm, ProfileForm, UserForm, ChangePassForm, PassResetRequest + +#RECOVER PASS IMPORTS +from django.contrib.auth.tokens import default_token_generator +from django.core.mail import send_mail +from django.conf import settings +from django.utils.encoding import force_bytes +from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode +from django.template import loader #API IMPORTS from rest_framework import viewsets @@ -342,6 +346,57 @@ class RegisterUser(generic.edit.CreateView): return super(RegisterUser, self).form_valid(form) +class ForgotPassword(generic.FormView): + template_name = "users/forgot_password.html" + success_url = reverse_lazy('users:login') + form_class = PassResetRequest + + def get_context_data(self, **kwargs): + context = super(ForgotPassword, self).get_context_data(**kwargs) + context['title'] = _('Forgot Password') + + return context + + def post(self, request, *args, **kwargs): + form = self.get_form() + + if form.is_valid(): + email = form.cleaned_data['email'] + + users = User.objects.filter(email = email) + + if users.exists(): + for user in users: + c = { + 'email': user.email, + 'domain': 'amadeus.com.br', #or your domain + 'site_name': 'Amadeus', + 'uid': urlsafe_base64_encode(force_bytes(user.pk)), + 'user': user, + 'token': default_token_generator.make_token(user), + 'protocol': 'http', + } + + subject_template_name='registration/password_reset_subject.txt' + email_template_name = 'recover_pass_email_template.html' + + subject = loader.render_to_string(subject_template_name, c) + # Email subject *must not* contain newlines + subject = ''.join(subject.splitlines()) + email = loader.render_to_string(email_template_name, c) + + send_mail(subject, email, settings.DEFAULT_FROM_EMAIL , [user.email], fail_silently=False) + + result = self.form_valid(form) + messages.success(request, _("An email has been sent to the informed address. Please check its inbox to continue reseting password.")) + + return result + + result = self.form_invalid(form) + messages.error(request, _('No user is associated with this email address')) + + return result + def login(request): context = {} context['title'] = _('Log In') -- libgit2 0.21.2