allura-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From john...@apache.org
Subject [03/14] git commit: [#6783] ticket:463 added functionality to generate hash and change password
Date Thu, 07 Nov 2013 21:07:16 GMT
[#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 <sokandpal@yandex.ru>
Authored: Fri Oct 25 16:22:37 2013 +0300
Committer: Cory Johns <cjohns@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


Mime
View raw message