Commit ba9baf90 authored by Ivan Tyagov's avatar Ivan Tyagov

Allow ERP5UserManager to check (if configured) account's password expire

and account's number of failures and stop user (if required) from
logging in.
parent 4c32d6d6
......@@ -57,6 +57,7 @@
"""\n
from DateTime import DateTime\n
\n
request = context.REQUEST\n
portal = context.getPortalObject()\n
portal_preferences = portal.portal_preferences\n
\n
......@@ -86,6 +87,7 @@ if len(failures_for_period)>= max_authentication_failures:\n
context.log(\'check=%s block=%s release=%s-> %s\' %(check_duration, block_duration, block_timeout, failures_for_period))\n
if block_timeout > now:\n
context.log(\'block %s\' %context.getReference())\n
request.set(\'is_user_account_blocked\', True)\n
return 1\n
\n
return 0\n
......
......@@ -57,6 +57,7 @@
"""\n
from Products.ERP5Type.Cache import CachingMethod\n
\n
request = context.REQUEST\n
portal = context.getPortalObject()\n
\n
def _isPasswordExpired():\n
......@@ -66,15 +67,17 @@ def _isPasswordExpired():\n
max_password_lifetime_duration = portal.portal_preferences.getPreferredMaxPasswordLifetimeDuration()\n
last_password_modification_date = context.getLastPasswordModificationDate()\n
if last_password_modification_date is not None and \\\n
(last_password_modification_date + max_password_lifetime_duration*one_hour-5) < now:\n
(last_password_modification_date + max_password_lifetime_duration*one_hour) < now:\n
# password is expired\n
context.log(\'expired %s\' %context.getReference())\n
return 1\n
return 0\n
\n
_isPasswordExpired1 = CachingMethod(_isPasswordExpired,\n
_isPasswordExpired = CachingMethod(_isPasswordExpired,\n
id=\'Person_isPasswordExpired\',\n
cache_factory=\'erp5_content_short\')\n
is_password_expired = _isPasswordExpired()\n
request.set(\'is_user_account_password_expired\', is_password_expired)\n
return _isPasswordExpired()\n
......
......@@ -46,9 +46,32 @@
isAnon mtool/isAnonymousUser|nothing;">\n
<tal:block tal:condition="isAnon">\n
<tal:block tal:define="dummy python: response.expireCookie(\'__ac\', path=\'/\');\n
url python: \'%s/login_form?portal_status_message=%s\' % (here.absolute_url(), here.Base_translateString(\'Login and/or password is incorrect.\'));\n
url python: request.get(\'came_from\') and \'%s&amp;came_from=%s\' % (url, request[\'came_from\']) or url;\n
dummy python: response.redirect(url);" />\n
is_user_account_blocked python: request.get(\'is_user_account_blocked\', False);\n
is_user_account_password_expired python: request.get(\'is_user_account_password_expired\', False);\n
d python: context.log(\'? --%s %s\' %(is_user_account_blocked, is_user_account_password_expired));">\n
\n
<!-- Login and/or password is incorrect. -->\n
<tal:block tal:omit-tag="python: not is_user_account_blocked and not is_user_account_password_expired"\n
tal:define="url python: \'%s/login_form?portal_status_message=%s\' % (here.absolute_url(), here.Base_translateString(\'Login and/or password is incorrect.\'));\n
url python: request.get(\'came_from\') and \'%s&amp;came_from=%s\' % (url, request[\'came_from\']) or url;\n
dummy python: response.redirect(url);">\n
</tal:block>\n
\n
<!-- Login is blocked. -->\n
<tal:block tal:condition="is_user_account_blocked">\n
<tal:block tal:define="url python: \'%s/login_form?portal_status_message=%s\' % (here.absolute_url(), here.Base_translateString(\'Account is blocked.\'));\n
url python: request.get(\'came_from\') and \'%s&amp;came_from=%s\' % (url, request[\'came_from\']) or url;\n
dummy python: response.redirect(url);"/>\n
</tal:block>\n
\n
<!-- Password is expired. -->\n
<tal:block tal:condition="is_user_account_password_expired">\n
<tal:block tal:define="url python: \'%s/login_form?portal_status_message=%s\' % (here.absolute_url(), here.Base_translateString(\'Password is expired.\'));\n
url python: request.get(\'came_from\') and \'%s&amp;came_from=%s\' % (url, request[\'came_from\']) or url;\n
dummy python: response.redirect(url);"/>\n
</tal:block>\n
\n
</tal:block>\n
</tal:block>\n
<tal:block tal:condition="not: isAnon">\n
<tal:block tal:define="came_from python: request.get(\'came_from\') or here.absolute_url();\n
......@@ -73,7 +96,7 @@
</item>
<item>
<key> <string>output_encoding</string> </key>
<value> <string>utf-8</string> </value>
<value> <string>iso-8859-15</string> </value>
</item>
<item>
<key> <string>title</string> </key>
......
1
\ No newline at end of file
2
\ No newline at end of file
......@@ -163,12 +163,38 @@ class ERP5UserManager(BasePlugin):
id='ERP5UserManager_authenticateCredentials',
cache_factory='erp5_content_short')
try:
return _authenticateCredentials(
login=credentials.get('login'),
password=credentials.get('password'),
path=self.getPhysicalPath())
authentication_result = _authenticateCredentials(
login=credentials.get('login'),
password=credentials.get('password'),
path=self.getPhysicalPath())
except _AuthenticationFailure:
authentication_result = None
method = getattr(self, 'ERP5Site_isAuthenticationPolicyEnabled', None)
if method is None or (method is not None and not method()):
# stop here, no authentication policy enabled
# so just return authentication check result
# XXX: move to ERP5 Site API
return authentication_result
# authentication policy enabled, we need person object anyway
user_list = self.getUserByLogin(credentials.get('login'))
if not user_list:
# not an ERP5 Person object
return None
user = user_list[0]
if authentication_result is None:
# file a failed authentication attempt
user.notifyLoginFailure()
return None
# check if user account is blocked and if password is expired or not
if user.isLoginBlocked() or user.isPasswordExpired():
return None
return authentication_result
#
# IUserEnumerationPlugin implementation
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment