You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by je...@apache.org on 2015/02/24 12:48:31 UTC
[37/50] [abbrv] allura git commit: [#7786] Invalidate pwd reset
tokens after email/password change
[#7786] Invalidate pwd reset tokens after email/password change
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/b9225b8e
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/b9225b8e
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/b9225b8e
Branch: refs/heads/ib/7827
Commit: b9225b8e03c621ba07b63355d07f4b2c9cc71c14
Parents: 2d9bcf0
Author: Heith Seewald <hs...@slashdotmedia.com>
Authored: Wed Feb 4 08:16:17 2015 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Thu Feb 19 16:21:54 2015 +0000
----------------------------------------------------------------------
Allura/allura/controllers/auth.py | 10 +-
Allura/allura/tests/functional/test_auth.py | 117 +++++++++++++++++++++++
2 files changed, 126 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/b9225b8e/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 2183032..0bfe966 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -165,7 +165,7 @@ class AuthController(BaseController):
raise wexc.HTTPNotFound()
user = self._validate_hash(hash)
user.set_password(pw)
- user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='')
+ user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='') # Clear password reset token
h.auditlog_user('Password changed (through recovery process)', user=user)
flash('Password changed')
redirect('/auth/?return_to=/') # otherwise the default return_to would be the forgotten_password referrer page
@@ -409,6 +409,8 @@ class AuthController(BaseController):
expired_user = M.User.query.get(username=expired_username) if expired_username else None
ap.set_password(expired_user or c.user, kw['oldpw'], kw['pw'])
expired_user.set_tool_data('allura', pwd_reset_preserve_session=session.id)
+ expired_user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='') # Clear password reset token
+
except wexc.HTTPUnauthorized:
flash('Incorrect password', 'error')
redirect(tg.url('/auth/pwd_expired', dict(return_to=return_to)))
@@ -471,11 +473,13 @@ class PreferencesController(BaseController):
# clear it now, a new one will get set below
user.set_pref('email_address', None)
primary_addr = None
+ user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='')
h.auditlog_user('Email address deleted: %s', user.email_addresses[i], user=user)
del user.email_addresses[i]
if obj:
obj.delete()
if new_addr.get('claim') or new_addr.get('addr'):
+ user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='') # Clear password reset token
claimed_emails_limit = config.get('user_prefs.maximum_claimed_emails', None)
if claimed_emails_limit and len(user.email_addresses) >= int(claimed_emails_limit):
flash('You cannot claim more than %s email addresses.' % claimed_emails_limit, 'error')
@@ -505,6 +509,7 @@ class PreferencesController(BaseController):
em.send_claim_attempt()
if not admin:
+ user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='')
flash('A verification email has been sent. Please check your email and click to confirm.')
h.auditlog_user('New email address: %s', new_addr['addr'], user=user)
@@ -525,6 +530,7 @@ class PreferencesController(BaseController):
primary_addr,
user=user)
user.set_pref('email_address', primary_addr)
+ user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='')
@h.vardec
@expose()
@@ -561,6 +567,8 @@ class PreferencesController(BaseController):
try:
ap.set_password(c.user, kw['oldpw'], kw['pw'])
c.user.set_tool_data('allura', pwd_reset_preserve_session=session.id)
+ c.user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='')
+
except wexc.HTTPUnauthorized:
flash('Incorrect password', 'error')
redirect('.')
http://git-wip-us.apache.org/repos/asf/allura/blob/b9225b8e/Allura/allura/tests/functional/test_auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_auth.py b/Allura/allura/tests/functional/test_auth.py
index eacabd0..f288b0b 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -324,6 +324,90 @@ class TestAuth(TestController):
email = M.EmailAddress.find(dict(email=email_address, claimed_by_user_id=user._id)).first()
assert not email.confirmed
+ @staticmethod
+ def _create_password_reset_hash():
+ """ Generates a password reset token for a given user.
+
+ :return: User object
+ :rtype: User
+ """
+ # test-user claimed email address
+ user = M.User.by_username('test-admin')
+ user.set_tool_data('AuthPasswordReset',
+ hash="generated_hash_value",
+ hash_expiry="04-08-2020")
+ hash = user.get_tool_data('AuthPasswordReset', 'hash')
+ session(user).flush(user)
+
+ hash_expiry = user.get_tool_data('AuthPasswordReset', 'hash_expiry')
+ assert_equal(hash, 'generated_hash_value')
+ assert_equal(hash_expiry, '04-08-2020')
+ return user
+
+ def test_token_generator(self):
+ """ Generates new token invalidation tests.
+
+ The tests cover: changing, claiming, updating, removing email addresses.
+ :returns: email_change_invalidates_token
+ """
+ _params = [{'new_addr.addr': 'test_abcd@domain.net', # Change primary address
+ 'primary_addr': 'test@example.com', },
+ {'new_addr.addr': 'test@example.com', # Claim new address
+ 'new_addr.claim': 'Claim Address',
+ 'primary_addr': 'test-admin@users.localhost',
+ 'password': 'foo',
+ 'preferences.email_format': 'plain'},
+ {'addr-1.ord': '1', # remove test-admin@users.localhost
+ 'addr-1.delete': 'on',
+ 'addr-2.ord': '2',
+ 'new_addr.addr': '',
+ 'primary_addr': 'test-admin@users.localhost',
+ 'password': 'foo',
+ 'preferences.email_format': 'plain'},
+ {'addr-1.ord': '1', # Remove email
+ 'addr-2.ord': '2',
+ 'addr-2.delete': 'on',
+ 'new_addr.addr': '',
+ 'primary_addr': 'test-admin@users.localhost'}]
+
+ for param in _params:
+ yield self.email_change_invalidates_token, param
+
+ def email_change_invalidates_token(self, change_params):
+ user = self._create_password_reset_hash()
+ session(user).flush(user)
+
+ self.app.post('/auth/preferences/update_emails',
+ extra_environ=dict(username='test-admin'),
+ params=change_params)
+
+ u = M.User.by_username('test-admin')
+ print(u.get_tool_data('AuthPasswordReset', 'hash'))
+ assert_equal(u.get_tool_data('AuthPasswordReset', 'hash'), '')
+ assert_equal(u.get_tool_data('AuthPasswordReset', 'hash_expiry'), '')
+
+ @td.with_user_project('test-admin')
+ def test_change_password(self):
+ # Get and assert user with password reset token.
+ user = self._create_password_reset_hash()
+ old_pass = user.get_pref('password')
+
+ # Change password
+ self.app.post('/auth/preferences/change_password',
+ extra_environ=dict(username='test-admin'),
+ params={
+ 'oldpw': 'foo',
+ 'pw': 'asdfasdf',
+ 'pw2': 'asdfasdf',
+ })
+
+ # Confirm password was changed.
+ assert_not_equal(old_pass, user.get_pref('password'))
+
+ # Confirm any existing tokens were reset.
+ assert_equal(user.get_tool_data('AuthPasswordReset', 'hash'), '')
+ assert_equal(user.get_tool_data('AuthPasswordReset', 'hash_expiry'), '')
+
@td.with_user_project('test-admin')
def test_prefs(self):
r = self.app.get('/auth/preferences/',
@@ -1619,6 +1703,39 @@ class TestPasswordExpire(TestController):
r = self.login(pwd='foo')
assert_in('Invalid login', r)
+ def test_expired_pwd_change_invalidates_token(self):
+ self.set_expire_for_user()
+ with h.push_config(config, **{'auth.pwdexpire.days': 90}):
+ r = self.login()
+ assert_true(self.expired(r))
+ self.assert_redirects()
+ user = M.User.by_username('test-user')
+ user.set_tool_data('AuthPasswordReset',
+ hash="generated_hash_value",
+ hash_expiry="04-08-2020")
+ hash = user.get_tool_data('AuthPasswordReset', 'hash')
+ hash_expiry = user.get_tool_data('AuthPasswordReset', 'hash_expiry')
+ assert_equal(hash, 'generated_hash_value')
+ assert_equal(hash_expiry, '04-08-2020')
+ session(user).flush(user)
+
+ # Change expired password
+ r = self.app.get('/auth/pwd_expired', extra_environ={'username': 'test-user'})
+ f = r.forms[0]
+ f['oldpw'] = 'foo'
+ f['pw'] = 'qwerty'
+ f['pw2'] = 'qwerty'
+ r = f.submit(extra_environ={'username': 'test-user'}, status=302)
+ assert_equal(r.location, 'http://localhost/')
+
+ user = M.User.by_username('test-user')
+ hash = user.get_tool_data('AuthPasswordReset', 'hash')
+ hash_expiry = user.get_tool_data('AuthPasswordReset', 'hash_expiry')
+
+ assert_equal(hash, '')
+ assert_equal(hash_expiry, '')
+
+
def check_validation(self, oldpw, pw, pw2):
user = M.User.by_username('test-user')
old_update_time = user.last_password_updated