Commit d7356d5a authored by Kazuhiko Shiozaki's avatar Kazuhiko Shiozaki

support unique selection for unique anonymous user using a different storage...

support unique selection for unique anonymous user using a different storage that should be volatile one like memcached. this feature is disabled by default.


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@38249 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 579bc9c9
......@@ -43,6 +43,8 @@ from Products.ERP5Form.Selection import Selection, DomainSelection
from ZPublisher.HTTPRequest import FileUpload
import md5
import string, re
from time import time
from random import random
from urlparse import urlsplit, urlunsplit
from zLOG import LOG, INFO
from Acquisition import aq_base
......@@ -139,14 +141,19 @@ class SelectionTool( BaseTool, SimpleItem ):
return storage_item_list
security.declareProtected( ERP5Permissions.ManagePortal, 'setStorage')
def setStorage(self, value, RESPONSE=None):
def setStorage(self, storage, anonymous_storage=None, RESPONSE=None):
"""
Set the storage of Selection Tool.
"""
if value in [item[1] for item in self.getStorageItemList()]:
self.storage = value
if storage in [item[1] for item in self.getStorageItemList()]:
self.storage = storage
else:
raise ValueError, 'Given storage type (%s) is now supported.' % (value,)
raise ValueError, 'Given storage type (%s) is now supported.' % (storage,)
anonymous_storage = anonymous_storage or None
if anonymous_storage in [item[1] for item in self.getStorageItemList()] + [None]:
self.anonymous_storage = anonymous_storage
else:
raise ValueError, 'Given storage type (%s) is now supported.' % (anonymous_storage,)
if RESPONSE is not None:
RESPONSE.redirect('%s/manage_configure' % (self.absolute_url()))
......@@ -167,6 +174,12 @@ class SelectionTool( BaseTool, SimpleItem ):
storage = 'selection_data'
return storage
security.declareProtected( ERP5Permissions.ManagePortal, 'getAnonymousStorage')
def getAnonymousStorage(self, default=None):
"""return the selected storage
"""
return getattr(aq_base(self), 'anonymous_storage', default)
def _redirectToOriginalForm(self, REQUEST=None, form_id=None, dialog_id=None,
query_string=None,
no_reset=False, no_report_depth=False):
......@@ -267,6 +280,9 @@ class SelectionTool( BaseTool, SimpleItem ):
"""
if not selection_name:
return
if self._isAnonymous():
self.REQUEST.response.setCookie('anonymous_uid',
self.REQUEST.get('anonymous_uid'))
if selection_object != None:
# Set the name so that this selection itself can get its own name.
selection_object.edit(name=selection_name)
......@@ -1365,9 +1381,19 @@ class SelectionTool( BaseTool, SimpleItem ):
return SelectionTool.inheritedAttribute('_aq_dynamic')(self, name)
def _getUserId(self):
return self.portal_membership.getAuthenticatedMember().getUserName()
# XXX It would be good to add somthing here
# So that 2 anonymous users do not share the same selection
tv = getTransactionalVariable(self)
user_id = tv.get('_user_id', None)
if user_id is not None:
return user_id
user_id = self.portal_membership.getAuthenticatedMember().getUserName()
if user_id == 'Anonymous User' and self.getAnonymousStorage() is not None:
anonymous_uid = self.REQUEST.get('anonymous_uid', None)
if anonymous_uid is None:
anonymous_uid = md5.new('%s.%s' % (time(), random())).hexdigest()
self.REQUEST['anonymous_uid'] = anonymous_uid
user_id = 'Anonymous:%s' % anonymous_uid
tv['_user_id'] = user_id
return user_id
def getTemporarySelectionDict(self):
""" Temporary selections are used in push/pop nested scope,
......@@ -1432,9 +1458,16 @@ class SelectionTool( BaseTool, SimpleItem ):
return list(set(self._getContainer().getSelectionNameList(user_id) + \
self.getTemporarySelectionDict().keys()))
def _isAnonymous(self):
return self.portal_membership.isAnonymousUser()
def _getContainer(self):
container_id = '_v_selection_container'
storage = self.getStorage()
if self._isAnonymous():
container_id = '_v_anonymous_selection_container'
storage = self.getAnonymousStorage()
else:
container_id = '_v_selection_container'
storage = self.getStorage()
container = getattr(aq_base(self), container_id, None)
if container is None:
if storage.startswith('portal_memcached/'):
......
......@@ -5,22 +5,12 @@
<p>
Selection Tool supports Memcached Tool and Persistent Mapping for its storage.
</p>
<div>
<dtml-let storage_item_list="getStorageItemList()">
<dtml-in prefix="store" name="storage_item_list">
<dtml-let storage="store_item[1]"
storage_title="store_item[0]"
selected="storage == getStorage()">
<dtml-if selected>
Current setting: <dtml-var storage_title html_quote>
</dtml-if>
</dtml-let>
</dtml-in>
</dtml-let>
</div>
<form action="setStorage" method="post">
<select name="value">
<h4>
Storage for logged-in users' Selection objects.
</h4>
<select name="storage">
<dtml-let storage_item_list="getStorageItemList()">
<dtml-in prefix="store" name="storage_item_list">
<dtml-let storage="store_item[1]"
......@@ -31,7 +21,27 @@
</dtml-in>
</dtml-let>
</select>
<input type="submit" value="Change"/>
<h4>
Storage for anonymous users' Selection objects.
</h4>
<p>
You can specify another storage to store unique Selection objects for each anonymous user. If you select nothing here, the same Selection object will be shared for all anonymous users and will be stored in the storage selected above. Using a volatile storage (like memcached) is highly recommended.
</p>
<select name="anonymous_storage">
<option value="">&nbsp;</option>
<dtml-let storage_item_list="getStorageItemList()">
<dtml-in prefix="store" name="storage_item_list">
<dtml-let storage="store_item[1]"
storage_title="store_item[0]"
selected="storage == getAnonymousStorage() and 'selected' or ''">
<option value="&dtml-storage;" &dtml-selected;>&dtml-storage_title;</option>
</dtml-let>
</dtml-in>
</dtml-let>
</select>
<p>
<input type="submit" value="Change"/>
</p>
</form>
<dtml-var manage_page_footer>
......@@ -246,6 +246,7 @@ class TestSelectionPersistence(unittest.TestCase):
# find the current user name
SelectionTool._getUserId_saved = SelectionTool._getUserId
SelectionTool._getUserId = lambda self: 'user'
SelectionTool._isAnonymous = lambda self: 0
self.db = ZODButil.makeDB()
self.cnx = self.db.open()
......
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