[CalendarServer-changes] [1056] CalendarServer/branches/users/cdaboo/od-schema-1044/twistedcaldav/ directory

source_changes at macosforge.org source_changes at macosforge.org
Wed Jan 17 11:35:05 PST 2007


Revision: 1056
          http://trac.macosforge.org/projects/calendarserver/changeset/1056
Author:   cdaboo at apple.com
Date:     2007-01-17 11:35:05 -0800 (Wed, 17 Jan 2007)

Log Message:
-----------
Do calendar user address template substitutions.

Modified Paths:
--------------
    CalendarServer/branches/users/cdaboo/od-schema-1044/twistedcaldav/directory/appleopendirectory.py
    CalendarServer/branches/users/cdaboo/od-schema-1044/twistedcaldav/directory/test/test_opendirectoryschema.py

Modified: CalendarServer/branches/users/cdaboo/od-schema-1044/twistedcaldav/directory/appleopendirectory.py
===================================================================
--- CalendarServer/branches/users/cdaboo/od-schema-1044/twistedcaldav/directory/appleopendirectory.py	2007-01-17 16:27:13 UTC (rev 1055)
+++ CalendarServer/branches/users/cdaboo/od-schema-1044/twistedcaldav/directory/appleopendirectory.py	2007-01-17 19:35:05 UTC (rev 1056)
@@ -166,6 +166,24 @@
             log.msg(msg)
             raise OpenDirectoryInitError(msg)
             
+        # Get host name
+        hostname = vhosts[hostguid].get("hostname", None)
+        if not hostname:
+            msg = "Open Directory (node=%s) /Computers/%s record does not have any host name in its XMLPlist attribute value" % (self.realmName, self.computerRecordName,)
+            log.msg(msg)
+            raise OpenDirectoryInitError(msg)
+        
+        # Get host details and create host templates
+        hostdetails = vhosts[hostguid].get("hostDetails", None)
+        if not hostdetails:
+            msg = "Open Directory (node=%s) /Computers/%s record does not have any host details in its XMLPlist attribute value" % (self.realmName, self.computerRecordName,)
+            log.msg(msg)
+            raise OpenDirectoryInitError(msg)
+        self.hostvariants = []
+        for key, value in hostdetails.iteritems():
+            self.hostvariants.append((key, hostname, value["port"],))
+        self.hostvariants = tuple(self.hostvariants)
+        
         # Look at the service data
         serviceInfos = vhosts[hostguid].get("serviceInfo", None)
         if not serviceInfos or not serviceInfos.has_key("calendar"):
@@ -189,11 +207,66 @@
             raise OpenDirectoryInitError(msg)
         
         # Grab the templates we need for calendar user addresses
-        self.cuaddrtemplates = templates["calendarUserAddresses"]
+        self.cuaddrtemplates = tuple(templates["calendarUserAddresses"])
         
         # Create the string we will use to match users with accounts on this server
         self.servicetag = "%s:%s:calendar" % (recordguid, hostguid,)
     
+    def _templateExpandCalendarUserAddresses(self, recordType, recordName, record):
+        """
+        Expand this services calendar user address templates for the specified record.
+        
+        @param recordName: a C{str} containing the record name being operated on.
+        @param record: a C{dict} containing the attributes retrieved from the directory.
+        @return: a C{set} of C{str} for each expanded calendar user address.
+        """
+        
+        # Make a dict of the substitutions we can do for this record. The only record parameters
+        # we substitute are name, guid and email. Note that email is multi-valued so we have to
+        # create a list of dicts for each one of those.
+        name = recordName
+        type = recordType
+        guid = record.get(dsattributes.kDS1AttrGeneratedUID)
+        emails = record.get(dsattributes.kDSNAttrEMailAddress)
+        if emails is not None and isinstance(emails, str):
+            emails = [emails]
+            
+        subslist = []
+        if emails:
+            for email in emails:
+                subslist.append({
+                    "name"  : name,
+                    "type"  : type,
+                    "guid"  : guid,
+                    "email" : email,
+                })
+        else:
+            subslist.append({
+                "name"  : name,
+                "type"  : type,
+                "guid"  : guid,
+            })
+        
+        # Now do substitutions    
+        result = set()
+        for template in self.cuaddrtemplates:
+            for scheme, hostname, port in self.hostvariants:
+                for subs in subslist:
+                    # Add in host substitution values
+                    subs.update({
+                        "scheme"   : scheme,
+                        "hostname" : hostname,
+                        "port"     : port,
+                    })
+                    
+                    # Special check for no email address for this record
+                    if (template.find("%(email)s") != -1) and not emails:
+                        continue
+
+                    result.add(template % subs)
+                
+        return result
+
     def setup(self):
         self._lookupVHostRecord()
 
