
1) Remove mongo limitations (no 'or' when querying for either username or email). 2) Lost password function revealed if an user name or email address is registered, which can be considered a data leak. Leaking user names is OK, they are public anyway, but don't reveal lookup success in case the lookup happened by email address. Simply respond: "If you have an account here, we have send you your email"? 3) username and email search was case sensitive. Made username search case insensitive (they are always stored lowercase in the db). Keep email-address search case sensitive for now. This might need further discussion 4) Remove a whole bunch of indention in the style of: if no error: ... if no error: ... if no error: actually do something in the regular case by restructuring the function. 5) Outsource the sanity checking for username and email fields into the validator function. This way, we get automatic case sanity checking and sanitizing for all required fields. 6) Require 5-char password and fix tests Originally, the Change password form required a password between 6-30 chars while the registration and login form did not require anything special. This commit introduces a common minimum limit for all forms which breaks the test suite which uses a 5 char password by default. :-). As 5 chars seem sensible enough to enforce (people should be picking much longer ones anyway), just reduce the limit to 5 chars, thereby making all tests pass. Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
95 lines
3.5 KiB
Python
95 lines
3.5 KiB
Python
# GNU MediaGoblin -- federated, autonomous media hosting
|
|
# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU Affero General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Affero General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
import wtforms
|
|
import re
|
|
|
|
from mediagoblin.tools.mail import normalize_email
|
|
from mediagoblin.tools.translate import fake_ugettext_passthrough as _
|
|
|
|
def normalize_user_or_email_field(allow_email=True, allow_user=True):
|
|
"""Check if we were passed a field that matches a username and/or email pattern
|
|
|
|
This is useful for fields that can take either a username or email
|
|
address. Use the parameters if you want to only allow a username for
|
|
instance"""
|
|
message = _(u'Invalid User name or email address.')
|
|
nomail_msg = _(u"This field does not take email addresses.")
|
|
nouser_msg = _(u"This field requires an email address.")
|
|
|
|
def _normalize_field(form, field):
|
|
email = u'@' in field.data
|
|
if email: # normalize email address casing
|
|
if not allow_email:
|
|
raise wtforms.ValidationError(nomail_msg)
|
|
wtforms.validators.Email()(form, field)
|
|
field.data = normalize_email(field.data)
|
|
else: # lower case user names
|
|
if not allow_user:
|
|
raise wtforms.ValidationError(nouser_msg)
|
|
wtforms.validators.Length(min=3, max=30)(form, field)
|
|
wtforms.validators.Regexp(r'^\w+$')(form, field)
|
|
field.data = field.data.lower()
|
|
if field.data is None: # should not happen, but be cautious anyway
|
|
raise wtforms.ValidationError(message)
|
|
return _normalize_field
|
|
|
|
|
|
class RegistrationForm(wtforms.Form):
|
|
username = wtforms.TextField(
|
|
_('Username'),
|
|
[wtforms.validators.Required(),
|
|
normalize_user_or_email_field(allow_email=False)])
|
|
password = wtforms.PasswordField(
|
|
_('Password'),
|
|
[wtforms.validators.Required(),
|
|
wtforms.validators.Length(min=5, max=1024)])
|
|
email = wtforms.TextField(
|
|
_('Email address'),
|
|
[wtforms.validators.Required(),
|
|
normalize_user_or_email_field(allow_user=False)])
|
|
|
|
|
|
class LoginForm(wtforms.Form):
|
|
username = wtforms.TextField(
|
|
_('Username'),
|
|
[wtforms.validators.Required(),
|
|
normalize_user_or_email_field(allow_email=False)])
|
|
password = wtforms.PasswordField(
|
|
_('Password'),
|
|
[wtforms.validators.Required(),
|
|
wtforms.validators.Length(min=5, max=1024)])
|
|
|
|
|
|
class ForgotPassForm(wtforms.Form):
|
|
username = wtforms.TextField(
|
|
_('Username or email'),
|
|
[wtforms.validators.Required(),
|
|
normalize_user_or_email_field()])
|
|
|
|
|
|
class ChangePassForm(wtforms.Form):
|
|
password = wtforms.PasswordField(
|
|
'Password',
|
|
[wtforms.validators.Required(),
|
|
wtforms.validators.Length(min=5, max=1024)])
|
|
userid = wtforms.HiddenField(
|
|
'',
|
|
[wtforms.validators.Required()])
|
|
token = wtforms.HiddenField(
|
|
'',
|
|
[wtforms.validators.Required()])
|