[Checkins] SVN: Products.CMFCore/trunk/Products/CMFCore/ - split up MemberData class
Yvo Schubbe
y.2011 at wcm-solutions.de
Tue Feb 22 05:33:41 EST 2011
Log message for revision 120512:
- split up MemberData class
Changed:
U Products.CMFCore/trunk/Products/CMFCore/CHANGES.txt
U Products.CMFCore/trunk/Products/CMFCore/MemberDataTool.py
U Products.CMFCore/trunk/Products/CMFCore/tests/test_MemberDataTool.py
U Products.CMFCore/trunk/Products/CMFCore/tool.zcml
-=-
Modified: Products.CMFCore/trunk/Products/CMFCore/CHANGES.txt
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/CHANGES.txt 2011-02-22 10:04:27 UTC (rev 120511)
+++ Products.CMFCore/trunk/Products/CMFCore/CHANGES.txt 2011-02-22 10:33:40 UTC (rev 120512)
@@ -4,6 +4,10 @@
2.3.0-alpha (unreleased)
------------------------
+- MemberDataTool: Split up MemberData class.
+ The old MemberData API is now provided by the new MemberAdapter. The
+ persistent MemberData objects are just used for storing member data.
+
- interfaces: Added 'IMember' interface.
- permissions: Marked 'setDefaultRoles' as deprecated.
Modified: Products.CMFCore/trunk/Products/CMFCore/MemberDataTool.py
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/MemberDataTool.py 2011-02-22 10:04:27 UTC (rev 120511)
+++ Products.CMFCore/trunk/Products/CMFCore/MemberDataTool.py 2011-02-22 10:33:40 UTC (rev 120512)
@@ -13,13 +13,19 @@
""" Basic member data tool.
"""
+from AccessControl.interfaces import IUser
from AccessControl.SecurityInfo import ClassSecurityInfo
-from Acquisition import aq_inner, aq_parent, aq_base
+from Acquisition import aq_base
+from Acquisition import aq_inner
+from Acquisition import aq_parent
from App.class_init import InitializeClass
from App.special_dtml import DTMLFile
from BTrees.OOBTree import OOBTree
from OFS.PropertyManager import PropertyManager
from OFS.SimpleItem import SimpleItem
+from Persistence import Persistent
+from zope.component import adapts
+from zope.component import getMultiAdapter
from zope.component import queryUtility
from zope.component.factory import Factory
from zope.component.interfaces import IFactory
@@ -191,17 +197,7 @@
If possible, returns the Member object that corresponds
to the given User object.
'''
- id = u.getId()
- members = self._members
- if not id in members:
- member_factory = queryUtility(IFactory, u'MemberData')
- if member_factory is None:
- member_factory = MemberData
- base = aq_base(self)
- members[id] = member_factory(base, id)
- # Return a wrapper with self as containment and
- # the user as context.
- return members[id].__of__(self).__of__(u)
+ return getMultiAdapter((u, self), IMember)
security.declarePrivate('registerMemberData')
def registerMemberData(self, m, id):
@@ -224,39 +220,50 @@
registerToolInterface('portal_memberdata', IMemberDataTool)
-class MemberData(SimpleItem):
+class MemberData(Persistent):
+ def __init__(self, id):
+ self.id = id
+
+memberFactory = Factory(MemberData)
+
+
+class MemberAdapter(object):
+
+ """Member data adapter.
+ """
+
+ adapts(IUser, IMemberDataTool)
implements(IMember)
security = ClassSecurityInfo()
- def __init__(self, tool, id):
- self.id = id
+ def __init__(self, user, tool):
+ self._user = user
+ self._tool = tool
+ self.__parent__ = aq_parent(aq_inner(user))
+ id = user.getId()
+ members = tool._members
+ if not id in members:
+ member_factory = queryUtility(IFactory, u'MemberData')
+ if member_factory is None:
+ member_factory = MemberData
+ members[id] = member_factory(id)
+ self._md = members[id]
+
security.declarePrivate('notifyModified')
def notifyModified(self):
# Links self to parent for full persistence.
- self.getTool().registerMemberData(self, self.getId())
+ self._tool.registerMemberData(self._md, self.getId())
security.declarePublic('getUser')
def getUser(self):
- # The user object is our context, but it's possible for
- # restricted code to strip context while retaining
- # containment. Therefore we need a simple security check.
- parent = aq_parent(self)
- bcontext = aq_base(parent)
- bcontainer = aq_base(aq_parent(aq_inner(self)))
- if bcontext is bcontainer or not hasattr(bcontext, 'getUserName'):
- raise 'MemberDataError', "Can't find user data"
- # Return the user object, which is our context.
- return parent
+ return self._user
- def getTool(self):
- return aq_parent(aq_inner(self))
-
security.declarePublic('getMemberId')
def getMemberId(self):
- return self.getUser().getId()
+ return self._user.getId()
security.declareProtected(SetOwnProperties, 'setProperties')
def setProperties(self, properties=None, **kw):
@@ -268,8 +275,8 @@
# it depends on a non-utility tool
if properties is None:
properties = kw
- membership = getToolByName(self, 'portal_membership')
- registration = getToolByName(self, 'portal_registration', None)
+ membership = getToolByName(self._tool, 'portal_membership')
+ registration = getToolByName(self._tool, 'portal_registration', None)
if not membership.isAnonymousUser():
member = membership.getAuthenticatedMember()
if registration:
@@ -285,33 +292,29 @@
'''Sets the properties of the member.
'''
# Sets the properties given in the MemberDataTool.
- tool = self.getTool()
+ tool = self._tool
for id in tool.propertyIds():
if mapping.has_key(id):
- if not self.__class__.__dict__.has_key(id):
+ if not self._md.__class__.__dict__.has_key(id):
value = mapping[id]
- if type(value)==type(''):
+ if isinstance(value, str):
proptype = tool.getPropertyType(id) or 'string'
if type_converters.has_key(proptype):
value = type_converters[proptype](value)
- setattr(self, id, value)
+ setattr(self._md, id, value)
# Hopefully we can later make notifyModified() implicit.
self.notifyModified()
security.declarePublic('getProperty')
def getProperty(self, id, default=_marker):
-
- tool = self.getTool()
- base = aq_base( self )
-
# First, check the wrapper (w/o acquisition).
- value = getattr( base, id, _marker )
+ value = getattr(self._md, id, _marker)
if value is not _marker:
return value
# Then, check the tool and the user object for a value.
- tool_value = tool.getProperty( id, _marker )
- user_value = getattr( self.getUser(), id, _marker )
+ tool_value = self._tool.getProperty(id, _marker)
+ user_value = getattr(self._user, id, _marker)
# If the tool doesn't have the property, use user_value or default
if tool_value is _marker:
@@ -332,12 +335,12 @@
security.declarePrivate('getPassword')
def getPassword(self):
"""Return the password of the user."""
- return self.getUser()._getPassword()
+ return self._user._getPassword()
security.declarePrivate('setSecurityProfile')
def setSecurityProfile(self, password=None, roles=None, domains=None):
"""Set the user's basic security profile"""
- u = self.getUser()
+ u = self._user
# The Zope User API is stupid, it should check for None.
if roles is None:
@@ -350,7 +353,7 @@
u.userFolderEditUser(u.getId(), password, roles, domains)
def __str__(self):
- return self.getMemberId()
+ return self._user.getId()
#
# 'IUser' interface methods
@@ -359,40 +362,38 @@
def getId(self):
"""Get the ID of the user.
"""
- return self.getUser().getId()
+ return self._user.getId()
security.declarePublic('getUserName')
def getUserName(self):
"""Get the name used by the user to log into the system.
"""
- return self.getUser().getUserName()
+ return self._user.getUserName()
security.declarePublic('getRoles')
def getRoles(self):
"""Get a sequence of the global roles assigned to the user.
"""
- return self.getUser().getRoles()
+ return self._user.getRoles()
security.declarePublic('getRolesInContext')
def getRolesInContext(self, object):
"""Get a sequence of the roles assigned to the user in a context.
"""
- return self.getUser().getRolesInContext(object)
+ return self._user.getRolesInContext(object)
security.declarePublic('getDomains')
def getDomains(self):
"""Get a sequence of the domain restrictions for the user.
"""
- return self.getUser().getDomains()
+ return self._user.getDomains()
security.declarePublic('has_role')
def has_role(self, roles, object=None):
"""Check to see if a user has a given role or roles."""
- return self.getUser().has_role(roles, object)
+ return self._user.has_role(roles, object)
# There are other parts of the interface but they are
# deprecated for use with CMF applications.
-InitializeClass(MemberData)
-
-memberFactory = Factory(MemberData)
+InitializeClass(MemberAdapter)
Modified: Products.CMFCore/trunk/Products/CMFCore/tests/test_MemberDataTool.py
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/tests/test_MemberDataTool.py 2011-02-22 10:04:27 UTC (rev 120511)
+++ Products.CMFCore/trunk/Products/CMFCore/tests/test_MemberDataTool.py 2011-02-22 10:33:40 UTC (rev 120512)
@@ -65,9 +65,10 @@
class DummyMemberDataTool(Acquisition.Implicit):
- pass
+ _members = {}
+
class MemberDataToolTests(unittest.TestCase):
def _getTargetClass(self):
@@ -78,9 +79,6 @@
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
- def tearDown(self):
- cleanUp()
-
def test_interfaces(self):
from Products.CMFCore.interfaces import IMemberDataTool
@@ -123,32 +121,24 @@
self.assertEqual(info_dict['member_count'], 0)
self.assertEqual(info_dict['orphan_count'], 0)
- def test_switching_memberdata_factory(self):
- from Products.CMFCore.MemberDataTool import MemberData
- tool = self._makeOne()
- user = DummyUser('dummy', '', [], [])
- member = Acquisition.aq_base(tool.wrapUser(user))
- self.assertEquals(getattr(member, 'iamnew', None), None)
- class NewMemberData(MemberData):
- iamnew = 'yes'
- provideUtility(NewMemberData, IFactory, 'MemberData')
+class MemberAdapterTests(unittest.TestCase):
- user = DummyUser('dummy2', '', [], [])
- member = Acquisition.aq_base(tool.wrapUser(user))
- self.assertEquals(getattr(member, 'iamnew', None), 'yes')
-
-
-class MemberDataTests(unittest.TestCase):
-
def _getTargetClass(self):
- from Products.CMFCore.MemberDataTool import MemberData
+ from Products.CMFCore.MemberDataTool import MemberAdapter
- return MemberData
+ return MemberAdapter
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
+ def setUp(self):
+ self.mdtool = DummyMemberDataTool()
+ self.aclu = DummyUserFolder()
+
+ def tearDown(self):
+ cleanUp()
+
def test_interfaces(self):
from AccessControl.interfaces import IUser
from Products.CMFCore.interfaces import IMember
@@ -159,12 +149,10 @@
verifyClass(IUser, self._getTargetClass())
def test_setSecurityProfile(self):
- mdtool = DummyMemberDataTool()
- aclu = DummyUserFolder()
user = DummyUser('bob', 'pw', ['Role'], ['domain'])
- aclu._addUser(user)
- user = user.__of__(aclu)
- member = self._makeOne(None, 'bob').__of__(mdtool).__of__(user)
+ self.aclu._addUser(user)
+ user = user.__of__(self.aclu)
+ member = self._makeOne(user, self.mdtool)
member.setSecurityProfile(password='newpw')
self.assertEqual(user.__, 'newpw')
self.assertEqual(list(user.roles), ['Role'])
@@ -178,9 +166,24 @@
self.assertEqual(list(user.roles), ['NewRole'])
self.assertEqual(list(user.domains), ['newdomain'])
+ def test_switching_memberdata_factory(self):
+ from Products.CMFCore.MemberDataTool import MemberData
+ user1 = DummyUser('dummy', '', [], []).__of__(self.aclu)
+ member = self._makeOne(user1, self.mdtool)
+ self.assertEqual(getattr(member._md, 'iamnew', None), None)
+
+ class NewMemberData(MemberData):
+ iamnew = 'yes'
+ provideUtility(NewMemberData, IFactory, 'MemberData')
+
+ user2 = DummyUser('dummy2', '', [], []).__of__(self.aclu)
+ member = self._makeOne(user2, self.mdtool)
+ self.assertEqual(getattr(member._md, 'iamnew', None), 'yes')
+
+
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(MemberDataToolTests),
- unittest.makeSuite(MemberDataTests),
+ unittest.makeSuite(MemberAdapterTests),
))
Modified: Products.CMFCore/trunk/Products/CMFCore/tool.zcml
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/tool.zcml 2011-02-22 10:04:27 UTC (rev 120511)
+++ Products.CMFCore/trunk/Products/CMFCore/tool.zcml 2011-02-22 10:33:40 UTC (rev 120512)
@@ -41,6 +41,8 @@
name="MemberData"
/>
+ <adapter factory=".MemberDataTool.MemberAdapter"/>
+
<adapter factory=".WorkflowTool.DefaultWorkflowStatus" />
<adapter factory=".WorkflowTool.default_workflow_history" />
More information about the checkins
mailing list