@@ -221,7 +294,7 @@
             attrs = [
                 dsattributes.kDS1AttrGeneratedUID,
                 dsattributes.kDS1AttrDistinguishedName,
-                dsattributes.kDSNAttrCalendarPrincipalURI,
+                dsattributes.kDSNAttrEMailAddress,
             ]
 
             if recordType == DirectoryService.recordType_users:
@@ -251,15 +324,8 @@
                     continue
                 realName = value.get(dsattributes.kDS1AttrDistinguishedName)
 
-                # FIXME: We get email address also
-                # FIXME: In new schema, kDSNAttrCalendarPrincipalURI goes away
-                cuaddrs = value.get(dsattributes.kDSNAttrCalendarPrincipalURI)
-                cuaddrset = set()
-                if cuaddrs is not None:
-                    if isinstance(cuaddrs, str):
-                        cuaddrset.add(cuaddrs)
-                    else:
-                        cuaddrset.update(cuaddrs)
+                # Get calendar user addresses expanded from service record templates.
+                cuaddrset = self._templateExpandCalendarUserAddresses(recordType, key, value)
 
                 if recordType == DirectoryService.recordType_groups:
                     memberGUIDs = value.get(dsattributes.kDSNAttrGroupMembers)

Modified: CalendarServer/branches/users/cdaboo/od-schema-1044/twistedcaldav/directory/test/test_opendirectoryschema.py
===================================================================
--- CalendarServer/branches/users/cdaboo/od-schema-1044/twistedcaldav/directory/test/test_opendirectoryschema.py	2007-01-17 16:27:13 UTC (rev 1055)
+++ CalendarServer/branches/users/cdaboo/od-schema-1044/twistedcaldav/directory/test/test_opendirectoryschema.py	2007-01-17 19:35:05 UTC (rev 1056)
@@ -19,9 +19,11 @@
 try:
     from twistedcaldav.directory.appleopendirectory import OpenDirectoryService
     from twistedcaldav.directory.appleopendirectory import OpenDirectoryInitError
+    import dsattributes
 except ImportError:
     pass
 else:
+    from twistedcaldav.directory.directory import DirectoryService
     import twisted.trial.unittest
 
     class PlistParse (twisted.trial.unittest.TestCase):
@@ -316,7 +318,7 @@
                             <string>/principals/%(type)s/%(name)s</string>
                             <key>calendarUserAddresses</key>
                             <array>
-                                <string>%(principal URI)s</string>
+                                <string>%(scheme)s://%(hostname)s:%(port)s/principals/%(type)s/%(name)s</string>
                                 <string>mailto:%(email)s</string>
                                 <string>urn:uuid:%(guid)s</string>
                             </array>
