X-Git-Url: https://svn.cri.ensmp.fr/git/Plinn.git/blobdiff_plain/b3b52f5b0ad754fd9036f816d0ab8e98a5373f40..f1ca43660dc87bfce8b9838102dac0c10f4d5d31:/MembershipTool.py diff --git a/MembershipTool.py b/MembershipTool.py index 29960e7..3b3da9a 100755 --- a/MembershipTool.py +++ b/MembershipTool.py @@ -19,8 +19,8 @@ ####################################################################################### """ Plinn portal_membership -$Id: MembershipTool.py 1547 2010-01-05 16:24:22Z pin $ -$URL: http://svn.cri.ensmp.fr/svn/Plinn/branches/CMF-2.1/MembershipTool.py $ + + """ from AccessControl import ClassSecurityInfo, getSecurityManager @@ -35,7 +35,8 @@ from Products.CMFDefault.MembershipTool import MembershipTool as BaseTool from Products.CMFCore.permissions import View, ListPortalMembers, ManagePortal, SetOwnPassword, ChangePermissions from permissions import RemoveMember, SetLocalRoles, CheckMemberPermission from utils import _checkMemberPermission -from Products.CMFCore.utils import getToolByName, _checkPermission, _getAuthenticatedUser +from Products.CMFCore.utils import _checkPermission, _getAuthenticatedUser +from Products.CMFCore.utils import getUtilityByInterfaceName from utils import formatFullName, translate from Products.CMFDefault.utils import decode from Products.CMFDefault.Document import addDocument @@ -50,418 +51,381 @@ console = getLogger('Plinn.MembershipTool') class MembershipTool( BaseTool ): - """ Implement 'portal_membership' interface using "stock" policies. - """ - - - meta_type = 'Plinn Membership Tool' - - manage_options=( ({ 'label' : 'Configuration' - , 'action' : 'manage_mapRoles' - },) + BaseTool.manage_options[1:]) - - security = ClassSecurityInfo() - - security.declareProtected(ManagePortal, 'manage_mapRoles') - manage_mapRoles = PageTemplateFile('www/configureMembershipTool', globals(), - __name__='manage_mapRoles') - - # - # 'portal_membership' interface methods - # - - # change security settings for inherited methods - security.declareProtected(ListPortalMembers, 'getMemberById') - - - memberareaPortalType = 'Folder' - - - security.declareProtected(SetOwnPassword, 'setPassword') - def setPassword(self, password, domains=None): - '''Allows the authenticated member to set his/her own password. - ''' - user_folder = self.__getPUS() - if user_folder.meta_type == 'Group User Folder' : - registration = getToolByName(self, 'portal_registration', None) - if not self.isAnonymousUser(): - member = self.getAuthenticatedMember() - if registration: - failMessage = registration.testPasswordValidity(password) - if failMessage is not None: - raise 'Bad Request', failMessage - member.setSecurityProfile(password=password, domains=domains) - member.changePassword(password) - else: - raise 'Bad Request', 'Not logged in.' - - else : - BaseTool.setPassword(self, password, domains=None) - - - - security.declareProtected(ListPortalMembers, 'listMemberIds') - def listMemberIds(self): - '''Lists the ids of all members. This may eventually be - replaced with a set of methods for querying pieces of the - list rather than the entire list at once. - ''' - user_folder = self.__getPUS() - if user_folder.meta_type == 'Group User Folder' : - return user_folder.getPureUserNames() - else : - return [ x.getId() for x in user_folder.getUsers() ] - - - security.declareProtected(CheckMemberPermission, 'checkMemberPermission') - def checkMemberPermission(self, userid, permissionName, object, subobjectName=None): - ''' - Checks whether the current user has the given permission on - the given object or subobject. - ''' - if subobjectName is not None: - object = getattr(object, subobjectName) - - return _checkMemberPermission(userid, permissionName, object) - - security.declareProtected(ListPortalMembers, 'listMembers') - def listMembers(self): - '''Gets the list of all members. - ''' - user_folder = self.__getPUS() - if user_folder.meta_type == 'Group User Folder' : - return map(self.wrapUser, user_folder.getPureUsers()) - else : - return map(self.wrapUser, user_folder.getUsers()) - - - security.declareProtected(View, 'getCandidateLocalRoles') - def getCandidateLocalRoles(self, obj) : - """ What local roles can I assign? - """ - member = self.getAuthenticatedMember() - valid_roles = obj.valid_roles() - if 'Manager' in member.getRoles(): - local_roles = [r for r in valid_roles if r != 'Anonymous'] - else: - sm = getSecurityManager() - allPermissions = self.ac_inherited_permissions(1) - - # construct a dictionary of permissions indexed by role - # and get permissions of user in obj context - memberPermissions = Set() - rolesMappings = {} - for role in valid_roles : - rolesMappings[role] = Set() - - for p in allPermissions: - name, value = p[:2] - - p=Permission(name,value,obj) - rolesOfPerm = p.getRoles() - - for role in rolesOfPerm : - try : rolesMappings[role].add(name) - except KeyError : - trName = p._p - if hasattr(obj, trName): - l = list(getattr(obj, trName)) - l.remove(role) - setattr(obj, trName, tuple(l)) - msg = '%s role has been removed for %s permission on %s ' % (role, name, obj.absolute_url()) - #LOG('portal_membership', WARNING, msg) - - parent = obj.aq_inner.aq_parent - while type(rolesOfPerm) != TupleType : - p=Permission(name, value, parent) - rolesOfPerm = p.getRoles() - for role in rolesOfPerm : - try : rolesMappings[role].add(name) - except KeyError : pass - try : parent = parent.aq_inner.aq_parent - except AttributeError : break - - - if sm.checkPermission(name, obj) : - memberPermissions.add(name) - - local_roles = [] - for role in valid_roles : - if rolesMappings[role] and rolesMappings[role].issubset(memberPermissions) : - local_roles.append(role) - - local_roles = [ role for role in local_roles if role not in ('Shared', 'Authenticated', 'Member', 'Anonymous') ] - local_roles.sort() - return tuple(local_roles) - - - security.declareProtected(View, 'setLocalRoles') - def setLocalRoles( self, obj, member_ids, role, remove=0, reindex=1 ): - """ Set local roles on an item """ - if role not in self.getCandidateLocalRoles(obj) : - raise Unauthorized, "You are not allowed to manage %s role" % role - - if self.checkPermission(SetLocalRoles, obj) : - if not remove : - for member_id in member_ids : - # current roles for user id in obj - roles = list(obj.get_local_roles_for_userid( userid=member_id )) - if role not in roles : - roles.append(role) - obj.manage_setLocalRoles( member_id, roles) - else : - for member_id in member_ids : - # current roles for user id in obj - roles = list(obj.get_local_roles_for_userid( userid=member_id )) - try : roles.remove(role) - except ValueError : pass - else : - if len(roles) >= 1 : - obj.manage_setLocalRoles( member_id, roles) - else : - obj.manage_delLocalRoles( userids=[member_id] ) - - else : - raise Unauthorized - - if reindex: - # It is assumed that all objects have the method - # reindexObjectSecurity, which is in CMFCatalogAware and - # thus PortalContent and PortalFolder. - obj.reindexObjectSecurity() - - - security.declarePublic('getMemberFullNameById') - def getMemberFullNameById(self, userid, nameBefore = 1) : - """ Return the best formated representation of user fullname. """ - - memberFullName = '' - if userid and userid != 'No owner' : - # No owner is a possible value returned by DefaultDublinCoreImpl.Creator - member = self.getMemberById(userid) - if not member : - return userid - memberName = getattr(member, 'name', '') - memberGivenName = getattr(member, 'given_name', '') - memberId = member.id - memberFullName = formatFullName(memberName, memberGivenName, memberId, nameBefore = nameBefore) - - return memberFullName - - security.declareProtected(ListPortalMembers, 'getMembers') - def getMembers(self, users) : - """ Return wraped users """ - members = [] - for user in users : - members.append(self.getMemberById(user)) - - members = filter(None, members) - members.sort( lambda m0, m1 : cmp(m0.getMemberSortableFormat(), m1.getMemberSortableFormat()) ) - return members - - - security.declareProtected(ListPortalMembers, 'getOtherMembers') - def getOtherMembers(self, users) : - """ Return members who are not in users list""" - allMemberIds = self.listMemberIds() - otherMemberIds = [ userId for userId in allMemberIds if userId not in users ] - return self.getMembers(otherMemberIds) - - - - security.declareProtected(ListPortalMembers, 'getMembersMetadata') - def getMembersMetadata(self, users) : - """ return metadatas from portal_catalog """ - userDict = {} - for u in users : userDict[u] = True - ctool = getToolByName(self, 'portal_catalog') - memberBrains = ctool(portal_type='Member Data', sort_on='getMemberSortableFormat') - memberList = [] - complementList = [] - - if users : - for mb in memberBrains : - metadatas = {'id' : mb.getId, 'fullname' : mb.getMemberFullName} - if userDict.has_key(mb.getId) : - memberList.append(metadatas) - else : - complementList.append(metadatas) - else : - complementList = [{'id' : mb.getId, 'fullname' : mb.getMemberFullName} for mb in memberBrains] - - return {'memberList' : memberList, 'complementList' : complementList} - - - - security.declareProtected(RemoveMember, 'removeMembers') - def removeMembers(self, memberIds = []) : - """ remove member - """ - # TODO : remove member document ? - mdtool = getToolByName(self, 'portal_memberdata') - for m in self.getMembers(memberIds) : - m.manage_beforeDelete() - mdtool.deleteMemberData(m.getId()) - - self.aq_inner.acl_users.deleteUsers(users = memberIds) - - - - security.declareProtected(ManagePortal, 'setMemberAreaPortalType') - def setMemberAreaPortalType(self, member_folder_portal_type): - """ Set member area portal type to construct.""" - ttool = getToolByName(self, 'portal_types') - if member_folder_portal_type not in ttool.objectIds() : - raise ValueError, "Unknown portal type : %s" % str(member_folder_portal_type) - - self.memberareaPortalType = member_folder_portal_type - return MessageDialog(title ='Type updated', - message='The member area type have been updated', - action ='manage_mapRoles') - - def getMemberAreaPortalType(self) : - return self.memberareaPortalType - - - def getHomeFolder(self, id=None, verifyPermission=0): - """ Return a member's home folder object, or None. - """ - if id is None: - member = self.getAuthenticatedMember() - if not hasattr(member, 'getMemberId'): - return None - id = member.getMemberId() - members = self.getMembersFolder() - if members is not None: - if not hasattr(members, id) and getattr(self, 'memberareaCreationFlag', 0) != 0 : - self.createMemberArea(id) - try: - folder = members._getOb(id) - if verifyPermission and not _checkPermission(View, folder): - # Don't return the folder if the user can't get to it. - return None - return folder - except (AttributeError, TypeError, KeyError): - pass - return None - - security.declarePublic('createMemberArea') - def createMemberArea(self, member_id=''): - """ Create a member area for 'member_id' or authenticated user. - """ - if not self.getMemberareaCreationFlag(): - return None - members = self.getMembersFolder() - if not members: - return None - if self.isAnonymousUser(): - return None - # Note: We can't use getAuthenticatedMember() and getMemberById() - # because they might be wrapped by MemberDataTool. - user = _getAuthenticatedUser(self) - user_id = user.getId() - if member_id in ('', user_id): - member = user - member_id = user_id - else: - if _checkPermission(ManageUsers, self): - member = self.acl_users.getUserById(member_id, None) - if member: - member = member.__of__(self.acl_users) - else: - raise ValueError, 'Member %s does not exist' % member_id - else: - return None - - if hasattr( aq_base(members), member_id ): - return None - - ttool = getToolByName(self, 'portal_types') - info = getattr(ttool, self.memberareaPortalType) - - f = info._constructInstance( members, member_id ) - memberFullName = self.getMemberFullNameById(member_id, nameBefore = 0) - - # Grant Ownership and Owner role to Member - f.changeOwnership(user) - f.__ac_local_roles__ = None - f.manage_setLocalRoles(member_id, ['Owner']) - - f.setTitle(memberFullName) - info._finishConstruction(f) - - # Create Member's initial content. - if hasattr(self, 'createMemberContent') : - self.createMemberContent(member=user, - member_id=member_id, - member_folder=f) - else : - def _(message, context, expand=()) : - trmessage = decode(translate(message, context), context) - expand = tuple([decode(e, context) for e in expand]) - return (trmessage % expand).encode('utf-8') - - # Create Member's home page. - addDocument( f - , 'index_html' - , title = _("%s's Home", self, (memberFullName,)) - , description = _("%s's front page", self, (memberFullName,)) - , text_format = "html" - , text = self.default_member_content(memberFullName=memberFullName).encode('utf-8') - ) - - # Grant Ownership and Owner role to Member - f.index_html.changeOwnership(user) - f.index_html.__ac_local_roles__ = None - f.index_html.manage_setLocalRoles(member_id, ['Owner']) - - f.index_html._setPortalTypeName( 'Document' ) - - # Overcome an apparent catalog bug. - f.index_html.reindexObject() - wftool = getToolByName( f, 'portal_workflow' ) - wftool.notifyCreated( f.index_html ) - - return f - - - security.declareProtected(ListPortalMembers, 'looseSearchMembers') - def looseSearchMembers(self, searchString) : - """ """ - - words = searchString.strip().split() - words = [word.lower() for word in words] - - mdtool = getToolByName(self, 'portal_memberdata') - mdProperties = mdtool.propertyIds() - searchableProperties = [ p['id'] for p in mdtool.propertyMap() if p['type'] == 'string' ] + ['id'] - try : searchableProperties.remove('portal_skin') - except ValueError : pass - - match = [] - for m in self.listMembers() : - allWordsMatch = False - for word in words : - for p in searchableProperties : - if str(m.getProperty(p, '')).lower().find(word) != -1 : - allWordsMatch = True - break - else : - allWordsMatch = False - - if not allWordsMatch : - break - else : - match.append(m) - - return match - - def __getPUS(self): - # CMFCore.MembershipTool.MembershipTool tests 'getUsers' method but : - # "enumeration" methods ('getUserNames', 'getUsers') are *not* - # part of the contract! See IEnumerableUserFolder. - # (from PluggableAuthService.interfaces.authservice #233) - return self.acl_users - - + """ Implement 'portal_membership' interface using "stock" policies. + """ + + + meta_type = 'Plinn Membership Tool' + + manage_options=( ({ 'label' : 'Configuration' + , 'action' : 'manage_mapRoles' + },) + BaseTool.manage_options[1:]) + + security = ClassSecurityInfo() + + security.declareProtected(ManagePortal, 'manage_mapRoles') + manage_mapRoles = PageTemplateFile('www/configureMembershipTool', globals(), + __name__='manage_mapRoles') + + # + # 'portal_membership' interface methods + # + + # change security settings for inherited methods + security.declareProtected(ListPortalMembers, 'getMemberById') + + + memberareaPortalType = 'Huge Plinn Folder' + + +# security.declareProtected(SetOwnPassword, 'setPassword') +# def setPassword(self, password, domains=None): +# '''Allows the authenticated member to set his/her own password. +# ''' +# user_folder = self.__getPUS() +# if user_folder.meta_type == 'Group User Folder' : +# registration = getToolByName(self, 'portal_registration', None) +# if not self.isAnonymousUser(): +# member = self.getAuthenticatedMember() +# if registration: +# failMessage = registration.testPasswordValidity(password) +# if failMessage is not None: +# raise 'Bad Request', failMessage +# member.setSecurityProfile(password=password, domains=domains) +# member.changePassword(password) +# else: +# raise 'Bad Request', 'Not logged in.' +# +# else : +# BaseTool.setPassword(self, password, domains=None) + + + + security.declareProtected(ListPortalMembers, 'listMemberIds') + def listMemberIds(self): + '''Lists the ids of all members. This may eventually be + replaced with a set of methods for querying pieces of the + list rather than the entire list at once. + ''' + user_folder = self.__getPUS() + if user_folder.meta_type == 'Group User Folder' : + return user_folder.getPureUserNames() + else : + return [ x.getId() for x in user_folder.getUsers() ] + + + security.declareProtected(CheckMemberPermission, 'checkMemberPermission') + def checkMemberPermission(self, userid, permissionName, object, subobjectName=None): + ''' + Checks whether the current user has the given permission on + the given object or subobject. + ''' + if subobjectName is not None: + object = getattr(object, subobjectName) + + return _checkMemberPermission(userid, permissionName, object) + + security.declareProtected(ListPortalMembers, 'listMembers') + def listMembers(self): + '''Gets the list of all members. + ''' + user_folder = self.__getPUS() + if user_folder.meta_type == 'Group User Folder' : + return map(self.wrapUser, user_folder.getPureUsers()) + else : + return map(self.wrapUser, user_folder.getUsers()) + + + security.declareProtected(View, 'getCandidateLocalRoles') + def getCandidateLocalRoles(self, obj) : + """ What local roles can I assign? + """ + member = self.getAuthenticatedMember() + valid_roles = obj.valid_roles() + if 'Manager' in member.getRoles(): + local_roles = [r for r in valid_roles if r != 'Anonymous'] + else: + sm = getSecurityManager() + allPermissions = self.ac_inherited_permissions(1) + + # construct a dictionary of permissions indexed by role + # and get permissions of user in obj context + memberPermissions = Set() + rolesMappings = {} + for role in valid_roles : + rolesMappings[role] = Set() + + for p in allPermissions: + name, value = p[:2] + + p=Permission(name,value,obj) + rolesOfPerm = p.getRoles() + + for role in rolesOfPerm : + try : rolesMappings[role].add(name) + except KeyError : + trName = p._p + if hasattr(obj, trName): + l = list(getattr(obj, trName)) + l.remove(role) + setattr(obj, trName, tuple(l)) + msg = '%s role has been removed for %s permission on %s ' % (role, name, obj.absolute_url()) + #LOG('portal_membership', WARNING, msg) + + parent = obj.aq_inner.aq_parent + while type(rolesOfPerm) != TupleType : + p=Permission(name, value, parent) + rolesOfPerm = p.getRoles() + for role in rolesOfPerm : + try : rolesMappings[role].add(name) + except KeyError : pass + try : parent = parent.aq_inner.aq_parent + except AttributeError : break + + + if sm.checkPermission(name, obj) : + memberPermissions.add(name) + + local_roles = [] + for role in valid_roles : + if rolesMappings[role] and rolesMappings[role].issubset(memberPermissions) : + local_roles.append(role) + + local_roles = [ role for role in local_roles if role not in ('Shared', 'Authenticated', 'Member', 'Anonymous') ] + local_roles.sort() + return tuple(local_roles) + + + security.declareProtected(View, 'setLocalRoles') + def setLocalRoles( self, obj, member_ids, role, remove=0, reindex=1 ): + """ Set local roles on an item """ + if role not in self.getCandidateLocalRoles(obj) : + raise Unauthorized, "You are not allowed to manage %s role" % role + + if self.checkPermission(SetLocalRoles, obj) : + if not remove : + for member_id in member_ids : + # current roles for user id in obj + roles = list(obj.get_local_roles_for_userid( userid=member_id )) + if role not in roles : + roles.append(role) + obj.manage_setLocalRoles( member_id, roles) + else : + for member_id in member_ids : + # current roles for user id in obj + roles = list(obj.get_local_roles_for_userid( userid=member_id )) + try : roles.remove(role) + except ValueError : pass + else : + if len(roles) >= 1 : + obj.manage_setLocalRoles( member_id, roles) + else : + obj.manage_delLocalRoles( userids=[member_id] ) + + else : + raise Unauthorized + + if reindex: + # It is assumed that all objects have the method + # reindexObjectSecurity, which is in CMFCatalogAware and + # thus PortalContent and PortalFolder. + obj.reindexObjectSecurity() + + + security.declarePublic('getMemberFullNameById') + def getMemberFullNameById(self, userid, nameBefore = 1) : + """ Return the best formated representation of user fullname. """ + + memberFullName = '' + if userid and userid != 'No owner' : + # No owner is a possible value returned by DefaultDublinCoreImpl.Creator + member = self.getMemberById(userid) + if not member : + return userid + memberFullName = member.getMemberFullName(nameBefore=nameBefore) + + return memberFullName + + security.declareProtected(ListPortalMembers, 'getMembers') + def getMembers(self, users) : + """ Return wraped users """ + members = [] + for user in users : + members.append(self.getMemberById(user)) + + members = filter(None, members) + members.sort( lambda m0, m1 : cmp(m0.getMemberSortableFormat(), m1.getMemberSortableFormat()) ) + return members + + + security.declareProtected(ListPortalMembers, 'getOtherMembers') + def getOtherMembers(self, users) : + """ Return members who are not in users list""" + allMemberIds = self.listMemberIds() + otherMemberIds = [ userId for userId in allMemberIds if userId not in users ] + return self.getMembers(otherMemberIds) + + + + security.declareProtected(ListPortalMembers, 'getMembersMetadata') + def getMembersMetadata(self, users) : + """ return metadata from portal_catalog """ + userDict = {} + for u in users : userDict[u] = True + ctool = getUtilityByInterfaceName('Products.CMFCore.interfaces.ICatalogTool') + memberBrains = ctool(portal_type='Member Data', sort_on='getMemberSortableFormat') + memberList = [] + complementList = [] + + if users : + for mb in memberBrains : + metadata = {'id' : mb.getId, 'fullname' : mb.getMemberFullName} + if userDict.has_key(mb.getId) : + memberList.append(metadata) + else : + complementList.append(metadata) + else : + complementList = [{'id' : mb.getId, 'fullname' : mb.getMemberFullName} for mb in memberBrains] + + return {'memberList' : memberList, 'complementList' : complementList} + + + + security.declareProtected(RemoveMember, 'removeMembers') + def removeMembers(self, memberIds = []) : + """ remove member + """ + # TODO : remove member document ? + mdtool = getUtilityByInterfaceName('Products.CMFCore.interfaces.IMemberDataTool') + for m in self.getMembers(memberIds) : + m.manage_beforeDelete() + mdtool.deleteMemberData(m.getId()) + + self.aq_inner.acl_users.deleteUsers(users = memberIds) + + + + security.declareProtected(ManagePortal, 'setMemberAreaPortalType') + def setMemberAreaPortalType(self, member_folder_portal_type): + """ Set member area portal type to construct.""" + ttool = getUtilityByInterfaceName('Products.CMFCore.interfaces.ITypesTool') + if member_folder_portal_type not in ttool.objectIds() : + raise ValueError, "Unknown portal type : %s" % str(member_folder_portal_type) + + self.memberareaPortalType = member_folder_portal_type + return MessageDialog(title ='Type updated', + message='The member area type have been updated', + action ='manage_mapRoles') + + def getMemberAreaPortalType(self) : + return self.memberareaPortalType + + + def getHomeFolder(self, id=None, verifyPermission=0): + """ Return a member's home folder object, or None. + """ + if id is None: + member = self.getAuthenticatedMember() + if not hasattr(member, 'getMemberId'): + return None + id = member.getMemberId() + members = self.getMembersFolder() + if members is not None: + if not hasattr(members, id) and getattr(self, 'memberareaCreationFlag', 0) != 0 : + self.createMemberArea(id) + try: + folder = members._getOb(id) + if verifyPermission and not _checkPermission(View, folder): + # Don't return the folder if the user can't get to it. + return None + return folder + except (AttributeError, TypeError, KeyError): + pass + return None + + security.declarePublic('createMemberArea') + def createMemberArea(self, member_id=''): + """ Create a member area for 'member_id' or authenticated user. + """ + if not self.getMemberareaCreationFlag(): + return None + members = self.getMembersFolder() + if not members: + return None + if self.isAnonymousUser(): + return None + # Note: We can't use getAuthenticatedMember() and getMemberById() + # because they might be wrapped by MemberDataTool. + user = _getAuthenticatedUser(self) + user_id = user.getId() + if member_id in ('', user_id): + member = user + member_id = user_id + else: + if _checkPermission(ManageUsers, self): + member = self.acl_users.getUserById(member_id, None) + if member: + member = member.__of__(self.acl_users) + else: + raise ValueError, 'Member %s does not exist' % member_id + else: + return None + + if hasattr( aq_base(members), member_id ): + return None + + ttool = getUtilityByInterfaceName('Products.CMFCore.interfaces.ITypesTool') + info = getattr(ttool, self.memberareaPortalType) + + memberFullName = self.getMemberFullNameById(member_id, nameBefore = 0) + f = info._constructInstance( members, member_id, title=memberFullName ) + + # Grant Ownership and Owner role to Member + f.changeOwnership(user) + f.__ac_local_roles__ = None + f.manage_setLocalRoles(member_id, ['Owner']) + + f.reindexObjectSecurity() + return f + + + security.declareProtected(ListPortalMembers, 'looseSearchMembers') + def looseSearchMembers(self, searchString) : + """ """ + + words = searchString.strip().split() + words = [word.lower() for word in words] + + mdtool = getUtilityByInterfaceName('Products.CMFCore.interfaces.IMemberDataTool') + mdProperties = mdtool.propertyIds() + searchableProperties = [ p['id'] for p in mdtool.propertyMap() if p['type'] == 'string' ] + ['id'] + try : searchableProperties.remove('portal_skin') + except ValueError : pass + + match = [] + for m in self.listMembers() : + allWordsMatch = False + for word in words : + for p in searchableProperties : + if str(m.getProperty(p, '')).lower().find(word) != -1 : + allWordsMatch = True + break + else : + allWordsMatch = False + + if not allWordsMatch : + break + else : + match.append(m) + + return match + + def __getPUS(self): + # CMFCore.MembershipTool.MembershipTool tests 'getUsers' method but : + # "enumeration" methods ('getUserNames', 'getUsers') are *not* + # part of the contract! See IEnumerableUserFolder. + # (from PluggableAuthService.interfaces.authservice #233) + return self.acl_users + + InitializeClass(MembershipTool)