class TestSimpleCache(unittest.TestCase): def setUp(self): from Products.LDAPUserFolder.SimpleCache import SimpleCache self.cache = SimpleCache() self.cache.setTimeout(0.1) def testInstantiation(self): self.assertEqual(len(self.cache.getCache()), 0) def testCaching(self): nonauth_ob = CacheObject('nonauth') self.cache.set('TestId', nonauth_ob) self.assertEqual(len(self.cache.getCache()), 1) self.assertEqual(self.cache.get('testid', password=None), nonauth_ob) time.sleep(0.5) self.assertEqual(self.cache.get('testid', password=None), None) self.assertEqual(len(self.cache.getCache()), 0) auth_ob = CacheObject('auth') self.cache.set('NewId', auth_ob) self.assertEqual(len(self.cache.getCache()), 1) self.assertEqual(self.cache.get('newid', password=TESTPWD), auth_ob) time.sleep(0.5) self.assertEqual(self.cache.get('newid', password=TESTPWD), None) self.assertEqual(len(self.cache.getCache()), 0) def testRemove(self): nonauth_ob = CacheObject('nonauth') self.cache.set('TestId', nonauth_ob) self.cache.remove('testid') self.assertEqual(len(self.cache.getCache()), 0) auth_ob = CacheObject('auth') self.cache.set('NewId', auth_ob) self.cache.remove('newid') self.assertEqual(len(self.cache.getCache()), 0) def testClear(self): nonauth_ob = CacheObject('nonauth') self.cache.set('TestId', nonauth_ob) auth_ob = CacheObject('auth') self.cache.set('NewId', auth_ob) self.cache.clear() self.assertEqual(len(self.cache.getCache()), 0) self.assertEqual(len(self.cache.getCache()), 0)
class LDAPGroupFolder(SimpleItem): """ """ security = ClassSecurityInfo() meta_type = 'LDAPGroupFolder' id = 'acl_users' isPrincipiaFolderish = 1 isAUserFolder = 1 manage_options = (({ 'label': 'Groups', 'action': 'manage_main', }, ) + SimpleItem.manage_options) security.declareProtected(view_management_screens, 'manage_main') manage_main = DTMLFile('dtml/groups', globals()) def __setstate__(self, v): """ """ LDAPGroupFolder.inheritedAttribute('__setstate__')(self, v) self._cache = SimpleCache() self._cache.setTimeout(600) self._cache.clear() def __init__(self, title, luf=''): """ """ self._luf = luf self._cache = SimpleCache() self._cache.setTimeout(600) self._cache.clear() security.declarePrivate(manage_users, 'getGRUF') def getGRUF(self): """ """ return self.aq_parent.aq_parent security.declareProtected(manage_users, 'getLUF') def getLUF(self): """ """ s = self.getGRUF().getUserSource(self._luf) if getattr(s, 'meta_type', None) != "LDAPUserFolder": # whoops, we moved LDAPUF... let's try to find it back Log(LOG_WARNING, "LDAPUserFolder moved. Trying to find it back.") s = None for src in self.getGRUF().listUserSources(): if src.meta_type == "LDAPUserFolder": self._luf = src.getPhysicalPath()[-2] s = src break if not s: raise RuntimeError, "You must change your groups source in GRUF if you do not have a LDAPUserFolder as a users source." return s security.declareProtected(manage_users, 'getGroups') def getGroups(self, dn='*', attr=None, pwd=''): """ """ return self.getLUF().getGroups(dn, attr, pwd) security.declareProtected(manage_users, 'getGroupType') def getGroupType(self, group_dn): """ """ return self.getLUF().getGroupType(group_dn) security.declareProtected(manage_users, 'getGroupMappings') def getGroupMappings(self): """ """ return self.getLUF().getGroupMappings() security.declareProtected(manage_users, 'manage_addGroupMapping') def manage_addGroupMapping(self, group_name, role_name, REQUEST=None): """ """ self._cache.remove(group_name) self.getLUF().manage_addGroupMapping(group_name, role_name, None) if REQUEST: msg = 'Added LDAP group to Zope role mapping: %s -> %s' % ( group_name, role_name) return self.manage_main(manage_tabs_message=msg) manage_addGroupMapping = postonly(manage_addGroupMapping) security.declareProtected(manage_users, 'manage_deleteGroupMappings') def manage_deleteGroupMappings(self, group_names, REQUEST=None): """ Delete mappings from LDAP group to Zope role """ self._cache.clear() self.getLUF().manage_deleteGroupMappings(group_names, None) if REQUEST: msg = 'Deleted LDAP group to Zope role mapping for: %s' % ( ', '.join(group_names)) return self.manage_main(manage_tabs_message=msg) manage_deleteGroupMappings = postonly(manage_deleteGroupMappings) security.declareProtected(manage_users, 'manage_addGroup') def manage_addGroup(self, newgroup_name, newgroup_type='groupOfUniqueNames', REQUEST=None): """Add a new group in groups_base. """ self.getLUF().manage_addGroup(newgroup_name, newgroup_type, None) if REQUEST: msg = 'Added new group %s' % (newgroup_name) return self.manage_main(manage_tabs_message=msg) manage_addGroup = postonly(manage_addGroup) security.declareProtected(manage_users, 'manage_deleteGroups') def manage_deleteGroups(self, dns=[], REQUEST=None): """ Delete groups from groups_base """ self.getLUF().manage_deleteGroups(dns, None) self._cache.clear() if REQUEST: msg = 'Deleted group(s):<br> %s' % '<br>'.join(dns) return self.manage_main(manage_tabs_message=msg) manage_deleteGroups = postonly(manage_deleteGroups) security.declareProtected(manage_users, 'getUser') def getUser(self, name): """ """ # Prevent locally stored groups luf = self.getLUF() if luf._local_groups: return [] # Get the group from the cache user = self._cache.get(name, '') if user: return user # Scan groups to find the proper user. # THIS MAY BE EXPENSIVE AND HAS TO BE OPTIMIZED... grps = self.getLUF().getGroups() valid_roles = self.userFolderGetRoles() dn = None for n, g_dn in grps: if n == name: dn = g_dn break if not dn: return None # Current mapping roles = self.getLUF()._mapRoles([name]) # Nested groups groups = list(self.getLUF().getGroups( dn=dn, attr='cn', )) roles.extend(self.getLUF()._mapRoles(groups)) # !!! start test Log(LOG_DEBUG, name, "roles", groups, roles) Log(LOG_DEBUG, name, "mapping", getattr(self.getLUF(), '_groups_mappings', {})) # !!! end test actual_roles = [] for r in roles: if r in valid_roles: actual_roles.append(r) elif "%s%s" % (GROUP_PREFIX, r) in valid_roles: actual_roles.append("%s%s" % (GROUP_PREFIX, r)) Log(LOG_DEBUG, name, "actual roles", actual_roles) user = GroupUser(n, '', actual_roles, []) self._cache.set(name, user) return user security.declareProtected(manage_users, 'getUserNames') def getUserNames(self): """ """ Log( LOG_DEBUG, "getUserNames", ) LogCallStack(LOG_DEBUG) # Prevent locally stored groups luf = self.getLUF() if luf._local_groups: return [] return [g[0] for g in luf.getGroups()] security.declareProtected(manage_users, 'getUsers') def getUsers(self, authenticated=1): """ """ # Prevent locally stored groups luf = self.getLUF() if luf._local_groups: return [] data = [] grps = self.getLUF().getGroups() valid_roles = self.userFolderGetRoles() for n, dn in grps: # Group mapping roles = self.getLUF()._mapRoles([n]) # computation actual_roles = [] for r in roles: if r in valid_roles: actual_roles.append(r) elif "%s%s" % (GROUP_PREFIX, r) in valid_roles: actual_roles.append("%s%s" % (GROUP_PREFIX, r)) user = GroupUser(n, '', actual_roles, []) data.append(user) return data security.declarePrivate('_doAddUser') def _doAddUser(self, name, password, roles, domains, **kw): """WARNING: If a role with exists with the same name as the group, we do not add the group mapping for it, but we create it as if it were a Zope ROLE. Ie. it's not possible to have a GRUF Group name = a Zope role name, BUT, with this system, it's possible to differenciate between LDAP groups and LDAP roles. """ self.getLUF().manage_addGroup(name) self.manage_addGroupMapping( name, "group_" + name, None, ) self._doChangeUser(name, password, roles, domains, **kw) security.declarePrivate('_doDelUsers') def _doDelUsers(self, names): dns = [] luf = self.getLUF() for g_name, dn in luf.getGroups(): if g_name in names: dns.append(dn) self._cache.clear() return luf.manage_deleteGroups(dns) security.declarePrivate('_doChangeUser') def _doChangeUser(self, name, password, roles, domains, **kw): """ This is used to change the groups (especially their roles). [ THIS TEXT IS OUTDATED : WARNING: If a ZOPE role with the same name as the GRUF group exists, we do not add the group mapping for it, but we create it as if it were a Zope ROLE. Ie. it's not possible to have a GRUF Group name = a Zope role name, BUT, with this system, it's possible to differenciate between LDAP groups and LDAP roles. ] """ luf = self.getLUF() self._cache.remove(name) # Get group DN dn = None for g_name, g_dn in luf.getGroups(): if g_name == name: dn = g_dn break if not dn: raise ValueError, "Invalid LDAP group: '%s'" % (name, ) # Edit group mappings ## if name in self.aq_parent.valid_roles(): ## # This is, in fact, a role ## self.getLUF().manage_addGroupMapping(name, name) ## else: ## # This is a group -> we set it as a group ## self.getLUF().manage_addGroupMapping(name, self.getGroupPrefix() + name) # Change roles if luf._local_groups: luf.manage_editUserRoles(dn, roles) else: # We have to transform roles into group dns: transform them as a dict role_dns = [] all_groups = luf.getGroups() all_roles = luf.valid_roles() groups = {} for g in all_groups: groups[g[0]] = g[1] # LDAPUF < 2.4Beta3 adds possibly invalid roles to the user roles # (for example, adding the cn of a group additionnaly to the mapped zope role). # So we must remove from our 'roles' list all roles which are prefixed by group prefix # but are not actually groups. # If a group has the same name as a role, we assume that it should be a _role_. # We should check against group/role mapping here, but... well... XXX TODO ! # See "HERE IT IS" comment below. # Scan roles we are asking for to manage groups correctly for role in roles: if not role in all_roles: continue # Do not allow propagation of invalid roles if role.startswith(GROUP_PREFIX): role = role[ GROUP_PREFIX_LEN:] # Remove group prefix : groups are stored WITHOUT prefix in LDAP if role in all_roles: continue # HERE IT IS r = groups.get(role, None) if not r: Log( LOG_WARNING, "LDAP Server doesn't provide a '%s' group (asked for user '%s')." % ( role, name, )) continue role_dns.append(r) # Perform the change luf.manage_editGroupRoles(dn, role_dns)
class TestSimpleCache(unittest.TestCase): def setUp(self): self.cache = SimpleCache() self.cache.setTimeout(0.1) def testInstantiation(self): self.assertEqual(len(self.cache.getCache()), 0) def testCaching(self): nonauth_ob = CacheObject('nonauth') self.cache.set('TestId', nonauth_ob) self.assertEqual(len(self.cache.getCache()), 1) self.assertEqual( self.cache.get('testid', password=None) , nonauth_ob ) time.sleep(0.5) self.assertEqual( self.cache.get('testid', password=None) , None ) self.assertEqual(len(self.cache.getCache()), 0) auth_ob = CacheObject('auth') self.cache.set('NewId', auth_ob) self.assertEqual(len(self.cache.getCache()), 1) self.assertEqual( self.cache.get('newid', password=TESTPWD) , auth_ob ) time.sleep(0.5) self.assertEqual( self.cache.get('newid', password=TESTPWD) , None ) self.assertEqual(len(self.cache.getCache()), 0) def testRemove(self): nonauth_ob = CacheObject('nonauth') self.cache.set('TestId', nonauth_ob) self.cache.remove('testid') self.assertEqual(len(self.cache.getCache()), 0) auth_ob = CacheObject('auth') self.cache.set('NewId', auth_ob) self.cache.remove('newid') self.assertEqual(len(self.cache.getCache()), 0) def testClear(self): nonauth_ob = CacheObject('nonauth') self.cache.set('TestId', nonauth_ob) auth_ob = CacheObject('auth') self.cache.set('NewId', auth_ob) self.cache.clear() self.assertEqual(len(self.cache.getCache()), 0) self.assertEqual(len(self.cache.getCache()), 0)
class LDAPGroupFolder(SimpleItem): """ """ security = ClassSecurityInfo() meta_type = 'LDAPGroupFolder' id = 'acl_users' isPrincipiaFolderish=1 isAUserFolder=1 manage_options=( ({'label' : 'Groups', 'action' : 'manage_main',},) + SimpleItem.manage_options ) security.declareProtected(view_management_screens, 'manage_main') manage_main = DTMLFile('dtml/groups', globals()) def __setstate__(self, v): """ """ LDAPGroupFolder.inheritedAttribute('__setstate__')(self, v) self._cache = SimpleCache() self._cache.setTimeout(600) self._cache.clear() def __init__( self, title, luf=''): """ """ self._luf = luf self._cache = SimpleCache() self._cache.setTimeout(600) self._cache.clear() security.declarePrivate(manage_users, 'getGRUF') def getGRUF(self): """ """ return self.aq_parent.aq_parent security.declareProtected(manage_users, 'getLUF') def getLUF(self): """ """ s = self.getGRUF().getUserSource(self._luf) if getattr(s, 'meta_type', None) != "LDAPUserFolder": # whoops, we moved LDAPUF... let's try to find it back Log(LOG_WARNING, "LDAPUserFolder moved. Trying to find it back.") s = None for src in self.getGRUF().listUserSources(): if src.meta_type == "LDAPUserFolder": self._luf = src.getPhysicalPath()[-2] s = src break if not s: raise RuntimeError, "You must change your groups source in GRUF if you do not have a LDAPUserFolder as a users source." return s security.declareProtected(manage_users, 'getGroups') def getGroups(self, dn='*', attr=None, pwd=''): """ """ return self.getLUF().getGroups(dn, attr, pwd) security.declareProtected(manage_users, 'getGroupType') def getGroupType(self, group_dn): """ """ return self.getLUF().getGroupType(group_dn) security.declareProtected(manage_users, 'getGroupMappings') def getGroupMappings(self): """ """ return self.getLUF().getGroupMappings() security.declareProtected(manage_users, 'manage_addGroupMapping') def manage_addGroupMapping(self, group_name, role_name, REQUEST=None): """ """ self._cache.remove(group_name) self.getLUF().manage_addGroupMapping(group_name, role_name, None) if REQUEST: msg = 'Added LDAP group to Zope role mapping: %s -> %s' % ( group_name, role_name) return self.manage_main(manage_tabs_message=msg) manage_addGroupMapping = postonly(manage_addGroupMapping) security.declareProtected(manage_users, 'manage_deleteGroupMappings') def manage_deleteGroupMappings(self, group_names, REQUEST=None): """ Delete mappings from LDAP group to Zope role """ self._cache.clear() self.getLUF().manage_deleteGroupMappings(group_names, None) if REQUEST: msg = 'Deleted LDAP group to Zope role mapping for: %s' % ( ', '.join(group_names)) return self.manage_main(manage_tabs_message=msg) manage_deleteGroupMappings = postonly(manage_deleteGroupMappings) security.declareProtected(manage_users, 'manage_addGroup') def manage_addGroup( self , newgroup_name , newgroup_type='groupOfUniqueNames' , REQUEST=None ): """Add a new group in groups_base. """ self.getLUF().manage_addGroup(newgroup_name, newgroup_type, None) if REQUEST: msg = 'Added new group %s' % (newgroup_name) return self.manage_main(manage_tabs_message=msg) manage_addGroup = postonly(manage_addGroup) security.declareProtected(manage_users, 'manage_deleteGroups') def manage_deleteGroups(self, dns=[], REQUEST=None): """ Delete groups from groups_base """ self.getLUF().manage_deleteGroups(dns, None) self._cache.clear() if REQUEST: msg = 'Deleted group(s):<br> %s' % '<br>'.join(dns) return self.manage_main(manage_tabs_message=msg) manage_deleteGroups = postonly(manage_deleteGroups) security.declareProtected(manage_users, 'getUser') def getUser(self, name): """ """ # Prevent locally stored groups luf = self.getLUF() if luf._local_groups: return [] # Get the group from the cache user = self._cache.get(name, '') if user: return user # Scan groups to find the proper user. # THIS MAY BE EXPENSIVE AND HAS TO BE OPTIMIZED... grps = self.getLUF().getGroups() valid_roles = self.userFolderGetRoles() dn = None for n, g_dn in grps: if n == name: dn = g_dn break if not dn: return None # Current mapping roles = self.getLUF()._mapRoles([name]) # Nested groups groups = list(self.getLUF().getGroups(dn=dn, attr='cn', )) roles.extend(self.getLUF()._mapRoles(groups)) # !!! start test Log(LOG_DEBUG, name, "roles", groups, roles) Log(LOG_DEBUG, name, "mapping", getattr(self.getLUF(), '_groups_mappings', {})) # !!! end test actual_roles = [] for r in roles: if r in valid_roles: actual_roles.append(r) elif "%s%s" % (GROUP_PREFIX, r) in valid_roles: actual_roles.append("%s%s" % (GROUP_PREFIX, r)) Log(LOG_DEBUG, name, "actual roles", actual_roles) user = GroupUser(n, '', actual_roles, []) self._cache.set(name, user) return user security.declareProtected(manage_users, 'getUserNames') def getUserNames(self): """ """ Log(LOG_DEBUG, "getUserNames", ) LogCallStack(LOG_DEBUG) # Prevent locally stored groups luf = self.getLUF() if luf._local_groups: return [] return [g[0] for g in luf.getGroups()] security.declareProtected(manage_users, 'getUsers') def getUsers(self, authenticated=1): """ """ # Prevent locally stored groups luf = self.getLUF() if luf._local_groups: return [] data = [] grps = self.getLUF().getGroups() valid_roles = self.userFolderGetRoles() for n, dn in grps: # Group mapping roles = self.getLUF()._mapRoles([n]) # computation actual_roles = [] for r in roles: if r in valid_roles: actual_roles.append(r) elif "%s%s" % (GROUP_PREFIX, r) in valid_roles: actual_roles.append("%s%s" % (GROUP_PREFIX, r)) user = GroupUser(n, '', actual_roles, []) data.append(user) return data security.declarePrivate('_doAddUser') def _doAddUser(self, name, password, roles, domains, **kw): """WARNING: If a role with exists with the same name as the group, we do not add the group mapping for it, but we create it as if it were a Zope ROLE. Ie. it's not possible to have a GRUF Group name = a Zope role name, BUT, with this system, it's possible to differenciate between LDAP groups and LDAP roles. """ self.getLUF().manage_addGroup(name) self.manage_addGroupMapping(name, "group_" + name, None, ) self._doChangeUser(name, password, roles, domains, **kw) security.declarePrivate('_doDelUsers') def _doDelUsers(self, names): dns = [] luf = self.getLUF() for g_name, dn in luf.getGroups(): if g_name in names: dns.append(dn) self._cache.clear() return luf.manage_deleteGroups(dns) security.declarePrivate('_doChangeUser') def _doChangeUser(self, name, password, roles, domains, **kw): """ This is used to change the groups (especially their roles). [ THIS TEXT IS OUTDATED : WARNING: If a ZOPE role with the same name as the GRUF group exists, we do not add the group mapping for it, but we create it as if it were a Zope ROLE. Ie. it's not possible to have a GRUF Group name = a Zope role name, BUT, with this system, it's possible to differenciate between LDAP groups and LDAP roles. ] """ luf = self.getLUF() self._cache.remove(name) # Get group DN dn = None for g_name, g_dn in luf.getGroups(): if g_name == name: dn = g_dn break if not dn: raise ValueError, "Invalid LDAP group: '%s'" % (name, ) # Edit group mappings ## if name in self.aq_parent.valid_roles(): ## # This is, in fact, a role ## self.getLUF().manage_addGroupMapping(name, name) ## else: ## # This is a group -> we set it as a group ## self.getLUF().manage_addGroupMapping(name, self.getGroupPrefix() + name) # Change roles if luf._local_groups: luf.manage_editUserRoles(dn, roles) else: # We have to transform roles into group dns: transform them as a dict role_dns = [] all_groups = luf.getGroups() all_roles = luf.valid_roles() groups = {} for g in all_groups: groups[g[0]] = g[1] # LDAPUF < 2.4Beta3 adds possibly invalid roles to the user roles # (for example, adding the cn of a group additionnaly to the mapped zope role). # So we must remove from our 'roles' list all roles which are prefixed by group prefix # but are not actually groups. # If a group has the same name as a role, we assume that it should be a _role_. # We should check against group/role mapping here, but... well... XXX TODO ! # See "HERE IT IS" comment below. # Scan roles we are asking for to manage groups correctly for role in roles: if not role in all_roles: continue # Do not allow propagation of invalid roles if role.startswith(GROUP_PREFIX): role = role[GROUP_PREFIX_LEN:] # Remove group prefix : groups are stored WITHOUT prefix in LDAP if role in all_roles: continue # HERE IT IS r = groups.get(role, None) if not r: Log(LOG_WARNING, "LDAP Server doesn't provide a '%s' group (asked for user '%s')." % (role, name, )) continue role_dns.append(r) # Perform the change luf.manage_editGroupRoles(dn, role_dns)