diff --git a/layerindex/forms.py b/layerindex/forms.py index 328d992..fa1e168 100644 --- a/layerindex/forms.py +++ b/layerindex/forms.py @@ -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): diff --git a/layerindex/views.py b/layerindex/views.py index 0b2d0a9..c54e22b 100644 --- a/layerindex/views.py +++ b/layerindex/views.py @@ -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') diff --git a/templates/layerindex/profile.html b/templates/layerindex/profile.html index 2dbd568..212cf51 100644 --- a/templates/layerindex/profile.html +++ b/templates/layerindex/profile.html @@ -26,7 +26,7 @@ {% endfor %} {% for field in form.visible_fields %} - {% if field.errors %} + {% if field.name in error_fields %}
{{ field.errors }} {% else %}