[CalendarServer-changes] [12256] CalendarServer/trunk/twistedcaldav/directory
source_changes at macosforge.org
source_changes at macosforge.org
Wed Mar 12 11:23:55 PDT 2014
Revision: 12256
http://trac.calendarserver.org//changeset/12256
Author: sagen at apple.com
Date: 2014-01-07 11:53:20 -0800 (Tue, 07 Jan 2014)
Log Message:
-----------
lint
Modified Paths:
--------------
CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py
CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py
Modified: CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py 2014-01-07 18:34:58 UTC (rev 12255)
+++ CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py 2014-01-07 19:53:20 UTC (rev 12256)
@@ -40,7 +40,8 @@
"LdapDirectoryService",
]
-import ldap, ldap.async
+import ldap
+import ldap.async
from ldap.filter import escape_filter_chars as ldapEsc
try:
@@ -52,8 +53,9 @@
import time
from twisted.cred.credentials import UsernamePassword
-from twistedcaldav.directory.cachingdirectory import (CachingDirectoryService,
- CachingDirectoryRecord)
+from twistedcaldav.directory.cachingdirectory import (
+ CachingDirectoryService, CachingDirectoryRecord
+)
from twistedcaldav.directory.directory import DirectoryConfigurationError
from twistedcaldav.directory.augment import AugmentRecord
from twistedcaldav.directory.util import splitIntoBatches, normalizeUUID
@@ -63,6 +65,8 @@
from txweb2.http import HTTPError, StatusResponse
from txweb2 import responsecode
+
+
class LdapDirectoryService(CachingDirectoryService):
"""
LDAP based implementation of L{IDirectoryService}.
@@ -72,8 +76,9 @@
baseGUID = "5A871574-0C86-44EE-B11B-B9440C3DC4DD"
def __repr__(self):
- return "<%s %r: %r>" % (self.__class__.__name__, self.realmName,
- self.uri)
+ return "<%s %r: %r>" % (
+ self.__class__.__name__, self.realmName, self.uri
+ )
def __init__(self, params):
@@ -85,15 +90,15 @@
"""
defaults = {
- "augmentService" : None,
- "groupMembershipCache" : None,
- "cacheTimeout": 1, # Minutes
+ "augmentService": None,
+ "groupMembershipCache": None,
+ "cacheTimeout": 1, # Minutes
"negativeCaching": False,
"warningThresholdSeconds": 3,
- "batchSize": 500, # for splitting up large queries
- "requestTimeoutSeconds" : 10,
- "requestResultsLimit" : 200,
- "optimizeMultiName" : False,
+ "batchSize": 500, # for splitting up large queries
+ "requestTimeoutSeconds": 10,
+ "requestResultsLimit": 200,
+ "optimizeMultiName": False,
"queryLocationsImplicitly": True,
"restrictEnabledRecords": False,
"restrictToGroup": "",
@@ -102,7 +107,7 @@
"tls": False,
"tlsCACertFile": None,
"tlsCACertDir": None,
- "tlsRequireCert": None, # never, allow, try, demand, hard
+ "tlsRequireCert": None, # never, allow, try, demand, hard
"credentials": {
"dn": None,
"password": None,
@@ -113,68 +118,68 @@
"guidAttr": "entryUUID",
"users": {
"rdn": "ou=People",
- "filter": None, # additional filter for this type
- "loginEnabledAttr" : "", # attribute controlling login
- "loginEnabledValue" : "yes", # "True" value of above attribute
- "calendarEnabledAttr" : "", # attribute controlling enabledForCalendaring
- "calendarEnabledValue" : "yes", # "True" value of above attribute
- "mapping" : { # maps internal record names to LDAP
+ "filter": None, # additional filter for this type
+ "loginEnabledAttr": "", # attribute controlling login
+ "loginEnabledValue": "yes", # "True" value of above attribute
+ "calendarEnabledAttr": "", # attribute controlling enabledForCalendaring
+ "calendarEnabledValue": "yes", # "True" value of above attribute
+ "mapping": { # maps internal record names to LDAP
"recordName": "uid",
- "fullName" : "cn",
- "emailAddresses" : ["mail"], # multiple LDAP fields supported
- "firstName" : "givenName",
- "lastName" : "sn",
+ "fullName": "cn",
+ "emailAddresses": ["mail"], # multiple LDAP fields supported
+ "firstName": "givenName",
+ "lastName": "sn",
},
},
"groups": {
"rdn": "ou=Group",
- "filter": None, # additional filter for this type
- "mapping" : { # maps internal record names to LDAP
+ "filter": None, # additional filter for this type
+ "mapping": { # maps internal record names to LDAP
"recordName": "cn",
- "fullName" : "cn",
- "emailAddresses" : ["mail"], # multiple LDAP fields supported
- "firstName" : "givenName",
- "lastName" : "sn",
+ "fullName": "cn",
+ "emailAddresses": ["mail"], # multiple LDAP fields supported
+ "firstName": "givenName",
+ "lastName": "sn",
},
},
"locations": {
"rdn": "ou=Places",
- "filter": None, # additional filter for this type
- "calendarEnabledAttr" : "", # attribute controlling enabledForCalendaring
- "calendarEnabledValue" : "yes", # "True" value of above attribute
- "associatedAddressAttr" : "",
- "mapping" : { # maps internal record names to LDAP
+ "filter": None, # additional filter for this type
+ "calendarEnabledAttr": "", # attribute controlling enabledForCalendaring
+ "calendarEnabledValue": "yes", # "True" value of above attribute
+ "associatedAddressAttr": "",
+ "mapping": { # maps internal record names to LDAP
"recordName": "cn",
- "fullName" : "cn",
- "emailAddresses" : ["mail"], # multiple LDAP fields supported
+ "fullName": "cn",
+ "emailAddresses": ["mail"], # multiple LDAP fields supported
},
},
"resources": {
"rdn": "ou=Resources",
- "filter": None, # additional filter for this type
- "calendarEnabledAttr" : "", # attribute controlling enabledForCalendaring
- "calendarEnabledValue" : "yes", # "True" value of above attribute
- "mapping" : { # maps internal record names to LDAP
+ "filter": None, # additional filter for this type
+ "calendarEnabledAttr": "", # attribute controlling enabledForCalendaring
+ "calendarEnabledValue": "yes", # "True" value of above attribute
+ "mapping": { # maps internal record names to LDAP
"recordName": "cn",
- "fullName" : "cn",
- "emailAddresses" : ["mail"], # multiple LDAP fields supported
+ "fullName": "cn",
+ "emailAddresses": ["mail"], # multiple LDAP fields supported
},
},
"addresses": {
"rdn": "ou=Buildings",
- "filter": None, # additional filter for this type
- "streetAddressAttr" : "",
- "geoAttr" : "",
- "mapping" : { # maps internal record names to LDAP
+ "filter": None, # additional filter for this type
+ "streetAddressAttr": "",
+ "geoAttr": "",
+ "mapping": { # maps internal record names to LDAP
"recordName": "cn",
- "fullName" : "cn",
+ "fullName": "cn",
},
},
},
"groupSchema": {
- "membersAttr": "member", # how members are specified
- "nestedGroupsAttr": None, # how nested groups are specified
- "memberIdAttr": None, # which attribute the above refer to (None means use DN)
+ "membersAttr": "member", # how members are specified
+ "nestedGroupsAttr": None, # how nested groups are specified
+ "memberIdAttr": None, # which attribute the above refer to (None means use DN)
},
"resourceSchema": {
# Either set this attribute to retrieve the plist version
@@ -184,12 +189,12 @@
# individually:
"autoScheduleAttr": None,
"autoScheduleEnabledValue": "yes",
- "proxyAttr": None, # list of GUIDs
- "readOnlyProxyAttr": None, # list of GUIDs
- "autoAcceptGroupAttr": None, # single group GUID
+ "proxyAttr": None, # list of GUIDs
+ "readOnlyProxyAttr": None, # list of GUIDs
+ "autoAcceptGroupAttr": None, # single group GUID
},
"poddingSchema": {
- "serverIdAttr": None, # maps to augments server-id
+ "serverIdAttr": None, # maps to augments server-id
},
}
ignored = None
@@ -238,7 +243,7 @@
if self.rdnSchema[recordType]["attr"]:
attrSet.add(self.rdnSchema[recordType]["attr"])
for n in ("calendarEnabledAttr", "associatedAddressAttr",
- "streetAddressAttr", "geoAttr"):
+ "streetAddressAttr", "geoAttr"):
if self.rdnSchema[recordType].get(n, False):
attrSet.add(self.rdnSchema[recordType][n])
for attrList in self.rdnSchema[recordType]["mapping"].values():
@@ -311,15 +316,16 @@
# Query the LDAP server
self.log.debug("Querying ldap for records matching base {base} and "
- "filter {filter} for attributes {attrs}.",
- base=ldap.dn.dn2str(base), filter=filterstr, attrs=self.attrlist)
+ "filter {filter} for attributes {attrs}.",
+ base=ldap.dn.dn2str(base), filter=filterstr,
+ attrs=self.attrlist)
# This takes a while, so if you don't want to have a "long request"
# warning logged, use this instead of timedSearch:
# results = self.ldap.search_s(ldap.dn.dn2str(base),
# ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=self.attrlist)
- results = self.timedSearch(ldap.dn.dn2str(base),
- ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=self.attrlist)
+ results = self.timedSearch(ldap.dn.dn2str(base), ldap.SCOPE_SUBTREE,
+ filterstr=filterstr, attrlist=self.attrlist)
records = []
numMissingGuids = 0
@@ -337,7 +343,8 @@
continue
if not unrestricted:
- self.log.debug("{dn} is not enabled because it's not a member of group: {group}",
+ self.log.debug(
+ "{dn} is not enabled because it's not a member of group: {group}",
dn=dn, group=self.restrictToGroup)
record.enabledForCalendaring = False
record.enabledForAddressBooks = False
@@ -346,7 +353,8 @@
if numMissingGuids:
self.log.info("{num} {recordType} records are missing {attr}",
- num=numMissingGuids, recordType=recordType, attr=guidAttr)
+ num=numMissingGuids, recordType=recordType,
+ attr=guidAttr)
return records
@@ -400,11 +408,13 @@
# Query the LDAP server
self.log.debug("Querying ldap for records matching base {base} and "
- "filter {filter} for attributes {attrs}.",
- base=ldap.dn.dn2str(self.base), filter=filterstr, attrs=attrlist)
+ "filter {filter} for attributes {attrs}.",
+ base=ldap.dn.dn2str(self.base), filter=filterstr,
+ attrs=attrlist)
results = self.timedSearch(ldap.dn.dn2str(self.base),
- ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=attrlist)
+ ldap.SCOPE_SUBTREE, filterstr=filterstr,
+ attrlist=attrlist)
for dn, attrs in results:
dn = normalizeDNstr(dn)
@@ -415,12 +425,12 @@
if readDelegate:
readDelegate = normalizeUUID(readDelegate)
assignments.append(("%s#calendar-proxy-read" % (guid,),
- [readDelegate]))
+ [readDelegate]))
writeDelegate = self._getUniqueLdapAttribute(attrs, writeAttr)
if writeDelegate:
writeDelegate = normalizeUUID(writeDelegate)
assignments.append(("%s#calendar-proxy-write" % (guid,),
- [writeDelegate]))
+ [writeDelegate]))
return assignments
@@ -433,11 +443,11 @@
if self.credentials.get("dn", ""):
try:
self.log.info("Binding to LDAP {dn}",
- dn=repr(self.credentials.get("dn")))
+ dn=repr(self.credentials.get("dn")))
self.ldap.simple_bind_s(self.credentials.get("dn"),
- self.credentials.get("password"))
+ self.credentials.get("password"))
self.log.info("Successfully authenticated with LDAP as {dn}",
- dn=repr(self.credentials.get("dn")))
+ dn=repr(self.credentials.get("dn")))
except ldap.INVALID_CREDENTIALS:
self.log.error("Can't bind to LDAP {uri}: check credentials", uri=self.uri)
raise DirectoryConfigurationError()
@@ -498,7 +508,7 @@
except ldap.NO_SUCH_OBJECT:
self.log.error("LDAP Authentication error for %s: NO_SUCH_OBJECT"
- % (dn,))
+ % (dn,))
# fall through to try again; could be transient
except ldap.INVALID_CREDENTIALS:
@@ -526,7 +536,7 @@
def timedSearch(self, base, scope, filterstr="(objectClass=*)",
- attrlist=None, timeoutSeconds=-1, resultLimit=0):
+ attrlist=None, timeoutSeconds=-1, resultLimit=0):
"""
Execute an LDAP query, retrying up to 3 times in case the LDAP server has
gone down and we need to reconnect. If it takes longer than the configured
@@ -541,8 +551,7 @@
try:
s = ldap.async.List(self.getLDAPConnection())
s.startSearch(base, scope, filterstr, attrList=attrlist,
- timeout=timeoutSeconds,
- sizelimit=resultLimit)
+ timeout=timeoutSeconds, sizelimit=resultLimit)
startTime = time.time()
s.processResults()
except ldap.NO_SUCH_OBJECT:
@@ -566,8 +575,10 @@
if totalTime > self.warningThresholdSeconds:
if filterstr and len(filterstr) > 100:
filterstr = "%s..." % (filterstr[:100],)
- self.log.error("LDAP query exceeded threshold: %.2f seconds for %s %s %s (#results=%d)" %
- (totalTime, base, filterstr, attrlist, len(result)))
+ self.log.error(
+ "LDAP query exceeded threshold: %.2f seconds for %s %s %s (#results=%d)" %
+ (totalTime, base, filterstr, attrlist, len(result))
+ )
return result
raise HTTPError(StatusResponse(responsecode.SERVICE_UNAVAILABLE, "LDAP server unavailable"))
@@ -589,7 +600,7 @@
return True
if self.groupSchema["memberIdAttr"]:
value = self._getUniqueLdapAttribute(attrs, self.groupSchema["memberIdAttr"])
- else: # No memberIdAttr implies DN
+ else: # No memberIdAttr implies DN
value = dn
return value in self.restrictedPrincipals
@@ -610,9 +621,11 @@
# TODO: This shouldn't be hardcoded to cn
filterstr = "(cn=%s)" % (self.restrictToGroup,)
self.log.debug("Retrieving ldap record with base %s and filter %s." %
- (ldap.dn.dn2str(base), filterstr))
+ (ldap.dn.dn2str(base), filterstr))
result = self.timedSearch(ldap.dn.dn2str(base),
- ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=self.attrlist)
+ ldap.SCOPE_SUBTREE,
+ filterstr=filterstr,
+ attrlist=self.attrlist)
members = []
nestedGroups = []
@@ -621,16 +634,20 @@
dn, attrs = result[0]
dn = normalizeDNstr(dn)
if self.groupSchema["membersAttr"]:
- members = self._getMultipleLdapAttributes(attrs,
- self.groupSchema["membersAttr"])
- if not self.groupSchema["memberIdAttr"]: # these are DNs
+ members = self._getMultipleLdapAttributes(
+ attrs,
+ self.groupSchema["membersAttr"]
+ )
+ if not self.groupSchema["memberIdAttr"]: # these are DNs
members = [normalizeDNstr(m) for m in members]
members = set(members)
if self.groupSchema["nestedGroupsAttr"]:
- nestedGroups = self._getMultipleLdapAttributes(attrs,
- self.groupSchema["nestedGroupsAttr"])
- if not self.groupSchema["memberIdAttr"]: # these are DNs
+ nestedGroups = self._getMultipleLdapAttributes(
+ attrs,
+ self.groupSchema["nestedGroupsAttr"]
+ )
+ if not self.groupSchema["memberIdAttr"]: # these are DNs
nestedGroups = [normalizeDNstr(g) for g in nestedGroups]
nestedGroups = set(nestedGroups)
else:
@@ -639,8 +656,9 @@
nestedGroups = members
members = set()
- self._cachedRestrictedPrincipals = set(self._expandGroupMembership(members,
- nestedGroups))
+ self._cachedRestrictedPrincipals = set(
+ self._expandGroupMembership(members, nestedGroups)
+ )
self.log.info("Got %d restricted group members" % (
len(self._cachedRestrictedPrincipals),))
self.restrictedTimestamp = time.time()
@@ -695,15 +713,17 @@
scope = ldap.SCOPE_SUBTREE
base = self.typeDNs[recordType]
filterstr = "(%s=%s)" % (self.groupSchema["memberIdAttr"], group)
- else: # Use DN
+ else: # Use DN
scope = ldap.SCOPE_BASE
base = ldap.dn.str2dn(group)
filterstr = "(objectClass=*)"
self.log.debug("Retrieving ldap record with base %s and filter %s." %
- (ldap.dn.dn2str(base), filterstr))
+ (ldap.dn.dn2str(base), filterstr))
result = self.timedSearch(ldap.dn.dn2str(base),
- scope, filterstr=filterstr, attrlist=self.attrlist)
+ scope,
+ filterstr=filterstr,
+ attrlist=self.attrlist)
if len(result) == 0:
continue
@@ -714,24 +734,29 @@
dn, attrs = result[0]
dn = normalizeDNstr(dn)
if self.groupSchema["membersAttr"]:
- subMembers = self._getMultipleLdapAttributes(attrs,
- self.groupSchema["membersAttr"])
- if not self.groupSchema["memberIdAttr"]: # these are DNs
+ subMembers = self._getMultipleLdapAttributes(
+ attrs,
+ self.groupSchema["membersAttr"]
+ )
+ if not self.groupSchema["memberIdAttr"]: # these are DNs
subMembers = [normalizeDNstr(m) for m in subMembers]
subMembers = set(subMembers)
if self.groupSchema["nestedGroupsAttr"]:
- subNestedGroups = self._getMultipleLdapAttributes(attrs,
- self.groupSchema["nestedGroupsAttr"])
- if not self.groupSchema["memberIdAttr"]: # these are DNs
+ subNestedGroups = self._getMultipleLdapAttributes(
+ attrs,
+ self.groupSchema["nestedGroupsAttr"]
+ )
+ if not self.groupSchema["memberIdAttr"]: # these are DNs
subNestedGroups = [normalizeDNstr(g) for g in subNestedGroups]
subNestedGroups = set(subNestedGroups)
processedItems.add(group)
yield group
- for item in self._expandGroupMembership(subMembers, subNestedGroups,
- processedItems):
+ for item in self._expandGroupMembership(subMembers,
+ subNestedGroups,
+ processedItems):
yield item
@@ -805,8 +830,10 @@
emailSuffix = self.rdnSchema[recordType].get("emailSuffix", None)
if len(emailAddresses) == 0 and emailSuffix:
- emailPrefix = self._getUniqueLdapAttribute(attrs,
- self.rdnSchema[recordType].get("attr", "cn"))
+ emailPrefix = self._getUniqueLdapAttribute(
+ attrs,
+ self.rdnSchema[recordType].get("attr", "cn")
+ )
emailAddresses.add(emailPrefix + emailSuffix)
proxyGUIDs = ()
@@ -837,7 +864,7 @@
memberGUIDs.extend(members)
# Normalize members if they're in DN form
- if not self.groupSchema["memberIdAttr"]: # empty = dn
+ if not self.groupSchema["memberIdAttr"]: # empty = dn
guids = list(memberGUIDs)
memberGUIDs = []
for dnStr in guids:
@@ -849,14 +876,16 @@
self.log.warn("Bad LDAP DN: %s" % (dnStr,))
elif recordType in (self.recordType_resources,
- self.recordType_locations):
+ self.recordType_locations):
fullName = self._getUniqueLdapAttribute(attrs, self.rdnSchema[recordType]["mapping"]["fullName"])
enabledForCalendaring = True
enabledForAddressBooks = False
enabledForLogin = False
if self.resourceSchema["resourceInfoAttr"]:
- resourceInfo = self._getUniqueLdapAttribute(attrs,
- self.resourceSchema["resourceInfoAttr"])
+ resourceInfo = self._getUniqueLdapAttribute(
+ attrs,
+ self.resourceSchema["resourceInfoAttr"]
+ )
if resourceInfo:
try:
(
@@ -876,45 +905,66 @@
readOnlyProxyGUIDs = (readOnlyProxy,)
except ValueError, e:
self.log.error("Unable to parse resource info (%s)" % (e,))
- else: # the individual resource attributes might be specified
+ else: # the individual resource attributes might be specified
if self.resourceSchema["autoScheduleAttr"]:
- autoScheduleValue = self._getUniqueLdapAttribute(attrs,
- self.resourceSchema["autoScheduleAttr"])
- autoSchedule = (autoScheduleValue ==
- self.resourceSchema["autoScheduleEnabledValue"])
+ autoScheduleValue = self._getUniqueLdapAttribute(
+ attrs,
+ self.resourceSchema["autoScheduleAttr"]
+ )
+ autoSchedule = (
+ autoScheduleValue == self.resourceSchema["autoScheduleEnabledValue"]
+ )
if self.resourceSchema["proxyAttr"]:
- proxyGUIDs = set(self._getMultipleLdapAttributes(attrs,
- self.resourceSchema["proxyAttr"]))
+ proxyGUIDs = set(
+ self._getMultipleLdapAttributes(
+ attrs,
+ self.resourceSchema["proxyAttr"]
+ )
+ )
if self.resourceSchema["readOnlyProxyAttr"]:
- readOnlyProxyGUIDs = set(self._getMultipleLdapAttributes(attrs,
- self.resourceSchema["readOnlyProxyAttr"]))
+ readOnlyProxyGUIDs = set(
+ self._getMultipleLdapAttributes(
+ attrs,
+ self.resourceSchema["readOnlyProxyAttr"]
+ )
+ )
if self.resourceSchema["autoAcceptGroupAttr"]:
- autoAcceptGroup = self._getUniqueLdapAttribute(attrs,
- self.resourceSchema["autoAcceptGroupAttr"])
+ autoAcceptGroup = self._getUniqueLdapAttribute(
+ attrs,
+ self.resourceSchema["autoAcceptGroupAttr"]
+ )
if recordType == self.recordType_locations:
if self.rdnSchema[recordType]["associatedAddressAttr"]:
- associatedAddress = self._getUniqueLdapAttribute(attrs,
- self.rdnSchema[recordType]["associatedAddressAttr"])
+ associatedAddress = self._getUniqueLdapAttribute(
+ attrs,
+ self.rdnSchema[recordType]["associatedAddressAttr"]
+ )
if associatedAddress:
extras["associatedAddress"] = associatedAddress
elif recordType == self.recordType_addresses:
if self.rdnSchema[recordType].get("geoAttr", ""):
- geo = self._getUniqueLdapAttribute(attrs,
- self.rdnSchema[recordType]["geoAttr"])
+ geo = self._getUniqueLdapAttribute(
+ attrs,
+ self.rdnSchema[recordType]["geoAttr"]
+ )
if geo:
extras["geo"] = geo
if self.rdnSchema[recordType].get("streetAddressAttr", ""):
- street = self._getUniqueLdapAttribute(attrs,
- self.rdnSchema[recordType]["streetAddressAttr"])
+ street = self._getUniqueLdapAttribute(
+ attrs,
+ self.rdnSchema[recordType]["streetAddressAttr"]
+ )
if street:
extras["streetAddress"] = street
serverID = None
if self.poddingSchema["serverIdAttr"]:
- serverID = self._getUniqueLdapAttribute(attrs,
- self.poddingSchema["serverIdAttr"])
+ serverID = self._getUniqueLdapAttribute(
+ attrs,
+ self.poddingSchema["serverIdAttr"]
+ )
record = LdapDirectoryRecord(
service=self,
@@ -940,8 +990,7 @@
# TODO: this needs to be deferred but for now we hard code
# the deferred result because we know it is completing
# immediately.
- d = self.augmentService.getAugmentRecord(record.guid,
- recordType)
+ d = self.augmentService.getAugmentRecord(record.guid, recordType)
d.addCallback(lambda x: record.addAugmentInformation(x))
else:
@@ -953,7 +1002,7 @@
enabledForCalendaring=enabledForCalendaring,
autoSchedule=autoSchedule,
autoAcceptGroup=autoAcceptGroup,
- enabledForAddressBooks=enabledForAddressBooks, # TODO: add to LDAP?
+ enabledForAddressBooks=enabledForAddressBooks, # TODO: add to LDAP?
enabledForLogin=enabledForLogin,
)
record.addAugmentInformation(augmentRecord)
@@ -963,15 +1012,18 @@
loginEnabledAttr = self.rdnSchema[recordType]["loginEnabledAttr"]
if loginEnabledAttr:
loginEnabledValue = self.rdnSchema[recordType]["loginEnabledValue"]
- record.enabledForLogin = self._getUniqueLdapAttribute(attrs,
- loginEnabledAttr) == loginEnabledValue
+ record.enabledForLogin = self._getUniqueLdapAttribute(
+ attrs, loginEnabledAttr
+ ) == loginEnabledValue
# Override with LDAP calendar-enabled control if attribute specified
calendarEnabledAttr = self.rdnSchema[recordType].get("calendarEnabledAttr", "")
if calendarEnabledAttr:
calendarEnabledValue = self.rdnSchema[recordType]["calendarEnabledValue"]
- record.enabledForCalendaring = self._getUniqueLdapAttribute(attrs,
- calendarEnabledAttr) == calendarEnabledValue
+ record.enabledForCalendaring = self._getUniqueLdapAttribute(
+ attrs,
+ calendarEnabledAttr
+ ) == calendarEnabledValue
return record
@@ -994,7 +1046,7 @@
queryMethod = self.timedSearch
self.log.debug("LDAP query for types %s, indexType %s and indexKey %s"
- % (recordTypes, indexType, indexKey))
+ % (recordTypes, indexType, indexKey))
guidAttr = self.rdnSchema["guidAttr"]
for recordType in recordTypes:
@@ -1024,7 +1076,7 @@
elif indexType == self.INDEX_TYPE_CUA:
# indexKey is of the form "mailto:test at example.net"
- email = indexKey[7:] # strip "mailto:"
+ email = indexKey[7:] # strip "mailto:"
emailSuffix = self.rdnSchema[recordType].get("emailSuffix", None)
if emailSuffix is not None and email.partition("@")[2] == emailSuffix:
filterstr = "(&%s(|(&(!(mail=*))(%s=%s))(mail=%s)))" % (
@@ -1040,7 +1092,7 @@
if ldapFields:
subfilter = "(%s=%s)" % (ldapFields, ldapEsc(email))
else:
- continue # No LDAP attribute assigned for emailAddresses
+ continue # No LDAP attribute assigned for emailAddresses
else:
subfilter = []
@@ -1048,7 +1100,7 @@
if ldapField:
subfilter.append("(%s=%s)" % (ldapField, ldapEsc(email)))
if not subfilter:
- continue # No LDAP attribute assigned for emailAddresses
+ continue # No LDAP attribute assigned for emailAddresses
subfilter = "(|%s)" % ("".join(subfilter))
filterstr = "(&%s%s)" % (filterstr, subfilter)
@@ -1058,9 +1110,11 @@
# Query the LDAP server
self.log.debug("Retrieving ldap record with base %s and filter %s." %
- (ldap.dn.dn2str(base), filterstr))
+ (ldap.dn.dn2str(base), filterstr))
result = queryMethod(ldap.dn.dn2str(base),
- ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=self.attrlist)
+ ldap.SCOPE_SUBTREE,
+ filterstr=filterstr,
+ attrlist=self.attrlist)
if result:
dn, attrs = result.pop()
@@ -1079,20 +1133,26 @@
record.applySACLs()
- self.recordCacheForType(recordType).addRecord(record,
- indexType, indexKey
+ self.recordCacheForType(recordType).addRecord(
+ record, indexType, indexKey
)
# We got a match, so don't bother checking other types
break
except MissingRecordNameException:
- self.log.warn("Ignoring record missing record name attribute: recordType %s, indexType %s and indexKey %s"
- % (recordTypes, indexType, indexKey))
+ self.log.warn(
+ "Ignoring record missing record name "
+ "attribute: recordType %s, indexType %s and indexKey %s"
+ % (recordTypes, indexType, indexKey)
+ )
except MissingGuidException:
- self.log.warn("Ignoring record missing guid attribute: recordType %s, indexType %s and indexKey %s"
- % (recordTypes, indexType, indexKey))
+ self.log.warn(
+ "Ignoring record missing guid attribute: "
+ "recordType %s, indexType %s and indexKey %s"
+ % (recordTypes, indexType, indexKey)
+ )
def recordsMatchingTokens(self, tokens, context=None, limitResults=50, timeoutSeconds=10):
@@ -1131,17 +1191,27 @@
base = self.typeDNs[recordType]
scope = ldap.SCOPE_SUBTREE
extraFilter = self.rdnSchema[recordType].get("filter", "")
- filterstr = buildFilterFromTokens(recordType, self.rdnSchema[recordType]["mapping"],
- tokens, extra=extraFilter)
+ filterstr = buildFilterFromTokens(
+ recordType,
+ self.rdnSchema[recordType]["mapping"],
+ tokens,
+ extra=extraFilter
+ )
if filterstr is not None:
# Query the LDAP server
- self.log.debug("LDAP search %s %s (limit=%d)" %
- (ldap.dn.dn2str(base), filterstr, limitResults))
- results = self.timedSearch(ldap.dn.dn2str(base), scope,
- filterstr=filterstr, attrlist=self.attrlist,
+ self.log.debug(
+ "LDAP search %s %s (limit=%d)" %
+ (ldap.dn.dn2str(base), filterstr, limitResults)
+ )
+ results = self.timedSearch(
+ ldap.dn.dn2str(base),
+ scope,
+ filterstr=filterstr,
+ attrlist=self.attrlist,
timeoutSeconds=timeoutSeconds,
- resultLimit=limitResults)
+ resultLimit=limitResults
+ )
numMissingGuids = 0
numMissingRecordNames = 0
numNotEnabled = 0
@@ -1149,8 +1219,10 @@
dn = normalizeDNstr(dn)
# Skip if group restriction is in place and guid is not
# a member
- if (recordType != self.recordType_groups and
- not self.isAllowedByRestrictToGroup(dn, attrs)):
+ if (
+ recordType != self.recordType_groups and
+ not self.isAllowedByRestrictToGroup(dn, attrs)
+ ):
continue
try:
@@ -1219,19 +1291,27 @@
else:
scope = ldap.SCOPE_SUBTREE
- filterstr = buildFilter(recordType,
+ filterstr = buildFilter(
+ recordType,
self.rdnSchema[recordType]["mapping"],
- fields, operand=operand,
- optimizeMultiName=self.optimizeMultiName)
+ fields,
+ operand=operand,
+ optimizeMultiName=self.optimizeMultiName
+ )
if filterstr is not None:
# Query the LDAP server
self.log.debug("LDAP search %s %s %s" %
- (ldap.dn.dn2str(base), scope, filterstr))
- results = (yield deferToThread(self.timedSearch, ldap.dn.dn2str(base), scope,
- filterstr=filterstr, attrlist=self.attrlist,
+ (ldap.dn.dn2str(base), scope, filterstr))
+ results = (yield deferToThread(
+ self.timedSearch,
+ ldap.dn.dn2str(base),
+ scope,
+ filterstr=filterstr,
+ attrlist=self.attrlist,
timeoutSeconds=self.requestTimeoutSeconds,
- resultLimit=self.requestResultsLimit))
+ resultLimit=self.requestResultsLimit)
+ )
self.log.debug("LDAP search returned %d results" % (len(results),))
numMissingGuids = 0
numMissingRecordNames = 0
@@ -1239,8 +1319,10 @@
dn = normalizeDNstr(dn)
# Skip if group restriction is in place and guid is not
# a member
- if (recordType != self.recordType_groups and
- not self.isAllowedByRestrictToGroup(dn, attrs)):
+ if (
+ recordType != self.recordType_groups and
+ not self.isAllowedByRestrictToGroup(dn, attrs)
+ ):
continue
try:
@@ -1262,11 +1344,11 @@
if numMissingGuids:
self.log.warn("%d %s records are missing %s" %
- (numMissingGuids, recordType, guidAttr))
+ (numMissingGuids, recordType, guidAttr))
if numMissingRecordNames:
self.log.warn("%d %s records are missing record name" %
- (numMissingRecordNames, recordType))
+ (numMissingRecordNames, recordType))
self.log.debug("Principal property search matched %d records" % (len(records),))
returnValue(records)
@@ -1300,16 +1382,24 @@
# recordsMatchingFields for *each* DN.
for value in valuesToFetch:
fields = [["dn", value, False, "equals"]]
- result = (yield self.recordsMatchingFields(fields,
- recordType=self.recordType_groups))
+ result = (
+ yield self.recordsMatchingFields(
+ fields,
+ recordType=self.recordType_groups
+ )
+ )
results.extend(result)
else:
for batch in splitIntoBatches(valuesToFetch, self.batchSize):
fields = []
for value in batch:
fields.append([attributeToSearch, value, False, "equals"])
- result = (yield self.recordsMatchingFields(fields,
- recordType=self.recordType_groups))
+ result = (
+ yield self.recordsMatchingFields(
+ fields,
+ recordType=self.recordType_groups
+ )
+ )
results.extend(result)
# Reset values for next iteration
@@ -1329,7 +1419,7 @@
# cut: we know we only need to examine groups, and
# those will be children of the groups DN
if not dnContainedIn(ldap.dn.str2dn(memberAlias),
- groupsDN):
+ groupsDN):
continue
if memberAlias not in recordsByAlias:
valuesToFetch.add(memberAlias)
@@ -1351,7 +1441,7 @@
"""
dn = ldap.dn.str2dn(dnStr.lower())
for recordType in self.recordTypes():
- base = self.typeDNs[recordType] # already lowercase
+ base = self.typeDNs[recordType] # already lowercase
if dnContainedIn(dn, base):
return recordType
return None
@@ -1431,7 +1521,8 @@
if firstName != lastName:
firstValue = _convertValue(firstName, firstMatchType)
lastValue = _convertValue(lastName, lastMatchType)
- converted.append("(&(%s=%s)(%s=%s))" %
+ converted.append(
+ "(&(%s=%s)(%s=%s))" %
(mapping["firstName"], firstValue,
mapping["lastName"], lastValue)
)
@@ -1575,8 +1666,10 @@
# Identifier of this record as a group member
memberIdAttr = self.service.groupSchema["memberIdAttr"]
if memberIdAttr:
- self._memberId = self.service._getUniqueLdapAttribute(attrs,
- memberIdAttr)
+ self._memberId = self.service._getUniqueLdapAttribute(
+ attrs,
+ memberIdAttr
+ )
else:
self._memberId = normalizeDNstr(self.dn)
@@ -1604,18 +1697,23 @@
base = self.service.base
filterstr = "(%s=%s)" % (memberIdAttr, ldapEsc(memberId))
self.log.debug("Retrieving subtree of %s with filter %s" %
- (ldap.dn.dn2str(base), filterstr),
- system="LdapDirectoryService")
- result = self.service.timedSearch(ldap.dn.dn2str(base),
- ldap.SCOPE_SUBTREE, filterstr=filterstr,
- attrlist=self.service.attrlist)
+ (ldap.dn.dn2str(base), filterstr),
+ system="LdapDirectoryService")
+ result = self.service.timedSearch(
+ ldap.dn.dn2str(base),
+ ldap.SCOPE_SUBTREE,
+ filterstr=filterstr,
+ attrlist=self.service.attrlist
+ )
- else: # using DN
+ else: # using DN
self.log.debug("Retrieving %s." % memberId,
- system="LdapDirectoryService")
- result = self.service.timedSearch(memberId,
- ldap.SCOPE_BASE, attrlist=self.service.attrlist)
+ system="LdapDirectoryService")
+ result = self.service.timedSearch(
+ memberId,
+ ldap.SCOPE_BASE, attrlist=self.service.attrlist
+ )
if result:
@@ -1627,12 +1725,16 @@
self.log.error("Unable to map %s to a record type" % (dn,))
continue
- shortName = self.service._getUniqueLdapAttribute(attrs,
- self.service.rdnSchema[recordType]["mapping"]["recordName"])
+ shortName = self.service._getUniqueLdapAttribute(
+ attrs,
+ self.service.rdnSchema[recordType]["mapping"]["recordName"]
+ )
if shortName:
- record = self.service.recordWithShortName(recordType,
- shortName)
+ record = self.service.recordWithShortName(
+ recordType,
+ shortName
+ )
if record:
results.append(record)
@@ -1663,7 +1765,8 @@
if len(membersAttrs) == 1:
filterstr = "(%s=%s)" % (membersAttrs[0], self._memberId)
else:
- filterstr = "(|%s)" % ("".join(
+ filterstr = "(|%s)" % (
+ "".join(
["(%s=%s)" % (a, self._memberId) for a in membersAttrs]
),
)
@@ -1671,8 +1774,12 @@
groups = []
try:
- results = self.service.timedSearch(ldap.dn.dn2str(base),
- ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=self.service.attrlist)
+ results = self.service.timedSearch(
+ ldap.dn.dn2str(base),
+ ldap.SCOPE_SUBTREE,
+ filterstr=filterstr,
+ attrlist=self.service.attrlist
+ )
for dn, attrs in results:
dn = normalizeDNstr(dn)
@@ -1753,12 +1860,13 @@
except ldap.INVALID_CREDENTIALS:
self.log.info("Invalid credentials for {dn}",
- dn=repr(self.dn), system="LdapDirectoryService")
+ dn=repr(self.dn),
+ system="LdapDirectoryService")
return False
else:
self.log.error("Unknown Authentication Method '{method}'",
- method=self.service.authMethod.upper())
+ method=self.service.authMethod.upper())
raise DirectoryConfigurationError()
return super(LdapDirectoryRecord, self).verifyCredentials(credentials)
Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py 2014-01-07 18:34:58 UTC (rev 12255)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py 2014-01-07 19:53:20 UTC (rev 12256)
@@ -1270,6 +1270,7 @@
}
)
+
def setupService(self, scenario):
self.service = LdapDirectoryService(scenario[1])
self.service.ldap = LdapDirectoryTestWrapper(self.service.ldap, scenario[0])
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140312/214d5888/attachment.html>
More information about the calendarserver-changes
mailing list