@@ -330,6 +332,213 @@
 </plist>
 """
 
+        plist_nohostname = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+    <dict>
+        <key>ReplicaName</key>
+        <string>Master</string>
+
+        <key>com.apple.od.role</key>
+        <string>master</string>
+
+        <key>com.apple.macosxserver.virtualhosts</key>
+        <dict>
+            <key>4F088107-51FD-4DE5-904D-2C0AD9C6C893</key>
+            <dict>
+                <key>hostname</key>
+                <string>foo.apple.com</string>
+
+                <key>hostDetails</key>
+                <dict>
+                    <key>http</key>
+                    <dict>
+                        <key>port</key>
+                        <string>80</string>
+                    </dict>
+                    <key>https</key>
+                    <dict>
+                        <key>port</key>
+                        <string>443</string>
+                    </dict>
+                </dict>
+
+                <key>serviceType</key>
+                <array>
+                    <string>wiki</string>
+                    <string>webCalendar</string>
+                    <string>webMailingList</string>
+                </array>
+
+                <key>serviceInfo</key>
+                <dict>
+                    <key>webCalendar</key>
+                    <dict>
+                        <key>enabled</key>
+                        <string>YES</string>
+                        <key>urlMask</key>
+                        <string>%(scheme)s://%(hostname)s:%(port)s/groups/%(groupname)s/webcalendar</string>
+                    </dict>
+                    <key>wiki</key>
+                    <dict>
+                        <key>enabled</key>
+                        <string>YES</string>
+                        <key>urlMask</key>
+                        <string>%(scheme)s://%(hostname)s:%(port)s/groups/%(groupname)s/wiki</string>
+                    </dict>
+                    <key>webMailingList</key>
+                    <dict>
+                        <key>enabled</key>
+                        <true/>
+                        <key>urlMask</key>
+                        <string>%(scheme)s://%(hostname)s:%(port)s/groups/%(groupname)s/mailinglist</string>
+                    </dict>
+                </dict>
+            </dict>
+            
+            <key>C18C34AC-3D9E-403C-8A33-BFC303F3840E</key>
+            <dict>
+                <key>hostDetails</key>
+                <dict>
+                    <key>http</key>
+                    <dict>
+                        <key>port</key>
+                        <string>8008</string>
+                    </dict>
+                    <key>https</key>
+                    <dict>
+                        <key>port</key>
+                        <string>8443</string>
+                    </dict>
+                </dict>
+
+                <key>serviceType</key>
+                <array>
+                    <string>calendar</string>
+                </array>
+
+                <key>serviceInfo</key>
+                <dict>
+                    <key>calendar</key>
+                    <dict>
+                        <key>templates</key>
+                        <dict>
+                            <key>principalPath</key>
+                            <string>/principals/%(type)s/%(name)s</string>
+                            <key>calendarUserAddresses</key>
+                            <array>
+                                <string>%(scheme)s://%(hostname)s:%(port)s/principals/%(type)s/%(name)s</string>
+                                <string>mailto:%(email)s</string>
+                                <string>urn:uuid:%(guid)s</string>
+                            </array>
+                        </dict>
+                    </dict>
+                </dict>
+            </dict>
+
+        </dict>
+    </dict>
+</plist>
+"""
+
+        plist_nohostdetails = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+    <dict>
+        <key>ReplicaName</key>
+        <string>Master</string>
+
+        <key>com.apple.od.role</key>
+        <string>master</string>
+
+        <key>com.apple.macosxserver.virtualhosts</key>
+        <dict>
+            <key>4F088107-51FD-4DE5-904D-2C0AD9C6C893</key>
+            <dict>
+                <key>hostname</key>
+                <string>foo.apple.com</string>
+
+                <key>hostDetails</key>
+                <dict>
+                    <key>http</key>
+                    <dict>
+                        <key>port</key>
+                        <string>80</string>
+                    </dict>
+                    <key>https</key>
+                    <dict>
+                        <key>port</key>
+                        <string>443</string>
+                    </dict>
+                </dict>
+
+                <key>serviceType</key>
+                <array>
+                    <string>wiki</string>
+                    <string>webCalendar</string>
+                    <string>webMailingList</string>
+                </array>
+
+                <key>serviceInfo</key>
+                <dict>
+                    <key>webCalendar</key>
+                    <dict>
+                        <key>enabled</key>
+                        <string>YES</string>
+                        <key>urlMask</key>
+                        <string>%(scheme)s://%(hostname)s:%(port)s/groups/%(groupname)s/webcalendar</string>
+                    </dict>
+                    <key>wiki</key>
+                    <dict>
+                        <key>enabled</key>
+                        <string>YES</string>
+                        <key>urlMask</key>
+                        <string>%(scheme)s://%(hostname)s:%(port)s/groups/%(groupname)s/wiki</string>
+                    </dict>
+                    <key>webMailingList</key>
+                    <dict>
+                        <key>enabled</key>
+                        <true/>
+                        <key>urlMask</key>
+                        <string>%(scheme)s://%(hostname)s:%(port)s/groups/%(groupname)s/mailinglist</string>
+                    </dict>
+                </dict>
+            </dict>
+            
+            <key>C18C34AC-3D9E-403C-8A33-BFC303F3840E</key>
+            <dict>
+                <key>hostname</key>
+                <string>calendar.apple.com</string>
+
+                <key>serviceType</key>
+                <array>
+                    <string>calendar</string>
+                </array>
+
+                <key>serviceInfo</key>
+                <dict>
+                    <key>calendar</key>
+                    <dict>
+                        <key>templates</key>
+                        <dict>
+                            <key>principalPath</key>
+                            <string>/principals/%(type)s/%(name)s</string>
+                            <key>calendarUserAddresses</key>
+                            <array>
+                                <string>%(scheme)s://%(hostname)s:%(port)s/principals/%(type)s/%(name)s</string>
+                                <string>mailto:%(email)s</string>
+                                <string>urn:uuid:%(guid)s</string>
+                            </array>
+                        </dict>
+                    </dict>
+                </dict>
+            </dict>
+
+        </dict>
+    </dict>
+</plist>
+"""
+
         plist_nocuaddrtemplates = """<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
