Compare commits

...
14 Commits
9 changed files with 53 additions and 16 deletions
+17
View File
@@ -3,6 +3,23 @@ Flask-Security Changelog
Here you can see the full list of changes between each Flask-Security release. Here you can see the full list of changes between each Flask-Security release.
Version 1.6.7
-------------
Released July 11th 2013
- Made password length form error message configurable
- Fixed email confirmation bug that prevented logged in users from confirming their email
Version 1.6.6
-------------
Released June 28th 2013
- Fixed dependency versions
Version 1.6.5 Version 1.6.5
------------- -------------
+1 -1
View File
@@ -9,7 +9,7 @@
<ul> <ul>
<li><a href="http://pypi.python.org/pypi/Flask-Security">Flask-Security @ PyPI</a></li> <li><a href="http://pypi.python.org/pypi/Flask-Security">Flask-Security @ PyPI</a></li>
<li><a href="http://github.com/mattupstate/flask-security">Flask-Security @ github</a></li> <li><a href="http://github.com/mattupstate/flask-security">Flask-Security @ github</a></li>
<li><a href="http://github.com/jfinkels/flask-security/issues">Issue Tracker</a></li> <li><a href="http://github.com/mattupstate/flask-security/issues">Issue Tracker</a></li>
</ul> </ul>
<ul> <ul>
<li><a href="http://pypi.python.org/pypi/Flask-Social">Flask-Social</a></li> <li><a href="http://pypi.python.org/pypi/Flask-Social">Flask-Social</a></li>
+1 -1
View File
@@ -49,7 +49,7 @@ copyright = u'2012, Matt Wright'
# built documents. # built documents.
# #
# The short X.Y version. # The short X.Y version.
version = '1.6.5' version = '1.6.7'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = version release = version
+1 -1
View File
@@ -10,7 +10,7 @@
:license: MIT, see LICENSE for more details. :license: MIT, see LICENSE for more details.
""" """
__version__ = '1.6.5' __version__ = '1.6.7'
from .core import Security, RoleMixin, UserMixin, AnonymousUser, current_user from .core import Security, RoleMixin, UserMixin, AnonymousUser, current_user
from .datastore import SQLAlchemyUserDatastore, MongoEngineUserDatastore, PeeweeUserDatastore from .datastore import SQLAlchemyUserDatastore, MongoEngineUserDatastore, PeeweeUserDatastore
+1
View File
@@ -110,6 +110,7 @@ _default_messages = {
'EMAIL_NOT_PROVIDED': ('Email not provided', 'error'), 'EMAIL_NOT_PROVIDED': ('Email not provided', 'error'),
'INVALID_EMAIL_ADDRESS': ('Invalid email address', 'error'), 'INVALID_EMAIL_ADDRESS': ('Invalid email address', 'error'),
'PASSWORD_NOT_PROVIDED': ('Password not provided', 'error'), 'PASSWORD_NOT_PROVIDED': ('Password not provided', 'error'),
'PASSWORD_INVALID_LENGTH': ('Password must be at least 6 characters', 'error'),
'USER_DOES_NOT_EXIST': ('Specified user does not exist', 'error'), 'USER_DOES_NOT_EXIST': ('Specified user does not exist', 'error'),
'INVALID_PASSWORD': ('Invalid password', 'error'), 'INVALID_PASSWORD': ('Invalid password', 'error'),
'PASSWORDLESS_LOGIN_SUCCESSFUL': ('You have successfuly logged in.', 'success'), 'PASSWORDLESS_LOGIN_SUCCESSFUL': ('You have successfuly logged in.', 'success'),
+3 -4
View File
@@ -69,6 +69,7 @@ class Length(ValidatorMixin, wtf.Length):
email_required = Required(message='EMAIL_NOT_PROVIDED') email_required = Required(message='EMAIL_NOT_PROVIDED')
email_validator = Email(message='INVALID_EMAIL_ADDRESS') email_validator = Email(message='INVALID_EMAIL_ADDRESS')
password_required = Required(message='PASSWORD_NOT_PROVIDED') password_required = Required(message='PASSWORD_NOT_PROVIDED')
password_length = Length(min=6, max=128, message='PASSWORD_INVALID_LENGTH')
def get_form_field_label(key): def get_form_field_label(key):
@@ -122,8 +123,7 @@ class PasswordFormMixin():
class NewPasswordFormMixin(): class NewPasswordFormMixin():
password = PasswordField(get_form_field_label('password'), password = PasswordField(get_form_field_label('password'),
validators=[password_required, validators=[password_required, password_length])
Length(min=6, max=128)])
class PasswordConfirmFormMixin(): class PasswordConfirmFormMixin():
@@ -256,8 +256,7 @@ class ChangePasswordForm(Form, PasswordFormMixin):
"""The default change password form""" """The default change password form"""
new_password = PasswordField(get_form_field_label('new_password'), new_password = PasswordField(get_form_field_label('new_password'),
validators=[password_required, validators=[password_required, password_length])
Length(min=6, max=128)])
new_password_confirm = PasswordField(get_form_field_label('retype_password'), new_password_confirm = PasswordField(get_form_field_label('retype_password'),
validators=[EqualTo('new_password', message='RETYPE_PASSWORD_MISMATCH')]) validators=[EqualTo('new_password', message='RETYPE_PASSWORD_MISMATCH')])
+4 -2
View File
@@ -200,7 +200,6 @@ def send_confirmation():
**_ctx('send_confirmation')) **_ctx('send_confirmation'))
@anonymous_user_required
def confirm_email(token): def confirm_email(token):
"""View function which handles a email confirmation request.""" """View function which handles a email confirmation request."""
@@ -217,8 +216,11 @@ def confirm_email(token):
return redirect(get_url(_security.confirm_error_view) or return redirect(get_url(_security.confirm_error_view) or
url_for('send_confirmation')) url_for('send_confirmation'))
if user != current_user:
logout_user()
login_user(user)
confirm_user(user) confirm_user(user)
login_user(user)
after_this_request(_commit) after_this_request(_commit)
do_flash(*get_message('EMAIL_CONFIRMED')) do_flash(*get_message('EMAIL_CONFIRMED'))
+5 -5
View File
@@ -20,7 +20,7 @@ from setuptools import setup
setup( setup(
name='Flask-Security', name='Flask-Security',
version='1.6.5', version='1.6.7',
url='https://github.com/mattupstate/flask-security', url='https://github.com/mattupstate/flask-security',
license='MIT', license='MIT',
author='Matt Wright', author='Matt Wright',
@@ -35,10 +35,10 @@ setup(
platforms='any', platforms='any',
install_requires=[ install_requires=[
'Flask>=0.9', 'Flask>=0.9',
'Flask-Login==0.2.3', 'Flask-Login>=0.2.3',
'Flask-Mail==0.7.3', 'Flask-Mail>=0.7.3',
'Flask-Principal==0.3.3', 'Flask-Principal>=0.3.3',
'Flask-WTF==0.8', 'Flask-WTF>=0.8',
'itsdangerous>=0.17', 'itsdangerous>=0.17',
'passlib>=1.6.1', 'passlib>=1.6.1',
], ],
+19 -1
View File
@@ -336,6 +336,24 @@ class LoginWithoutImmediateConfirmTests(SecurityTest):
r = self._post('/register', data=data, follow_redirects=True) r = self._post('/register', data=data, follow_redirects=True)
self.assertIn(e, r.data) self.assertIn(e, r.data)
def test_confirm_email_of_user_different_than_current_user(self):
e1 = 'dude@lp.com'
e2 = 'lady@lp.com'
with capture_registrations() as registrations:
self.register(e1)
self.register(e2)
token1 = registrations[0]['confirm_token']
token2 = registrations[1]['confirm_token']
self.client.get('/confirm/' + token1, follow_redirects=True)
self.client.get('/logout')
self.authenticate(email=e1)
r = self.client.get('/confirm/' + token2, follow_redirects=True)
msg = self.app.config['SECURITY_MSG_EMAIL_CONFIRMED'][0]
self.assertIn(msg, r.data)
self.assertIn('Hello %s' % e2, r.data)
class RecoverableTests(SecurityTest): class RecoverableTests(SecurityTest):
@@ -459,7 +477,7 @@ class ChangePasswordTest(SecurityTest):
'new_password_confirm': 'a' 'new_password_confirm': 'a'
}, follow_redirects=True) }, follow_redirects=True)
self.assertNotIn('You successfully changed your password', r.data) self.assertNotIn('You successfully changed your password', r.data)
self.assertIn('Field must be between', r.data) self.assertIn('Password must be at least 6 characters', r.data)
def test_change_password_success(self): def test_change_password_success(self):
self.authenticate() self.authenticate()