224 строки
7.2 KiB
Python
224 строки
7.2 KiB
Python
import os
|
|
|
|
from django import forms
|
|
from django.conf import settings
|
|
from django.contrib.auth import forms as auth_forms
|
|
from django.forms.util import ErrorList
|
|
|
|
import captcha.fields
|
|
import commonware.log
|
|
import happyforms
|
|
from tower import ugettext as _, ugettext_lazy as _lazy
|
|
|
|
from .models import UserProfile, BlacklistedUsername
|
|
import tasks
|
|
|
|
log = commonware.log.getLogger('z.users')
|
|
|
|
|
|
class AuthenticationForm(auth_forms.AuthenticationForm):
|
|
rememberme = forms.BooleanField(required=False)
|
|
|
|
|
|
class PasswordResetForm(auth_forms.PasswordResetForm):
|
|
def save(self, **kw):
|
|
for user in self.users_cache:
|
|
log.info(u'Password reset email sent for user (%s)' % user)
|
|
super(PasswordResetForm, self).save(**kw)
|
|
|
|
|
|
class SetPasswordForm(auth_forms.SetPasswordForm):
|
|
def __init__(self, user, *args, **kwargs):
|
|
super(SetPasswordForm, self).__init__(user, *args, **kwargs)
|
|
if self.user:
|
|
# We store our password in the users table, not auth_user like
|
|
# Django expects
|
|
self.user = self.user.get_profile()
|
|
|
|
def save(self, **kw):
|
|
log.info(u'User (%s) changed password with reset form' % self.user)
|
|
super(SetPasswordForm, self).save(**kw)
|
|
|
|
|
|
class UserDeleteForm(forms.Form):
|
|
password = forms.CharField(max_length=255, required=True,
|
|
widget=forms.PasswordInput(render_value=False))
|
|
confirm = forms.BooleanField(required=True)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
self.request = kwargs.pop('request', None)
|
|
super(UserDeleteForm, self).__init__(*args, **kwargs)
|
|
|
|
def clean_password(self):
|
|
data = self.cleaned_data
|
|
amouser = self.request.user.get_profile()
|
|
if not amouser.check_password(data["password"]):
|
|
raise forms.ValidationError(_("Wrong password entered!"))
|
|
|
|
def clean(self):
|
|
amouser = self.request.user.get_profile()
|
|
if amouser.is_developer:
|
|
# This is tampering because the form isn't shown on the page if the
|
|
# user is a developer
|
|
log.warning(u'[Tampering] Attempt to delete developer account (%s)'
|
|
% self.request.user)
|
|
raise forms.ValidationError("")
|
|
|
|
def save(self, **kw):
|
|
log.info(u'User (%s) has successfully deleted their account.'
|
|
% self.request.user)
|
|
super(UserDeleteForm, self).save(**kw)
|
|
|
|
|
|
class UserRegisterForm(happyforms.ModelForm):
|
|
"""
|
|
For registering users. We're not building off
|
|
d.contrib.auth.forms.UserCreationForm because it doesn't do a lot of the
|
|
details here, so we'd have to rewrite most of it anyway.
|
|
"""
|
|
|
|
password = forms.CharField(max_length=255,
|
|
widget=forms.PasswordInput(render_value=False))
|
|
|
|
password2 = forms.CharField(max_length=255,
|
|
widget=forms.PasswordInput(render_value=False))
|
|
recaptcha = captcha.fields.ReCaptchaField()
|
|
|
|
class Meta:
|
|
model = UserProfile
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super(UserRegisterForm, self).__init__(*args, **kwargs)
|
|
|
|
if not settings.RECAPTCHA_PRIVATE_KEY:
|
|
del self.fields['recaptcha']
|
|
|
|
def clean_username(self):
|
|
name = self.cleaned_data['username']
|
|
if BlacklistedUsername.blocked(name):
|
|
raise forms.ValidationError(_('This username is invalid.'))
|
|
return name
|
|
|
|
def clean(self):
|
|
super(UserRegisterForm, self).clean()
|
|
|
|
data = self.cleaned_data
|
|
|
|
# Passwords
|
|
p1 = data.get('password')
|
|
p2 = data.get('password2')
|
|
|
|
if p1 != p2:
|
|
msg = _('The passwords did not match.')
|
|
self._errors['password2'] = ErrorList([msg])
|
|
if p2:
|
|
del data['password2']
|
|
|
|
return data
|
|
|
|
|
|
class UserEditForm(UserRegisterForm):
|
|
oldpassword = forms.CharField(max_length=255, required=False,
|
|
widget=forms.PasswordInput(render_value=False))
|
|
password = forms.CharField(max_length=255, required=False,
|
|
widget=forms.PasswordInput(render_value=False))
|
|
|
|
password2 = forms.CharField(max_length=255, required=False,
|
|
widget=forms.PasswordInput(render_value=False))
|
|
|
|
photo = forms.FileField(label=_lazy('Profile Photo'), required=False)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
self.request = kwargs.pop('request', None)
|
|
super(UserEditForm, self).__init__(*args, **kwargs)
|
|
|
|
# TODO: We should inherit from a base form not UserRegisterForm
|
|
if self.fields.get('recaptcha'):
|
|
del self.fields['recaptcha']
|
|
|
|
class Meta:
|
|
model = UserProfile
|
|
exclude = ['password']
|
|
|
|
def clean(self):
|
|
|
|
data = self.cleaned_data
|
|
amouser = self.request.user.get_profile()
|
|
|
|
# Passwords
|
|
p1 = data.get("password")
|
|
p2 = data.get("password2")
|
|
|
|
if p1 or p2:
|
|
if not amouser.check_password(data["oldpassword"]):
|
|
msg = _("Wrong password entered!")
|
|
self._errors["oldpassword"] = ErrorList([msg])
|
|
del data["oldpassword"]
|
|
|
|
super(UserEditForm, self).clean()
|
|
return data
|
|
|
|
def clean_photo(self):
|
|
photo = self.cleaned_data['photo']
|
|
|
|
if not photo:
|
|
return
|
|
|
|
if photo.content_type not in ('image/png', 'image/jpeg'):
|
|
raise forms.ValidationError(
|
|
_('Images must be either PNG or JPG.'))
|
|
|
|
if photo.size > settings.MAX_PHOTO_UPLOAD_SIZE:
|
|
raise forms.ValidationError(
|
|
_('Please use images smaller than %dMB.' %
|
|
(settings.MAX_PHOTO_UPLOAD_SIZE / 1024 / 1024 - 1)))
|
|
|
|
return photo
|
|
|
|
def save(self):
|
|
u = super(UserEditForm, self).save(commit=False)
|
|
data = self.cleaned_data
|
|
photo = data['photo']
|
|
if photo:
|
|
u.picture_type = 'image/png'
|
|
tmp_destination = u.picture_path + '__unconverted'
|
|
|
|
if not os.path.exists(u.picture_dir):
|
|
os.mkdir(u.picture_dir)
|
|
|
|
fh = open(tmp_destination, 'w')
|
|
for chunk in photo.chunks():
|
|
fh.write(chunk)
|
|
|
|
fh.close()
|
|
tasks.resize_photo.delay(tmp_destination, u.picture_path)
|
|
|
|
if data['password']:
|
|
u.set_password(data['password'])
|
|
log.info(u'User (%s) changed their password' % u)
|
|
|
|
log.debug(u'User (%s) updated their profile' % u)
|
|
|
|
u.save()
|
|
return u
|
|
|
|
|
|
class BlacklistedUsernameAddForm(forms.Form):
|
|
"""Form for adding blacklisted username in bulk fashion."""
|
|
usernames = forms.CharField(widget=forms.Textarea(
|
|
attrs={'cols': 40, 'rows': 16}))
|
|
|
|
def clean(self):
|
|
super(BlacklistedUsernameAddForm, self).clean()
|
|
data = self.cleaned_data
|
|
|
|
if 'usernames' in data:
|
|
data['usernames'] = os.linesep.join(
|
|
[s.strip() for s in data['usernames'].splitlines()
|
|
if s.strip()])
|
|
if 'usernames' not in data or data['usernames'] == '':
|
|
msg = 'Please enter at least one username to blacklist.'
|
|
self._errors['usernames'] = ErrorList([msg])
|
|
|
|
return data
|