@@ -534,7 +743,7 @@
                             <string>/principals/%(type)s/%(name)s</string>
                             <key>calendarUserAddresses</key>
                             <array>
-                                <string>%(principal URI)s</string>
+                                <string>%(scheme)s://%(hostname)s:%(port)s/principals/%(type)s/%(name)s</string>
                                 <string>mailto:%(email)s</string>
                                 <string>urn:uuid:%(guid)s</string>
                             </array>
@@ -562,6 +771,8 @@
                 (PlistParse.plist_nocalendarservice,  "nocalendarservice"),
                 (PlistParse.plist_noserviceinfo,      "noserviceinfo"),
                 (PlistParse.plist_disabledservice,    "disabledservice"),
+                (PlistParse.plist_nohostname,         "nohostname"),
+                (PlistParse.plist_nohostdetails,      "nohostdetails"),
                 (PlistParse.plist_nocuaddrtemplates,  "nocuaddrtemplates"),
             )
             for plist, title in plists:
@@ -573,6 +784,62 @@
             
             # Verify that we extracted the proper items
             self.assertEqual(service.servicetag, "GUIDIFY:C18C34AC-3D9E-403C-8A33-BFC303F3840E:calendar")
-            self.assertEqual(service.cuaddrtemplates, ["%(principal URI)s", "mailto:%(email)s", "urn:uuid:%(guid)s"])
+            self.assertEqual(service.hostvariants, (("http", "calendar.apple.com", "8008"), ("https", "calendar.apple.com", "8443")))
+            self.assertEqual(service.cuaddrtemplates, ("%(scheme)s://%(hostname)s:%(port)s/principals/%(type)s/%(name)s", "mailto:%(email)s", "urn:uuid:%(guid)s"))
+
+        def test_expandcuaddrs(self):
+            def _doTest(recordName, record, result, title):
+                service = OpenDirectoryService(node="/Search", dosetup=False)
+                service._parseXMLPlist(PlistParse.plist_good, "GUIDIFY")
+                expanded = service._templateExpandCalendarUserAddresses(DirectoryService.recordType_users, recordName, record)
+    
+                # Verify that we extracted the proper items
+                self.assertEqual(expanded, result, msg=title % (expanded, result,))
             
+            data = (
+                (
+                 "user01",
+                 {
+                    dsattributes.kDS1AttrGeneratedUID: "GUID-USER-01",
+                    dsattributes.kDSNAttrEMailAddress: "user01 at example.com",
+                 },
+                 set((
+                    "http://calendar.apple.com:8008/principals/users/user01",
+                    "https://calendar.apple.com:8443/principals/users/user01",
+                    "mailto:user01 at example.com",
+                    "urn:uuid:GUID-USER-01",
+                 )),
+                 "User with one email address, %s != %s",
+                ),
+                (
+                 "user02",
+                 {
+                    dsattributes.kDS1AttrGeneratedUID: "GUID-USER-02",
+                    dsattributes.kDSNAttrEMailAddress: ["user02 at example.com", "user02 at calendar.example.com"],
+                 },
+                 set((
+                    "http://calendar.apple.com:8008/principals/users/user02",
+                    "https://calendar.apple.com:8443/principals/users/user02",
+                    "mailto:user02 at example.com",
+                    "mailto:user02 at calendar.example.com",
+                    "urn:uuid:GUID-USER-02",
+                 )),
+                 "User with multiple email addresses, %s != %s",
+                ),
+                (
+                 "user03",
+                 {
+                    dsattributes.kDS1AttrGeneratedUID: "GUID-USER-03",
+                 },
+                 set((
+                    "http://calendar.apple.com:8008/principals/users/user03",
+                    "https://calendar.apple.com:8443/principals/users/user03",
+                    "urn:uuid:GUID-USER-03",
+                 )),
+                 "User with no email addresses, %s != %s",
+                ),
+            )
+            
+            for recordName, record, result, title in data:
+                _doTest(recordName, record, result, title)
             
\ No newline at end of file

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20070117/ab1ae51e/attachment.html


More information about the calendarserver-changes mailing list