1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
# Re-define a few methods
from global_symbols import *
# These mandatory attributes are required by LDAP schema.
# They will be filled with user name as a default value.
# You have to provide a gruf_ldap_required_fields python script
# in your Plone's skins if you want to override this.
MANDATORY_ATTRIBUTES = ("sn", "cn", )
def _doAddUser(self, name, password, roles, domains, **kw):
"""
Special user adding method for use with LDAPUserFolder.
This will ensure parameters are correct for LDAP management
"""
kwargs = {} # We will pass this dict
attrs = {}
# Get gruf_ldap_required_fields result and fill in mandatory stuff
if hasattr(self, "gruf_ldap_required_fields"):
attrs = self.gruf_ldap_required_fields(login = name)
else:
for attr in MANDATORY_ATTRIBUTES:
attrs[attr] = name
kwargs.update(attrs)
# We assume that name is rdn attribute
rdn_attr = self._rdnattr
kwargs[rdn_attr] = name
# Manage password(s)
kwargs['user_pw'] = password
kwargs['confirm_pw'] = password
# Mangle roles
kwargs['user_roles'] = self._mangleRoles(name, roles)
# Delegate to LDAPUF default method
msg = self.manage_addUser(kwargs = kwargs)
if msg:
raise RuntimeError, msg
def _doDelUsers(self, names):
"""
Remove a bunch of users from LDAP.
We have to call manage_deleteUsers but, before, we need to find their dn.
"""
dns = []
for name in names:
dns.append(self._find_user_dn(name))
self.manage_deleteUsers(dns)
def _find_user_dn(self, name):
"""
Convert a name to an LDAP dn
"""
# Search records matching name
rdn_attr = self._rdnattr
v = self.findUser(search_param = rdn_attr, search_term = name)
# Filter to keep exact matches only
v = filter(lambda x: x[rdn_attr] == name, v)
# Now, decide what to do
l = len(v)
if not l:
# Invalid name
raise "Invalid user name: '%s'" % (name, )
elif l > 1:
# Several records... don't know how to handle
raise "Duplicate user name for '%s'" % (name, )
return v[0]['dn']
def _mangleRoles(self, name, roles):
"""
Return role_dns for this user
"""
# Local groups => the easiest part
if self._local_groups:
return roles
# We have to transform roles into group dns: transform them as a dict
role_dns = []
all_groups = self.getGroups()
all_roles = self.valid_roles()
groups = {}
for g in all_groups:
groups[g[0]] = g[1]
# LDAPUF does the mistake of adding 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.
# See http://www.dataflake.org/tracker/issue_00376 for more information on that
# particular issue.
# 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
Log(LOG_DEBUG, "Scanning roles for", name, roles, )
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 (required for user '%s')." % (role, name, ))
role_dns.append(r)
Log(LOG_DEBUG, name, role_dns)
return role_dns
def _doChangeUser(self, name, password, roles, domains, **kw):
"""
Update a user
"""
# Find the dn at first
dn = self._find_user_dn(name)
# Change password
if password is not None:
if password == '':
raise ValueError, "Password must not be empty for LDAP users."
self.manage_editUserPassword(dn, password)
# Perform role change
self.manage_editUserRoles(dn, self._mangleRoles(name, roles))
# (No domain management with LDAP.)
def manage_editGroupRoles(self, user_dn, role_dns=[], REQUEST=None):
""" Edit the roles (groups) of a group """
from Products.LDAPUserFolder.utils import ldap_scopes, GROUP_MEMBER_MAP, filter_format
from Products.LDAPUserFolder.LDAPDelegate import ADD, DELETE, REPLACE, BASE
msg = ""
## Log(LOG_DEBUG, "assigning", role_dns, "to", user_dn)
all_groups = self.getGroups(attr='dn')
cur_groups = self.getGroups(dn=user_dn, attr='dn')
group_dns = []
for group in role_dns:
if group.find('=') == -1:
group_dns.append('cn=%s,%s' % (group, self.groups_base))
else:
group_dns.append(group)
if self._local_groups:
if len(role_dns) == 0:
del self._groups_store[user_dn]
else:
self._groups_store[user_dn] = role_dns
else:
for group in all_groups:
member_attr = GROUP_MEMBER_MAP.get(self.getGroupType(group))
if group in cur_groups and group not in group_dns:
action = DELETE
elif group in group_dns and group not in cur_groups:
action = ADD
else:
action = None
if action is not None:
msg = self._delegate.modify(
group
, action
, {member_attr : [user_dn]}
)
## Log(LOG_DEBUG, "group", group, "subgroup", user_dn, "result", msg)
if msg:
raise RuntimeError, msg
|