You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2014/06/20 17:52:21 UTC
[04/15] git commit: [#7432] ticket:598 Auth provider methods for pwd
expiration support
[#7432] ticket:598 Auth provider methods for pwd expiration support
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/899e1444
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/899e1444
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/899e1444
Branch: refs/heads/master
Commit: 899e1444266e9523e4b329e54444a3c9cdb7420d
Parents: 899d182
Author: Igor Bondarenko <je...@gmail.com>
Authored: Wed Jun 4 16:10:21 2014 +0300
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Fri Jun 20 15:39:17 2014 +0000
----------------------------------------------------------------------
Allura/allura/lib/plugin.py | 27 ++++++++++
Allura/allura/model/auth.py | 1 +
Allura/allura/tests/model/test_auth.py | 51 ++++++++++++++----
Allura/allura/tests/unit/test_auth_provider.py | 60 +++++++++++++++++++++
4 files changed, 130 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/899e1444/Allura/allura/lib/plugin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index ffe9d29..f9467be 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -229,6 +229,26 @@ class AuthenticationProvider(object):
'''
raise NotImplementedError, 'user_registration_date'
+ def get_last_password_updated(self, user):
+ '''
+ Returns the date when the user updated password for a last time.
+
+ :param user: a :class:`User <allura.model.auth.User>`
+ :rtype: :class:`datetime <datetime.datetime>`
+ '''
+ raise NotImplementedError, 'get_last_password_updated'
+
+ def is_password_expired(self, user):
+ days = asint(config.get('auth.pwdexpire.days', 0))
+ before = asint(config.get('auth.pwdexpire.before', 0))
+ now = datetime.utcnow()
+ last_updated = self.get_last_password_updated(user)
+ if days and now - last_updated > timedelta(days=days):
+ return True
+ if before and last_updated < datetime.fromtimestamp(before):
+ return True
+ return False
+
class LocalAuthenticationProvider(AuthenticationProvider):
@@ -280,6 +300,7 @@ class LocalAuthenticationProvider(AuthenticationProvider):
def set_password(self, user, old_password, new_password):
user.password = self._encode_password(new_password)
+ user.last_password_updated = datetime.utcnow()
def _encode_password(self, password, salt=None):
from allura import model as M
@@ -304,6 +325,12 @@ class LocalAuthenticationProvider(AuthenticationProvider):
return user._id.generation_time
return datetime.utcnow()
+ def get_last_password_updated(self, user):
+ d = user.last_password_updated
+ if d is None:
+ return self.user_registration_date(user)
+ return d
+
def ldap_conn(who=None, cred=None):
'''
http://git-wip-us.apache.org/repos/asf/allura/blob/899e1444/Allura/allura/model/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/auth.py b/Allura/allura/model/auth.py
index 17f1175..c7b1004 100644
--- a/Allura/allura/model/auth.py
+++ b/Allura/allura/model/auth.py
@@ -226,6 +226,7 @@ class User(MappedClass, ActivityNode, ActivityObject):
username = FieldProperty(str)
email_addresses = FieldProperty([str])
password = FieldProperty(str)
+ last_password_updated = FieldProperty(datetime)
projects = FieldProperty(S.Deprecated)
# full mount point: prefs dict
tool_preferences = FieldProperty({str: {str: None}})
http://git-wip-us.apache.org/repos/asf/allura/blob/899e1444/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 35f056e..49dc839 100644
--- a/Allura/allura/tests/model/test_auth.py
+++ b/Allura/allura/tests/model/test_auth.py
@@ -20,12 +20,19 @@
"""
Model tests for auth
"""
-from nose.tools import with_setup, assert_equal, assert_not_in, assert_in
+from nose.tools import (
+ with_setup,
+ assert_equal,
+ assert_not_in,
+ assert_in,
+ assert_true,
+)
from pylons import tmpl_context as c, app_globals as g
from webob import Request
-from mock import patch
+from mock import patch, Mock
from datetime import datetime, timedelta
+from bson import ObjectId
from pymongo.errors import DuplicateKeyError
from ming.orm.ormsession import ThreadLocalORMSession
@@ -41,13 +48,39 @@ def setUp():
setup_global_objects()
-@with_setup(setUp)
-def test_password_encoder():
- # Verify salt
- ep = plugin.LocalAuthenticationProvider(
- Request.blank('/'))._encode_password
- assert ep('test_pass') != ep('test_pass')
- assert ep('test_pass', '0000') == ep('test_pass', '0000')
+class TestLocalAuthenticationProvider(object):
+
+ def setUp(self):
+ setUp()
+ self.provider = plugin.LocalAuthenticationProvider(Request.blank('/'))
+
+ def test_password_encoder(self):
+ # Verify salt
+ ep = self.provider._encode_password
+ assert ep('test_pass') != ep('test_pass')
+ assert ep('test_pass', '0000') == ep('test_pass', '0000')
+
+ def test_set_password_sets_last_updated(self):
+ user = Mock()
+ user.last_password_updated = None
+ now1 = datetime.utcnow()
+ self.provider.set_password(user, '', '')
+ now2 = datetime.utcnow()
+ assert_true(user.last_password_updated > now1)
+ assert_true(user.last_password_updated < now2)
+
+ def test_get_last_password_updated_not_set(self):
+ user = Mock()
+ user._id = ObjectId()
+ user.last_password_updated = None
+ upd = self.provider.get_last_password_updated(user)
+ assert_equal(upd, user._id.generation_time)
+
+ def test_get_last_password_updated(self):
+ user = Mock()
+ user.last_password_updated = datetime(2014, 06, 04, 13, 13, 13)
+ upd = self.provider.get_last_password_updated(user)
+ assert_equal(upd, user.last_password_updated)
@with_setup(setUp)
http://git-wip-us.apache.org/repos/asf/allura/blob/899e1444/Allura/allura/tests/unit/test_auth_provider.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/unit/test_auth_provider.py b/Allura/allura/tests/unit/test_auth_provider.py
new file mode 100644
index 0000000..2ecd109
--- /dev/null
+++ b/Allura/allura/tests/unit/test_auth_provider.py
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+
+# 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.
+
+import datetime as dt
+import calendar
+
+import tg
+from mock import Mock
+from nose.tools import assert_true, assert_false
+from webob import Request
+
+from alluratest.controller import setup_basic_test
+from allura.lib import plugin
+from allura.lib import helpers as h
+
+
+class TestAuthenticationProvider(object):
+
+ def setUp(self):
+ setup_basic_test()
+ self.provider = plugin.AuthenticationProvider(Request.blank('/'))
+ self.pwd_updated = dt.datetime.utcnow() - dt.timedelta(days=100)
+ self.provider.get_last_password_updated = lambda u: self.pwd_updated
+ self.user = Mock()
+
+ def test_is_password_expired_disabled(self):
+ assert_false(self.provider.is_password_expired(self.user))
+
+ def test_is_password_expired_days(self):
+ with h.push_config(tg.config, **{'auth.pwdexpire.days': '180'}):
+ assert_false(self.provider.is_password_expired(self.user))
+ with h.push_config(tg.config, **{'auth.pwdexpire.days': '90'}):
+ assert_true(self.provider.is_password_expired(self.user))
+
+ def test_is_password_expired_before(self):
+ before = dt.datetime.utcnow() - dt.timedelta(days=180)
+ before = calendar.timegm(before.timetuple())
+ with h.push_config(tg.config, **{'auth.pwdexpire.before': str(before)}):
+ assert_false(self.provider.is_password_expired(self.user))
+
+ before = dt.datetime.utcnow() - dt.timedelta(days=1)
+ before = calendar.timegm(before.timetuple())
+ with h.push_config(tg.config, **{'auth.pwdexpire.before': str(before)}):
+ assert_true(self.provider.is_password_expired(self.user))