Commit 63c3da2b authored by Vincent Pelletier's avatar Vincent Pelletier

erp5_core: Merge erp5_auto_logout.

Disabled by default (configurable by user preference).

Also, reorganise erp5_auto_logout code:
- logout: Do not duplicate original code.
- twiddleAuthCookie: Simplify & factorise.
- setAuthCookie: Resync features with Cookie Crumbler's, and set http_only flag.
- ERP5Site_getMaxUserInactivityDuration: Cached access takes the same time as actual access (and access is surprisingly slow, actually), so do not cache.
- Base_getAutoLogoutSessionKey: New script, to factorise session key generation.
parent 7a14683b
2009-01-14 ivan
* Moved to public bt5 repository
2009-01-12 ivan
* Initial import
\ No newline at end of file
Copyright (c) 2001-2006 Nexedi SARL
\ No newline at end of file
This bt5 provides support for automatically logging out inactive users of ERP5 based on a maximum user inactive duration as specified in preferences.
\ No newline at end of file
GPL
\ No newline at end of file
erp5_auto_logout
\ No newline at end of file
......@@ -50,26 +50,20 @@
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>""" Get (in seconds) authentication expire interval for an user. """\n
from Products.ERP5Type.Cache import CachingMethod\n
\n
def getMaxUserInactivityDuration():\n
return context.portal_preferences.getPreferredMaxUserInactivityDuration()\n
\n
getMaxUserInactivityDuration = CachingMethod( \\\n
getMaxUserInactivityDuration, \\\n
"ERP5Site_getMaxUserInactivityDuration_%s" % (user_name, ), \\\n
cache_factory=\'erp5_ui_medium\')\n
return getMaxUserInactivityDuration()\n
<value> <string>from AccessControl import getSecurityManager\n
from zExceptions import Unauthorized\n
if REQUEST is not None: # Cheap "do not call from URL" protection - not that the session key is secret\n
raise Unauthorized\n
return \'ac_cookie_\' + str(getSecurityManager().getUser())\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>user_name=None</string> </value>
<value> <string>REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ERP5Site_getMaxUserInactivityDuration</string> </value>
<value> <string>Base_getAutoLogoutSessionKey</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -170,14 +170,11 @@
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>REQUEST = context.REQUEST\n
# delete session\n
context.portal_sessions.manage_delObjects(\'ac_cookie_%s\' \\\n
%REQUEST.get(\'__ac_name\', None))\n
if REQUEST.has_key(\'portal_skin\'):\n
context.portal_skins.clearSkinCookie()\n
REQUEST.RESPONSE.expireCookie(\'__ac\', path=\'/\')\n
return REQUEST.RESPONSE.redirect(REQUEST.URL1+\'/logged_out\')\n
<value> <string>portal = context.getPortalObject()\n
portal.portal_sessions.manage_delObjects(portal.Base_getAutoLogoutSessionKey())\n
# XXX: I would like to use skinSuper, but this may not be defined on context (it\'s defined on ERP5Type.Base, and context may be ERP5.ERP5Site).\n
# As a result, hardcode expected logout location (which is marginally better than duplicating it).\n
return portal.portal_skins.zpt_control.logout()\n
</string> </value>
</item>
<item>
......
......@@ -172,29 +172,25 @@
<key> <string>_body</string> </key>
<value> <string encoding="cdata"><![CDATA[
from DateTime import DateTime\n
kw = {\'name\': cookie_name,\n
\'value\': cookie_value,\n
\'path\': \'/\'}\n
ac_session_key_pattern = \'ac_cookie_%s\'\n
user_name = context.REQUEST.get(\'__ac_name\', None)\n
expire_interval = context.ERP5Site_getMaxUserInactivityDuration(user_name)\n
\n
# set cookie expire argument only if it\'s defined for current user\n
if expire_interval not in (\'\', None):\n
expire_interval /= 86400. # seconds -> days\n
ac_expires = DateTime() + expire_interval\n
ac_renew = DateTime() + expire_interval / 2\n
kw[\'expires\'] = ac_expires.toZone(\'GMT\').rfc822()\n
# save next \'__ac\' renew time\n
context.portal_sessions[ac_session_key_pattern %user_name][\'ac_renew\'] = ac_renew.millis()\n
portal = context.getPortalObject()\n
kw = {}\n
expire_interval = portal.portal_preferences.getPreferredMaxUserInactivityDuration()\n
if expire_interval in (\'\', None):\n
ac_renew = float(\'inf\')\n
else:\n
# cookie will expire at client browser end of session, \n
# mark it at server side with zero (0)\n
context.portal_sessions[ac_session_key_pattern %user_name][\'ac_renew\'] = 0\n
\n
# set cookie\n
resp.setCookie(**kw)\n
expire_interval /= 86400. # seconds -> days\n
now = DateTime()\n
kw[\'expires\'] = (now + expire_interval).toZone(\'GMT\').rfc822()\n
ac_renew = (now + expire_interval / 2).millis()\n
portal.portal_sessions[portal.Base_getAutoLogoutSessionKey()][\'ac_renew\'] = ac_renew\n
resp.setCookie(\n
name=cookie_name,\n
value=cookie_value,\n
path=\'/\',\n
secure=getattr(portal, \'REQUEST\', {}).get(\'SERVER_URL\', \'\').startswith(\'https:\'),\n
http_only=True,\n
**kw\n
)\n
]]></string> </value>
......
......@@ -172,24 +172,9 @@
<key> <string>_body</string> </key>
<value> <string encoding="cdata"><![CDATA[
# check if required to renew cookie from sessios\n
ac_session_key_pattern = \'ac_cookie_%s\'\n
user_name = context.REQUEST.cookies.get(\'__ac_name\', None)\n
try:\n
session = context.portal_sessions[ac_session_key_pattern %user_name]\n
except KeyError:\n
session = None\n
if session is not None:\n
from DateTime import DateTime\n
now = DateTime()\n
ac_renew = session.get(\'ac_renew\', None)\n
if ac_renew not in (0, None) and now.millis() >= ac_renew:\n
# renew cookie (cookies without expire value will not be renewed)\n
context.setAuthCookie(resp, cookie_name, cookie_value)\n
elif ac_renew is None:\n
# our portal_session at server side might have expired, either\n
# due to a cache expire or server restart, renew cookie anyway\n
context.setAuthCookie(resp, cookie_name, cookie_value)\n
portal = context.getPortalObject()\n
if DateTime().millis() >= portal.portal_sessions[portal.Base_getAutoLogoutSessionKey()].get(\'ac_renew\', 0):\n
portal.setAuthCookie(resp, cookie_name, cookie_value)\n
]]></string> </value>
......
erp5_auto_logout
erp5_core
\ No newline at end of file
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