Commit 22b917518e2e1105fb74278490055ecc978528a4
1 parent
fbf424a9
Exists in
master
and in
39 other branches
Fixed admin for User model
(flake8 checks as well)
Showing
2 changed files
with
97 additions
and
103 deletions
Show diff stats
colab/accounts/admin.py
| 1 | 1 | ||
| 2 | -from django import forms | ||
| 3 | from django.contrib import admin | 2 | from django.contrib import admin |
| 4 | from django.contrib.auth import get_user_model | 3 | from django.contrib.auth import get_user_model |
| 5 | from django.contrib.auth.admin import UserAdmin | 4 | from django.contrib.auth.admin import UserAdmin |
| 6 | from django.utils.translation import ugettext_lazy as _ | 5 | from django.utils.translation import ugettext_lazy as _ |
| 7 | 6 | ||
| 8 | -from .forms import UserCreationForm | 7 | +from .forms import UserCreationForm, UserChangeForm |
| 9 | 8 | ||
| 10 | User = get_user_model() | 9 | User = get_user_model() |
| 11 | 10 | ||
| 12 | 11 | ||
| 13 | -class CustomUserCreationForm(UserCreationForm): | ||
| 14 | - class Meta: | ||
| 15 | - model = User | ||
| 16 | - fields = ("username", "email") | ||
| 17 | - | ||
| 18 | - #def __init__(self, *args, **kwargs): | ||
| 19 | - # super(CustomUserCreationForm, self).__init__(*args, **kwargs) | ||
| 20 | - # self.fields['email'].required = True | ||
| 21 | - | ||
| 22 | - | ||
| 23 | -class UserChangeForm(forms.ModelForm): | ||
| 24 | - class Meta: | ||
| 25 | - model = User | ||
| 26 | - fields = ('username', 'first_name', 'last_name', 'email', 'is_active', | ||
| 27 | - 'is_staff', 'is_superuser', 'groups', 'last_login', | ||
| 28 | - 'date_joined', 'twitter', 'facebook', 'google_talk', | ||
| 29 | - 'webpage') | ||
| 30 | - | ||
| 31 | - def __init__(self, *args, **kwargs): | ||
| 32 | - super(UserChangeForm, self).__init__(*args, **kwargs) | ||
| 33 | - self.fields['email'].required = True | ||
| 34 | - | ||
| 35 | - | ||
| 36 | - | ||
| 37 | -class MyUserAdmin(UserAdmin): | 12 | +class CustomUserAdmin(UserAdmin): |
| 38 | form = UserChangeForm | 13 | form = UserChangeForm |
| 39 | - add_form = CustomUserCreationForm | 14 | + add_form = UserCreationForm |
| 40 | 15 | ||
| 41 | fieldsets = ( | 16 | fieldsets = ( |
| 42 | (None, {'fields': ('username', 'email', 'password')}), | 17 | (None, {'fields': ('username', 'email', 'password')}), |
| 43 | - (_('Personal info'), {'fields': ('first_name', 'last_name', 'twitter', | ||
| 44 | - 'facebook', 'google_talk', 'webpage', | ||
| 45 | - )}), | ||
| 46 | - (_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser', | 18 | + (_('Personal info'), {'fields': ('first_name', |
| 19 | + 'last_name', | ||
| 20 | + 'twitter', | ||
| 21 | + 'facebook', | ||
| 22 | + 'google_talk', | ||
| 23 | + 'webpage')}), | ||
| 24 | + (_('Permissions'), {'fields': ('is_active', | ||
| 25 | + 'is_staff', | ||
| 26 | + 'is_superuser', | ||
| 47 | 'groups')}), | 27 | 'groups')}), |
| 48 | (_('Important dates'), {'fields': ('last_login', 'date_joined')}) | 28 | (_('Important dates'), {'fields': ('last_login', 'date_joined')}) |
| 49 | ) | 29 | ) |
| @@ -56,4 +36,4 @@ class MyUserAdmin(UserAdmin): | @@ -56,4 +36,4 @@ class MyUserAdmin(UserAdmin): | ||
| 56 | ) | 36 | ) |
| 57 | 37 | ||
| 58 | 38 | ||
| 59 | -admin.site.register(User, MyUserAdmin) | 39 | +admin.site.register(User, CustomUserAdmin) |
colab/accounts/forms.py
| 1 | # -*- coding: utf-8 -*- | 1 | # -*- coding: utf-8 -*- |
| 2 | 2 | ||
| 3 | +from collections import OrderedDict | ||
| 4 | + | ||
| 3 | from django import forms | 5 | from django import forms |
| 4 | -from django.contrib.auth import get_user_model | ||
| 5 | -from django.contrib.auth.forms import OrderedDict, ReadOnlyPasswordHashField, \ | ||
| 6 | - default_token_generator | 6 | +from django.contrib.auth import authenticate, get_user_model |
| 7 | +from django.contrib.auth.forms import ReadOnlyPasswordHashField | ||
| 8 | +from django.contrib.auth.tokens import default_token_generator | ||
| 9 | +from django.contrib.sites.shortcuts import get_current_site | ||
| 10 | +from django.template import loader | ||
| 11 | +from django.utils.encoding import force_bytes | ||
| 12 | +from django.utils.http import urlsafe_base64_encode | ||
| 13 | +from django.utils.text import capfirst | ||
| 7 | from django.utils.translation import ugettext_lazy as _ | 14 | from django.utils.translation import ugettext_lazy as _ |
| 8 | 15 | ||
| 9 | from conversejs.models import XMPPAccount | 16 | from conversejs.models import XMPPAccount |
| 10 | 17 | ||
| 11 | -from ..super_archives.models import MailingList | ||
| 12 | from .utils.validators import validate_social_account | 18 | from .utils.validators import validate_social_account |
| 13 | from .utils import mailman | 19 | from .utils import mailman |
| 14 | 20 | ||
| @@ -32,7 +38,7 @@ class UserForm(forms.ModelForm): | @@ -32,7 +38,7 @@ class UserForm(forms.ModelForm): | ||
| 32 | username = forms.CharField( | 38 | username = forms.CharField( |
| 33 | 39 | ||
| 34 | # Forces username to be lowercase always | 40 | # Forces username to be lowercase always |
| 35 | - widget=forms.TextInput(attrs={'style' : 'text-transform: lowercase;'}), | 41 | + widget=forms.TextInput(attrs={'style': 'text-transform: lowercase;'}), |
| 36 | ) | 42 | ) |
| 37 | required = ('first_name', 'last_name', 'username') | 43 | required = ('first_name', 'last_name', 'username') |
| 38 | 44 | ||
| @@ -50,48 +56,6 @@ class UserForm(forms.ModelForm): | @@ -50,48 +56,6 @@ class UserForm(forms.ModelForm): | ||
| 50 | field.required = True | 56 | field.required = True |
| 51 | 57 | ||
| 52 | 58 | ||
| 53 | -class UserCreationForm(UserForm): | ||
| 54 | - | ||
| 55 | - class Meta: | ||
| 56 | - model = User | ||
| 57 | - fields = ('first_name', 'last_name', 'username') | ||
| 58 | - | ||
| 59 | - def clean_username(self): | ||
| 60 | - username = self.cleaned_data['username'] | ||
| 61 | - username = username.strip() | ||
| 62 | - if not username: | ||
| 63 | - raise forms.ValidationError(_('This field cannot be blank.')) | ||
| 64 | - return username | ||
| 65 | - | ||
| 66 | - | ||
| 67 | -class UserCreationFormNoBrowserId(UserCreationForm): | ||
| 68 | - | ||
| 69 | - password1 = forms.CharField(label=_("Password"), widget=forms.PasswordInput) | ||
| 70 | - password2 = forms.CharField(label=_("Confirm Password "), widget=forms.PasswordInput) | ||
| 71 | - email = forms.EmailField(label=_("Email address"), required=True) | ||
| 72 | - | ||
| 73 | - class Meta: | ||
| 74 | - model = User | ||
| 75 | - fields = ('first_name', 'last_name','email', 'username') | ||
| 76 | - | ||
| 77 | - def clean_password2(self): | ||
| 78 | - password1 = self.cleaned_data.get('password1') | ||
| 79 | - password2 = self.cleaned_data.get('password2') | ||
| 80 | - | ||
| 81 | - if password1 and password2 and password1 != password2: | ||
| 82 | - raise forms.ValidationError(_("The two password fields didn't match.")) | ||
| 83 | - return password2 | ||
| 84 | - | ||
| 85 | - def save(self, commit=True): | ||
| 86 | - """ | ||
| 87 | - Saves the new password. | ||
| 88 | - """ | ||
| 89 | - self.instance.set_password(self.cleaned_data["password1"]) | ||
| 90 | - if commit: | ||
| 91 | - self.instance.save() | ||
| 92 | - return self.instance | ||
| 93 | - | ||
| 94 | - | ||
| 95 | class UserUpdateForm(UserForm): | 59 | class UserUpdateForm(UserForm): |
| 96 | bio = forms.CharField( | 60 | bio = forms.CharField( |
| 97 | widget=forms.Textarea(attrs={'rows': '6', 'maxlength': '200'}), | 61 | widget=forms.Textarea(attrs={'rows': '6', 'maxlength': '200'}), |
| @@ -102,10 +66,9 @@ class UserUpdateForm(UserForm): | @@ -102,10 +66,9 @@ class UserUpdateForm(UserForm): | ||
| 102 | ) | 66 | ) |
| 103 | 67 | ||
| 104 | def __init__(self, *args, **kwargs): | 68 | def __init__(self, *args, **kwargs): |
| 105 | - super (UserUpdateForm, self).__init__(*args, **kwargs) | 69 | + super(UserUpdateForm, self).__init__(*args, **kwargs) |
| 106 | self.fields.pop('username') | 70 | self.fields.pop('username') |
| 107 | 71 | ||
| 108 | - | ||
| 109 | class Meta: | 72 | class Meta: |
| 110 | model = User | 73 | model = User |
| 111 | fields = ('first_name', 'last_name', | 74 | fields = ('first_name', 'last_name', |
| @@ -113,7 +76,8 @@ class UserUpdateForm(UserForm): | @@ -113,7 +76,8 @@ class UserUpdateForm(UserForm): | ||
| 113 | 'google_talk', 'github', 'webpage', 'bio') | 76 | 'google_talk', 'github', 'webpage', 'bio') |
| 114 | 77 | ||
| 115 | twitter = SocialAccountField(url='https://twitter.com/', required=False) | 78 | twitter = SocialAccountField(url='https://twitter.com/', required=False) |
| 116 | - facebook = SocialAccountField(url='https://graph.facebook.com/', required=False) | 79 | + facebook = SocialAccountField(url='https://graph.facebook.com/', |
| 80 | + required=False) | ||
| 117 | 81 | ||
| 118 | 82 | ||
| 119 | class ListsForm(forms.Form): | 83 | class ListsForm(forms.Form): |
| @@ -129,10 +93,11 @@ class ListsForm(forms.Form): | @@ -129,10 +93,11 @@ class ListsForm(forms.Form): | ||
| 129 | 93 | ||
| 130 | class ChangeXMPPPasswordForm(forms.ModelForm): | 94 | class ChangeXMPPPasswordForm(forms.ModelForm): |
| 131 | password1 = forms.CharField(label=_("Password"), | 95 | password1 = forms.CharField(label=_("Password"), |
| 132 | - widget=forms.PasswordInput) | 96 | + widget=forms.PasswordInput) |
| 133 | password2 = forms.CharField(label=_("Password confirmation"), | 97 | password2 = forms.CharField(label=_("Password confirmation"), |
| 134 | - widget=forms.PasswordInput, | ||
| 135 | - help_text=_("Enter the same password as above, for verification.")) | 98 | + widget=forms.PasswordInput, |
| 99 | + help_text=_(("Enter the same password as above" | ||
| 100 | + ", for verification."))) | ||
| 136 | 101 | ||
| 137 | class Meta: | 102 | class Meta: |
| 138 | model = XMPPAccount | 103 | model = XMPPAccount |
| @@ -161,6 +126,7 @@ class ChangeXMPPPasswordForm(forms.ModelForm): | @@ -161,6 +126,7 @@ class ChangeXMPPPasswordForm(forms.ModelForm): | ||
| 161 | self.instance.save() | 126 | self.instance.save() |
| 162 | return self.instance | 127 | return self.instance |
| 163 | 128 | ||
| 129 | + | ||
| 164 | class UserCreationForm(forms.ModelForm): | 130 | class UserCreationForm(forms.ModelForm): |
| 165 | """ | 131 | """ |
| 166 | A form that creates a user, with no privileges, from the given username and | 132 | A form that creates a user, with no privileges, from the given username and |
| @@ -171,17 +137,21 @@ class UserCreationForm(forms.ModelForm): | @@ -171,17 +137,21 @@ class UserCreationForm(forms.ModelForm): | ||
| 171 | 'password_mismatch': _("The two password fields didn't match."), | 137 | 'password_mismatch': _("The two password fields didn't match."), |
| 172 | } | 138 | } |
| 173 | username = forms.RegexField(label=_("Username"), max_length=30, | 139 | username = forms.RegexField(label=_("Username"), max_length=30, |
| 174 | - regex=r'^[\w.@+-]+$', | ||
| 175 | - help_text=_("Required. 30 characters or fewer. Letters, digits and " | ||
| 176 | - "@/./+/-/_ only."), | ||
| 177 | - error_messages={ | ||
| 178 | - 'invalid': _("This value may contain only letters, numbers and " | ||
| 179 | - "@/./+/-/_ characters.")}) | 140 | + regex=r'^[\w.@+-]+$', |
| 141 | + help_text=_(("Required. 30 characters or fewer" | ||
| 142 | + ". Letters, digits and " | ||
| 143 | + "@/./+/-/_ only.")), | ||
| 144 | + error_messages={ | ||
| 145 | + 'invalid': _(("This value may contain only" | ||
| 146 | + " letters, numbers and " | ||
| 147 | + "@/./+/-/_ characters."))}) | ||
| 180 | password1 = forms.CharField(label=_("Password"), | 148 | password1 = forms.CharField(label=_("Password"), |
| 181 | - widget=forms.PasswordInput) | 149 | + widget=forms.PasswordInput) |
| 182 | password2 = forms.CharField(label=_("Password confirmation"), | 150 | password2 = forms.CharField(label=_("Password confirmation"), |
| 183 | - widget=forms.PasswordInput, | ||
| 184 | - help_text=_("Enter the same password as above, for verification.")) | 151 | + widget=forms.PasswordInput, |
| 152 | + help_text=_(("Enter the same password as above" | ||
| 153 | + ", for verification."))) | ||
| 154 | + email = forms.EmailField(required=True) | ||
| 185 | 155 | ||
| 186 | class Meta: | 156 | class Meta: |
| 187 | model = User | 157 | model = User |
| @@ -190,7 +160,7 @@ class UserCreationForm(forms.ModelForm): | @@ -190,7 +160,7 @@ class UserCreationForm(forms.ModelForm): | ||
| 190 | def clean_username(self): | 160 | def clean_username(self): |
| 191 | # Since User.username is unique, this check is redundant, | 161 | # Since User.username is unique, this check is redundant, |
| 192 | # but it sets a nicer error message than the ORM. See #13147. | 162 | # but it sets a nicer error message than the ORM. See #13147. |
| 193 | - username = self.cleaned_data["username"] | 163 | + username = self.cleaned_data["username"].strip() |
| 194 | try: | 164 | try: |
| 195 | User._default_manager.get(username=username) | 165 | User._default_manager.get(username=username) |
| 196 | except User.DoesNotExist: | 166 | except User.DoesNotExist: |
| @@ -227,9 +197,15 @@ class UserChangeForm(forms.ModelForm): | @@ -227,9 +197,15 @@ class UserChangeForm(forms.ModelForm): | ||
| 227 | 'invalid': _("This value may contain only letters, numbers and " | 197 | 'invalid': _("This value may contain only letters, numbers and " |
| 228 | "@/./+/-/_ characters.")}) | 198 | "@/./+/-/_ characters.")}) |
| 229 | password = ReadOnlyPasswordHashField(label=_("Password"), | 199 | password = ReadOnlyPasswordHashField(label=_("Password"), |
| 230 | - help_text=_("Raw passwords are not stored, so there is no way to see " | ||
| 231 | - "this user's password, but you can change the password " | ||
| 232 | - "using <a href=\"password/\">this form</a>.")) | 200 | + help_text=_("Raw passwords are not" |
| 201 | + " stored, so there is no" | ||
| 202 | + " way to see " | ||
| 203 | + "this user's password, " | ||
| 204 | + "but you can change the " | ||
| 205 | + "password " | ||
| 206 | + "using <a " | ||
| 207 | + "href=\"password/\">this" | ||
| 208 | + " form</a>.")) | ||
| 233 | 209 | ||
| 234 | class Meta: | 210 | class Meta: |
| 235 | model = User | 211 | model = User |
| @@ -241,6 +217,9 @@ class UserChangeForm(forms.ModelForm): | @@ -241,6 +217,9 @@ class UserChangeForm(forms.ModelForm): | ||
| 241 | if f is not None: | 217 | if f is not None: |
| 242 | f.queryset = f.queryset.select_related('content_type') | 218 | f.queryset = f.queryset.select_related('content_type') |
| 243 | 219 | ||
| 220 | + # Set email as required field | ||
| 221 | + self.fields['email'].required = True | ||
| 222 | + | ||
| 244 | def clean_password(self): | 223 | def clean_password(self): |
| 245 | # Regardless of what the user provides, return the initial value. | 224 | # Regardless of what the user provides, return the initial value. |
| 246 | # This is done here, rather than on the field, because the | 225 | # This is done here, rather than on the field, because the |
| @@ -248,6 +227,37 @@ class UserChangeForm(forms.ModelForm): | @@ -248,6 +227,37 @@ class UserChangeForm(forms.ModelForm): | ||
| 248 | return self.initial["password"] | 227 | return self.initial["password"] |
| 249 | 228 | ||
| 250 | 229 | ||
| 230 | +class UserCreationFormNoBrowserId(UserCreationForm): | ||
| 231 | + | ||
| 232 | + password1 = forms.CharField(label=_("Password"), | ||
| 233 | + widget=forms.PasswordInput) | ||
| 234 | + password2 = forms.CharField(label=_("Confirm Password "), | ||
| 235 | + widget=forms.PasswordInput) | ||
| 236 | + email = forms.EmailField(label=_("Email address"), required=True) | ||
| 237 | + | ||
| 238 | + class Meta: | ||
| 239 | + model = User | ||
| 240 | + fields = ('first_name', 'last_name', 'email', 'username') | ||
| 241 | + | ||
| 242 | + def clean_password2(self): | ||
| 243 | + password1 = self.cleaned_data.get('password1') | ||
| 244 | + password2 = self.cleaned_data.get('password2') | ||
| 245 | + | ||
| 246 | + if password1 and password2 and password1 != password2: | ||
| 247 | + raise forms.ValidationError( | ||
| 248 | + _("The two password fields didn't match.")) | ||
| 249 | + return password2 | ||
| 250 | + | ||
| 251 | + def save(self, commit=True): | ||
| 252 | + """ | ||
| 253 | + Saves the new password. | ||
| 254 | + """ | ||
| 255 | + self.instance.set_password(self.cleaned_data["password1"]) | ||
| 256 | + if commit: | ||
| 257 | + self.instance.save() | ||
| 258 | + return self.instance | ||
| 259 | + | ||
| 260 | + | ||
| 251 | class AuthenticationForm(forms.Form): | 261 | class AuthenticationForm(forms.Form): |
| 252 | """ | 262 | """ |
| 253 | Base class for authenticating users. Extend this to get a form that accepts | 263 | Base class for authenticating users. Extend this to get a form that accepts |
| @@ -273,9 +283,11 @@ class AuthenticationForm(forms.Form): | @@ -273,9 +283,11 @@ class AuthenticationForm(forms.Form): | ||
| 273 | 283 | ||
| 274 | # Set the label for the "username" field. | 284 | # Set the label for the "username" field. |
| 275 | UserModel = get_user_model() | 285 | UserModel = get_user_model() |
| 276 | - self.username_field = UserModel._meta.get_field(UserModel.USERNAME_FIELD) | 286 | + self.username_field = UserModel._meta.get_field( |
| 287 | + UserModel.USERNAME_FIELD) | ||
| 277 | if self.fields['username'].label is None: | 288 | if self.fields['username'].label is None: |
| 278 | - self.fields['username'].label = capfirst(self.username_field.verbose_name) | 289 | + self.fields['username'].label = capfirst( |
| 290 | + self.username_field.verbose_name) | ||
| 279 | 291 | ||
| 280 | def clean(self): | 292 | def clean(self): |
| 281 | username = self.cleaned_data.get('username') | 293 | username = self.cleaned_data.get('username') |
| @@ -362,10 +374,12 @@ class PasswordResetForm(forms.Form): | @@ -362,10 +374,12 @@ class PasswordResetForm(forms.Form): | ||
| 362 | email = loader.render_to_string(email_template_name, c) | 374 | email = loader.render_to_string(email_template_name, c) |
| 363 | 375 | ||
| 364 | if html_email_template_name: | 376 | if html_email_template_name: |
| 365 | - html_email = loader.render_to_string(html_email_template_name, c) | 377 | + html_email = loader.render_to_string(html_email_template_name, |
| 378 | + c) | ||
| 366 | else: | 379 | else: |
| 367 | html_email = None | 380 | html_email = None |
| 368 | - send_mail(subject, email, from_email, [user.email], html_message=html_email) | 381 | + send_mail(subject, email, from_email, [user.email], |
| 382 | + html_message=html_email) | ||
| 369 | 383 | ||
| 370 | 384 | ||
| 371 | class SetPasswordForm(forms.Form): | 385 | class SetPasswordForm(forms.Form): |