Commit 8c074c34cfba0614c2c81632acd2ea9c7f5dd7b1
1 parent
df035675
Exists in
master
and in
3 other branches
Adding change password
Showing
9 changed files
with
139 additions
and
141 deletions
Show diff stats
amadeus/templates/base.html
| ... | ... | @@ -118,7 +118,7 @@ |
| 118 | 118 | <ul class="dropdown-menu pull-right"> |
| 119 | 119 | <li><a href="{% url 'users:profile' %}">{% trans 'Profile' %}</a></li> |
| 120 | 120 | <li><a href="{% url 'users:edit_profile' %}">{% trans 'Edit Profile' %}</a></li> |
| 121 | - <li><a href="#">{% trans 'Change Password' %}</a></li> | |
| 121 | + <li><a href="{% url 'users:change_pass' %}">{% trans 'Change Password' %}</a></li> | |
| 122 | 122 | <li><a href="#">{% trans 'Delete Account' %}</a></li> |
| 123 | 123 | </ul> |
| 124 | 124 | </li> | ... | ... |
users/forms.py
| ... | ... | @@ -2,6 +2,7 @@ |
| 2 | 2 | from django import forms |
| 3 | 3 | from django.utils.translation import ugettext_lazy as _ |
| 4 | 4 | from rolepermissions.shortcuts import assign_role |
| 5 | +from django.contrib.auth import update_session_auth_hash | |
| 5 | 6 | from .models import User |
| 6 | 7 | |
| 7 | 8 | class Validation(forms.ModelForm): |
| ... | ... | @@ -14,49 +15,57 @@ class Validation(forms.ModelForm): |
| 14 | 15 | if image: |
| 15 | 16 | if hasattr(image, '_size'): |
| 16 | 17 | if image._size > self.MAX_UPLOAD_SIZE: |
| 17 | - raise forms.ValidationError(_("The image is too large. It should have less than 2MB.")) | |
| 18 | + self._errors['image'] = [_("The image is too large. It should have less than 2MB.")] | |
| 18 | 19 | |
| 19 | - return image | |
| 20 | + return ValueError | |
| 20 | 21 | |
| 21 | - def clean_password(self): | |
| 22 | - password = self.cleaned_data.get('password') | |
| 22 | + return image | |
| 23 | 23 | |
| 24 | + def clean_new_password(self): | |
| 25 | + password = self.cleaned_data.get('new_password') | |
| 26 | + print(self.cleaned_data) | |
| 24 | 27 | if self.is_edit and len(password) == 0: |
| 25 | 28 | return password |
| 26 | 29 | |
| 27 | 30 | # At least MIN_LENGTH long |
| 28 | 31 | if len(password) < self.MIN_PASS_LENGTH: |
| 29 | - raise forms.ValidationError(_("The password must contain at least % d characters." % self.MIN_PASS_LENGTH)) | |
| 32 | + self._errors['new_password'] = [_("The new password must contain at least % d characters." % self.MIN_PASS_LENGTH)] | |
| 33 | + | |
| 34 | + return ValueError | |
| 30 | 35 | |
| 31 | 36 | # At least one letter and one non-letter |
| 32 | 37 | first_isalpha = password[0].isalpha() |
| 33 | 38 | if all(c.isalpha() == first_isalpha for c in password): |
| 34 | - raise forms.ValidationError(_('The password must contain at least one letter and at least one digit or a punctuation character.')) | |
| 39 | + self._errors['new_password'] = [_('The password must contain at least one letter and at least one digit or a punctuation character.')] | |
| 40 | + | |
| 41 | + return ValueError | |
| 35 | 42 | |
| 36 | 43 | return password |
| 37 | 44 | |
| 38 | 45 | def clean_password2(self): |
| 39 | - password = self.cleaned_data.get("password") | |
| 46 | + password = self.cleaned_data.get("new_password") | |
| 40 | 47 | password2 = self.cleaned_data.get("password2") |
| 41 | 48 | |
| 42 | 49 | if self.is_edit and len(password) == 0: |
| 43 | 50 | return password2 |
| 44 | 51 | |
| 45 | 52 | if password and password2 and password != password2: |
| 46 | - raise forms.ValidationError(_('The confirmation password is incorrect.')) | |
| 53 | + self._errors['password2'] = [_('The confirmation password is incorrect.')] | |
| 54 | + | |
| 55 | + return ValueError | |
| 47 | 56 | |
| 48 | 57 | return password2 |
| 49 | 58 | |
| 50 | 59 | class RegisterUserForm(Validation): |
| 51 | - password = forms.CharField(label=_('Password'), widget = forms.PasswordInput) | |
| 52 | - password2 = forms.CharField(label = _('Confirm Password'), widget = forms.PasswordInput) | |
| 60 | + new_password = forms.CharField(label=_('Password'), widget = forms.PasswordInput(render_value=True)) | |
| 61 | + password2 = forms.CharField(label = _('Confirm Password'), widget = forms.PasswordInput(render_value=True)) | |
| 53 | 62 | |
| 54 | 63 | is_edit = False |
| 55 | 64 | |
| 56 | 65 | def save(self, commit=True): |
| 57 | 66 | super(RegisterUserForm, self).save(commit=False) |
| 58 | 67 | |
| 59 | - self.instance.set_password(self.cleaned_data['password']) | |
| 68 | + self.instance.set_password(self.cleaned_data['new_password']) | |
| 60 | 69 | |
| 61 | 70 | self.instance.save() |
| 62 | 71 | |
| ... | ... | @@ -94,19 +103,19 @@ class UserForm(Validation): |
| 94 | 103 | self.is_edit = is_update |
| 95 | 104 | |
| 96 | 105 | if self.is_edit: |
| 97 | - del self.fields['password'] | |
| 106 | + del self.fields['new_password'] | |
| 98 | 107 | del self.fields['password2'] |
| 99 | 108 | |
| 100 | 109 | if not is_edit: |
| 101 | - password = forms.CharField(label=_('Password'), widget = forms.PasswordInput, required = False) | |
| 102 | - password2 = forms.CharField(label = _('Confirm Password'), widget = forms.PasswordInput, required = False) | |
| 110 | + new_password = forms.CharField(label=_('Password'), widget = forms.PasswordInput(render_value=True), required = False) | |
| 111 | + password2 = forms.CharField(label = _('Confirm Password'), widget = forms.PasswordInput(render_value=True), required = False) | |
| 103 | 112 | |
| 104 | 113 | |
| 105 | 114 | def save(self, commit=True): |
| 106 | 115 | super(UserForm, self).save(commit=False) |
| 107 | 116 | |
| 108 | 117 | if not self.is_edit: |
| 109 | - self.instance.set_password(self.cleaned_data['password']) | |
| 118 | + self.instance.set_password(self.cleaned_data['new_password']) | |
| 110 | 119 | |
| 111 | 120 | self.instance.save() |
| 112 | 121 | |
| ... | ... | @@ -117,4 +126,46 @@ class UserForm(Validation): |
| 117 | 126 | fields = ['email', 'username', 'last_name', 'social_name', 'description', 'show_email', 'image', 'is_staff', 'is_active'] |
| 118 | 127 | widgets = { |
| 119 | 128 | 'description': forms.Textarea, |
| 120 | - } | |
| 121 | 129 | \ No newline at end of file |
| 130 | + } | |
| 131 | + | |
| 132 | +class ChangePassForm(Validation): | |
| 133 | + def __init__(self, *args, **kwargs): | |
| 134 | + self.user = kwargs.pop('user', None) | |
| 135 | + self.request = kwargs.pop('request', None) | |
| 136 | + super(ChangePassForm, self).__init__(*args, **kwargs) | |
| 137 | + | |
| 138 | + is_edit = False | |
| 139 | + | |
| 140 | + new_password = forms.CharField(label=_('New Password'), widget = forms.PasswordInput(render_value=True), required = True) | |
| 141 | + password2 = forms.CharField(label = _('Confirm Password'), widget = forms.PasswordInput(render_value=True), required = True) | |
| 142 | + | |
| 143 | + def clean_password(self): | |
| 144 | + password = self.cleaned_data.get('password', None) | |
| 145 | + | |
| 146 | + if not self.user.check_password(password): | |
| 147 | + self._errors['password'] = [_('The value inputed does not match with your actual password.')] | |
| 148 | + | |
| 149 | + return ValueError | |
| 150 | + | |
| 151 | + return password | |
| 152 | + | |
| 153 | + def save(self, commit=True): | |
| 154 | + super(ChangePassForm, self).save(commit=False) | |
| 155 | + | |
| 156 | + self.instance.set_password(self.cleaned_data['new_password']) | |
| 157 | + | |
| 158 | + update_session_auth_hash(self.request, self.instance) | |
| 159 | + | |
| 160 | + self.instance.save() | |
| 161 | + | |
| 162 | + return self.instance | |
| 163 | + | |
| 164 | + class Meta: | |
| 165 | + model = User | |
| 166 | + fields = ['password'] | |
| 167 | + labels = { | |
| 168 | + 'password': _('Actual Password') | |
| 169 | + } | |
| 170 | + widgets = { | |
| 171 | + 'password': forms.PasswordInput | |
| 172 | + } | |
| 122 | 173 | \ No newline at end of file | ... | ... |
users/templates/users/_form.html
| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | <div class="form-group{% if form.has_error %} has-error {% endif %} is-fileinput"> |
| 8 | 8 | {% if field.auto_id == 'id_image' %} |
| 9 | 9 | {% if field.field.required %} |
| 10 | - <label for="{{ field.auto_id }}">{{ field.label }}<span>*</span></label> | |
| 10 | + <label for="{{ field.auto_id }}">{{ field.label }} <span>*</span></label> | |
| 11 | 11 | {% else %} |
| 12 | 12 | <label for="{{ field.auto_id }}">{{ field.label }}</label> |
| 13 | 13 | {% endif %} |
| ... | ... | @@ -22,7 +22,7 @@ |
| 22 | 22 | </div> |
| 23 | 23 | {% elif field.auto_id == 'id_description' %} |
| 24 | 24 | {% if field.field.required %} |
| 25 | - <label for="{{ field.auto_id }}">{{ field.label }}<span>*</span></label> | |
| 25 | + <label for="{{ field.auto_id }}">{{ field.label }} <span>*</span></label> | |
| 26 | 26 | {% else %} |
| 27 | 27 | <label for="{{ field.auto_id }}">{{ field.label }}</label> |
| 28 | 28 | {% endif %} |
| ... | ... | @@ -35,7 +35,7 @@ |
| 35 | 35 | </div> |
| 36 | 36 | {% else %} |
| 37 | 37 | {% if field.field.required %} |
| 38 | - <label for="{{ field.auto_id }}">{{ field.label }}<span>*</span></label> | |
| 38 | + <label for="{{ field.auto_id }}">{{ field.label }} <span>*</span></label> | |
| 39 | 39 | {% else %} |
| 40 | 40 | <label for="{{ field.auto_id }}">{{ field.label }}</label> |
| 41 | 41 | {% endif %} |
| ... | ... | @@ -56,7 +56,12 @@ |
| 56 | 56 | {% endif %} |
| 57 | 57 | </div> |
| 58 | 58 | {% endfor %} |
| 59 | - <div class="col-md-12 col-lg-12 col-sm-12 col-xs-12 text-center"> | |
| 60 | - <input type="submit" value="{% trans 'Save' %}" class="btn btn-raised btn-primary" /> | |
| 59 | + <div class="col-md-12 col-lg-12 col-sm-12 col-xs-12"> | |
| 60 | + <div class="pull-left"> | |
| 61 | + <input type="submit" value="{% trans 'Save' %}" class="btn btn-raised btn-primary" /> | |
| 62 | + </div> | |
| 63 | + <div class="pull-right"> | |
| 64 | + <a href="{% url back_url %}" class="btn btn-raised btn-default">{% trans 'Cancel' %}</a> | |
| 65 | + </div> | |
| 61 | 66 | </div> |
| 62 | 67 | </form> |
| 63 | 68 | \ No newline at end of file | ... | ... |
users/templates/users/change_password.html
| ... | ... | @@ -5,53 +5,16 @@ |
| 5 | 5 | {% load django_bootstrap_breadcrumbs %} |
| 6 | 6 | |
| 7 | 7 | {% block breadcrumbs %} |
| 8 | - | |
| 9 | - {{ block.super }} | |
| 10 | - {% breadcrumb 'Edit' 'users:update_profile' %} | |
| 11 | - | |
| 8 | + {{ block.super }} | |
| 9 | + {% breadcrumb 'Change Password' 'users:change_pass' %} | |
| 12 | 10 | {% endblock %} |
| 13 | 11 | |
| 14 | 12 | {% block content %} |
| 15 | - {% if messages %} | |
| 16 | - {% for message in messages %} | |
| 17 | - <div class="alert alert-success alert-dismissible" role="alert"> | |
| 18 | - <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
| 19 | - <span aria-hidden="true">×</span> | |
| 20 | - </button> | |
| 21 | - <p>{{ message }}</p> | |
| 22 | - </div> | |
| 23 | - {% endfor %} | |
| 24 | - {% endif %} | |
| 25 | - <div class="row"> | |
| 26 | - <div class="col-md-12"> | |
| 27 | - <div class="well well-lg"> | |
| 28 | - <form method="post" action="" enctype="multipart/form-data"> | |
| 29 | - {% csrf_token %} | |
| 30 | - <div class="form-group"> | |
| 31 | - <label class="control-label" for="focusedInput1">{% trans 'Current Password' %}</label> | |
| 32 | - <input type="password" class="form-control" id="inputPassword" placeholder="{% trans 'Password' %}"> | |
| 33 | - </div> | |
| 34 | - <div class="form-group"> | |
| 35 | - <label class="control-label" for="focusedInput1">{% trans 'New Password' %}</label> | |
| 36 | - <input type="password" class="form-control" id="inputPassword" placeholder="{% trans 'Password' %}"> | |
| 37 | - </div> | |
| 38 | - <div class="form-group"> | |
| 39 | - <label class="control-label" for="focusedInput1">{% trans 'Confirmation' %}</label> | |
| 40 | - <input type="password" class="form-control" id="inputPassword" placeholder="{% trans 'Password' %}"> | |
| 41 | - </div> | |
| 42 | - <div class="row"> | |
| 43 | - <div class="col-md-3 col-sm-2 col-xs-2"> | |
| 44 | - <input type="submit" value="{% trans 'Save' %}" class="btn btn-raised btn-block btn-success" /> | |
| 13 | + <div class="card"> | |
| 14 | + <div class="card-content"> | |
| 15 | + <div class="card-body"> | |
| 16 | + {% include "users/_form.html" with back_url="users:profile" %} | |
| 45 | 17 | </div> |
| 46 | - <div class="col-md-3 col-sm-2 col-xs-2"> | |
| 47 | - <a href="{% url 'users:profile' %}" class="btn btn-raised btn-block btn-default" >{% trans 'Cancel' %}</a> | |
| 48 | - </div> | |
| 49 | - </div> | |
| 50 | - </form> | |
| 51 | - </div> | |
| 52 | - </div> | |
| 18 | + </div> | |
| 53 | 19 | </div> |
| 54 | - | |
| 55 | - | |
| 56 | - <br clear="all" /> | |
| 57 | 20 | {% endblock %} | ... | ... |
users/templates/users/create.html
users/templates/users/edit_profile.html
| ... | ... | @@ -12,62 +12,13 @@ |
| 12 | 12 | |
| 13 | 13 | |
| 14 | 14 | {% block content %} |
| 15 | - {% if messages %} | |
| 16 | - {% for message in messages %} | |
| 17 | - <div class="alert alert-success alert-dismissible" role="alert"> | |
| 18 | - <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
| 19 | - <span aria-hidden="true">×</span> | |
| 20 | - </button> | |
| 21 | - <p>{{ message }}</p> | |
| 22 | - </div> | |
| 23 | - {% endfor %} | |
| 24 | - {% endif %} | |
| 25 | - <div class="card mg-b-5m"> | |
| 26 | - <div class="card-content"> | |
| 27 | - <div class="card-body"> | |
| 28 | - <form method="post" action="" enctype="multipart/form-data"> | |
| 29 | - {% csrf_token %} | |
| 30 | - {% for field in form %} | |
| 31 | - <div class="form-group{% if form.has_error %} has-error {% endif %} is-fileinput"> | |
| 32 | - <label for="{{ field.auto_id }}">{{ field.label }}</label> | |
| 33 | - {% if field.auto_id == 'id_image' %} | |
| 34 | - {% render_field field class='form-control input-sm' %} | |
| 35 | - <div class="input-group"> | |
| 36 | - <input type="text" readonly="" class="form-control" placeholder="{% trans 'Choose your file...' %}"> | |
| 37 | - <span class="input-group-btn input-group-sm"> | |
| 38 | - <button type="button" class="btn btn-fab btn-fab-mini"> | |
| 39 | - <i class="material-icons">attach_file</i> | |
| 40 | - </button> | |
| 41 | - </span> | |
| 42 | - </div> | |
| 43 | - {% elif field.auto_id == 'id_description' %} | |
| 44 | - {% render_field field class='form-control text_wysiwyg' %} | |
| 45 | - {% else %} | |
| 46 | - {% render_field field class='form-control' %} | |
| 47 | - <span id="helpBlock" class="help-block">{{ field.help_text }}</span> | |
| 48 | - {% endif %} | |
| 49 | - {% if field.errors %} | |
| 50 | - <div class="alert alert-danger alert-dismissible" role="alert"> | |
| 51 | - <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
| 52 | - <span aria-hidden="true">×</span> | |
| 53 | - </button> | |
| 54 | - <ul> | |
| 55 | - {% for error in field.errors %} | |
| 56 | - <li>{{ error }}</li> | |
| 57 | - {% endfor %} | |
| 58 | - </ul> | |
| 59 | - </div> | |
| 60 | - {% endif %} | |
| 61 | - </div> | |
| 62 | - {% endfor %} | |
| 63 | - <div class="col-md-offset-2 col-md-2 col-sm-2 col-xs-2"> | |
| 64 | - <input type="submit" value="{% trans 'Save' %}" class="btn btn-raised btn-success" /> | |
| 65 | - </div> | |
| 66 | - <div class="col-md-offset-3 col-md-2 col-sm-2 col-xs-2"> | |
| 67 | - <a href="{% url 'users:profile' %}" class="btn btn-raised btn-default" >{% trans 'Cancel' %}</a> | |
| 68 | - </div> | |
| 69 | - </form> | |
| 70 | - </div> | |
| 71 | - </div> | |
| 72 | - </div> | |
| 15 | + <div class="card"> | |
| 16 | + <div class="card-content"> | |
| 17 | + <div class="card-body"> | |
| 18 | + {% include "users/_form.html" with back_url="users:profile" %} | |
| 19 | + </div> | |
| 20 | + </div> | |
| 21 | + </div> | |
| 22 | + <br clear="all" /> | |
| 23 | + <br clear="all" /> | |
| 73 | 24 | {% endblock %} | ... | ... |
users/templates/users/update.html
| ... | ... | @@ -14,21 +14,10 @@ |
| 14 | 14 | |
| 15 | 15 | |
| 16 | 16 | {% block content %} |
| 17 | - {% if messages %} | |
| 18 | - {% for message in messages %} | |
| 19 | - <div class="alert alert-success alert-dismissible" role="alert"> | |
| 20 | - <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
| 21 | - <span aria-hidden="true">×</span> | |
| 22 | - </button> | |
| 23 | - <p>{{ message }}</p> | |
| 24 | - </div> | |
| 25 | - {% endfor %} | |
| 26 | - {% endif %} | |
| 27 | - | |
| 28 | 17 | <div class="card mg-b-5m"> |
| 29 | 18 | <div class="card-content"> |
| 30 | 19 | <div class="card-body"> |
| 31 | - {% include 'users/_form.html' %} | |
| 20 | + {% include 'users/_form.html' with back_url="users:manage" %} | |
| 32 | 21 | </div> |
| 33 | 22 | </div> |
| 34 | 23 | </div> | ... | ... |
users/urls.py
| ... | ... | @@ -12,4 +12,5 @@ urlpatterns = [ |
| 12 | 12 | url(r'^create/$', views.CreateView.as_view(), name = 'create'), |
| 13 | 13 | url(r'^profile/$', views.Profile.as_view(), name = 'profile'), |
| 14 | 14 | url(r'^edit_profile/$', views.UpdateProfile.as_view(), name = 'edit_profile'), |
| 15 | + url(r'^change_pass/$', views.ChangePassView.as_view(), name='change_pass'), | |
| 15 | 16 | ] | ... | ... |
users/views.py
| ... | ... | @@ -14,7 +14,7 @@ from itertools import chain |
| 14 | 14 | from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger |
| 15 | 15 | |
| 16 | 16 | from .models import User |
| 17 | -from .forms import RegisterUserForm, ProfileForm, UserForm | |
| 17 | +from .forms import RegisterUserForm, ProfileForm, UserForm, ChangePassForm | |
| 18 | 18 | |
| 19 | 19 | #API IMPORTS |
| 20 | 20 | from rest_framework import viewsets |
| ... | ... | @@ -179,6 +179,44 @@ class UpdateView(LoginRequiredMixin, generic.UpdateView): |
| 179 | 179 | |
| 180 | 180 | return context |
| 181 | 181 | |
| 182 | +class ChangePassView(LoginRequiredMixin, generic.UpdateView): | |
| 183 | + login_url = reverse_lazy("users:login") | |
| 184 | + redirect_field_name = 'next' | |
| 185 | + | |
| 186 | + template_name = 'users/change_password.html' | |
| 187 | + slug_field = 'email' | |
| 188 | + slug_url_kwarg = 'email' | |
| 189 | + context_object_name = 'acc' | |
| 190 | + model = User | |
| 191 | + form_class = ChangePassForm | |
| 192 | + success_url = reverse_lazy('users:profile') | |
| 193 | + | |
| 194 | + def get_form_kwargs(self): | |
| 195 | + kwargs = super(ChangePassView, self).get_form_kwargs() | |
| 196 | + | |
| 197 | + kwargs.update({'user': self.request.user}) | |
| 198 | + kwargs.update({'request': self.request}) | |
| 199 | + | |
| 200 | + return kwargs | |
| 201 | + | |
| 202 | + def get_object(self): | |
| 203 | + user = get_object_or_404(User, email = self.request.user.email) | |
| 204 | + | |
| 205 | + return user | |
| 206 | + | |
| 207 | + def form_valid(self, form): | |
| 208 | + form.save() | |
| 209 | + | |
| 210 | + messages.success(self.request, _('Password changed successfully!')) | |
| 211 | + | |
| 212 | + return super(ChangePassView, self).form_valid(form) | |
| 213 | + | |
| 214 | + def get_context_data (self, **kwargs): | |
| 215 | + context = super(ChangePassView, self).get_context_data(**kwargs) | |
| 216 | + context['title'] = _("Change Password") | |
| 217 | + | |
| 218 | + return context | |
| 219 | + | |
| 182 | 220 | class Profile(LoginRequiredMixin, generic.DetailView): |
| 183 | 221 | login_url = reverse_lazy("users:login") |
| 184 | 222 | redirect_field_name = 'next' |
| ... | ... | @@ -187,7 +225,7 @@ class Profile(LoginRequiredMixin, generic.DetailView): |
| 187 | 225 | template_name = 'users/profile.html' |
| 188 | 226 | |
| 189 | 227 | def get_object(self): |
| 190 | - user = get_object_or_404(User, username = self.request.user.username) | |
| 228 | + user = get_object_or_404(User, email = self.request.user.email) | |
| 191 | 229 | |
| 192 | 230 | return user |
| 193 | 231 | |
| ... | ... | @@ -254,12 +292,12 @@ def login(request): |
| 254 | 292 | user = authenticate(username=username, password=password) |
| 255 | 293 | if user is not None: |
| 256 | 294 | login_user(request, user) |
| 257 | - return redirect(reverse("users:login")) | |
| 295 | + return redirect(reverse("home")) | |
| 258 | 296 | else: |
| 259 | 297 | messages.add_message(request, messages.ERROR, _('E-mail or password are incorrect.')) |
| 260 | 298 | context["username"] = username |
| 261 | 299 | elif request.user.is_authenticated: |
| 262 | - return redirect('home') | |
| 300 | + return redirect(reverse('home')) | |
| 263 | 301 | |
| 264 | 302 | return render(request,"users/login.html",context) |
| 265 | 303 | ... | ... |