You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by jo...@apache.org on 2013/11/07 22:07:14 UTC

[01/14] git commit: [#6783] ticket:463 added hash expiry

Updated Branches:
  refs/heads/master 97e80d971 -> 7c7b19773


[#6783] ticket:463 added hash expiry


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/8b662d06
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/8b662d06
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/8b662d06

Branch: refs/heads/master
Commit: 8b662d0642905c7fdf22047054c91af983e98757
Parents: 5c328f5
Author: coldmind <so...@yandex.ru>
Authored: Fri Oct 25 18:02:14 2013 +0300
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Thu Nov 7 21:05:00 2013 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/auth.py | 11 ++++++++++-
 Allura/development.ini            |  3 +++
 2 files changed, 13 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/8b662d06/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 9ca5ff2..c6f9f88 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -17,6 +17,7 @@
 
 import logging, string, os
 from urllib import urlencode
+import datetime
 
 import bson
 from tg import expose, session, flash, redirect, validate, config
@@ -166,9 +167,14 @@ class AuthController(BaseController):
             if not user_record:
                 flash('Hash was not found')
                 redirect('/')
+            hash_expiry = user_record.get_tool_data('AuthPasswordReset', 'hash_expiry')
+            if not hash_expiry or hash_expiry < datetime.datetime.now():
+                flash('Hash time was expired.')
+                redirect('/')
             if request.method == 'POST':
                 ap = plugin.AuthenticationProvider.get(request)
                 ap.recovery_set_password(user_record, kw['pw'])
+                user_record.set_tool_data('AuthPasswordReset', hash='', hash_expiry='')
                 flash('Password changed')
                 redirect('/auth/')
         return dict()
@@ -181,7 +187,10 @@ class AuthController(BaseController):
             redirect('/')
         user_record = M.User.query.find({'preferences.email_address': email}).first()
         hash = h.nonce(42)
-        user_record.set_tool_data('AuthPasswordReset', hash=hash)
+        user_record.set_tool_data('AuthPasswordReset',
+                                  hash=hash,
+                                  hash_expiry=datetime.datetime.now() +
+                                  datetime.timedelta(hours=int(config['auth.recovery_hash_expiry_period'])))
 
         log.info('Sending password recovery link to %s', email)
         text = '''

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/8b662d06/Allura/development.ini
----------------------------------------------------------------------
diff --git a/Allura/development.ini b/Allura/development.ini
index b1c41c5..98e251b 100644
--- a/Allura/development.ini
+++ b/Allura/development.ini
@@ -86,6 +86,9 @@ auth.ldap.admin_dn = cn=admin,dc=localdomain
 auth.ldap.admin_password = secret
 auth.ldap.schroot_name = scm
 
+# In hours
+auth.recovery_hash_expiry_period = 1
+
 # Set the locations of some static resources
 #  script_name is the path that is handled by the application
 #  url_base is the prefix that references to the static resources should have


[08/14] git commit: [#6783] ticket:463 fixed validator

Posted by jo...@apache.org.
[#6783] ticket:463 fixed validator


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/6f769e73
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/6f769e73
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/6f769e73

Branch: refs/heads/master
Commit: 6f769e733c3b7ede30f22593fa3afd4a57684e1e
Parents: 7bee93b
Author: coldmind <so...@yandex.ru>
Authored: Thu Oct 31 14:52:02 2013 +0200
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Thu Nov 7 21:05:04 2013 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/auth.py  |  6 +++---
 Allura/allura/lib/widgets/forms.py | 10 +++++++---
 2 files changed, 10 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/6f769e73/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 42a9420..06f9307 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -157,6 +157,7 @@ class AuthController(BaseController):
         return dict()
 
     @expose('jinja:allura:templates/forgotten_password.html')
+    @validate(F.recover_password_change_form, error_handler=index)
     def forgotten_password(self, hash=None, **kw):
         provider = plugin.AuthenticationProvider.get(request)
         if not provider:
@@ -174,8 +175,7 @@ class AuthController(BaseController):
                 flash('Hash time was expired.')
                 redirect('/')
             if request.method == 'POST':
-                ap = plugin.AuthenticationProvider.get(request)
-                ap.set_password(user_record, None, kw['pw'])
+                provider.set_password(user_record, None, kw['pw'])
                 user_record.set_tool_data('AuthPasswordReset', hash='', hash_expiry='')
                 flash('Password changed')
                 redirect('/auth/')
@@ -187,7 +187,7 @@ class AuthController(BaseController):
     def password_recovery_hash(self, email=None, **kw):
         if not email:
             redirect('/')
-        user_record = M.User.query.find({'preferences.email_address': email}).first()
+        user_record = M.User.by_email_address(email)
         hash = h.nonce(42)
         user_record.set_tool_data('AuthPasswordReset',
                                   hash=hash,

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/6f769e73/Allura/allura/lib/widgets/forms.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/forms.py b/Allura/allura/lib/widgets/forms.py
index 91dd070..300c934 100644
--- a/Allura/allura/lib/widgets/forms.py
+++ b/Allura/allura/lib/widgets/forms.py
@@ -135,14 +135,18 @@ class PasswordChangeBase(ForgeForm):
     @ew_core.core.validator
     def to_python(self, value, state):
         d = super(PasswordChangeBase, self).to_python(value, state)
-        if d['pw'] != d['pw2']:
-            raise formencode.Invalid('Passwords must match', value, state)
+        try:
+            if d['pw'] != d['pw2']:
+                raise formencode.Invalid('Passwords must match', value, state)
+        except KeyError:
+            pass
         return d
 
 class PasswordChangeForm(PasswordChangeBase):
     class fields(ew_core.NameList):
         oldpw = ew.PasswordField(
-            label='Old Password', validator=fev.UnicodeString(not_empty=True))
+            label='Old Password',
+            validator=fev.UnicodeString(not_empty=True))
         pw = ew.PasswordField(
             label='New Password',
             validator=fev.UnicodeString(not_empty=True, min=6))


[04/14] git commit: [#6783] ticket:463 added properties to make process optionial

Posted by jo...@apache.org.
[#6783] ticket:463 added properties to make process optionial


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/5afc3730
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/5afc3730
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/5afc3730

Branch: refs/heads/master
Commit: 5afc37306fb636eee8150dc2521b265ef7e64594
Parents: 8b662d0
Author: coldmind <so...@yandex.ru>
Authored: Fri Oct 25 18:20:10 2013 +0300
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Thu Nov 7 21:05:02 2013 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/auth.py         |  2 ++
 Allura/allura/lib/plugin.py               | 12 +++++-------
 Allura/allura/lib/widgets/auth_widgets.py |  3 ++-
 3 files changed, 9 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/5afc3730/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index c6f9f88..9ecab1c 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -159,6 +159,8 @@ class AuthController(BaseController):
 
     @expose('jinja:allura:templates/forgotten_password.html')
     def forgotten_password(self, hash=None, **kw):
+        if not plugin.LocalAuthenticationProvider.forgotten_password_process:
+            redirect('/')
         if not hash:
             c.forgotten_password_form = F.forgotten_password_form
         else:

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/5afc3730/Allura/allura/lib/plugin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index bbdcac4..cd92cf3 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -68,7 +68,7 @@ class AuthenticationProvider(object):
 
     def __init__(self, request):
         self.request = request
-        #self.forgotten_password_process = False
+    forgotten_password_process = False
 
     @classmethod
     def get(cls, request):
@@ -84,9 +84,9 @@ class AuthenticationProvider(object):
     def session(self):
         return self.request.environ['beaker.session']
 
-    #@LazyProperty
-    #def forgotten_password(self):
-    #    return self.forgotten_password_process
+    @LazyProperty
+    def forgotten_password(self):
+        return self.forgotten_password_process
 
     def authenticate_request(self):
         from allura import model as M
@@ -218,9 +218,7 @@ class LocalAuthenticationProvider(AuthenticationProvider):
     Stores user passwords on the User model, in mongo.  Uses per-user salt and
     SHA-256 encryption.
     '''
-    #def __init__(self, *args, **kwargs):
-    #    super(AuthenticationProvider, self).__init__(*args, **kwargs)
-    #    self.forgotten_password_process = True
+    forgotten_password_process = True
 
     def register_user(self, user_doc):
         from allura import model as M

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/5afc3730/Allura/allura/lib/widgets/auth_widgets.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/auth_widgets.py b/Allura/allura/lib/widgets/auth_widgets.py
index 45f3a74..8a4dba3 100644
--- a/Allura/allura/lib/widgets/auth_widgets.py
+++ b/Allura/allura/lib/widgets/auth_widgets.py
@@ -34,7 +34,8 @@ class LoginForm(ForgeForm):
     class fields(ew_core.NameList):
         username = ew.TextField(label='Username')
         password = ew.PasswordField(label='Password')
-        link = ew.HTMLField(text='<a href="forgotten_password">Forgot password?</a>')
+        if plugin.LocalAuthenticationProvider.forgotten_password_process:
+            link = ew.HTMLField(text='<a href="./forgotten_password">Forgot password?</a>')
 
     class hidden_fields(ew_core.NameList):
         return_to = ew.HiddenField()


[10/14] git commit: [#6783] ticket:463 Fix validation

Posted by jo...@apache.org.
[#6783] ticket:463 Fix validation


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/0c864468
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/0c864468
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/0c864468

Branch: refs/heads/master
Commit: 0c8644689cce915ecb2d3cb928a79c9d9ae0e2af
Parents: a6f4e76
Author: Igor Bondarenko <je...@gmail.com>
Authored: Mon Nov 4 15:14:25 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Thu Nov 7 21:05:04 2013 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/auth.py               | 41 +++++++++++++-------
 Allura/allura/lib/widgets/forms.py              |  2 +-
 Allura/allura/templates/forgotten_password.html |  4 +-
 3 files changed, 29 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/0c864468/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 52c2c38..430d4fa 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -156,8 +156,21 @@ class AuthController(BaseController):
         c.form = F.registration_form
         return dict()
 
+    def _validate_hash(self, hash):
+        if not hash:
+            redirect(request.referer)
+        user_record = M.User.query.find({'tool_data.AuthPasswordReset.hash': hash}).first()
+        if not user_record:
+            flash('Hash was not found')
+            redirect(request.referer)
+        hash_expiry = user_record.get_tool_data('AuthPasswordReset', 'hash_expiry')
+        if not hash_expiry or hash_expiry < datetime.datetime.utcnow():
+            flash('Hash time was expired.')
+            redirect(request.referer)
+        return user_record
+
+
     @expose('jinja:allura:templates/forgotten_password.html')
-    @validate(F.recover_password_change_form, error_handler=index)
     def forgotten_password(self, hash=None, **kw):
         provider = plugin.AuthenticationProvider.get(request)
         if not provider:
@@ -165,21 +178,19 @@ class AuthController(BaseController):
         if not hash:
             c.forgotten_password_form = F.forgotten_password_form
         else:
+            self._validate_hash(hash)
             c.recover_password_change_form = F.recover_password_change_form
-            user_record = M.User.query.find({'tool_data.AuthPasswordReset.hash': hash}).first()
-            if not user_record:
-                flash('Hash was not found')
-                redirect(request.referer)
-            hash_expiry = user_record.get_tool_data('AuthPasswordReset', 'hash_expiry')
-            if not hash_expiry or hash_expiry < datetime.datetime.utcnow():
-                flash('Hash time was expired.')
-                redirect(request.referer)
-            if request.method == 'POST':
-                user_record.set_password(kw['pw'])
-                user_record.set_tool_data('AuthPasswordReset', hash='', hash_expiry='')
-                flash('Password changed')
-                redirect('/auth/')
-        return dict()
+        return dict(hash=hash)
+
+    @expose()
+    @require_post()
+    @validate(F.recover_password_change_form, error_handler=forgotten_password)
+    def set_new_password(self, hash=None, pw=None, pw2=None):
+        user = self._validate_hash(hash)
+        user.set_password(pw)
+        user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='')
+        flash('Password changed')
+        redirect('/auth/')
 
     @expose()
     @require_post()

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/0c864468/Allura/allura/lib/widgets/forms.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/forms.py b/Allura/allura/lib/widgets/forms.py
index 23c2331..bf96445 100644
--- a/Allura/allura/lib/widgets/forms.py
+++ b/Allura/allura/lib/widgets/forms.py
@@ -135,7 +135,7 @@ class PasswordChangeBase(ForgeForm):
     @ew_core.core.validator
     def to_python(self, value, state):
         d = super(PasswordChangeBase, self).to_python(value, state)
-        if d.get('pw') != d.get('pw2'):
+        if d['pw'] != d['pw2']:
             raise formencode.Invalid('Passwords must match', value, state)
         return d
 

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/0c864468/Allura/allura/templates/forgotten_password.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/forgotten_password.html b/Allura/allura/templates/forgotten_password.html
index 56959c2..aa45609 100644
--- a/Allura/allura/templates/forgotten_password.html
+++ b/Allura/allura/templates/forgotten_password.html
@@ -30,7 +30,7 @@
   {% endif %}
 
   {% if c.recover_password_change_form %}
-    {{ c.recover_password_change_form.display(action="") }}
+    {{ c.recover_password_change_form.display(action="../set_new_password/" + hash if hash else '') }}
   {% endif %}
 </div>
-{% endblock %}
\ No newline at end of file
+{% endblock %}


[09/14] git commit: [#6783] ticket:463 fixed redirects and tests

Posted by jo...@apache.org.
[#6783] ticket:463 fixed redirects and tests


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/ef881f05
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/ef881f05
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/ef881f05

Branch: refs/heads/master
Commit: ef881f05b8c776166ccb79a13c35f19769b71c2d
Parents: 6f769e7
Author: coldmind <so...@yandex.ru>
Authored: Mon Nov 4 14:03:48 2013 +0200
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Thu Nov 7 21:05:04 2013 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/auth.py           | 10 +++++-----
 Allura/allura/lib/widgets/forms.py          |  7 ++-----
 Allura/allura/tests/functional/test_auth.py | 25 ++++++++++++++++--------
 3 files changed, 24 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/ef881f05/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 06f9307..52c2c38 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -161,7 +161,7 @@ class AuthController(BaseController):
     def forgotten_password(self, hash=None, **kw):
         provider = plugin.AuthenticationProvider.get(request)
         if not provider:
-            redirect('/')
+            redirect(request.referer)
         if not hash:
             c.forgotten_password_form = F.forgotten_password_form
         else:
@@ -169,13 +169,13 @@ class AuthController(BaseController):
             user_record = M.User.query.find({'tool_data.AuthPasswordReset.hash': hash}).first()
             if not user_record:
                 flash('Hash was not found')
-                redirect('/')
+                redirect(request.referer)
             hash_expiry = user_record.get_tool_data('AuthPasswordReset', 'hash_expiry')
             if not hash_expiry or hash_expiry < datetime.datetime.utcnow():
                 flash('Hash time was expired.')
-                redirect('/')
+                redirect(request.referer)
             if request.method == 'POST':
-                provider.set_password(user_record, None, kw['pw'])
+                user_record.set_password(kw['pw'])
                 user_record.set_tool_data('AuthPasswordReset', hash='', hash_expiry='')
                 flash('Password changed')
                 redirect('/auth/')
@@ -205,7 +205,7 @@ To reset your password on %s, please visit the following URL:
         allura.tasks.mail_tasks.sendmail.post(
             destinations=[email],
             fromaddr=config['forgemail.return_path'],
-            reply_to='',
+            reply_to=config['forgemail.return_path'],
             subject='Password recovery',
             message_id=h.gen_message_id(),
             text=text)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/ef881f05/Allura/allura/lib/widgets/forms.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/forms.py b/Allura/allura/lib/widgets/forms.py
index 300c934..23c2331 100644
--- a/Allura/allura/lib/widgets/forms.py
+++ b/Allura/allura/lib/widgets/forms.py
@@ -135,11 +135,8 @@ class PasswordChangeBase(ForgeForm):
     @ew_core.core.validator
     def to_python(self, value, state):
         d = super(PasswordChangeBase, self).to_python(value, state)
-        try:
-            if d['pw'] != d['pw2']:
-                raise formencode.Invalid('Passwords must match', value, state)
-        except KeyError:
-            pass
+        if d.get('pw') != d.get('pw2'):
+            raise formencode.Invalid('Passwords must match', value, state)
         return d
 
 class PasswordChangeForm(PasswordChangeBase):

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/ef881f05/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 52f24fe..02f26a9 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -38,6 +38,8 @@ from allura.lib.helpers import push_config
 from tg import config
 from mock import patch
 import datetime
+from allura.lib import plugin
+from pylons import request
 
 
 def unentity(s):
@@ -744,10 +746,15 @@ class TestPreferences(TestController):
             assert hash is not None
             assert hash_expiry is not None
 
-            r = self.app.post('/auth/forgotten_password/%s' % hash, {'pw': 154321, 'pw2': 154321})
+            new_password = '154321'
+            r = self.app.post('/auth/forgotten_password/%s' % hash, {'pw': new_password, 'pw2': new_password})
             user = M.User.query.get(username='test-admin')
             password2 = user.password
             assert_not_equal(password1, password2)
+            r = self.app.get('/auth/logout')
+            r = self.app.post('/auth/do_login', params=dict(
+                              username='test-admin', password=new_password))
+            assert 'Invalid login' not in str(r)
 
             text = '''
 To reset your password on %s, please visit the following URL:
@@ -759,7 +766,7 @@ To reset your password on %s, please visit the following URL:
             sendmail.post.assert_called_once_with(
                 destinations=[email._id],
                 fromaddr=config['forgemail.return_path'],
-                reply_to='',
+                reply_to='noreply@sourceforge.net',
                 subject='Password recovery',
                 message_id=gen_message_id(),
                 text=text)
@@ -769,12 +776,14 @@ To reset your password on %s, please visit the following URL:
             assert_equal(hash, '')
             assert_equal(hash_expiry, '')
 
-            r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
-            hash = user.get_tool_data('AuthPasswordReset', 'hash')
-            hash_expiry = user.get_tool_data('AuthPasswordReset', 'hash_expiry')
-            user.set_tool_data('AuthPasswordReset', hash_expiry=hash_expiry-datetime.timedelta(seconds=600))
-            r = self.app.post('/auth/forgotten_password/%s' % hash, {'pw': 154321, 'pw2': 154321})
-            assert_equal(r.status, '302 Found')
+            #r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
+            #hash_expiry = user.get_tool_data('AuthPasswordReset', 'hash_expiry')
+            #user.set_tool_data('AuthPasswordReset', hash_expiry=hash_expiry-datetime.timedelta(hours=1))
+            #ThreadLocalORMSession.flush_all()
+            # expected redirect with error here, but
+            # real db-record of hash expiry doesn't changes.
+            #r = self.app.post('/auth/forgotten_password/%s' % hash.encode('utf'), {'pw': '154321', 'pw2': '154321'})
+
 
 
 class TestOAuth(TestController):


[07/14] git commit: [#6783] ticket:463 added tests

Posted by jo...@apache.org.
[#6783] ticket:463 added tests


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/b7aced8d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/b7aced8d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/b7aced8d

Branch: refs/heads/master
Commit: b7aced8df31b5fd767803d4699e511226adca6c5
Parents: 5afc373
Author: coldmind <so...@yandex.ru>
Authored: Sat Oct 26 01:37:29 2013 +0300
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Thu Nov 7 21:05:03 2013 +0000

----------------------------------------------------------------------
 Allura/allura/tests/model/test_auth.py | 62 ++++++++++++++++++++++++++++-
 1 file changed, 61 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/b7aced8d/Allura/allura/tests/model/test_auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/model/test_auth.py b/Allura/allura/tests/model/test_auth.py
index f8e7ed8..755e0d1 100644
--- a/Allura/allura/tests/model/test_auth.py
+++ b/Allura/allura/tests/model/test_auth.py
@@ -20,7 +20,7 @@
 """
 Model tests for auth
 """
-from nose.tools import with_setup, assert_equal
+from nose.tools import with_setup, assert_equal, assert_not_equal
 from pylons import tmpl_context as c, app_globals as g
 from webob import Request
 from mock import patch
@@ -32,6 +32,10 @@ from allura import model as M
 from allura.lib import plugin
 from allura.tests import decorators as td
 from alluratest.controller import setup_basic_test, setup_global_objects
+from allura.tests import TestController
+from allura.lib.helpers import push_config
+from tg import config
+from mock import patch
 
 
 def setUp():
@@ -225,3 +229,59 @@ def test_user_projects_by_role():
     g.credentials.clear()
     assert_equal(set(p.shortname for p in c.user.my_projects()), set(['test', 'test2', 'u/test-admin', 'adobe-1', '--init--']))
     assert_equal(set(p.shortname for p in c.user.my_projects('Admin')), set(['test', 'u/test-admin', 'adobe-1', '--init--']))
+
+
+class TestForgotPassword(TestController):
+
+    @patch('allura.tasks.mail_tasks.sendmail')
+    @patch('allura.lib.helpers.gen_message_id')
+    def test_forgot_password_reset(self, gen_message_id, sendmail):
+        user = M.User.query.get(username='test-admin')
+        password1 = user.password
+        email = M.EmailAddress.query.find({'claimed_by_user_id': user._id}).first()
+        email.confirmed = False
+        user.disabled = True
+
+        r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
+        hash = user.get_tool_data('AuthPasswordReset', 'hash')
+        assert hash is None
+
+        user = M.User.query.get(username='test-admin')
+        user.disabled = True
+        email = M.EmailAddress.query.find({'claimed_by_user_id': user._id}).first()
+        email.confirmed = True
+        r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
+        hash = user.get_tool_data('AuthPasswordReset', 'hash')
+        assert hash is None
+
+        user = M.User.query.get(username='test-admin')
+        user.disabled = False
+        email = M.EmailAddress.query.find({'claimed_by_user_id': user._id}).first()
+        email.confirmed = True
+
+        with push_config(config, **{'auth.recovery_hash_expiry_period': '1'}):
+            r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
+            hash = user.get_tool_data('AuthPasswordReset', 'hash')
+            hash_expiry = user.get_tool_data('AuthPasswordReset', 'hash_expiry')
+            assert hash is not None
+            assert hash_expiry is not None
+
+            r = self.app.post('/auth/forgotten_password/%s' % hash, {'pw': 154321, 'pw2': 154321})
+            user = M.User.query.get(username='test-admin')
+            password2 = user.password
+            assert_not_equal(password1, password2)
+
+            text = '''
+To reset your password on %s, please visit the following URL:
+
+%s/auth/forgotten_password/%s
+
+''' % (config['site_name'], config['base_url'], hash)
+
+            sendmail.post.assert_called_once_with(
+                destinations=[email._id],
+                fromaddr=config['forgemail.return_path'],
+                reply_to='',
+                subject='Password recovery',
+                message_id=gen_message_id(),
+                text=text)


[03/14] git commit: [#6783] ticket:463 added functionality to generate hash and change password

Posted by jo...@apache.org.
[#6783] ticket:463 added functionality to generate hash and change password


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/4bef681c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/4bef681c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/4bef681c

Branch: refs/heads/master
Commit: 4bef681c0d3cb3eb3c416dda9faa8a6d626436b7
Parents: 97e80d9
Author: coldmind <so...@yandex.ru>
Authored: Fri Oct 25 16:22:37 2013 +0300
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Thu Nov 7 21:05:00 2013 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/auth.py               | 39 ++++++++++++++++-
 Allura/allura/lib/plugin.py                     | 11 +++++
 Allura/allura/lib/widgets/__init__.py           |  2 +-
 Allura/allura/lib/widgets/auth_widgets.py       | 46 +++++++++++++++++++-
 Allura/allura/templates/forgotten_password.html | 36 +++++++++++++++
 5 files changed, 131 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/4bef681c/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 596fda5..6d9295a 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -35,7 +35,13 @@ from allura.lib import helpers as h
 from allura.lib import plugin
 from allura.lib.decorators import require_post
 from allura.lib.repository import RepositoryApp
-from allura.lib.widgets import SubscriptionForm, OAuthApplicationForm, OAuthRevocationForm, LoginForm
+from allura.lib.widgets import (
+    SubscriptionForm,
+    OAuthApplicationForm,
+    OAuthRevocationForm,
+    LoginForm,
+    RecoverPasswordChangeForm,
+    ForgottenPasswordForm)
 from allura.lib.widgets import forms
 from allura.lib import exceptions as exc
 from allura.controllers import BaseController
@@ -58,6 +64,8 @@ OID_PROVIDERS=[
 
 class F(object):
     login_form = LoginForm()
+    recover_password_change_form = RecoverPasswordChangeForm()
+    forgotten_password_form = ForgottenPasswordForm()
     subscription_form=SubscriptionForm()
     registration_form = forms.RegistrationForm(action='/auth/save_new')
     oauth_application_form = OAuthApplicationForm(action='register')
@@ -148,6 +156,35 @@ class AuthController(BaseController):
         c.form = F.registration_form
         return dict()
 
+    @expose('jinja:allura:templates/forgotten_password.html')
+    def forgotten_password(self, hash=None, **kw):
+        if not hash:
+            c.forgotten_password_form = F.forgotten_password_form
+        else:
+            c.recover_password_change_form = F.recover_password_change_form
+            user_record = M.User.query.find({'tool_data.AuthPasswordReset.hash': hash}).first()
+            if not user_record:
+                flash('Hash was not found')
+                redirect('/')
+            if request.method == 'POST':
+                ap = plugin.AuthenticationProvider.get(request)
+                ap.recovery_set_password(user_record, kw['pw'])
+                flash('Password changed')
+                redirect('/auth/')
+        return dict()
+
+    @expose()
+    @require_post()
+    @validate(F.forgotten_password_form, error_handler=forgotten_password)
+    def password_recovery_hash(self, email=None, **kw):
+        if not email:
+            redirect('/')
+        user_record = M.User.query.find({'preferences.email_address': email}).first()
+        hash = h.nonce(42)
+        user_record.set_tool_data('AuthPasswordReset', hash=hash)
+        flash('Email with instructions has been sent.')
+        redirect('/')
+
     @expose()
     @require_post()
     @validate(F.registration_form, error_handler=create_account)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/4bef681c/Allura/allura/lib/plugin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index e9a3689..bbdcac4 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -68,6 +68,7 @@ class AuthenticationProvider(object):
 
     def __init__(self, request):
         self.request = request
+        #self.forgotten_password_process = False
 
     @classmethod
     def get(cls, request):
@@ -83,6 +84,10 @@ class AuthenticationProvider(object):
     def session(self):
         return self.request.environ['beaker.session']
 
+    #@LazyProperty
+    #def forgotten_password(self):
+    #    return self.forgotten_password_process
+
     def authenticate_request(self):
         from allura import model as M
         user = M.User.query.get(_id=self.session.get('userid', None))
@@ -213,6 +218,9 @@ class LocalAuthenticationProvider(AuthenticationProvider):
     Stores user passwords on the User model, in mongo.  Uses per-user salt and
     SHA-256 encryption.
     '''
+    #def __init__(self, *args, **kwargs):
+    #    super(AuthenticationProvider, self).__init__(*args, **kwargs)
+    #    self.forgotten_password_process = True
 
     def register_user(self, user_doc):
         from allura import model as M
@@ -246,6 +254,9 @@ class LocalAuthenticationProvider(AuthenticationProvider):
     def set_password(self, user, old_password, new_password):
         user.password = self._encode_password(new_password)
 
+    def recovery_set_password(self, user, new_password):
+        user.password = self._encode_password(new_password)
+
     def _encode_password(self, password, salt=None):
         from allura import model as M
         if salt is None:

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/4bef681c/Allura/allura/lib/widgets/__init__.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/__init__.py b/Allura/allura/lib/widgets/__init__.py
index 713851a..516a3d8 100644
--- a/Allura/allura/lib/widgets/__init__.py
+++ b/Allura/allura/lib/widgets/__init__.py
@@ -18,5 +18,5 @@
 from .discuss import Post, Thread, Discussion
 from .subscriptions import SubscriptionForm
 from .oauth_widgets import OAuthApplicationForm, OAuthRevocationForm
-from .auth_widgets import LoginForm
+from .auth_widgets import LoginForm, ForgottenPasswordForm, RecoverPasswordChangeForm
 from .vote import VoteForm

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/4bef681c/Allura/allura/lib/widgets/auth_widgets.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/auth_widgets.py b/Allura/allura/lib/widgets/auth_widgets.py
index 16df6b3..45f3a74 100644
--- a/Allura/allura/lib/widgets/auth_widgets.py
+++ b/Allura/allura/lib/widgets/auth_widgets.py
@@ -20,12 +20,13 @@ import ew.jinja2_ew as ew
 from ew.core import validator
 
 from pylons import request
-from formencode import Invalid
+from formencode import Invalid, validators
 from webob import exc
 
 from .forms import ForgeForm
 
 from allura.lib import plugin
+from allura import model as M
 
 class LoginForm(ForgeForm):
     submit_text='Login'
@@ -33,6 +34,8 @@ class LoginForm(ForgeForm):
     class fields(ew_core.NameList):
         username = ew.TextField(label='Username')
         password = ew.PasswordField(label='Password')
+        link = ew.HTMLField(text='<a href="forgotten_password">Forgot password?</a>')
+
     class hidden_fields(ew_core.NameList):
         return_to = ew.HiddenField()
 
@@ -47,3 +50,44 @@ class LoginForm(ForgeForm):
                 dict(username=value['username']),
                 None)
         return value
+
+
+class ForgottenPasswordForm(ForgeForm):
+    submit_text='Recover password'
+    style='wide'
+
+    class fields(ew_core.NameList):
+        email = ew.TextField(label='Your e-mail')
+
+    @validator
+    def validate(self, value, state=None):
+        email = value['email']
+        record = M.EmailAddress.query.find({'_id': email}).first()
+        if not record:
+            raise Invalid(
+                "Email doesn't exists",
+                dict(email=value['email']),
+                None)
+        user_record = M.User.query.find({'_id': record.claimed_by_user_id}).first()
+        if not record.confirmed or not user_record or user_record.disabled:
+            raise Invalid(
+                "Email doesn't verified or user record disabled",
+                dict(email=value['email']),
+                None)
+        return value
+
+class RecoverPasswordChangeForm(ForgeForm):
+    class fields(ew_core.NameList):
+        pw = ew.PasswordField(
+            label='New Password',
+            validator=validators.UnicodeString(not_empty=True, min=6))
+        pw2 = ew.PasswordField(
+            label='New Password (again)',
+            validator=validators.UnicodeString(not_empty=True))
+
+    @validator
+    def to_python(self, value, state):
+        d = super(RecoverPasswordChangeForm, self).to_python(value, state)
+        if d['pw'] != d['pw2']:
+            raise Invalid('Passwords must match', value, state)
+        return d

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/4bef681c/Allura/allura/templates/forgotten_password.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/forgotten_password.html b/Allura/allura/templates/forgotten_password.html
new file mode 100644
index 0000000..dbd4f19
--- /dev/null
+++ b/Allura/allura/templates/forgotten_password.html
@@ -0,0 +1,36 @@
+{#-
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+-#}
+{% set hide_left_bar = True %}
+{% extends g.theme.master %}
+
+{% block title %}Forgotten password recovery{% endblock %}
+
+{% block header %}Forgotten password recovery{% endblock %}
+
+{% block content %}
+<div class="grid-20">
+  {% if c.forgotten_password_form %}
+    {{ c.forgotten_password_form.display(action="../password_recovery_hash") }}
+  {% endif %}
+
+  {% if c.recover_password_change_form %}
+    {{ c.recover_password_change_form.display(action="") }}
+  {% endif %}
+</div>
+{% endblock %}
\ No newline at end of file


[02/14] git commit: [#6783] ticket:463 sending email with link to password recovery

Posted by jo...@apache.org.
[#6783] ticket:463 sending email with link to password recovery


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/5c328f5a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/5c328f5a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/5c328f5a

Branch: refs/heads/master
Commit: 5c328f5ad07068b628349662198b9ed6ed8bfe95
Parents: 4bef681
Author: coldmind <so...@yandex.ru>
Authored: Fri Oct 25 17:24:31 2013 +0300
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Thu Nov 7 21:05:00 2013 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/auth.py               | 17 +++++++++++++++++
 Allura/allura/templates/forgotten_password.html |  2 +-
 2 files changed, 18 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/5c328f5a/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 6d9295a..9ca5ff2 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -182,6 +182,23 @@ class AuthController(BaseController):
         user_record = M.User.query.find({'preferences.email_address': email}).first()
         hash = h.nonce(42)
         user_record.set_tool_data('AuthPasswordReset', hash=hash)
+
+        log.info('Sending password recovery link to %s', email)
+        text = '''
+To reset your password on %s, please visit the following URL:
+
+%s/auth/forgotten_password/%s
+
+''' % (config['site_name'], config['base_url'], hash)
+
+        allura.tasks.mail_tasks.sendmail.post(
+            destinations=[email],
+            fromaddr=config['forgemail.return_path'],
+            reply_to='',
+            subject='Password recovery',
+            message_id=h.gen_message_id(),
+            text=text)
+
         flash('Email with instructions has been sent.')
         redirect('/')
 

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/5c328f5a/Allura/allura/templates/forgotten_password.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/forgotten_password.html b/Allura/allura/templates/forgotten_password.html
index dbd4f19..56959c2 100644
--- a/Allura/allura/templates/forgotten_password.html
+++ b/Allura/allura/templates/forgotten_password.html
@@ -26,7 +26,7 @@
 {% block content %}
 <div class="grid-20">
   {% if c.forgotten_password_form %}
-    {{ c.forgotten_password_form.display(action="../password_recovery_hash") }}
+    {{ c.forgotten_password_form.display(action="./password_recovery_hash") }}
   {% endif %}
 
   {% if c.recover_password_change_form %}


[06/14] git commit: [#6783] ticket:463 fixed view and tests

Posted by jo...@apache.org.
[#6783] ticket:463 fixed view and tests


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/c80b0cda
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/c80b0cda
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/c80b0cda

Branch: refs/heads/master
Commit: c80b0cda9f61cb1cbded2dcc7db74bbd8d0591e2
Parents: b7aced8
Author: coldmind <so...@yandex.ru>
Authored: Sat Oct 26 02:18:53 2013 +0300
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Thu Nov 7 21:05:03 2013 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/auth.py      |  4 ++--
 Allura/allura/tests/model/test_auth.py | 13 +++++++++++++
 2 files changed, 15 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c80b0cda/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 9ecab1c..700db60 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -170,7 +170,7 @@ class AuthController(BaseController):
                 flash('Hash was not found')
                 redirect('/')
             hash_expiry = user_record.get_tool_data('AuthPasswordReset', 'hash_expiry')
-            if not hash_expiry or hash_expiry < datetime.datetime.now():
+            if not hash_expiry or hash_expiry < datetime.datetime.utcnow():
                 flash('Hash time was expired.')
                 redirect('/')
             if request.method == 'POST':
@@ -191,7 +191,7 @@ class AuthController(BaseController):
         hash = h.nonce(42)
         user_record.set_tool_data('AuthPasswordReset',
                                   hash=hash,
-                                  hash_expiry=datetime.datetime.now() +
+                                  hash_expiry=datetime.datetime.utcnow() +
                                   datetime.timedelta(hours=int(config['auth.recovery_hash_expiry_period'])))
 
         log.info('Sending password recovery link to %s', email)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/c80b0cda/Allura/allura/tests/model/test_auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/model/test_auth.py b/Allura/allura/tests/model/test_auth.py
index 755e0d1..027ae01 100644
--- a/Allura/allura/tests/model/test_auth.py
+++ b/Allura/allura/tests/model/test_auth.py
@@ -36,6 +36,7 @@ from allura.tests import TestController
 from allura.lib.helpers import push_config
 from tg import config
 from mock import patch
+import datetime
 
 
 def setUp():
@@ -285,3 +286,15 @@ To reset your password on %s, please visit the following URL:
                 subject='Password recovery',
                 message_id=gen_message_id(),
                 text=text)
+            user = M.User.query.get(username='test-admin')
+            hash = user.get_tool_data('AuthPasswordReset', 'hash')
+            hash_expiry = user.get_tool_data('AuthPasswordReset', 'hash_expiry')
+            assert_equal(hash, '')
+            assert_equal(hash_expiry, '')
+
+            r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
+            hash = user.get_tool_data('AuthPasswordReset', 'hash')
+            hash_expiry = user.get_tool_data('AuthPasswordReset', 'hash_expiry')
+            user.set_tool_data('AuthPasswordReset', hash_expiry=hash_expiry-datetime.timedelta(hours=1))
+            r = self.app.post('/auth/forgotten_password/%s' % hash, {'pw': 154321, 'pw2': 154321})
+            assert_equal(r.status, '302 Found')


[13/14] git commit: [#6783] ticket:463 Fix test

Posted by jo...@apache.org.
[#6783] ticket:463 Fix test


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/4c1a5f16
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/4c1a5f16
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/4c1a5f16

Branch: refs/heads/master
Commit: 4c1a5f16ea028f29b2b6675eb75dbcd4c42c3d7a
Parents: 0c86446
Author: Igor Bondarenko <je...@gmail.com>
Authored: Tue Nov 5 08:34:29 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Thu Nov 7 21:05:05 2013 +0000

----------------------------------------------------------------------
 Allura/allura/tests/functional/test_auth.py | 28 ++++++++++++++----------
 1 file changed, 16 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/4c1a5f16/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 672bba8..7385ed1 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -26,7 +26,8 @@ from nose.tools import (
         assert_not_equal,
         assert_is_none,
         assert_is_not_none,
-        assert_in
+        assert_in,
+        assert_true
     )
 from pylons import tmpl_context as c
 from allura.tests import TestController
@@ -715,7 +716,7 @@ class TestPreferences(TestController):
     @patch('allura.lib.helpers.gen_message_id')
     def test_forgot_password_reset(self, gen_message_id, sendmail):
         user = M.User.query.get(username='test-admin')
-        password1 = user.password
+        old_pw_hash = user.password
 
         email = M.EmailAddress.query.find({'claimed_by_user_id': user._id}).first()
         email.confirmed = False
@@ -746,15 +747,16 @@ class TestPreferences(TestController):
             assert hash is not None
             assert hash_expiry is not None
 
-            new_password = '154321'
-            r = self.app.post('/auth/forgotten_password/%s' % hash, {'pw': new_password, 'pw2': new_password})
+            r = self.app.get('/auth/forgotten_password/%s' % hash)
+            assert_in('New Password:', r)
+            assert_in('New Password (again):', r)
+            form = r.forms[0]
+            form['pw'] = form['pw2'] = new_password = '154321'
+            r = form.submit()
             user = M.User.query.get(username='test-admin')
-            password2 = user.password
-            assert_not_equal(password1, password2)
-            r = self.app.get('/auth/logout')
-            r = self.app.post('/auth/do_login', params=dict(
-                              username='test-admin', password=new_password))
-            assert 'Invalid login' not in str(r)
+            assert_not_equal(old_pw_hash, user.password)
+            provider = plugin.LocalAuthenticationProvider(None)
+            assert_true(provider._validate_password(user, new_password))
 
             text = '''
 To reset your password on %s, please visit the following URL:
@@ -779,8 +781,10 @@ To reset your password on %s, please visit the following URL:
             r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
             user = M.User.by_username('test-admin')
             hash = user.get_tool_data('AuthPasswordReset', 'hash')
-            user.set_tool_data('AuthPasswordReset', hash_expiry= datetime.datetime(2000, 10, 10))
-            r = self.app.post('/auth/forgotten_password/%s' % hash.encode('utf-8'), {'pw': '154321', 'pw2': '154321'})
+            user.set_tool_data('AuthPasswordReset', hash_expiry=datetime.datetime(2000, 10, 10))
+            r = self.app.post('/auth/set_new_password/%s' % hash.encode('utf-8'), {'pw': '154321', 'pw2': '154321'})
+            assert_in('Hash time was expired', r.follow().body)
+            r = self.app.get('/auth/forgotten_password/%s' % hash.encode('utf-8'))
             assert_in('Hash time was expired', r.follow().body)
 
 


[12/14] git commit: [#6783] ticket:463 Don't display 'Forgot password?' link if auth provider doesn't support recovery

Posted by jo...@apache.org.
[#6783] ticket:463 Don't display 'Forgot password?' link if auth provider doesn't support recovery


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/aa9a89c3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/aa9a89c3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/aa9a89c3

Branch: refs/heads/master
Commit: aa9a89c39795c5032ac81d4f25648bb9aaefbabb
Parents: 4c1a5f1
Author: Igor Bondarenko <je...@gmail.com>
Authored: Tue Nov 5 09:09:03 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Thu Nov 7 21:05:05 2013 +0000

----------------------------------------------------------------------
 Allura/allura/lib/widgets/auth_widgets.py | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/aa9a89c3/Allura/allura/lib/widgets/auth_widgets.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/auth_widgets.py b/Allura/allura/lib/widgets/auth_widgets.py
index 5b9bf2b..f83ec48 100644
--- a/Allura/allura/lib/widgets/auth_widgets.py
+++ b/Allura/allura/lib/widgets/auth_widgets.py
@@ -34,12 +34,17 @@ class LoginForm(ForgeForm):
     class fields(ew_core.NameList):
         username = ew.TextField(label='Username')
         password = ew.PasswordField(label='Password')
-        if plugin.LocalAuthenticationProvider.forgotten_password_process:
-            link = ew.HTMLField(text='<a href="./forgotten_password">Forgot password?</a>')
+        link = ew.HTMLField(text='<a href="./forgotten_password">Forgot password?</a>')
 
     class hidden_fields(ew_core.NameList):
         return_to = ew.HiddenField()
 
+    def __init__(self, *args, **kw):
+        super(LoginForm, self).__init__(*args, **kw)
+        if not plugin.AuthenticationProvider.get(request).forgotten_password_process:
+            # auth provider has no method of recovering password - do not show the link
+            self.fields.link.text = ''
+
     @validator
     def validate(self, value, state=None):
         try:


[05/14] git commit: [#6783] ticket:463 some code refactoring

Posted by jo...@apache.org.
[#6783] ticket:463 some code refactoring


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/7bee93b3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/7bee93b3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/7bee93b3

Branch: refs/heads/master
Commit: 7bee93b379babfb796fdaf8eeada9cb20b0d5e1b
Parents: c80b0cd
Author: coldmind <so...@yandex.ru>
Authored: Thu Oct 31 14:30:17 2013 +0200
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Thu Nov 7 21:05:03 2013 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/auth.py           | 10 ++--
 Allura/allura/lib/plugin.py                 | 11 +---
 Allura/allura/lib/widgets/__init__.py       |  2 +-
 Allura/allura/lib/widgets/auth_widgets.py   | 22 +------
 Allura/allura/lib/widgets/forms.py          | 17 ++++--
 Allura/allura/tests/functional/test_auth.py | 73 ++++++++++++++++++++++-
 Allura/allura/tests/model/test_auth.py      | 75 +-----------------------
 Allura/development.ini                      |  4 +-
 8 files changed, 100 insertions(+), 114 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/7bee93b3/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 700db60..42a9420 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -41,7 +41,6 @@ from allura.lib.widgets import (
     OAuthApplicationForm,
     OAuthRevocationForm,
     LoginForm,
-    RecoverPasswordChangeForm,
     ForgottenPasswordForm)
 from allura.lib.widgets import forms
 from allura.lib import exceptions as exc
@@ -65,7 +64,7 @@ OID_PROVIDERS=[
 
 class F(object):
     login_form = LoginForm()
-    recover_password_change_form = RecoverPasswordChangeForm()
+    recover_password_change_form = forms.PasswordChangeBase()
     forgotten_password_form = ForgottenPasswordForm()
     subscription_form=SubscriptionForm()
     registration_form = forms.RegistrationForm(action='/auth/save_new')
@@ -159,7 +158,8 @@ class AuthController(BaseController):
 
     @expose('jinja:allura:templates/forgotten_password.html')
     def forgotten_password(self, hash=None, **kw):
-        if not plugin.LocalAuthenticationProvider.forgotten_password_process:
+        provider = plugin.AuthenticationProvider.get(request)
+        if not provider:
             redirect('/')
         if not hash:
             c.forgotten_password_form = F.forgotten_password_form
@@ -175,7 +175,7 @@ class AuthController(BaseController):
                 redirect('/')
             if request.method == 'POST':
                 ap = plugin.AuthenticationProvider.get(request)
-                ap.recovery_set_password(user_record, kw['pw'])
+                ap.set_password(user_record, None, kw['pw'])
                 user_record.set_tool_data('AuthPasswordReset', hash='', hash_expiry='')
                 flash('Password changed')
                 redirect('/auth/')
@@ -192,7 +192,7 @@ class AuthController(BaseController):
         user_record.set_tool_data('AuthPasswordReset',
                                   hash=hash,
                                   hash_expiry=datetime.datetime.utcnow() +
-                                  datetime.timedelta(hours=int(config['auth.recovery_hash_expiry_period'])))
+                                  datetime.timedelta(seconds=int(config.get('auth.recovery_hash_expiry_period', 600))))
 
         log.info('Sending password recovery link to %s', email)
         text = '''

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/7bee93b3/Allura/allura/lib/plugin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index cd92cf3..0c6c3b1 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -66,9 +66,10 @@ class AuthenticationProvider(object):
     Then in your .ini file, set ``auth.method=myprovider``
     '''
 
+    forgotten_password_process = False
+
     def __init__(self, request):
         self.request = request
-    forgotten_password_process = False
 
     @classmethod
     def get(cls, request):
@@ -84,10 +85,6 @@ class AuthenticationProvider(object):
     def session(self):
         return self.request.environ['beaker.session']
 
-    @LazyProperty
-    def forgotten_password(self):
-        return self.forgotten_password_process
-
     def authenticate_request(self):
         from allura import model as M
         user = M.User.query.get(_id=self.session.get('userid', None))
@@ -218,6 +215,7 @@ class LocalAuthenticationProvider(AuthenticationProvider):
     Stores user passwords on the User model, in mongo.  Uses per-user salt and
     SHA-256 encryption.
     '''
+
     forgotten_password_process = True
 
     def register_user(self, user_doc):
@@ -252,9 +250,6 @@ class LocalAuthenticationProvider(AuthenticationProvider):
     def set_password(self, user, old_password, new_password):
         user.password = self._encode_password(new_password)
 
-    def recovery_set_password(self, user, new_password):
-        user.password = self._encode_password(new_password)
-
     def _encode_password(self, password, salt=None):
         from allura import model as M
         if salt is None:

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/7bee93b3/Allura/allura/lib/widgets/__init__.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/__init__.py b/Allura/allura/lib/widgets/__init__.py
index 516a3d8..cef0d29 100644
--- a/Allura/allura/lib/widgets/__init__.py
+++ b/Allura/allura/lib/widgets/__init__.py
@@ -18,5 +18,5 @@
 from .discuss import Post, Thread, Discussion
 from .subscriptions import SubscriptionForm
 from .oauth_widgets import OAuthApplicationForm, OAuthRevocationForm
-from .auth_widgets import LoginForm, ForgottenPasswordForm, RecoverPasswordChangeForm
+from .auth_widgets import LoginForm, ForgottenPasswordForm
 from .vote import VoteForm

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/7bee93b3/Allura/allura/lib/widgets/auth_widgets.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/auth_widgets.py b/Allura/allura/lib/widgets/auth_widgets.py
index 8a4dba3..5b9bf2b 100644
--- a/Allura/allura/lib/widgets/auth_widgets.py
+++ b/Allura/allura/lib/widgets/auth_widgets.py
@@ -64,31 +64,15 @@ class ForgottenPasswordForm(ForgeForm):
     def validate(self, value, state=None):
         email = value['email']
         record = M.EmailAddress.query.find({'_id': email}).first()
-        if not record:
+        if not record or not record.confirmed:
             raise Invalid(
                 "Email doesn't exists",
                 dict(email=value['email']),
                 None)
-        user_record = M.User.query.find({'_id': record.claimed_by_user_id}).first()
-        if not record.confirmed or not user_record or user_record.disabled:
+        user_record = M.User.by_email_address(email)
+        if not user_record or user_record.disabled:
             raise Invalid(
                 "Email doesn't verified or user record disabled",
                 dict(email=value['email']),
                 None)
         return value
-
-class RecoverPasswordChangeForm(ForgeForm):
-    class fields(ew_core.NameList):
-        pw = ew.PasswordField(
-            label='New Password',
-            validator=validators.UnicodeString(not_empty=True, min=6))
-        pw2 = ew.PasswordField(
-            label='New Password (again)',
-            validator=validators.UnicodeString(not_empty=True))
-
-    @validator
-    def to_python(self, value, state):
-        d = super(RecoverPasswordChangeForm, self).to_python(value, state)
-        if d['pw'] != d['pw2']:
-            raise Invalid('Passwords must match', value, state)
-        return d

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/7bee93b3/Allura/allura/lib/widgets/forms.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/forms.py b/Allura/allura/lib/widgets/forms.py
index de90d39..91dd070 100644
--- a/Allura/allura/lib/widgets/forms.py
+++ b/Allura/allura/lib/widgets/forms.py
@@ -123,10 +123,8 @@ class ForgeForm(ew.SimpleForm):
             display = "%s<div class='error'>%s</div>" % (display, ctx['errors'])
         return display
 
-class PasswordChangeForm(ForgeForm):
+class PasswordChangeBase(ForgeForm):
     class fields(ew_core.NameList):
-        oldpw = ew.PasswordField(
-            label='Old Password', validator=fev.UnicodeString(not_empty=True))
         pw = ew.PasswordField(
             label='New Password',
             validator=fev.UnicodeString(not_empty=True, min=6))
@@ -136,11 +134,22 @@ class PasswordChangeForm(ForgeForm):
 
     @ew_core.core.validator
     def to_python(self, value, state):
-        d = super(PasswordChangeForm, self).to_python(value, state)
+        d = super(PasswordChangeBase, self).to_python(value, state)
         if d['pw'] != d['pw2']:
             raise formencode.Invalid('Passwords must match', value, state)
         return d
 
+class PasswordChangeForm(PasswordChangeBase):
+    class fields(ew_core.NameList):
+        oldpw = ew.PasswordField(
+            label='Old Password', validator=fev.UnicodeString(not_empty=True))
+        pw = ew.PasswordField(
+            label='New Password',
+            validator=fev.UnicodeString(not_empty=True, min=6))
+        pw2 = ew.PasswordField(
+            label='New Password (again)',
+            validator=fev.UnicodeString(not_empty=True))
+
 class PersonalDataForm(ForgeForm):
     class fields(ew_core.NameList):
         sex = ew.SingleSelectField(

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/7bee93b3/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 a945c1a..52f24fe 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -22,18 +22,22 @@ from urlparse import urlparse, parse_qs
 
 import mock
 from nose.tools import (
+        assert_equal,
         assert_not_equal,
         assert_is_none,
         assert_is_not_none,
         assert_in
     )
-from datadiff.tools import assert_equal
 from pylons import tmpl_context as c
 from allura.tests import TestController
 from allura.tests import decorators as td
 from allura import model as M
 from ming.orm.ormsession import ThreadLocalORMSession, session
 from allura.lib import oid_helper
+from allura.lib.helpers import push_config
+from tg import config
+from mock import patch
+import datetime
 
 
 def unentity(s):
@@ -705,6 +709,73 @@ class TestPreferences(TestController):
         user = M.User.query.get(username='test-admin')
         assert len(user.skills) == 0
 
+    @patch('allura.tasks.mail_tasks.sendmail')
+    @patch('allura.lib.helpers.gen_message_id')
+    def test_forgot_password_reset(self, gen_message_id, sendmail):
+        user = M.User.query.get(username='test-admin')
+        password1 = user.password
+
+        email = M.EmailAddress.query.find({'claimed_by_user_id': user._id}).first()
+        email.confirmed = False
+        user.disabled = True
+        ThreadLocalORMSession.flush_all()
+        r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
+        hash = user.get_tool_data('AuthPasswordReset', 'hash')
+        assert hash is None
+
+        user = M.User.query.get(username='test-admin')
+        user.disabled = True
+        email = M.EmailAddress.query.find({'claimed_by_user_id': user._id}).first()
+        email.confirmed = True
+        ThreadLocalORMSession.flush_all()
+        r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
+        hash = user.get_tool_data('AuthPasswordReset', 'hash')
+        assert hash is None
+
+        user = M.User.query.get(username='test-admin')
+        user.disabled = False
+        email = M.EmailAddress.query.find({'claimed_by_user_id': user._id}).first()
+        email.confirmed = True
+        ThreadLocalORMSession.flush_all()
+        with push_config(config, **{'auth.recovery_hash_expiry_period': '600'}):
+            r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
+            hash = user.get_tool_data('AuthPasswordReset', 'hash')
+            hash_expiry = user.get_tool_data('AuthPasswordReset', 'hash_expiry')
+            assert hash is not None
+            assert hash_expiry is not None
+
+            r = self.app.post('/auth/forgotten_password/%s' % hash, {'pw': 154321, 'pw2': 154321})
+            user = M.User.query.get(username='test-admin')
+            password2 = user.password
+            assert_not_equal(password1, password2)
+
+            text = '''
+To reset your password on %s, please visit the following URL:
+
+%s/auth/forgotten_password/%s
+
+''' % (config['site_name'], config['base_url'], hash)
+
+            sendmail.post.assert_called_once_with(
+                destinations=[email._id],
+                fromaddr=config['forgemail.return_path'],
+                reply_to='',
+                subject='Password recovery',
+                message_id=gen_message_id(),
+                text=text)
+            user = M.User.query.get(username='test-admin')
+            hash = user.get_tool_data('AuthPasswordReset', 'hash')
+            hash_expiry = user.get_tool_data('AuthPasswordReset', 'hash_expiry')
+            assert_equal(hash, '')
+            assert_equal(hash_expiry, '')
+
+            r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
+            hash = user.get_tool_data('AuthPasswordReset', 'hash')
+            hash_expiry = user.get_tool_data('AuthPasswordReset', 'hash_expiry')
+            user.set_tool_data('AuthPasswordReset', hash_expiry=hash_expiry-datetime.timedelta(seconds=600))
+            r = self.app.post('/auth/forgotten_password/%s' % hash, {'pw': 154321, 'pw2': 154321})
+            assert_equal(r.status, '302 Found')
+
 
 class TestOAuth(TestController):
 

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/7bee93b3/Allura/allura/tests/model/test_auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/model/test_auth.py b/Allura/allura/tests/model/test_auth.py
index 027ae01..f8e7ed8 100644
--- a/Allura/allura/tests/model/test_auth.py
+++ b/Allura/allura/tests/model/test_auth.py
@@ -20,7 +20,7 @@
 """
 Model tests for auth
 """
-from nose.tools import with_setup, assert_equal, assert_not_equal
+from nose.tools import with_setup, assert_equal
 from pylons import tmpl_context as c, app_globals as g
 from webob import Request
 from mock import patch
@@ -32,11 +32,6 @@ from allura import model as M
 from allura.lib import plugin
 from allura.tests import decorators as td
 from alluratest.controller import setup_basic_test, setup_global_objects
-from allura.tests import TestController
-from allura.lib.helpers import push_config
-from tg import config
-from mock import patch
-import datetime
 
 
 def setUp():
@@ -230,71 +225,3 @@ def test_user_projects_by_role():
     g.credentials.clear()
     assert_equal(set(p.shortname for p in c.user.my_projects()), set(['test', 'test2', 'u/test-admin', 'adobe-1', '--init--']))
     assert_equal(set(p.shortname for p in c.user.my_projects('Admin')), set(['test', 'u/test-admin', 'adobe-1', '--init--']))
-
-
-class TestForgotPassword(TestController):
-
-    @patch('allura.tasks.mail_tasks.sendmail')
-    @patch('allura.lib.helpers.gen_message_id')
-    def test_forgot_password_reset(self, gen_message_id, sendmail):
-        user = M.User.query.get(username='test-admin')
-        password1 = user.password
-        email = M.EmailAddress.query.find({'claimed_by_user_id': user._id}).first()
-        email.confirmed = False
-        user.disabled = True
-
-        r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
-        hash = user.get_tool_data('AuthPasswordReset', 'hash')
-        assert hash is None
-
-        user = M.User.query.get(username='test-admin')
-        user.disabled = True
-        email = M.EmailAddress.query.find({'claimed_by_user_id': user._id}).first()
-        email.confirmed = True
-        r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
-        hash = user.get_tool_data('AuthPasswordReset', 'hash')
-        assert hash is None
-
-        user = M.User.query.get(username='test-admin')
-        user.disabled = False
-        email = M.EmailAddress.query.find({'claimed_by_user_id': user._id}).first()
-        email.confirmed = True
-
-        with push_config(config, **{'auth.recovery_hash_expiry_period': '1'}):
-            r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
-            hash = user.get_tool_data('AuthPasswordReset', 'hash')
-            hash_expiry = user.get_tool_data('AuthPasswordReset', 'hash_expiry')
-            assert hash is not None
-            assert hash_expiry is not None
-
-            r = self.app.post('/auth/forgotten_password/%s' % hash, {'pw': 154321, 'pw2': 154321})
-            user = M.User.query.get(username='test-admin')
-            password2 = user.password
-            assert_not_equal(password1, password2)
-
-            text = '''
-To reset your password on %s, please visit the following URL:
-
-%s/auth/forgotten_password/%s
-
-''' % (config['site_name'], config['base_url'], hash)
-
-            sendmail.post.assert_called_once_with(
-                destinations=[email._id],
-                fromaddr=config['forgemail.return_path'],
-                reply_to='',
-                subject='Password recovery',
-                message_id=gen_message_id(),
-                text=text)
-            user = M.User.query.get(username='test-admin')
-            hash = user.get_tool_data('AuthPasswordReset', 'hash')
-            hash_expiry = user.get_tool_data('AuthPasswordReset', 'hash_expiry')
-            assert_equal(hash, '')
-            assert_equal(hash_expiry, '')
-
-            r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
-            hash = user.get_tool_data('AuthPasswordReset', 'hash')
-            hash_expiry = user.get_tool_data('AuthPasswordReset', 'hash_expiry')
-            user.set_tool_data('AuthPasswordReset', hash_expiry=hash_expiry-datetime.timedelta(hours=1))
-            r = self.app.post('/auth/forgotten_password/%s' % hash, {'pw': 154321, 'pw2': 154321})
-            assert_equal(r.status, '302 Found')

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/7bee93b3/Allura/development.ini
----------------------------------------------------------------------
diff --git a/Allura/development.ini b/Allura/development.ini
index 98e251b..4a96528 100644
--- a/Allura/development.ini
+++ b/Allura/development.ini
@@ -86,8 +86,8 @@ auth.ldap.admin_dn = cn=admin,dc=localdomain
 auth.ldap.admin_password = secret
 auth.ldap.schroot_name = scm
 
-# In hours
-auth.recovery_hash_expiry_period = 1
+# In seconds
+auth.recovery_hash_expiry_period = 600
 
 # Set the locations of some static resources
 #  script_name is the path that is handled by the application


[11/14] git commit: [#6783] ticket:463 Fix expiry test

Posted by jo...@apache.org.
[#6783] ticket:463 Fix expiry test


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/a6f4e769
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/a6f4e769
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/a6f4e769

Branch: refs/heads/master
Commit: a6f4e7696f84a492380740c0045b6ca595868825
Parents: ef881f0
Author: Igor Bondarenko <je...@gmail.com>
Authored: Mon Nov 4 13:36:49 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Thu Nov 7 21:05:04 2013 +0000

----------------------------------------------------------------------
 Allura/allura/tests/functional/test_auth.py | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/a6f4e769/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 02f26a9..672bba8 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -776,14 +776,12 @@ To reset your password on %s, please visit the following URL:
             assert_equal(hash, '')
             assert_equal(hash_expiry, '')
 
-            #r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
-            #hash_expiry = user.get_tool_data('AuthPasswordReset', 'hash_expiry')
-            #user.set_tool_data('AuthPasswordReset', hash_expiry=hash_expiry-datetime.timedelta(hours=1))
-            #ThreadLocalORMSession.flush_all()
-            # expected redirect with error here, but
-            # real db-record of hash expiry doesn't changes.
-            #r = self.app.post('/auth/forgotten_password/%s' % hash.encode('utf'), {'pw': '154321', 'pw2': '154321'})
-
+            r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
+            user = M.User.by_username('test-admin')
+            hash = user.get_tool_data('AuthPasswordReset', 'hash')
+            user.set_tool_data('AuthPasswordReset', hash_expiry= datetime.datetime(2000, 10, 10))
+            r = self.app.post('/auth/forgotten_password/%s' % hash.encode('utf-8'), {'pw': '154321', 'pw2': '154321'})
+            assert_in('Hash time was expired', r.follow().body)
 
 
 class TestOAuth(TestController):


[14/14] git commit: [#6783] Tweak error messages, re-org tests slightly

Posted by jo...@apache.org.
[#6783] Tweak error messages, re-org tests slightly

Signed-off-by: Cory Johns <cj...@slashdotmedia.com>


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/7c7b1977
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/7c7b1977
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/7c7b1977

Branch: refs/heads/master
Commit: 7c7b197731db0c89985d3629eea66fb9f5acc12f
Parents: aa9a89c
Author: Cory Johns <cj...@slashdotmedia.com>
Authored: Thu Nov 7 21:03:52 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Thu Nov 7 21:05:05 2013 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/auth.py           |  14 ++-
 Allura/allura/lib/widgets/auth_widgets.py   |  37 ++++----
 Allura/allura/model/auth.py                 |   2 +-
 Allura/allura/tests/functional/test_auth.py | 104 +++++++++++++----------
 4 files changed, 80 insertions(+), 77 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/7c7b1977/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 430d4fa..35bcf81 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -157,24 +157,22 @@ class AuthController(BaseController):
         return dict()
 
     def _validate_hash(self, hash):
+        login_url = config.get('auth.login_url', '/auth/')
         if not hash:
-            redirect(request.referer)
+            redirect(login_url)
         user_record = M.User.query.find({'tool_data.AuthPasswordReset.hash': hash}).first()
         if not user_record:
-            flash('Hash was not found')
-            redirect(request.referer)
+            flash('Unable to process reset, please try again')
+            redirect(login_url)
         hash_expiry = user_record.get_tool_data('AuthPasswordReset', 'hash_expiry')
         if not hash_expiry or hash_expiry < datetime.datetime.utcnow():
-            flash('Hash time was expired.')
-            redirect(request.referer)
+            flash('Unable to process reset, please try again')
+            redirect(login_url)
         return user_record
 
-
     @expose('jinja:allura:templates/forgotten_password.html')
     def forgotten_password(self, hash=None, **kw):
         provider = plugin.AuthenticationProvider.get(request)
-        if not provider:
-            redirect(request.referer)
         if not hash:
             c.forgotten_password_form = F.forgotten_password_form
         else:

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/7c7b1977/Allura/allura/lib/widgets/auth_widgets.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/auth_widgets.py b/Allura/allura/lib/widgets/auth_widgets.py
index f83ec48..93e8826 100644
--- a/Allura/allura/lib/widgets/auth_widgets.py
+++ b/Allura/allura/lib/widgets/auth_widgets.py
@@ -31,20 +31,21 @@ from allura import model as M
 class LoginForm(ForgeForm):
     submit_text='Login'
     style='wide'
-    class fields(ew_core.NameList):
-        username = ew.TextField(label='Username')
-        password = ew.PasswordField(label='Password')
-        link = ew.HTMLField(text='<a href="./forgotten_password">Forgot password?</a>')
+
+    @property
+    def fields(self):
+        fields = [
+            ew.TextField(name='username', label='Username'),
+            ew.PasswordField(name='password', label='Password')
+        ]
+        if plugin.AuthenticationProvider.get(request).forgotten_password_process:
+            # only show link if auth provider has method of recovering password
+            fields.append(ew.HTMLField(name='link', text='<a href="forgotten_password">Forgot password?</a>'))
+        return fields
 
     class hidden_fields(ew_core.NameList):
         return_to = ew.HiddenField()
 
-    def __init__(self, *args, **kw):
-        super(LoginForm, self).__init__(*args, **kw)
-        if not plugin.AuthenticationProvider.get(request).forgotten_password_process:
-            # auth provider has no method of recovering password - do not show the link
-            self.fields.link.text = ''
-
     @validator
     def validate(self, value, state=None):
         try:
@@ -68,16 +69,10 @@ class ForgottenPasswordForm(ForgeForm):
     @validator
     def validate(self, value, state=None):
         email = value['email']
-        record = M.EmailAddress.query.find({'_id': email}).first()
-        if not record or not record.confirmed:
+        email_record = M.EmailAddress.query.find({'_id': email}).first()
+        user = M.User.by_email_address(email)
+        if user is None or not email_record.confirmed:
             raise Invalid(
-                "Email doesn't exists",
-                dict(email=value['email']),
-                None)
-        user_record = M.User.by_email_address(email)
-        if not user_record or user_record.disabled:
-            raise Invalid(
-                "Email doesn't verified or user record disabled",
-                dict(email=value['email']),
-                None)
+                    'Unable to recover password for this email',
+                    {'email': email}, None)
         return value

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/7c7b1977/Allura/allura/model/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/auth.py b/Allura/allura/model/auth.py
index 18e8b2e..2bc0ba3 100644
--- a/Allura/allura/model/auth.py
+++ b/Allura/allura/model/auth.py
@@ -300,7 +300,7 @@ class User(MappedClass, ActivityNode, ActivityObject):
     class __mongometa__:
         name='user'
         session = main_orm_session
-        indexes = [ 'tool_data.sfx.userid' ]
+        indexes = [ 'tool_data.sfx.userid', 'tool_data.AuthPasswordReset.hash' ]
         unique_indexes = [ 'username' ]
 
     _id=FieldProperty(S.ObjectId)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/7c7b1977/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 7385ed1..7919206 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -712,80 +712,90 @@ class TestPreferences(TestController):
         user = M.User.query.get(username='test-admin')
         assert len(user.skills) == 0
 
+
+class TestPasswordReset(TestController):
     @patch('allura.tasks.mail_tasks.sendmail')
     @patch('allura.lib.helpers.gen_message_id')
-    def test_forgot_password_reset(self, gen_message_id, sendmail):
+    def test_email_unconfirmed(self, gen_message_id, sendmail):
         user = M.User.query.get(username='test-admin')
-        old_pw_hash = user.password
-
         email = M.EmailAddress.query.find({'claimed_by_user_id': user._id}).first()
         email.confirmed = False
-        user.disabled = True
         ThreadLocalORMSession.flush_all()
         r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
         hash = user.get_tool_data('AuthPasswordReset', 'hash')
         assert hash is None
 
+    @patch('allura.tasks.mail_tasks.sendmail')
+    @patch('allura.lib.helpers.gen_message_id')
+    def test_user_disabled(self, gen_message_id, sendmail):
         user = M.User.query.get(username='test-admin')
-        user.disabled = True
         email = M.EmailAddress.query.find({'claimed_by_user_id': user._id}).first()
-        email.confirmed = True
+        user.disabled = True
         ThreadLocalORMSession.flush_all()
         r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
         hash = user.get_tool_data('AuthPasswordReset', 'hash')
         assert hash is None
 
+    @patch('allura.tasks.mail_tasks.sendmail')
+    @patch('allura.lib.helpers.gen_message_id')
+    def test_password_reset(self, gen_message_id, sendmail):
         user = M.User.query.get(username='test-admin')
-        user.disabled = False
         email = M.EmailAddress.query.find({'claimed_by_user_id': user._id}).first()
         email.confirmed = True
         ThreadLocalORMSession.flush_all()
-        with push_config(config, **{'auth.recovery_hash_expiry_period': '600'}):
-            r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
-            hash = user.get_tool_data('AuthPasswordReset', 'hash')
-            hash_expiry = user.get_tool_data('AuthPasswordReset', 'hash_expiry')
-            assert hash is not None
-            assert hash_expiry is not None
-
-            r = self.app.get('/auth/forgotten_password/%s' % hash)
-            assert_in('New Password:', r)
-            assert_in('New Password (again):', r)
-            form = r.forms[0]
-            form['pw'] = form['pw2'] = new_password = '154321'
-            r = form.submit()
-            user = M.User.query.get(username='test-admin')
-            assert_not_equal(old_pw_hash, user.password)
-            provider = plugin.LocalAuthenticationProvider(None)
-            assert_true(provider._validate_password(user, new_password))
-
-            text = '''
+        old_pw_hash = user.password
+        r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
+        hash = user.get_tool_data('AuthPasswordReset', 'hash')
+        hash_expiry = user.get_tool_data('AuthPasswordReset', 'hash_expiry')
+        assert hash is not None
+        assert hash_expiry is not None
+
+        r = self.app.get('/auth/forgotten_password/%s' % hash)
+        assert_in('New Password:', r)
+        assert_in('New Password (again):', r)
+        form = r.forms[0]
+        form['pw'] = form['pw2'] = new_password = '154321'
+        r = form.submit()
+        user = M.User.query.get(username='test-admin')
+        assert_not_equal(old_pw_hash, user.password)
+        provider = plugin.LocalAuthenticationProvider(None)
+        assert_true(provider._validate_password(user, new_password))
+
+        text = '''
 To reset your password on %s, please visit the following URL:
 
 %s/auth/forgotten_password/%s
 
 ''' % (config['site_name'], config['base_url'], hash)
 
-            sendmail.post.assert_called_once_with(
-                destinations=[email._id],
-                fromaddr=config['forgemail.return_path'],
-                reply_to='noreply@sourceforge.net',
-                subject='Password recovery',
-                message_id=gen_message_id(),
-                text=text)
-            user = M.User.query.get(username='test-admin')
-            hash = user.get_tool_data('AuthPasswordReset', 'hash')
-            hash_expiry = user.get_tool_data('AuthPasswordReset', 'hash_expiry')
-            assert_equal(hash, '')
-            assert_equal(hash_expiry, '')
-
-            r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
-            user = M.User.by_username('test-admin')
-            hash = user.get_tool_data('AuthPasswordReset', 'hash')
-            user.set_tool_data('AuthPasswordReset', hash_expiry=datetime.datetime(2000, 10, 10))
-            r = self.app.post('/auth/set_new_password/%s' % hash.encode('utf-8'), {'pw': '154321', 'pw2': '154321'})
-            assert_in('Hash time was expired', r.follow().body)
-            r = self.app.get('/auth/forgotten_password/%s' % hash.encode('utf-8'))
-            assert_in('Hash time was expired', r.follow().body)
+        sendmail.post.assert_called_once_with(
+            destinations=[email._id],
+            fromaddr=config['forgemail.return_path'],
+            reply_to='noreply@sourceforge.net',
+            subject='Password recovery',
+            message_id=gen_message_id(),
+            text=text)
+        user = M.User.query.get(username='test-admin')
+        hash = user.get_tool_data('AuthPasswordReset', 'hash')
+        hash_expiry = user.get_tool_data('AuthPasswordReset', 'hash_expiry')
+        assert_equal(hash, '')
+        assert_equal(hash_expiry, '')
+
+    @patch('allura.tasks.mail_tasks.sendmail')
+    @patch('allura.lib.helpers.gen_message_id')
+    def test_hash_expired(self, gen_message_id, sendmail):
+        user = M.User.query.get(username='test-admin')
+        email = M.EmailAddress.query.find({'claimed_by_user_id': user._id}).first()
+        email.confirmed = True
+        ThreadLocalORMSession.flush_all()
+        r = self.app.post('/auth/password_recovery_hash', {'email': email._id})
+        user = M.User.by_username('test-admin')
+        hash = user.get_tool_data('AuthPasswordReset', 'hash')
+        user.set_tool_data('AuthPasswordReset', hash_expiry=datetime.datetime(2000, 10, 10))
+        r = self.app.get('/auth/forgotten_password/%s' % hash.encode('utf-8'))
+        assert_in('Unable to process reset, please try again', r.follow().body)
+        r = self.app.post('/auth/set_new_password/%s' % hash.encode('utf-8'), {'pw': '154321', 'pw2': '154321'})
+        assert_in('Unable to process reset, please try again', r.follow().body)
 
 
 class TestOAuth(TestController):