Allow user to edit their username in the Edit Profile form

Users may want to change their usernames for a number of different
reasons, but at the moment we require them to contact an admin to do
that. Provided we validate the new username correctly and add a CAPTCHA
to make automated enumeration difficult, we can add username to the Edit
Profile form and then users can do that any time they wish.

While we're doing this, show a message when the profile is successfully
updated.

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
This commit is contained in:
Paul Eggleton 2018-10-18 10:09:06 +13:00
parent 2c8f979f9c
commit 091f5e4ef8
3 changed files with 35 additions and 3 deletions

View File

@ -8,6 +8,7 @@ from collections import OrderedDict
from layerindex.models import LayerItem, LayerBranch, LayerMaintainer, LayerNote, RecipeChangeset, RecipeChange, ClassicRecipe
from django import forms
from django.core.validators import URLValidator, RegexValidator, EmailValidator
from registration.validators import ReservedNameValidator, DEFAULT_RESERVED_NAMES, validate_confusables
from django.forms.models import inlineformset_factory, modelformset_factory
from captcha.fields import CaptchaField
from django.contrib.auth.models import User
@ -178,9 +179,24 @@ class EditNoteForm(StyledModelForm):
class EditProfileForm(StyledModelForm):
captcha = CaptchaField(label='Verification', help_text='Please enter the letters displayed for verification purposes', error_messages={'invalid':'Incorrect entry, please try again'})
class Meta:
model = User
fields = ('first_name', 'last_name', 'email')
fields = ('username', 'first_name', 'last_name', 'email', 'captcha')
def clean_username(self):
username = self.cleaned_data['username']
if 'username' in self.changed_data:
try:
reserved_validator = ReservedNameValidator(
reserved_names=DEFAULT_RESERVED_NAMES
)
reserved_validator(username)
validate_confusables(username)
except forms.ValidationError as v:
self.add_error('username', v)
return username
class ClassicRecipeForm(StyledModelForm):

View File

@ -824,16 +824,32 @@ class HistoryListView(ListView):
return Revision.objects.all().order_by('-date_created')
class EditProfileFormView(UpdateView):
class EditProfileFormView(SuccessMessageMixin, UpdateView):
form_class = EditProfileForm
def dispatch(self, request, *args, **kwargs):
self.user = request.user
return super(EditProfileFormView, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(EditProfileFormView, self).get_context_data(**kwargs)
form = context['form']
# Prepare a list of fields with errors
# We do this so that if there's a problem with the captcha, that's the only error shown
# (since we have a username field, we want to make user enumeration difficult)
if 'captcha' in form.errors:
error_fields = ['captcha']
else:
error_fields = form.errors.keys()
context['error_fields'] = error_fields
return context
def get_object(self, queryset=None):
return self.user
def get_success_message(self, cleaned_data):
return "Profile saved successfully"
def get_success_url(self):
return reverse('frontpage')

View File

@ -26,7 +26,7 @@
{% endfor %}
{% for field in form.visible_fields %}
{% if field.errors %}
{% if field.name in error_fields %}
<div class="form-group alert alert-danger">
{{ field.errors }}
{% else %}