<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[12256] CalendarServer/trunk/twistedcaldav/directory</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.calendarserver.org//changeset/12256">12256</a></dd>
<dt>Author</dt> <dd>sagen@apple.com</dd>
<dt>Date</dt> <dd>2014-01-07 11:53:20 -0800 (Tue, 07 Jan 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>lint</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServertrunktwistedcaldavdirectoryldapdirectorypy">CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdirectorytesttest_ldapdirectorypy">CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServertrunktwistedcaldavdirectoryldapdirectorypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py (12255 => 12256)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -40,7 +40,8 @@
</span><span class="cx"> "LdapDirectoryService",
</span><span class="cx"> ]
</span><span class="cx">
</span><del>-import ldap, ldap.async
</del><ins>+import ldap
+import ldap.async
</ins><span class="cx"> from ldap.filter import escape_filter_chars as ldapEsc
</span><span class="cx">
</span><span class="cx"> try:
</span><span class="lines">@@ -52,8 +53,9 @@
</span><span class="cx">
</span><span class="cx"> import time
</span><span class="cx"> from twisted.cred.credentials import UsernamePassword
</span><del>-from twistedcaldav.directory.cachingdirectory import (CachingDirectoryService,
- CachingDirectoryRecord)
</del><ins>+from twistedcaldav.directory.cachingdirectory import (
+ CachingDirectoryService, CachingDirectoryRecord
+)
</ins><span class="cx"> from twistedcaldav.directory.directory import DirectoryConfigurationError
</span><span class="cx"> from twistedcaldav.directory.augment import AugmentRecord
</span><span class="cx"> from twistedcaldav.directory.util import splitIntoBatches, normalizeUUID
</span><span class="lines">@@ -63,6 +65,8 @@
</span><span class="cx"> from txweb2.http import HTTPError, StatusResponse
</span><span class="cx"> from txweb2 import responsecode
</span><span class="cx">
</span><ins>+
+
</ins><span class="cx"> class LdapDirectoryService(CachingDirectoryService):
</span><span class="cx"> """
</span><span class="cx"> LDAP based implementation of L{IDirectoryService}.
</span><span class="lines">@@ -72,8 +76,9 @@
</span><span class="cx"> baseGUID = "5A871574-0C86-44EE-B11B-B9440C3DC4DD"
</span><span class="cx">
</span><span class="cx"> def __repr__(self):
</span><del>- return "<%s %r: %r>" % (self.__class__.__name__, self.realmName,
- self.uri)
</del><ins>+ return "<%s %r: %r>" % (
+ self.__class__.__name__, self.realmName, self.uri
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def __init__(self, params):
</span><span class="lines">@@ -85,15 +90,15 @@
</span><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> defaults = {
</span><del>- "augmentService" : None,
- "groupMembershipCache" : None,
- "cacheTimeout": 1, # Minutes
</del><ins>+ "augmentService": None,
+ "groupMembershipCache": None,
+ "cacheTimeout": 1, # Minutes
</ins><span class="cx"> "negativeCaching": False,
</span><span class="cx"> "warningThresholdSeconds": 3,
</span><del>- "batchSize": 500, # for splitting up large queries
- "requestTimeoutSeconds" : 10,
- "requestResultsLimit" : 200,
- "optimizeMultiName" : False,
</del><ins>+ "batchSize": 500, # for splitting up large queries
+ "requestTimeoutSeconds": 10,
+ "requestResultsLimit": 200,
+ "optimizeMultiName": False,
</ins><span class="cx"> "queryLocationsImplicitly": True,
</span><span class="cx"> "restrictEnabledRecords": False,
</span><span class="cx"> "restrictToGroup": "",
</span><span class="lines">@@ -102,7 +107,7 @@
</span><span class="cx"> "tls": False,
</span><span class="cx"> "tlsCACertFile": None,
</span><span class="cx"> "tlsCACertDir": None,
</span><del>- "tlsRequireCert": None, # never, allow, try, demand, hard
</del><ins>+ "tlsRequireCert": None, # never, allow, try, demand, hard
</ins><span class="cx"> "credentials": {
</span><span class="cx"> "dn": None,
</span><span class="cx"> "password": None,
</span><span class="lines">@@ -113,68 +118,68 @@
</span><span class="cx"> "guidAttr": "entryUUID",
</span><span class="cx"> "users": {
</span><span class="cx"> "rdn": "ou=People",
</span><del>- "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
</del><ins>+ "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
</ins><span class="cx"> "recordName": "uid",
</span><del>- "fullName" : "cn",
- "emailAddresses" : ["mail"], # multiple LDAP fields supported
- "firstName" : "givenName",
- "lastName" : "sn",
</del><ins>+ "fullName": "cn",
+ "emailAddresses": ["mail"], # multiple LDAP fields supported
+ "firstName": "givenName",
+ "lastName": "sn",
</ins><span class="cx"> },
</span><span class="cx"> },
</span><span class="cx"> "groups": {
</span><span class="cx"> "rdn": "ou=Group",
</span><del>- "filter": None, # additional filter for this type
- "mapping" : { # maps internal record names to LDAP
</del><ins>+ "filter": None, # additional filter for this type
+ "mapping": { # maps internal record names to LDAP
</ins><span class="cx"> "recordName": "cn",
</span><del>- "fullName" : "cn",
- "emailAddresses" : ["mail"], # multiple LDAP fields supported
- "firstName" : "givenName",
- "lastName" : "sn",
</del><ins>+ "fullName": "cn",
+ "emailAddresses": ["mail"], # multiple LDAP fields supported
+ "firstName": "givenName",
+ "lastName": "sn",
</ins><span class="cx"> },
</span><span class="cx"> },
</span><span class="cx"> "locations": {
</span><span class="cx"> "rdn": "ou=Places",
</span><del>- "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
</del><ins>+ "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
</ins><span class="cx"> "recordName": "cn",
</span><del>- "fullName" : "cn",
- "emailAddresses" : ["mail"], # multiple LDAP fields supported
</del><ins>+ "fullName": "cn",
+ "emailAddresses": ["mail"], # multiple LDAP fields supported
</ins><span class="cx"> },
</span><span class="cx"> },
</span><span class="cx"> "resources": {
</span><span class="cx"> "rdn": "ou=Resources",
</span><del>- "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
</del><ins>+ "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
</ins><span class="cx"> "recordName": "cn",
</span><del>- "fullName" : "cn",
- "emailAddresses" : ["mail"], # multiple LDAP fields supported
</del><ins>+ "fullName": "cn",
+ "emailAddresses": ["mail"], # multiple LDAP fields supported
</ins><span class="cx"> },
</span><span class="cx"> },
</span><span class="cx"> "addresses": {
</span><span class="cx"> "rdn": "ou=Buildings",
</span><del>- "filter": None, # additional filter for this type
- "streetAddressAttr" : "",
- "geoAttr" : "",
- "mapping" : { # maps internal record names to LDAP
</del><ins>+ "filter": None, # additional filter for this type
+ "streetAddressAttr": "",
+ "geoAttr": "",
+ "mapping": { # maps internal record names to LDAP
</ins><span class="cx"> "recordName": "cn",
</span><del>- "fullName" : "cn",
</del><ins>+ "fullName": "cn",
</ins><span class="cx"> },
</span><span class="cx"> },
</span><span class="cx"> },
</span><span class="cx"> "groupSchema": {
</span><del>- "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)
</del><ins>+ "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)
</ins><span class="cx"> },
</span><span class="cx"> "resourceSchema": {
</span><span class="cx"> # Either set this attribute to retrieve the plist version
</span><span class="lines">@@ -184,12 +189,12 @@
</span><span class="cx"> # individually:
</span><span class="cx"> "autoScheduleAttr": None,
</span><span class="cx"> "autoScheduleEnabledValue": "yes",
</span><del>- "proxyAttr": None, # list of GUIDs
- "readOnlyProxyAttr": None, # list of GUIDs
- "autoAcceptGroupAttr": None, # single group GUID
</del><ins>+ "proxyAttr": None, # list of GUIDs
+ "readOnlyProxyAttr": None, # list of GUIDs
+ "autoAcceptGroupAttr": None, # single group GUID
</ins><span class="cx"> },
</span><span class="cx"> "poddingSchema": {
</span><del>- "serverIdAttr": None, # maps to augments server-id
</del><ins>+ "serverIdAttr": None, # maps to augments server-id
</ins><span class="cx"> },
</span><span class="cx"> }
</span><span class="cx"> ignored = None
</span><span class="lines">@@ -238,7 +243,7 @@
</span><span class="cx"> if self.rdnSchema[recordType]["attr"]:
</span><span class="cx"> attrSet.add(self.rdnSchema[recordType]["attr"])
</span><span class="cx"> for n in ("calendarEnabledAttr", "associatedAddressAttr",
</span><del>- "streetAddressAttr", "geoAttr"):
</del><ins>+ "streetAddressAttr", "geoAttr"):
</ins><span class="cx"> if self.rdnSchema[recordType].get(n, False):
</span><span class="cx"> attrSet.add(self.rdnSchema[recordType][n])
</span><span class="cx"> for attrList in self.rdnSchema[recordType]["mapping"].values():
</span><span class="lines">@@ -311,15 +316,16 @@
</span><span class="cx">
</span><span class="cx"> # Query the LDAP server
</span><span class="cx"> self.log.debug("Querying ldap for records matching base {base} and "
</span><del>- "filter {filter} for attributes {attrs}.",
- base=ldap.dn.dn2str(base), filter=filterstr, attrs=self.attrlist)
</del><ins>+ "filter {filter} for attributes {attrs}.",
+ base=ldap.dn.dn2str(base), filter=filterstr,
+ attrs=self.attrlist)
</ins><span class="cx">
</span><span class="cx"> # This takes a while, so if you don't want to have a "long request"
</span><span class="cx"> # warning logged, use this instead of timedSearch:
</span><span class="cx"> # results = self.ldap.search_s(ldap.dn.dn2str(base),
</span><span class="cx"> # ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=self.attrlist)
</span><del>- results = self.timedSearch(ldap.dn.dn2str(base),
- ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=self.attrlist)
</del><ins>+ results = self.timedSearch(ldap.dn.dn2str(base), ldap.SCOPE_SUBTREE,
+ filterstr=filterstr, attrlist=self.attrlist)
</ins><span class="cx">
</span><span class="cx"> records = []
</span><span class="cx"> numMissingGuids = 0
</span><span class="lines">@@ -337,7 +343,8 @@
</span><span class="cx"> continue
</span><span class="cx">
</span><span class="cx"> if not unrestricted:
</span><del>- self.log.debug("{dn} is not enabled because it's not a member of group: {group}",
</del><ins>+ self.log.debug(
+ "{dn} is not enabled because it's not a member of group: {group}",
</ins><span class="cx"> dn=dn, group=self.restrictToGroup)
</span><span class="cx"> record.enabledForCalendaring = False
</span><span class="cx"> record.enabledForAddressBooks = False
</span><span class="lines">@@ -346,7 +353,8 @@
</span><span class="cx">
</span><span class="cx"> if numMissingGuids:
</span><span class="cx"> self.log.info("{num} {recordType} records are missing {attr}",
</span><del>- num=numMissingGuids, recordType=recordType, attr=guidAttr)
</del><ins>+ num=numMissingGuids, recordType=recordType,
+ attr=guidAttr)
</ins><span class="cx">
</span><span class="cx"> return records
</span><span class="cx">
</span><span class="lines">@@ -400,11 +408,13 @@
</span><span class="cx">
</span><span class="cx"> # Query the LDAP server
</span><span class="cx"> self.log.debug("Querying ldap for records matching base {base} and "
</span><del>- "filter {filter} for attributes {attrs}.",
- base=ldap.dn.dn2str(self.base), filter=filterstr, attrs=attrlist)
</del><ins>+ "filter {filter} for attributes {attrs}.",
+ base=ldap.dn.dn2str(self.base), filter=filterstr,
+ attrs=attrlist)
</ins><span class="cx">
</span><span class="cx"> results = self.timedSearch(ldap.dn.dn2str(self.base),
</span><del>- ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=attrlist)
</del><ins>+ ldap.SCOPE_SUBTREE, filterstr=filterstr,
+ attrlist=attrlist)
</ins><span class="cx">
</span><span class="cx"> for dn, attrs in results:
</span><span class="cx"> dn = normalizeDNstr(dn)
</span><span class="lines">@@ -415,12 +425,12 @@
</span><span class="cx"> if readDelegate:
</span><span class="cx"> readDelegate = normalizeUUID(readDelegate)
</span><span class="cx"> assignments.append(("%s#calendar-proxy-read" % (guid,),
</span><del>- [readDelegate]))
</del><ins>+ [readDelegate]))
</ins><span class="cx"> writeDelegate = self._getUniqueLdapAttribute(attrs, writeAttr)
</span><span class="cx"> if writeDelegate:
</span><span class="cx"> writeDelegate = normalizeUUID(writeDelegate)
</span><span class="cx"> assignments.append(("%s#calendar-proxy-write" % (guid,),
</span><del>- [writeDelegate]))
</del><ins>+ [writeDelegate]))
</ins><span class="cx">
</span><span class="cx"> return assignments
</span><span class="cx">
</span><span class="lines">@@ -433,11 +443,11 @@
</span><span class="cx"> if self.credentials.get("dn", ""):
</span><span class="cx"> try:
</span><span class="cx"> self.log.info("Binding to LDAP {dn}",
</span><del>- dn=repr(self.credentials.get("dn")))
</del><ins>+ dn=repr(self.credentials.get("dn")))
</ins><span class="cx"> self.ldap.simple_bind_s(self.credentials.get("dn"),
</span><del>- self.credentials.get("password"))
</del><ins>+ self.credentials.get("password"))
</ins><span class="cx"> self.log.info("Successfully authenticated with LDAP as {dn}",
</span><del>- dn=repr(self.credentials.get("dn")))
</del><ins>+ dn=repr(self.credentials.get("dn")))
</ins><span class="cx"> except ldap.INVALID_CREDENTIALS:
</span><span class="cx"> self.log.error("Can't bind to LDAP {uri}: check credentials", uri=self.uri)
</span><span class="cx"> raise DirectoryConfigurationError()
</span><span class="lines">@@ -498,7 +508,7 @@
</span><span class="cx">
</span><span class="cx"> except ldap.NO_SUCH_OBJECT:
</span><span class="cx"> self.log.error("LDAP Authentication error for %s: NO_SUCH_OBJECT"
</span><del>- % (dn,))
</del><ins>+ % (dn,))
</ins><span class="cx"> # fall through to try again; could be transient
</span><span class="cx">
</span><span class="cx"> except ldap.INVALID_CREDENTIALS:
</span><span class="lines">@@ -526,7 +536,7 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def timedSearch(self, base, scope, filterstr="(objectClass=*)",
</span><del>- attrlist=None, timeoutSeconds=-1, resultLimit=0):
</del><ins>+ attrlist=None, timeoutSeconds=-1, resultLimit=0):
</ins><span class="cx"> """
</span><span class="cx"> Execute an LDAP query, retrying up to 3 times in case the LDAP server has
</span><span class="cx"> gone down and we need to reconnect. If it takes longer than the configured
</span><span class="lines">@@ -541,8 +551,7 @@
</span><span class="cx"> try:
</span><span class="cx"> s = ldap.async.List(self.getLDAPConnection())
</span><span class="cx"> s.startSearch(base, scope, filterstr, attrList=attrlist,
</span><del>- timeout=timeoutSeconds,
- sizelimit=resultLimit)
</del><ins>+ timeout=timeoutSeconds, sizelimit=resultLimit)
</ins><span class="cx"> startTime = time.time()
</span><span class="cx"> s.processResults()
</span><span class="cx"> except ldap.NO_SUCH_OBJECT:
</span><span class="lines">@@ -566,8 +575,10 @@
</span><span class="cx"> if totalTime > self.warningThresholdSeconds:
</span><span class="cx"> if filterstr and len(filterstr) > 100:
</span><span class="cx"> filterstr = "%s..." % (filterstr[:100],)
</span><del>- self.log.error("LDAP query exceeded threshold: %.2f seconds for %s %s %s (#results=%d)" %
- (totalTime, base, filterstr, attrlist, len(result)))
</del><ins>+ self.log.error(
+ "LDAP query exceeded threshold: %.2f seconds for %s %s %s (#results=%d)" %
+ (totalTime, base, filterstr, attrlist, len(result))
+ )
</ins><span class="cx"> return result
</span><span class="cx">
</span><span class="cx"> raise HTTPError(StatusResponse(responsecode.SERVICE_UNAVAILABLE, "LDAP server unavailable"))
</span><span class="lines">@@ -589,7 +600,7 @@
</span><span class="cx"> return True
</span><span class="cx"> if self.groupSchema["memberIdAttr"]:
</span><span class="cx"> value = self._getUniqueLdapAttribute(attrs, self.groupSchema["memberIdAttr"])
</span><del>- else: # No memberIdAttr implies DN
</del><ins>+ else: # No memberIdAttr implies DN
</ins><span class="cx"> value = dn
</span><span class="cx"> return value in self.restrictedPrincipals
</span><span class="cx">
</span><span class="lines">@@ -610,9 +621,11 @@
</span><span class="cx"> # TODO: This shouldn't be hardcoded to cn
</span><span class="cx"> filterstr = "(cn=%s)" % (self.restrictToGroup,)
</span><span class="cx"> self.log.debug("Retrieving ldap record with base %s and filter %s." %
</span><del>- (ldap.dn.dn2str(base), filterstr))
</del><ins>+ (ldap.dn.dn2str(base), filterstr))
</ins><span class="cx"> result = self.timedSearch(ldap.dn.dn2str(base),
</span><del>- ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=self.attrlist)
</del><ins>+ ldap.SCOPE_SUBTREE,
+ filterstr=filterstr,
+ attrlist=self.attrlist)
</ins><span class="cx">
</span><span class="cx"> members = []
</span><span class="cx"> nestedGroups = []
</span><span class="lines">@@ -621,16 +634,20 @@
</span><span class="cx"> dn, attrs = result[0]
</span><span class="cx"> dn = normalizeDNstr(dn)
</span><span class="cx"> if self.groupSchema["membersAttr"]:
</span><del>- members = self._getMultipleLdapAttributes(attrs,
- self.groupSchema["membersAttr"])
- if not self.groupSchema["memberIdAttr"]: # these are DNs
</del><ins>+ members = self._getMultipleLdapAttributes(
+ attrs,
+ self.groupSchema["membersAttr"]
+ )
+ if not self.groupSchema["memberIdAttr"]: # these are DNs
</ins><span class="cx"> members = [normalizeDNstr(m) for m in members]
</span><span class="cx"> members = set(members)
</span><span class="cx">
</span><span class="cx"> if self.groupSchema["nestedGroupsAttr"]:
</span><del>- nestedGroups = self._getMultipleLdapAttributes(attrs,
- self.groupSchema["nestedGroupsAttr"])
- if not self.groupSchema["memberIdAttr"]: # these are DNs
</del><ins>+ nestedGroups = self._getMultipleLdapAttributes(
+ attrs,
+ self.groupSchema["nestedGroupsAttr"]
+ )
+ if not self.groupSchema["memberIdAttr"]: # these are DNs
</ins><span class="cx"> nestedGroups = [normalizeDNstr(g) for g in nestedGroups]
</span><span class="cx"> nestedGroups = set(nestedGroups)
</span><span class="cx"> else:
</span><span class="lines">@@ -639,8 +656,9 @@
</span><span class="cx"> nestedGroups = members
</span><span class="cx"> members = set()
</span><span class="cx">
</span><del>- self._cachedRestrictedPrincipals = set(self._expandGroupMembership(members,
- nestedGroups))
</del><ins>+ self._cachedRestrictedPrincipals = set(
+ self._expandGroupMembership(members, nestedGroups)
+ )
</ins><span class="cx"> self.log.info("Got %d restricted group members" % (
</span><span class="cx"> len(self._cachedRestrictedPrincipals),))
</span><span class="cx"> self.restrictedTimestamp = time.time()
</span><span class="lines">@@ -695,15 +713,17 @@
</span><span class="cx"> scope = ldap.SCOPE_SUBTREE
</span><span class="cx"> base = self.typeDNs[recordType]
</span><span class="cx"> filterstr = "(%s=%s)" % (self.groupSchema["memberIdAttr"], group)
</span><del>- else: # Use DN
</del><ins>+ else: # Use DN
</ins><span class="cx"> scope = ldap.SCOPE_BASE
</span><span class="cx"> base = ldap.dn.str2dn(group)
</span><span class="cx"> filterstr = "(objectClass=*)"
</span><span class="cx">
</span><span class="cx"> self.log.debug("Retrieving ldap record with base %s and filter %s." %
</span><del>- (ldap.dn.dn2str(base), filterstr))
</del><ins>+ (ldap.dn.dn2str(base), filterstr))
</ins><span class="cx"> result = self.timedSearch(ldap.dn.dn2str(base),
</span><del>- scope, filterstr=filterstr, attrlist=self.attrlist)
</del><ins>+ scope,
+ filterstr=filterstr,
+ attrlist=self.attrlist)
</ins><span class="cx">
</span><span class="cx"> if len(result) == 0:
</span><span class="cx"> continue
</span><span class="lines">@@ -714,24 +734,29 @@
</span><span class="cx"> dn, attrs = result[0]
</span><span class="cx"> dn = normalizeDNstr(dn)
</span><span class="cx"> if self.groupSchema["membersAttr"]:
</span><del>- subMembers = self._getMultipleLdapAttributes(attrs,
- self.groupSchema["membersAttr"])
- if not self.groupSchema["memberIdAttr"]: # these are DNs
</del><ins>+ subMembers = self._getMultipleLdapAttributes(
+ attrs,
+ self.groupSchema["membersAttr"]
+ )
+ if not self.groupSchema["memberIdAttr"]: # these are DNs
</ins><span class="cx"> subMembers = [normalizeDNstr(m) for m in subMembers]
</span><span class="cx"> subMembers = set(subMembers)
</span><span class="cx">
</span><span class="cx"> if self.groupSchema["nestedGroupsAttr"]:
</span><del>- subNestedGroups = self._getMultipleLdapAttributes(attrs,
- self.groupSchema["nestedGroupsAttr"])
- if not self.groupSchema["memberIdAttr"]: # these are DNs
</del><ins>+ subNestedGroups = self._getMultipleLdapAttributes(
+ attrs,
+ self.groupSchema["nestedGroupsAttr"]
+ )
+ if not self.groupSchema["memberIdAttr"]: # these are DNs
</ins><span class="cx"> subNestedGroups = [normalizeDNstr(g) for g in subNestedGroups]
</span><span class="cx"> subNestedGroups = set(subNestedGroups)
</span><span class="cx">
</span><span class="cx"> processedItems.add(group)
</span><span class="cx"> yield group
</span><span class="cx">
</span><del>- for item in self._expandGroupMembership(subMembers, subNestedGroups,
- processedItems):
</del><ins>+ for item in self._expandGroupMembership(subMembers,
+ subNestedGroups,
+ processedItems):
</ins><span class="cx"> yield item
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -805,8 +830,10 @@
</span><span class="cx"> emailSuffix = self.rdnSchema[recordType].get("emailSuffix", None)
</span><span class="cx">
</span><span class="cx"> if len(emailAddresses) == 0 and emailSuffix:
</span><del>- emailPrefix = self._getUniqueLdapAttribute(attrs,
- self.rdnSchema[recordType].get("attr", "cn"))
</del><ins>+ emailPrefix = self._getUniqueLdapAttribute(
+ attrs,
+ self.rdnSchema[recordType].get("attr", "cn")
+ )
</ins><span class="cx"> emailAddresses.add(emailPrefix + emailSuffix)
</span><span class="cx">
</span><span class="cx"> proxyGUIDs = ()
</span><span class="lines">@@ -837,7 +864,7 @@
</span><span class="cx"> memberGUIDs.extend(members)
</span><span class="cx">
</span><span class="cx"> # Normalize members if they're in DN form
</span><del>- if not self.groupSchema["memberIdAttr"]: # empty = dn
</del><ins>+ if not self.groupSchema["memberIdAttr"]: # empty = dn
</ins><span class="cx"> guids = list(memberGUIDs)
</span><span class="cx"> memberGUIDs = []
</span><span class="cx"> for dnStr in guids:
</span><span class="lines">@@ -849,14 +876,16 @@
</span><span class="cx"> self.log.warn("Bad LDAP DN: %s" % (dnStr,))
</span><span class="cx">
</span><span class="cx"> elif recordType in (self.recordType_resources,
</span><del>- self.recordType_locations):
</del><ins>+ self.recordType_locations):
</ins><span class="cx"> fullName = self._getUniqueLdapAttribute(attrs, self.rdnSchema[recordType]["mapping"]["fullName"])
</span><span class="cx"> enabledForCalendaring = True
</span><span class="cx"> enabledForAddressBooks = False
</span><span class="cx"> enabledForLogin = False
</span><span class="cx"> if self.resourceSchema["resourceInfoAttr"]:
</span><del>- resourceInfo = self._getUniqueLdapAttribute(attrs,
- self.resourceSchema["resourceInfoAttr"])
</del><ins>+ resourceInfo = self._getUniqueLdapAttribute(
+ attrs,
+ self.resourceSchema["resourceInfoAttr"]
+ )
</ins><span class="cx"> if resourceInfo:
</span><span class="cx"> try:
</span><span class="cx"> (
</span><span class="lines">@@ -876,45 +905,66 @@
</span><span class="cx"> readOnlyProxyGUIDs = (readOnlyProxy,)
</span><span class="cx"> except ValueError, e:
</span><span class="cx"> self.log.error("Unable to parse resource info (%s)" % (e,))
</span><del>- else: # the individual resource attributes might be specified
</del><ins>+ else: # the individual resource attributes might be specified
</ins><span class="cx"> if self.resourceSchema["autoScheduleAttr"]:
</span><del>- autoScheduleValue = self._getUniqueLdapAttribute(attrs,
- self.resourceSchema["autoScheduleAttr"])
- autoSchedule = (autoScheduleValue ==
- self.resourceSchema["autoScheduleEnabledValue"])
</del><ins>+ autoScheduleValue = self._getUniqueLdapAttribute(
+ attrs,
+ self.resourceSchema["autoScheduleAttr"]
+ )
+ autoSchedule = (
+ autoScheduleValue == self.resourceSchema["autoScheduleEnabledValue"]
+ )
</ins><span class="cx"> if self.resourceSchema["proxyAttr"]:
</span><del>- proxyGUIDs = set(self._getMultipleLdapAttributes(attrs,
- self.resourceSchema["proxyAttr"]))
</del><ins>+ proxyGUIDs = set(
+ self._getMultipleLdapAttributes(
+ attrs,
+ self.resourceSchema["proxyAttr"]
+ )
+ )
</ins><span class="cx"> if self.resourceSchema["readOnlyProxyAttr"]:
</span><del>- readOnlyProxyGUIDs = set(self._getMultipleLdapAttributes(attrs,
- self.resourceSchema["readOnlyProxyAttr"]))
</del><ins>+ readOnlyProxyGUIDs = set(
+ self._getMultipleLdapAttributes(
+ attrs,
+ self.resourceSchema["readOnlyProxyAttr"]
+ )
+ )
</ins><span class="cx"> if self.resourceSchema["autoAcceptGroupAttr"]:
</span><del>- autoAcceptGroup = self._getUniqueLdapAttribute(attrs,
- self.resourceSchema["autoAcceptGroupAttr"])
</del><ins>+ autoAcceptGroup = self._getUniqueLdapAttribute(
+ attrs,
+ self.resourceSchema["autoAcceptGroupAttr"]
+ )
</ins><span class="cx">
</span><span class="cx"> if recordType == self.recordType_locations:
</span><span class="cx"> if self.rdnSchema[recordType]["associatedAddressAttr"]:
</span><del>- associatedAddress = self._getUniqueLdapAttribute(attrs,
- self.rdnSchema[recordType]["associatedAddressAttr"])
</del><ins>+ associatedAddress = self._getUniqueLdapAttribute(
+ attrs,
+ self.rdnSchema[recordType]["associatedAddressAttr"]
+ )
</ins><span class="cx"> if associatedAddress:
</span><span class="cx"> extras["associatedAddress"] = associatedAddress
</span><span class="cx">
</span><span class="cx"> elif recordType == self.recordType_addresses:
</span><span class="cx"> if self.rdnSchema[recordType].get("geoAttr", ""):
</span><del>- geo = self._getUniqueLdapAttribute(attrs,
- self.rdnSchema[recordType]["geoAttr"])
</del><ins>+ geo = self._getUniqueLdapAttribute(
+ attrs,
+ self.rdnSchema[recordType]["geoAttr"]
+ )
</ins><span class="cx"> if geo:
</span><span class="cx"> extras["geo"] = geo
</span><span class="cx"> if self.rdnSchema[recordType].get("streetAddressAttr", ""):
</span><del>- street = self._getUniqueLdapAttribute(attrs,
- self.rdnSchema[recordType]["streetAddressAttr"])
</del><ins>+ street = self._getUniqueLdapAttribute(
+ attrs,
+ self.rdnSchema[recordType]["streetAddressAttr"]
+ )
</ins><span class="cx"> if street:
</span><span class="cx"> extras["streetAddress"] = street
</span><span class="cx">
</span><span class="cx"> serverID = None
</span><span class="cx"> if self.poddingSchema["serverIdAttr"]:
</span><del>- serverID = self._getUniqueLdapAttribute(attrs,
- self.poddingSchema["serverIdAttr"])
</del><ins>+ serverID = self._getUniqueLdapAttribute(
+ attrs,
+ self.poddingSchema["serverIdAttr"]
+ )
</ins><span class="cx">
</span><span class="cx"> record = LdapDirectoryRecord(
</span><span class="cx"> service=self,
</span><span class="lines">@@ -940,8 +990,7 @@
</span><span class="cx"> # TODO: this needs to be deferred but for now we hard code
</span><span class="cx"> # the deferred result because we know it is completing
</span><span class="cx"> # immediately.
</span><del>- d = self.augmentService.getAugmentRecord(record.guid,
- recordType)
</del><ins>+ d = self.augmentService.getAugmentRecord(record.guid, recordType)
</ins><span class="cx"> d.addCallback(lambda x: record.addAugmentInformation(x))
</span><span class="cx">
</span><span class="cx"> else:
</span><span class="lines">@@ -953,7 +1002,7 @@
</span><span class="cx"> enabledForCalendaring=enabledForCalendaring,
</span><span class="cx"> autoSchedule=autoSchedule,
</span><span class="cx"> autoAcceptGroup=autoAcceptGroup,
</span><del>- enabledForAddressBooks=enabledForAddressBooks, # TODO: add to LDAP?
</del><ins>+ enabledForAddressBooks=enabledForAddressBooks, # TODO: add to LDAP?
</ins><span class="cx"> enabledForLogin=enabledForLogin,
</span><span class="cx"> )
</span><span class="cx"> record.addAugmentInformation(augmentRecord)
</span><span class="lines">@@ -963,15 +1012,18 @@
</span><span class="cx"> loginEnabledAttr = self.rdnSchema[recordType]["loginEnabledAttr"]
</span><span class="cx"> if loginEnabledAttr:
</span><span class="cx"> loginEnabledValue = self.rdnSchema[recordType]["loginEnabledValue"]
</span><del>- record.enabledForLogin = self._getUniqueLdapAttribute(attrs,
- loginEnabledAttr) == loginEnabledValue
</del><ins>+ record.enabledForLogin = self._getUniqueLdapAttribute(
+ attrs, loginEnabledAttr
+ ) == loginEnabledValue
</ins><span class="cx">
</span><span class="cx"> # Override with LDAP calendar-enabled control if attribute specified
</span><span class="cx"> calendarEnabledAttr = self.rdnSchema[recordType].get("calendarEnabledAttr", "")
</span><span class="cx"> if calendarEnabledAttr:
</span><span class="cx"> calendarEnabledValue = self.rdnSchema[recordType]["calendarEnabledValue"]
</span><del>- record.enabledForCalendaring = self._getUniqueLdapAttribute(attrs,
- calendarEnabledAttr) == calendarEnabledValue
</del><ins>+ record.enabledForCalendaring = self._getUniqueLdapAttribute(
+ attrs,
+ calendarEnabledAttr
+ ) == calendarEnabledValue
</ins><span class="cx">
</span><span class="cx"> return record
</span><span class="cx">
</span><span class="lines">@@ -994,7 +1046,7 @@
</span><span class="cx"> queryMethod = self.timedSearch
</span><span class="cx">
</span><span class="cx"> self.log.debug("LDAP query for types %s, indexType %s and indexKey %s"
</span><del>- % (recordTypes, indexType, indexKey))
</del><ins>+ % (recordTypes, indexType, indexKey))
</ins><span class="cx">
</span><span class="cx"> guidAttr = self.rdnSchema["guidAttr"]
</span><span class="cx"> for recordType in recordTypes:
</span><span class="lines">@@ -1024,7 +1076,7 @@
</span><span class="cx">
</span><span class="cx"> elif indexType == self.INDEX_TYPE_CUA:
</span><span class="cx"> # indexKey is of the form "mailto:test@example.net"
</span><del>- email = indexKey[7:] # strip "mailto:"
</del><ins>+ email = indexKey[7:] # strip "mailto:"
</ins><span class="cx"> emailSuffix = self.rdnSchema[recordType].get("emailSuffix", None)
</span><span class="cx"> if emailSuffix is not None and email.partition("@")[2] == emailSuffix:
</span><span class="cx"> filterstr = "(&%s(|(&(!(mail=*))(%s=%s))(mail=%s)))" % (
</span><span class="lines">@@ -1040,7 +1092,7 @@
</span><span class="cx"> if ldapFields:
</span><span class="cx"> subfilter = "(%s=%s)" % (ldapFields, ldapEsc(email))
</span><span class="cx"> else:
</span><del>- continue # No LDAP attribute assigned for emailAddresses
</del><ins>+ continue # No LDAP attribute assigned for emailAddresses
</ins><span class="cx">
</span><span class="cx"> else:
</span><span class="cx"> subfilter = []
</span><span class="lines">@@ -1048,7 +1100,7 @@
</span><span class="cx"> if ldapField:
</span><span class="cx"> subfilter.append("(%s=%s)" % (ldapField, ldapEsc(email)))
</span><span class="cx"> if not subfilter:
</span><del>- continue # No LDAP attribute assigned for emailAddresses
</del><ins>+ continue # No LDAP attribute assigned for emailAddresses
</ins><span class="cx">
</span><span class="cx"> subfilter = "(|%s)" % ("".join(subfilter))
</span><span class="cx"> filterstr = "(&%s%s)" % (filterstr, subfilter)
</span><span class="lines">@@ -1058,9 +1110,11 @@
</span><span class="cx">
</span><span class="cx"> # Query the LDAP server
</span><span class="cx"> self.log.debug("Retrieving ldap record with base %s and filter %s." %
</span><del>- (ldap.dn.dn2str(base), filterstr))
</del><ins>+ (ldap.dn.dn2str(base), filterstr))
</ins><span class="cx"> result = queryMethod(ldap.dn.dn2str(base),
</span><del>- ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=self.attrlist)
</del><ins>+ ldap.SCOPE_SUBTREE,
+ filterstr=filterstr,
+ attrlist=self.attrlist)
</ins><span class="cx">
</span><span class="cx"> if result:
</span><span class="cx"> dn, attrs = result.pop()
</span><span class="lines">@@ -1079,20 +1133,26 @@
</span><span class="cx">
</span><span class="cx"> record.applySACLs()
</span><span class="cx">
</span><del>- self.recordCacheForType(recordType).addRecord(record,
- indexType, indexKey
</del><ins>+ self.recordCacheForType(recordType).addRecord(
+ record, indexType, indexKey
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx"> # We got a match, so don't bother checking other types
</span><span class="cx"> break
</span><span class="cx">
</span><span class="cx"> except MissingRecordNameException:
</span><del>- self.log.warn("Ignoring record missing record name attribute: recordType %s, indexType %s and indexKey %s"
- % (recordTypes, indexType, indexKey))
</del><ins>+ self.log.warn(
+ "Ignoring record missing record name "
+ "attribute: recordType %s, indexType %s and indexKey %s"
+ % (recordTypes, indexType, indexKey)
+ )
</ins><span class="cx">
</span><span class="cx"> except MissingGuidException:
</span><del>- self.log.warn("Ignoring record missing guid attribute: recordType %s, indexType %s and indexKey %s"
- % (recordTypes, indexType, indexKey))
</del><ins>+ self.log.warn(
+ "Ignoring record missing guid attribute: "
+ "recordType %s, indexType %s and indexKey %s"
+ % (recordTypes, indexType, indexKey)
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def recordsMatchingTokens(self, tokens, context=None, limitResults=50, timeoutSeconds=10):
</span><span class="lines">@@ -1131,17 +1191,27 @@
</span><span class="cx"> base = self.typeDNs[recordType]
</span><span class="cx"> scope = ldap.SCOPE_SUBTREE
</span><span class="cx"> extraFilter = self.rdnSchema[recordType].get("filter", "")
</span><del>- filterstr = buildFilterFromTokens(recordType, self.rdnSchema[recordType]["mapping"],
- tokens, extra=extraFilter)
</del><ins>+ filterstr = buildFilterFromTokens(
+ recordType,
+ self.rdnSchema[recordType]["mapping"],
+ tokens,
+ extra=extraFilter
+ )
</ins><span class="cx">
</span><span class="cx"> if filterstr is not None:
</span><span class="cx"> # Query the LDAP server
</span><del>- 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,
</del><ins>+ 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,
</ins><span class="cx"> timeoutSeconds=timeoutSeconds,
</span><del>- resultLimit=limitResults)
</del><ins>+ resultLimit=limitResults
+ )
</ins><span class="cx"> numMissingGuids = 0
</span><span class="cx"> numMissingRecordNames = 0
</span><span class="cx"> numNotEnabled = 0
</span><span class="lines">@@ -1149,8 +1219,10 @@
</span><span class="cx"> dn = normalizeDNstr(dn)
</span><span class="cx"> # Skip if group restriction is in place and guid is not
</span><span class="cx"> # a member
</span><del>- if (recordType != self.recordType_groups and
- not self.isAllowedByRestrictToGroup(dn, attrs)):
</del><ins>+ if (
+ recordType != self.recordType_groups and
+ not self.isAllowedByRestrictToGroup(dn, attrs)
+ ):
</ins><span class="cx"> continue
</span><span class="cx">
</span><span class="cx"> try:
</span><span class="lines">@@ -1219,19 +1291,27 @@
</span><span class="cx">
</span><span class="cx"> else:
</span><span class="cx"> scope = ldap.SCOPE_SUBTREE
</span><del>- filterstr = buildFilter(recordType,
</del><ins>+ filterstr = buildFilter(
+ recordType,
</ins><span class="cx"> self.rdnSchema[recordType]["mapping"],
</span><del>- fields, operand=operand,
- optimizeMultiName=self.optimizeMultiName)
</del><ins>+ fields,
+ operand=operand,
+ optimizeMultiName=self.optimizeMultiName
+ )
</ins><span class="cx">
</span><span class="cx"> if filterstr is not None:
</span><span class="cx"> # Query the LDAP server
</span><span class="cx"> self.log.debug("LDAP search %s %s %s" %
</span><del>- (ldap.dn.dn2str(base), scope, filterstr))
- results = (yield deferToThread(self.timedSearch, ldap.dn.dn2str(base), scope,
- filterstr=filterstr, attrlist=self.attrlist,
</del><ins>+ (ldap.dn.dn2str(base), scope, filterstr))
+ results = (yield deferToThread(
+ self.timedSearch,
+ ldap.dn.dn2str(base),
+ scope,
+ filterstr=filterstr,
+ attrlist=self.attrlist,
</ins><span class="cx"> timeoutSeconds=self.requestTimeoutSeconds,
</span><del>- resultLimit=self.requestResultsLimit))
</del><ins>+ resultLimit=self.requestResultsLimit)
+ )
</ins><span class="cx"> self.log.debug("LDAP search returned %d results" % (len(results),))
</span><span class="cx"> numMissingGuids = 0
</span><span class="cx"> numMissingRecordNames = 0
</span><span class="lines">@@ -1239,8 +1319,10 @@
</span><span class="cx"> dn = normalizeDNstr(dn)
</span><span class="cx"> # Skip if group restriction is in place and guid is not
</span><span class="cx"> # a member
</span><del>- if (recordType != self.recordType_groups and
- not self.isAllowedByRestrictToGroup(dn, attrs)):
</del><ins>+ if (
+ recordType != self.recordType_groups and
+ not self.isAllowedByRestrictToGroup(dn, attrs)
+ ):
</ins><span class="cx"> continue
</span><span class="cx">
</span><span class="cx"> try:
</span><span class="lines">@@ -1262,11 +1344,11 @@
</span><span class="cx">
</span><span class="cx"> if numMissingGuids:
</span><span class="cx"> self.log.warn("%d %s records are missing %s" %
</span><del>- (numMissingGuids, recordType, guidAttr))
</del><ins>+ (numMissingGuids, recordType, guidAttr))
</ins><span class="cx">
</span><span class="cx"> if numMissingRecordNames:
</span><span class="cx"> self.log.warn("%d %s records are missing record name" %
</span><del>- (numMissingRecordNames, recordType))
</del><ins>+ (numMissingRecordNames, recordType))
</ins><span class="cx">
</span><span class="cx"> self.log.debug("Principal property search matched %d records" % (len(records),))
</span><span class="cx"> returnValue(records)
</span><span class="lines">@@ -1300,16 +1382,24 @@
</span><span class="cx"> # recordsMatchingFields for *each* DN.
</span><span class="cx"> for value in valuesToFetch:
</span><span class="cx"> fields = [["dn", value, False, "equals"]]
</span><del>- result = (yield self.recordsMatchingFields(fields,
- recordType=self.recordType_groups))
</del><ins>+ result = (
+ yield self.recordsMatchingFields(
+ fields,
+ recordType=self.recordType_groups
+ )
+ )
</ins><span class="cx"> results.extend(result)
</span><span class="cx"> else:
</span><span class="cx"> for batch in splitIntoBatches(valuesToFetch, self.batchSize):
</span><span class="cx"> fields = []
</span><span class="cx"> for value in batch:
</span><span class="cx"> fields.append([attributeToSearch, value, False, "equals"])
</span><del>- result = (yield self.recordsMatchingFields(fields,
- recordType=self.recordType_groups))
</del><ins>+ result = (
+ yield self.recordsMatchingFields(
+ fields,
+ recordType=self.recordType_groups
+ )
+ )
</ins><span class="cx"> results.extend(result)
</span><span class="cx">
</span><span class="cx"> # Reset values for next iteration
</span><span class="lines">@@ -1329,7 +1419,7 @@
</span><span class="cx"> # cut: we know we only need to examine groups, and
</span><span class="cx"> # those will be children of the groups DN
</span><span class="cx"> if not dnContainedIn(ldap.dn.str2dn(memberAlias),
</span><del>- groupsDN):
</del><ins>+ groupsDN):
</ins><span class="cx"> continue
</span><span class="cx"> if memberAlias not in recordsByAlias:
</span><span class="cx"> valuesToFetch.add(memberAlias)
</span><span class="lines">@@ -1351,7 +1441,7 @@
</span><span class="cx"> """
</span><span class="cx"> dn = ldap.dn.str2dn(dnStr.lower())
</span><span class="cx"> for recordType in self.recordTypes():
</span><del>- base = self.typeDNs[recordType] # already lowercase
</del><ins>+ base = self.typeDNs[recordType] # already lowercase
</ins><span class="cx"> if dnContainedIn(dn, base):
</span><span class="cx"> return recordType
</span><span class="cx"> return None
</span><span class="lines">@@ -1431,7 +1521,8 @@
</span><span class="cx"> if firstName != lastName:
</span><span class="cx"> firstValue = _convertValue(firstName, firstMatchType)
</span><span class="cx"> lastValue = _convertValue(lastName, lastMatchType)
</span><del>- converted.append("(&(%s=%s)(%s=%s))" %
</del><ins>+ converted.append(
+ "(&(%s=%s)(%s=%s))" %
</ins><span class="cx"> (mapping["firstName"], firstValue,
</span><span class="cx"> mapping["lastName"], lastValue)
</span><span class="cx"> )
</span><span class="lines">@@ -1575,8 +1666,10 @@
</span><span class="cx"> # Identifier of this record as a group member
</span><span class="cx"> memberIdAttr = self.service.groupSchema["memberIdAttr"]
</span><span class="cx"> if memberIdAttr:
</span><del>- self._memberId = self.service._getUniqueLdapAttribute(attrs,
- memberIdAttr)
</del><ins>+ self._memberId = self.service._getUniqueLdapAttribute(
+ attrs,
+ memberIdAttr
+ )
</ins><span class="cx"> else:
</span><span class="cx"> self._memberId = normalizeDNstr(self.dn)
</span><span class="cx">
</span><span class="lines">@@ -1604,18 +1697,23 @@
</span><span class="cx"> base = self.service.base
</span><span class="cx"> filterstr = "(%s=%s)" % (memberIdAttr, ldapEsc(memberId))
</span><span class="cx"> self.log.debug("Retrieving subtree of %s with filter %s" %
</span><del>- (ldap.dn.dn2str(base), filterstr),
- system="LdapDirectoryService")
- result = self.service.timedSearch(ldap.dn.dn2str(base),
- ldap.SCOPE_SUBTREE, filterstr=filterstr,
- attrlist=self.service.attrlist)
</del><ins>+ (ldap.dn.dn2str(base), filterstr),
+ system="LdapDirectoryService")
+ result = self.service.timedSearch(
+ ldap.dn.dn2str(base),
+ ldap.SCOPE_SUBTREE,
+ filterstr=filterstr,
+ attrlist=self.service.attrlist
+ )
</ins><span class="cx">
</span><del>- else: # using DN
</del><ins>+ else: # using DN
</ins><span class="cx">
</span><span class="cx"> self.log.debug("Retrieving %s." % memberId,
</span><del>- system="LdapDirectoryService")
- result = self.service.timedSearch(memberId,
- ldap.SCOPE_BASE, attrlist=self.service.attrlist)
</del><ins>+ system="LdapDirectoryService")
+ result = self.service.timedSearch(
+ memberId,
+ ldap.SCOPE_BASE, attrlist=self.service.attrlist
+ )
</ins><span class="cx">
</span><span class="cx"> if result:
</span><span class="cx">
</span><span class="lines">@@ -1627,12 +1725,16 @@
</span><span class="cx"> self.log.error("Unable to map %s to a record type" % (dn,))
</span><span class="cx"> continue
</span><span class="cx">
</span><del>- shortName = self.service._getUniqueLdapAttribute(attrs,
- self.service.rdnSchema[recordType]["mapping"]["recordName"])
</del><ins>+ shortName = self.service._getUniqueLdapAttribute(
+ attrs,
+ self.service.rdnSchema[recordType]["mapping"]["recordName"]
+ )
</ins><span class="cx">
</span><span class="cx"> if shortName:
</span><del>- record = self.service.recordWithShortName(recordType,
- shortName)
</del><ins>+ record = self.service.recordWithShortName(
+ recordType,
+ shortName
+ )
</ins><span class="cx"> if record:
</span><span class="cx"> results.append(record)
</span><span class="cx">
</span><span class="lines">@@ -1663,7 +1765,8 @@
</span><span class="cx"> if len(membersAttrs) == 1:
</span><span class="cx"> filterstr = "(%s=%s)" % (membersAttrs[0], self._memberId)
</span><span class="cx"> else:
</span><del>- filterstr = "(|%s)" % ("".join(
</del><ins>+ filterstr = "(|%s)" % (
+ "".join(
</ins><span class="cx"> ["(%s=%s)" % (a, self._memberId) for a in membersAttrs]
</span><span class="cx"> ),
</span><span class="cx"> )
</span><span class="lines">@@ -1671,8 +1774,12 @@
</span><span class="cx"> groups = []
</span><span class="cx">
</span><span class="cx"> try:
</span><del>- results = self.service.timedSearch(ldap.dn.dn2str(base),
- ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=self.service.attrlist)
</del><ins>+ results = self.service.timedSearch(
+ ldap.dn.dn2str(base),
+ ldap.SCOPE_SUBTREE,
+ filterstr=filterstr,
+ attrlist=self.service.attrlist
+ )
</ins><span class="cx">
</span><span class="cx"> for dn, attrs in results:
</span><span class="cx"> dn = normalizeDNstr(dn)
</span><span class="lines">@@ -1753,12 +1860,13 @@
</span><span class="cx">
</span><span class="cx"> except ldap.INVALID_CREDENTIALS:
</span><span class="cx"> self.log.info("Invalid credentials for {dn}",
</span><del>- dn=repr(self.dn), system="LdapDirectoryService")
</del><ins>+ dn=repr(self.dn),
+ system="LdapDirectoryService")
</ins><span class="cx"> return False
</span><span class="cx">
</span><span class="cx"> else:
</span><span class="cx"> self.log.error("Unknown Authentication Method '{method}'",
</span><del>- method=self.service.authMethod.upper())
</del><ins>+ method=self.service.authMethod.upper())
</ins><span class="cx"> raise DirectoryConfigurationError()
</span><span class="cx">
</span><span class="cx"> return super(LdapDirectoryRecord, self).verifyCredentials(credentials)
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdirectorytesttest_ldapdirectorypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py (12255 => 12256)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1270,6 +1270,7 @@
</span><span class="cx"> }
</span><span class="cx"> )
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def setupService(self, scenario):
</span><span class="cx"> self.service = LdapDirectoryService(scenario[1])
</span><span class="cx"> self.service.ldap = LdapDirectoryTestWrapper(self.service.ldap, scenario[0])
</span></span></pre>
</div>
</div>
</body>
</html>