Commit 22a6aaad authored by Arnaud Fontaine's avatar Arnaud Fontaine

ZODB Components: Migrate Products.ERP5Type.SessionTool from filesystem.

parent e1dd670f
Pipeline #10120 failed with stage
...@@ -31,7 +31,7 @@ import unittest ...@@ -31,7 +31,7 @@ import unittest
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from AccessControl.SecurityManagement import newSecurityManager from AccessControl.SecurityManagement import newSecurityManager
from Products.ERP5Type.tests.Sequence import SequenceList from Products.ERP5Type.tests.Sequence import SequenceList
from Products.ERP5Type.Tool.SessionTool import SESSION_CACHE_FACTORY from erp5.component.tool.SessionTool import SESSION_CACHE_FACTORY
from string import letters as LETTERS from string import letters as LETTERS
from random import choice from random import choice
import time import time
......
...@@ -111,7 +111,6 @@ class DistributedSession(Session): ...@@ -111,7 +111,6 @@ class DistributedSession(Session):
def _updateStorage(self): def _updateStorage(self):
""" Update backend storage. """ """ Update backend storage. """
global storage_plugin
storage_plugin.set(self.session_id, \ storage_plugin.set(self.session_id, \
SESSION_SCOPE, \ SESSION_SCOPE, \
value = self, \ value = self, \
...@@ -130,7 +129,7 @@ class DistributedSession(Session): ...@@ -130,7 +129,7 @@ class DistributedSession(Session):
Session.clear(self) Session.clear(self)
self._updateStorage() self._updateStorage()
def update(self, dict=None, **kwargs): def update(self, dict=None, **kwargs): # pylint: disable=redefined-builtin
Session.update(self, dict, **kwargs) Session.update(self, dict, **kwargs)
self._updateStorage() self._updateStorage()
...@@ -198,13 +197,13 @@ class SessionTool(BaseTool): ...@@ -198,13 +197,13 @@ class SessionTool(BaseTool):
security.declarePrivate('getSession') security.declarePrivate('getSession')
def getSession(self, session_id, session_duration=None): def getSession(self, session_id, session_duration=None):
""" Return session object. """ """ Return session object. """
storage_plugin = self._getStoragePlugin() storage_plugin_ = self._getStoragePlugin()
# expire explicitly as each session can have a different life duration # expire explicitly as each session can have a different life duration
storage_plugin.expireOldCacheEntries(forceCheck=1) storage_plugin_.expireOldCacheEntries(forceCheck=1)
session = storage_plugin.get(session_id, SESSION_SCOPE, None) session = storage_plugin_.get(session_id, SESSION_SCOPE, None)
if session is None: if session is None:
# init it in cache and use different Session types based on cache plugin type used as a storage # init it in cache and use different Session types based on cache plugin type used as a storage
storage_plugin_type = storage_plugin.__class__.__name__ storage_plugin_type = storage_plugin_.__class__.__name__
if storage_plugin_type in ("RamCache",): if storage_plugin_type in ("RamCache",):
session = RamSession() session = RamSession()
elif storage_plugin_type in ("DistributedRamCache",): elif storage_plugin_type in ("DistributedRamCache",):
...@@ -215,14 +214,14 @@ class SessionTool(BaseTool): ...@@ -215,14 +214,14 @@ class SessionTool(BaseTool):
cache_plugin = self.portal_caches[SESSION_CACHE_FACTORY].objectValues()[0] cache_plugin = self.portal_caches[SESSION_CACHE_FACTORY].objectValues()[0]
session_duration = cache_plugin.getCacheDuration() session_duration = cache_plugin.getCacheDuration()
session._updateSessionDuration(session_duration) session._updateSessionDuration(session_duration)
storage_plugin.set(session_id, SESSION_SCOPE, session, session_duration) storage_plugin_.set(session_id, SESSION_SCOPE, session, session_duration)
else: else:
# cache plugin returns wrapper (CacheEntry instance) # cache plugin returns wrapper (CacheEntry instance)
session = session.getValue() session = session.getValue()
return session return session
security.declarePublic('newContent') security.declarePublic('newContent')
def newContent(self, id, **kw): def newContent(self, id, **kw): # pylint: disable=redefined-builtin
""" Create new session object. """ """ Create new session object. """
session = self.getSession(id) session = self.getSession(id)
session._updatecontext(self) session._updatecontext(self)
...@@ -230,16 +229,16 @@ class SessionTool(BaseTool): ...@@ -230,16 +229,16 @@ class SessionTool(BaseTool):
return session return session
security.declareProtected(Permissions.AccessContentsInformation, 'manage_delObjects') security.declareProtected(Permissions.AccessContentsInformation, 'manage_delObjects')
def manage_delObjects(self, ids=[], REQUEST=None): def manage_delObjects(self, ids=(), REQUEST=None, *args, **kw):
""" Delete session object. """ """ Delete session object. """
storage_plugin = self._getStoragePlugin() storage_plugin_ = self._getStoragePlugin()
if not isinstance(ids, (list, tuple)): if not isinstance(ids, (list, tuple)):
ids = [ids] ids = [ids]
for session_id in ids: for session_id in ids:
storage_plugin.delete(session_id, SESSION_SCOPE) storage_plugin_.delete(session_id, SESSION_SCOPE)
def _getStoragePlugin(self): def _getStoragePlugin(self):
""" Get cache storage plugin.""" """ Get cache storage plugin."""
global storage_plugin global storage_plugin # pylint: disable=global-statement
storage_plugin = self.portal_caches.getRamCacheRoot()[SESSION_CACHE_FACTORY].getCachePluginList()[0] storage_plugin = self.portal_caches.getRamCacheRoot()[SESSION_CACHE_FACTORY].getCachePluginList()[0]
return storage_plugin return storage_plugin
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Tool Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SessionTool</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5Type.Tool.SessionTool</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>tool.erp5.SessionTool</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Tool Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -10,5 +10,6 @@ tool.erp5.NotificationTool ...@@ -10,5 +10,6 @@ tool.erp5.NotificationTool
tool.erp5.OrderTool tool.erp5.OrderTool
tool.erp5.PasswordTool tool.erp5.PasswordTool
tool.erp5.RuleTool tool.erp5.RuleTool
tool.erp5.SessionTool
tool.erp5.SimulationTool tool.erp5.SimulationTool
tool.erp5.TestTool tool.erp5.TestTool
\ No newline at end of file
...@@ -88,7 +88,7 @@ import Products.ERP5Type.Workflow ...@@ -88,7 +88,7 @@ import Products.ERP5Type.Workflow
def initialize( context ): def initialize( context ):
# Import Product Components # Import Product Components
from Tool import (CacheTool, MemcachedTool, SessionTool, from Tool import (CacheTool, MemcachedTool,
TypesTool, WebServiceTool, PropertySheetTool, TypesTool, WebServiceTool, PropertySheetTool,
ComponentTool) ComponentTool)
import Document import Document
...@@ -104,7 +104,6 @@ def initialize( context ): ...@@ -104,7 +104,6 @@ def initialize( context ):
ERP5TypeInformation, ) ERP5TypeInformation, )
portal_tools = ( CacheTool.CacheTool, portal_tools = ( CacheTool.CacheTool,
MemcachedTool.MemcachedTool, MemcachedTool.MemcachedTool,
SessionTool.SessionTool,
TypesTool.TypesTool, TypesTool.TypesTool,
WebServiceTool.WebServiceTool, WebServiceTool.WebServiceTool,
PropertySheetTool.PropertySheetTool, PropertySheetTool.PropertySheetTool,
......
  • For reference, this can cause difficulties when products are updated and business template is not yet updated. setAuthCookie here is using session tool to set the user cookie. This fail when session tool is broken (when removed from filesystem but not yet installed by business template).

    There are several easy workarounds, login in from / instead of /erp5 or apply a patch like this:

    diff --git a/product/ERP5Type/patches/CookieCrumbler.py b/product/ERP5Type/patches/CookieCrumbler.py
    index d73385ccbf..91638d7af3 100644
    --- a/product/ERP5Type/patches/CookieCrumbler.py
    +++ b/product/ERP5Type/patches/CookieCrumbler.py
    @@ -145,7 +145,13 @@ def modifyRequest(self, req, resp):
                                 path=self.getCookiePath())
             method = self.getCookieMethod( 'setAuthCookie'
                                            , self.defaultSetAuthCookie )
    +
    +        # XXX make sure we can login when session tool is not yet migrated
    +        from ZODB.broken import PersistentBroken
    +        if isinstance(getattr(self.getPortalObject(), 'portal_sessions', None), PersistentBroken):
    +          method = self.defaultSetAuthCookie
             method( resp, self.auth_cookie, quote( ac ) )
    +
           elif req.has_key(self.auth_cookie):
             # Attempt to resume a session if the cookie is valid.
             # Copy __ac to the auth header.
  • Maybe it would be nice to have a way to run upgrader that does not require any user action.

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