[CalendarServer-changes] [9044] CalendarServer/branches/users/gaya/ldapdirectorybacker
source_changes at macosforge.org
source_changes at macosforge.org
Thu Apr 12 14:56:30 PDT 2012
Revision: 9044
http://trac.macosforge.org/projects/calendarserver/changeset/9044
Author: gaya at apple.com
Date: 2012-04-12 14:56:29 -0700 (Thu, 12 Apr 2012)
Log Message:
-----------
add group vCard support to opendirectorybacker
Modified Paths:
--------------
CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-odtest.plist
CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py
CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/stdconfig.py
Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-odtest.plist
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-odtest.plist 2012-04-12 21:51:02 UTC (rev 9043)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/conf/carddav-odtest.plist 2012-04-12 21:56:29 UTC (rev 9044)
@@ -1019,9 +1019,17 @@
<!-- Search for people records -->
<key>queryPeopleRecords</key>
<true/>
- <!-- Search for people records in this directory service node -->
+ <!-- Search for people records in these directory service nodes -->
<key>peopleNode</key>
- <string>/Search/Contacts</string>
+ <array>
+ <string>/Search/Contacts</string>
+ </array>
+ <key>queryGroupRecords</key>
+ <true/>
+ <key>groupNode</key>
+ <array>
+ <string>/Search</string>
+ </array>
<!-- Search for user records -->
<key>queryUserRecords</key>
<true/>
@@ -1037,7 +1045,7 @@
<!-- approx. maximum number of records returned from a directory service query -->
<key>maxDSQueryRecords</key>
<integer>0</integer> <!-- use 0 to have server calculate the maximum based on MaxAddressBookQueryResults, MaxAddressBookMultigetHrefs keys -->
- <!-- ignore system records like "root" when creating vCards -->
+ <!-- ignore system records like "root" -->
<key>ignoreSystemRecords</key>
<true/>
<!-- fake the eTag. If false all directory service attributes are used to calculate the eTag -->
Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py 2012-04-12 21:51:02 UTC (rev 9043)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py 2012-04-12 21:56:29 UTC (rev 9044)
@@ -26,19 +26,15 @@
import traceback
import hashlib
-import os
import sys
import time
-from os.path import join
from random import random
from pycalendar.n import N
from pycalendar.adr import Adr
from pycalendar.datetime import PyCalendarDateTime
-from socket import getfqdn
-
from twisted.internet.defer import inlineCallbacks, returnValue, deferredGenerator, succeed
from txdav.xml import element as davxml
from txdav.xml.base import twisted_dav_namespace, dav_namespace, parse_date, twisted_private_namespace
@@ -78,6 +74,8 @@
peopleNode = "/Search/Contacts",
queryUserRecords=True,
userNode = "/Search",
+ queryGroupRecords=True,
+ groupNode = "/Search",
maxDSQueryRecords = 0, # maximum number of records requested for any ds query
queryDSLocal = False, #query in DSLocal -- debug
@@ -115,36 +113,47 @@
self.userDirectory = None
self.userNode = None
- self.realmName = None # needed for super
+ # get node to record type map
+ def addNodesToNodeRecordTypeMap(nodeList, recordType):
+ for node in nodeList if isinstance(nodeList, list) else (nodeList,):
+ if not node in nodeRecordTypeMap:
+ nodeRecordTypeMap[node] = []
+ nodeRecordTypeMap[node] += [recordType,]
+
+ nodeRecordTypeMap = {}
+ if queryPeopleRecords:
+ addNodesToNodeRecordTypeMap(peopleNode, dsattributes.kDSStdRecordTypePeople,)
+ if queryUserRecords:
+ addNodesToNodeRecordTypeMap(userNode, dsattributes.kDSStdRecordTypeUsers,)
+ if queryGroupRecords:
+ addNodesToNodeRecordTypeMap(groupNode, dsattributes.kDSStdRecordTypeGroups,)
+
+ # get query info
+ nodeDirectoryRecordTypeMap = {}
self.odModule = namedModule(config.OpenDirectoryModule)
-
- if queryPeopleRecords or not queryUserRecords:
- self.peopleNode = peopleNode
+ for node in nodeRecordTypeMap:
+ queryInfo = {"recordTypes":nodeRecordTypeMap[node]}
try:
- self.peopleDirectory = self.odModule.odInit(peopleNode)
+ queryInfo["directory"] = self.odModule.odInit(node)
except self.odModule.ODError, e:
- self.log_error("Open Directory (node=%s) Initialization error: %s" % (peopleNode, e))
+ self.log_error("Open Directory (node=%s) Initialization error: %s" % (node, e))
raise
- self.realmName = peopleNode
-
- if queryUserRecords:
- if self.peopleNode == userNode: # use sane directory and node if they are equal
- self.userNode = self.peopleNode
- self.userDirectory = self.peopleDirectory
- else:
- self.userNode = userNode
- try:
- self.userDirectory = self.odModule.odInit(userNode)
- except self.odModule.ODError, e:
- self.log_error("Open Directory (node=%s) Initialization error: %s" % (userNode, e))
- raise
- if self.realmName:
- self.realmName += "+" + userNode
- else:
- self.realmName = userNode
+
+ nodeDirectoryRecordTypeMap[node] = queryInfo
+ self.nodeDirectoryRecordTypeMap = nodeDirectoryRecordTypeMap
+
+ # calc realm name
+ realmName = None
+ for node in nodeDirectoryRecordTypeMap:
+ realmName = realmName + "+" + node if realmName else node
+ self.realmName = realmName # needed for super
+
+ self.queryPeopleRecords = queryPeopleRecords
+ self.queryUserRecords = queryUserRecords
+ self.queryGroupRecords = queryGroupRecords
self.maxDSQueryRecords = maxDSQueryRecords
self.ignoreSystemRecords = ignoreSystemRecords
@@ -214,13 +223,15 @@
returnedAttributes += self.requiredAttributes
if additionalAttributes:
- returnedAttributes += addtionalAttributes
+ returnedAttributes += additionalAttributes
if ignoreSystemRecords:
returnedAttributes += [dsattributes.kDS1AttrUniqueID,]
- if not self.queryDSLocal:
+ if not queryDSLocal:
returnedAttributes += [dsattributes.kDSNAttrMetaNodeLocation,]
-
+ if queryGroupRecords:
+ returnedAttributes += [dsattributes.kDSNAttrGroupMembers,]
+
self.returnedAttributes = list(set(returnedAttributes))
self.log_debug("self.returnedAttributes=%s" % (self.returnedAttributes, ))
@@ -249,16 +260,21 @@
def _isSystemRecord(self, recordShortName, recordAttributes):
+ recordType = recordAttributes.get(dsattributes.kDSNAttrRecordType)
guid = recordAttributes.get(dsattributes.kDS1AttrGeneratedUID)
if guid and guid.startswith("FFFFEEEE-DDDD-CCCC-BBBB-AAAA"):
- self.log_info("Ignoring system record %s with %s %s" % (recordShortName, dsattributes.kDS1AttrGeneratedUID, guid,))
+ self.log_info("Ignoring record %s (type %s) with %s %s" % (recordShortName, recordType, dsattributes.kDS1AttrGeneratedUID, guid,))
return True
uniqueID = recordAttributes.get(dsattributes.kDS1AttrUniqueID)
- if uniqueID and (int(uniqueID) < 500 or int(uniqueID) == 1000):
- self.log_info("Ignoring system record %s with %s %s" % (recordShortName, dsattributes.kDS1AttrUniqueID, uniqueID,))
+ if uniqueID and (int(uniqueID) < 500 or (recordType == dsattributes.kDSStdRecordTypeUsers and int(uniqueID) == 1000)):
+ self.log_info("Ignoring record %s (type %s) with %s %s" % (recordShortName, recordType, dsattributes.kDS1AttrUniqueID, uniqueID,))
return True
+ if recordShortName.startswith("_"):
+ self.log_info("Ignoring record %s (type %s) with %s %s" % (recordShortName, recordType, dsattributes.kDSNAttrRecordName, recordShortName,))
+ return True
+
return False
@@ -357,8 +373,10 @@
if not self.queryDSLocal:
# skip records in local node which happens for non-complex od queries
- if recordAttributes.get(dsattributes.kDSNAttrMetaNodeLocation, "").startswith("/Local/"):
- self.log_info("Record from local node %s ignored" % (recordShortName,))
+ node = recordAttributes.get(dsattributes.kDSNAttrMetaNodeLocation)
+ if node and node.startswith("/Local/"):
+ recordType = recordAttributes.get(dsattributes.kDSNAttrRecordType)
+ self.log_info("Ignoring record %s (type %s) with %s %s" % (recordShortName, recordType, dsattributes.kDSNAttrMetaNodeLocation, recordAttributes.get(dsattributes.kDSNAttrMetaNodeLocation),))
continue
result = ABDirectoryQueryResult(self.directoryBackedAddressBook, recordAttributes,
@@ -387,23 +405,13 @@
def _queryDirectory(self, query=None, attributes=None, maxRecords=0 ):
startTime = time.time()
-
-
if not attributes:
attributes = self.returnedAttributes
- directoryAndRecordTypes = []
- if self.peopleDirectory == self.userDirectory:
- # use single ds query if possible for best performance
- directoryAndRecordTypes.append( (self.peopleDirectory, self.peopleNode, (dsattributes.kDSStdRecordTypePeople, dsattributes.kDSStdRecordTypeUsers) ) )
- else:
- if self.peopleDirectory:
- directoryAndRecordTypes.append( (self.peopleDirectory, self.peopleNode, dsattributes.kDSStdRecordTypePeople) )
- if self.userDirectory:
- directoryAndRecordTypes.append( (self.userDirectory, self.userNode, dsattributes.kDSStdRecordTypeUsers) )
-
allResults = []
- for directory, node, recordType in directoryAndRecordTypes:
+ for node, queryInfo in self.nodeDirectoryRecordTypeMap.iteritems():
+ recordTypes = queryInfo["recordTypes"]
+ directory = queryInfo["directory"]
try:
if query:
if isinstance(query, dsquery.match) and query.value is not "":
@@ -413,7 +421,7 @@
query.value,
query.matchType,
False,
- recordType,
+ recordTypes,
attributes,
maxRecords,
))
@@ -424,7 +432,7 @@
query.value,
query.matchType,
False,
- recordType,
+ recordTypes,
attributes,
maxRecords,
))
@@ -433,7 +441,7 @@
node,
query.generate(),
False,
- recordType,
+ recordTypes,
attributes,
maxRecords,
))
@@ -442,21 +450,21 @@
directory,
query.generate(),
False,
- recordType,
+ recordTypes,
attributes,
maxRecords,
))
else:
self.log_debug("opendirectory.listAllRecordsWithAttributes_list(%r,%r,%r,%r)" % (
node,
- recordType,
+ recordTypes,
attributes,
maxRecords,
))
results = list(
self.odModule.listAllRecordsWithAttributes_list(
directory,
- recordType,
+ recordTypes,
attributes,
maxRecords,
))
@@ -1266,7 +1274,7 @@
# add constant properties - properties that are the same regardless of the record attributes
for key, value in ABDirectoryQueryResult.constantProperties.items():
vcard.addProperty(Property(key, value))
-
+
# 3.1 IDENTIFICATION TYPES http://tools.ietf.org/html/rfc2426#section-3.1
# 3.1.1 FN Type Definition
# dsattributes.kDS1AttrDistinguishedName, # Users distinguished or real name
@@ -1643,6 +1651,14 @@
managerValue = manager
addPropertyAndLabel( groupCount, "_$!<Manager>!$_", "X-ABRELATEDNAMES", managerValue, parameters={ "TYPE": ["Manager",]} )
+
+ # add apple-defined group vcard properties if record type is group
+ if self.firstValueForAttribute(dsattributes.kDSNAttrRecordType) == dsattributes.kDSStdRecordTypeGroups:
+ vcard.addProperty(Property("X-ADDRESSBOOKSERVER-KIND", "group"))
+
+ for memberguid in self.valuesForAttribute(dsattributes.kDSNAttrGroupMembers):
+ vcard.addProperty(Property("X-ADDRESSBOOKSERVER-MEMBER", "urn:uuid:" + memberguid))
+
"""
# UNIMPLEMENTED: X- attributes
Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/stdconfig.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/stdconfig.py 2012-04-12 21:51:02 UTC (rev 9043)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/stdconfig.py 2012-04-12 21:56:29 UTC (rev 9044)
@@ -216,7 +216,9 @@
"queryPeopleRecords": True,
"peopleNode": "/Search/Contacts",
"queryUserRecords": True,
- "userNode": "/Search/Contacts",
+ "userNode": "/Search",
+ "queryGroupRecords": True,
+ "groupNode": "/Search",
"maxDSQueryRecords":0,
"queryDSLocal": False,
"ignoreSystemRecords": True,
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120412/a6058f8c/attachment-0001.html>
More information about the calendarserver-changes
mailing list