[CalendarServer-changes] [2427] CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425

source_changes at macosforge.org source_changes at macosforge.org
Sun May 18 18:28:20 PDT 2008


Revision: 2427
          http://trac.macosforge.org/projects/calendarserver/changeset/2427
Author:   cdaboo at apple.com
Date:     2008-05-18 18:28:17 -0700 (Sun, 18 May 2008)

Log Message:
-----------
Add support for directory based read-only delegates for locations and resources.

Modified Paths:
--------------
    CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/conf/accounts-test.xml
    CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/conf/accounts.dtd
    CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/appleopendirectory.py
    CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/calendaruserproxy.py
    CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/directory.py
    CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/principal.py
    CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/test/accounts.xml
    CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/test/test_opendirectory.py
    CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/test/test_opendirectoryschema.py
    CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/test/test_principal.py
    CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/xmlaccountsparser.py
    CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/xmlfile.py

Modified: CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/conf/accounts-test.xml
===================================================================
--- CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/conf/accounts-test.xml	2008-05-18 01:07:42 UTC (rev 2426)
+++ CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/conf/accounts-test.xml	2008-05-19 01:28:17 UTC (rev 2427)
@@ -55,6 +55,9 @@
     <proxies>
       <member type="users">user01</member>
     </proxies>
+    <read-only-proxies>
+      <member type="users">user02</member>
+    </read-only-proxies>
   </resource>
   <group>
     <uid>group01</uid>

Modified: CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/conf/accounts.dtd
===================================================================
--- CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/conf/accounts.dtd	2008-05-18 01:07:42 UTC (rev 2426)
+++ CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/conf/accounts.dtd	2008-05-19 01:28:17 UTC (rev 2427)
@@ -25,22 +25,23 @@
   <!ELEMENT group (uid, guid, password, name, members, cuaddr*, disable-calendar?)>
     <!ATTLIST group repeat CDATA "1">
 
-  <!ELEMENT resource (uid, guid, password, name, cuaddr*, auto-schedule?, proxies?)>
+  <!ELEMENT resource (uid, guid, password, name, cuaddr*, auto-schedule?, proxies?, read-only-proxies?)>
     <!ATTLIST resource repeat CDATA "1">
 
-  <!ELEMENT location (uid, guid, password, name, cuaddr*, auto-schedule?, proxies?)>
+  <!ELEMENT location (uid, guid, password, name, cuaddr*, auto-schedule?, proxies?, read-only-proxies?)>
     <!ATTLIST location repeat CDATA "1">
 
   <!ELEMENT member (#PCDATA)>
     <!ATTLIST member type (users|groups|locations|resources) "users">
 
-  <!ELEMENT uid              (#PCDATA)>
-  <!ELEMENT guid             (#PCDATA)>
-  <!ELEMENT password         (#PCDATA)>
-  <!ELEMENT name             (#PCDATA)>
-  <!ELEMENT cuaddr           (#PCDATA)>
-  <!ELEMENT members          (member*)>
-  <!ELEMENT auto-schedule    EMPTY>
-  <!ELEMENT disable-calendar EMPTY>
-  <!ELEMENT proxies          (member*)>
+  <!ELEMENT uid               (#PCDATA)>
+  <!ELEMENT guid              (#PCDATA)>
+  <!ELEMENT password          (#PCDATA)>
+  <!ELEMENT name              (#PCDATA)>
+  <!ELEMENT cuaddr            (#PCDATA)>
+  <!ELEMENT members           (member*)>
+  <!ELEMENT auto-schedule     EMPTY>
+  <!ELEMENT disable-calendar  EMPTY>
+  <!ELEMENT proxies           (member*)>
+  <!ELEMENT read-only-proxies (member*)>
 >

Modified: CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/appleopendirectory.py
===================================================================
--- CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/appleopendirectory.py	2008-05-18 01:07:42 UTC (rev 2426)
+++ CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/appleopendirectory.py	2008-05-19 01:28:17 UTC (rev 2427)
@@ -345,13 +345,14 @@
         @type guid: str
         @param shortname: the record shortname of the record being parsed.
         @type shortname: str
-        @return: a C{tuple} of C{bool} for auto-accept and C{str} for proxy GUID.
+        @return: a C{tuple} of C{bool} for auto-accept, C{str} for proxy GUID, C{str} for read-only proxy GUID.
         """
         try:
             plist = readPlistFromString(plist)
             wpframework = plist.get("com.apple.WhitePagesFramework", {})
             autoaccept = wpframework.get("AutoAcceptsInvitation", False)
-            proxy = wpframework.get("CalendaringDelegate")
+            proxy = wpframework.get("CalendaringDelegate", None)
+            read_only_proxy = wpframework.get("ReadOnlyCalendaringDelegate", None)
         except AttributeError:
             self.log_error(
                 "Failed to parse ResourceInfo attribute of record %s (%s): %s" %
@@ -359,8 +360,9 @@
             )
             autoaccept = False
             proxy = None
+            read_only_proxy = None
 
-        return (autoaccept, proxy)
+        return (autoaccept, proxy, read_only_proxy,)
 
     def recordTypes(self):
         return (
@@ -542,12 +544,15 @@
             # Special case for resources and locations
             autoSchedule = False
             proxyGUIDs = ()
+            readOnlyProxyGUIDs = ()
             if recordType in (DirectoryService.recordType_resources, DirectoryService.recordType_locations):
                 resourceInfo = value.get(dsattributes.kDSNAttrResourceInfo)
                 if resourceInfo is not None:
-                    autoSchedule, proxy = self._parseResourceInfo(resourceInfo, recordGUID, recordShortName)
+                    autoSchedule, proxy, read_only_proxy = self._parseResourceInfo(resourceInfo, recordGUID, recordShortName)
                     if proxy:
                         proxyGUIDs = (proxy,)
+                    if read_only_proxy:
+                        readOnlyProxyGUIDs = (read_only_proxy,)
 
             record = OpenDirectoryRecord(
                 service               = self,
@@ -561,6 +566,7 @@
                 enabledForCalendaring = enabledForCalendaring,
                 memberGUIDs           = memberGUIDs,
                 proxyGUIDs            = proxyGUIDs,
+                readOnlyProxyGUIDs    = readOnlyProxyGUIDs,
             )
 
             def disableRecord(record):
@@ -772,7 +778,7 @@
     def __init__(
         self, service, recordType, guid, nodeName, shortName, fullName,
         calendarUserAddresses, autoSchedule, enabledForCalendaring,
-        memberGUIDs, proxyGUIDs,
+        memberGUIDs, proxyGUIDs, readOnlyProxyGUIDs,
     ):
         super(OpenDirectoryRecord, self).__init__(
             service               = service,
@@ -787,6 +793,7 @@
         self.nodeName = nodeName
         self._memberGUIDs = tuple(memberGUIDs)
         self._proxyGUIDs = tuple(proxyGUIDs)
+        self._readOnlyProxyGUIDs = tuple(readOnlyProxyGUIDs)
 
     def __repr__(self):
         if self.service.realmName == self.nodeName:
@@ -837,6 +844,25 @@
             if self.guid in proxyRecord._proxyGUIDs:
                 yield proxyRecord
 
+    def readOnlyProxies(self):
+        if self.recordType not in (DirectoryService.recordType_resources, DirectoryService.recordType_locations):
+            return
+
+        for guid in self._readOnlyProxyGUIDs:
+            proxyRecord = self.service.recordWithGUID(guid)
+            if proxyRecord is None:
+                self.log_error("No record for proxy in %s with GUID %s" % (self.shortName, guid))
+            else:
+                yield proxyRecord
+
+    def readOnlyProxyFor(self):
+        for proxyRecord in itertools.chain(
+            self.service.recordsForType(DirectoryService.recordType_resources).itervalues(),
+            self.service.recordsForType(DirectoryService.recordType_locations).itervalues(),
+        ):
+            if self.guid in proxyRecord._readOnlyProxyGUIDs:
+                yield proxyRecord
+
     def verifyCredentials(self, credentials):
         if isinstance(credentials, UsernamePassword):
             # Check cached password

Modified: CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/calendaruserproxy.py
===================================================================
--- CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/calendaruserproxy.py	2008-05-18 01:07:42 UTC (rev 2426)
+++ CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/calendaruserproxy.py	2008-05-19 01:28:17 UTC (rev 2427)
@@ -283,11 +283,11 @@
             members = self._index().getMembers(self.uid)
             return [p for p in [self.pcollection.principalForUID(uid) for uid in members] if p]
         else:
-            # Fixed proxies are only for read-write - the read-only list is empty
+            # Fixed proxies
             if self.proxyType == "calendar-proxy-write":
                 return self.parent.proxies()
             else:
-                return ()
+                return self.parent.readOnlyProxies()
 
 
     def groupMembers(self):

Modified: CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/directory.py
===================================================================
--- CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/directory.py	2008-05-18 01:07:42 UTC (rev 2426)
+++ CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/directory.py	2008-05-19 01:28:17 UTC (rev 2427)
@@ -206,6 +206,12 @@
     def proxyFor(self):
         return ()
 
+    def readOnlyProxies(self):
+        return ()
+
+    def readOnlyProxyFor(self):
+        return ()
+
     def hasEditableProxyMembership(self):
         return self.recordType in (DirectoryService.recordType_users, DirectoryService.recordType_groups)
 

Modified: CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/principal.py	2008-05-18 01:07:42 UTC (rev 2426)
+++ CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/principal.py	2008-05-19 01:28:17 UTC (rev 2427)
@@ -474,7 +474,7 @@
     def principalURL(self):
         return self._url
 
-    def _getRelatives(self, method, record=None, relatives=None, records=None, proxy=False):
+    def _getRelatives(self, method, record=None, relatives=None, records=None, proxy=None):
         if record is None:
             record = self.record
         if relatives is None:
@@ -492,7 +492,10 @@
                         log.err("No principal found for directory record: %r" % (relative,))
                     else:
                         if proxy:
-                            found = found.getChild("calendar-proxy-write")
+                            if proxy == "read-write":
+                                found = found.getChild("calendar-proxy-write")
+                            else:
+                                found = found.getChild("calendar-proxy-read")
                         relatives.add(found)
 
                     self._getRelatives(method, relative, relatives, records)
@@ -507,7 +510,8 @@
 
         if config.EnableProxyPrincipals:
             # Get any directory specified proxies
-            groups.update(self._getRelatives("proxyFor", proxy=True))
+            groups.update(self._getRelatives("proxyFor", proxy='read-write'))
+            groups.update(self._getRelatives("readOnlyProxyFor", proxy='read-only'))
 
             # Get proxy group UIDs and map to principal resources
             proxies = []
@@ -610,6 +614,9 @@
     def proxies(self):
         return self._getRelatives("proxies")
 
+    def readOnlyProxies(self):
+        return self._getRelatives("readOnlyProxies")
+
     def hasEditableProxyMembership(self):
         return self.record.hasEditableProxyMembership()
 

Modified: CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/test/accounts.xml
===================================================================
--- CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/test/accounts.xml	2008-05-18 01:07:42 UTC (rev 2426)
+++ CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/test/accounts.xml	2008-05-19 01:28:17 UTC (rev 2427)
@@ -197,5 +197,8 @@
     <proxies>
       <member type="groups">non_calendar_group</member>
     </proxies>
+    <read-only-proxies>
+      <member type="groups">recursive2_coasts</member>
+    </read-only-proxies>
   </resource>
 </accounts>

Modified: CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/test/test_opendirectory.py
===================================================================
--- CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/test/test_opendirectory.py	2008-05-18 01:07:42 UTC (rev 2426)
+++ CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/test/test_opendirectory.py	2008-05-19 01:28:17 UTC (rev 2427)
@@ -72,6 +72,7 @@
                 enabledForCalendaring = True,
                 memberGUIDs           = [],
                 proxyGUIDs            = (),
+                readOnlyProxyGUIDs    = (),
             )
 
             digestFields = {}

Modified: CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/test/test_opendirectoryschema.py
===================================================================
--- CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/test/test_opendirectoryschema.py	2008-05-18 01:07:42 UTC (rev 2426)
+++ CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/test/test_opendirectoryschema.py	2008-05-19 01:28:17 UTC (rev 2427)
@@ -1186,6 +1186,8 @@
         <string>Location</string>
         <key>CalendaringDelegate</key>
         <string>1234-GUID-5678</string>
+        <key>ReadOnlyCalendaringDelegate</key>
+        <string>1234-GUID-5679</string>
     </dict>
 </dict>
 </plist>
@@ -1203,6 +1205,8 @@
         <string>Location</string>
         <key>CalendaringDelegate</key>
         <string></string>
+        <key>ReadOnlyCalendaringDelegate</key>
+        <string></string>
     </dict>
 </dict>
 </plist>
@@ -1243,6 +1247,8 @@
         <string>Location</string>
         <key>CalendaringDelegate</key>
         <string>1234-GUID-5678</string>
+        <key>ReadOnlyCalendaringDelegate</key>
+        <string>1234-GUID-5679</string>
     </dict>
 </dict>
 </plist>
@@ -1260,18 +1266,19 @@
 """
 
         test_bool = (
-            (plist_good_false, False, "1234-GUID-5678"),
-            (plist_good_true, True, ""),
-            (plist_good_missing, False, None),
-            (plist_wrong, False, None),
-            (plist_bad, False, None),
-            (plist_invalid, False, None),
+            (plist_good_false, False, "1234-GUID-5678", "1234-GUID-5679"),
+            (plist_good_true, True, "", ""),
+            (plist_good_missing, False, None, None),
+            (plist_wrong, False, None, None),
+            (plist_bad, False, None, None),
+            (plist_invalid, False, None, None),
         )
 
         def test_plists(self):
             service = OpenDirectoryService(node="/Search", dosetup=False)
             
             for item in ODResourceInfoParse.test_bool:
-                item1, item2 = service._parseResourceInfo(item[0], "guid", "name")
+                item1, item2, item3 = service._parseResourceInfo(item[0], "guid", "name")
                 self.assertEqual(item1, item[1])
                 self.assertEqual(item2, item[2])
+                self.assertEqual(item3, item[3])

Modified: CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/test/test_principal.py
===================================================================
--- CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/test/test_principal.py	2008-05-18 01:07:42 UTC (rev 2426)
+++ CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/test/test_principal.py	2008-05-19 01:28:17 UTC (rev 2427)
@@ -267,6 +267,15 @@
                 self.failUnless(set(record.proxies()).issubset(set(r.record for r in recordResource.proxies())))
                 self.assertEqual(record.hasEditableProxyMembership(), recordResource.hasEditableProxyMembership())
 
+    def test_read_only_proxies(self):
+        """
+        DirectoryPrincipalResource.proxies()
+        """
+        for provisioningResource, recordType, recordResource, record in self._allRecords():
+            if record.enabledForCalendaring:
+                self.failUnless(set(record.readOnlyProxies()).issubset(set(r.record for r in recordResource.readOnlyProxies())))
+                self.assertEqual(record.hasEditableProxyMembership(), recordResource.hasEditableProxyMembership())
+
     def test_principalUID(self):
         """
         DirectoryPrincipalResource.principalUID()

Modified: CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/xmlaccountsparser.py
===================================================================
--- CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/xmlaccountsparser.py	2008-05-18 01:07:42 UTC (rev 2426)
+++ CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/xmlaccountsparser.py	2008-05-19 01:28:17 UTC (rev 2427)
@@ -29,26 +29,27 @@
 
 from twistedcaldav.directory.directory import DirectoryService
 
-ELEMENT_ACCOUNTS        = "accounts"
-ELEMENT_USER            = "user"
-ELEMENT_GROUP           = "group"
-ELEMENT_LOCATION        = "location"
-ELEMENT_RESOURCE        = "resource"
+ELEMENT_ACCOUNTS          = "accounts"
+ELEMENT_USER              = "user"
+ELEMENT_GROUP             = "group"
+ELEMENT_LOCATION          = "location"
+ELEMENT_RESOURCE          = "resource"
 
-ELEMENT_SHORTNAME       = "uid"
-ELEMENT_GUID            = "guid"
-ELEMENT_PASSWORD        = "password"
-ELEMENT_NAME            = "name"
-ELEMENT_MEMBERS         = "members"
-ELEMENT_MEMBER          = "member"
-ELEMENT_CUADDR          = "cuaddr"
-ELEMENT_AUTOSCHEDULE    = "auto-schedule"
-ELEMENT_DISABLECALENDAR = "disable-calendar"
-ELEMENT_PROXIES         = "proxies"
+ELEMENT_SHORTNAME         = "uid"
+ELEMENT_GUID              = "guid"
+ELEMENT_PASSWORD          = "password"
+ELEMENT_NAME              = "name"
+ELEMENT_MEMBERS           = "members"
+ELEMENT_MEMBER            = "member"
+ELEMENT_CUADDR            = "cuaddr"
+ELEMENT_AUTOSCHEDULE      = "auto-schedule"
+ELEMENT_DISABLECALENDAR   = "disable-calendar"
+ELEMENT_PROXIES           = "proxies"
+ELEMENT_READ_ONLY_PROXIES = "read-only-proxies"
 
-ATTRIBUTE_REALM         = "realm"
-ATTRIBUTE_REPEAT        = "repeat"
-ATTRIBUTE_RECORDTYPE    = "type"
+ATTRIBUTE_REALM           = "realm"
+ATTRIBUTE_REPEAT          = "repeat"
+ATTRIBUTE_RECORDTYPE      = "type"
 
 RECORD_TYPES = {
     ELEMENT_USER     : DirectoryService.recordType_users,
@@ -109,6 +110,12 @@
                 if item is not None:
                     item.proxyFor.add((proxier.recordType, proxier.shortName))
 
+            # Update read-only proxy membership
+            for recordType, shortName in proxier.readOnlyProxies:
+                item = self.items[recordType].get(shortName, None)
+                if item is not None:
+                    item.readOnlyProxyFor.add((proxier.recordType, proxier.shortName))
+
         for child in node._get_childNodes():
             child_name = child._get_localName()
             if child_name is None:
@@ -159,6 +166,8 @@
         self.enabledForCalendaring = True
         self.proxies = set()
         self.proxyFor = set()
+        self.readOnlyProxies = set()
+        self.readOnlyProxyFor = set()
 
     def repeat(self, ctr):
         """
@@ -199,6 +208,7 @@
         result.autoSchedule = self.autoSchedule
         result.enabledForCalendaring = self.enabledForCalendaring
         result.proxies = self.proxies
+        result.readOnlyProxies = self.readOnlyProxies
         return result
 
     def parseXML(self, node):
@@ -238,6 +248,11 @@
                 if self.recordType not in (DirectoryService.recordType_resources, DirectoryService.recordType_locations):
                     raise ValueError("<auto-schedule> element only allowed for Resources and Locations: %s" % (child_name,))
                 self._parseMembers(child, self.proxies)
+            elif child_name == ELEMENT_READ_ONLY_PROXIES:
+                # Only Resources & Locations
+                if self.recordType not in (DirectoryService.recordType_resources, DirectoryService.recordType_locations):
+                    raise ValueError("<auto-schedule> element only allowed for Resources and Locations: %s" % (child_name,))
+                self._parseMembers(child, self.readOnlyProxies)
             else:
                 raise RuntimeError("Unknown account attribute: %s" % (child_name,))
 

Modified: CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/xmlfile.py
===================================================================
--- CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/xmlfile.py	2008-05-18 01:07:42 UTC (rev 2426)
+++ CalendarServer/branches/users/cdaboo/read-only-directory-proxy-2425/twistedcaldav/directory/xmlfile.py	2008-05-19 01:28:17 UTC (rev 2427)
@@ -113,11 +113,13 @@
             enabledForCalendaring = xmlPrincipal.enabledForCalendaring,
         )
 
-        self.password     = xmlPrincipal.password
-        self._members     = xmlPrincipal.members
-        self._groups      = xmlPrincipal.groups
-        self._proxies     = xmlPrincipal.proxies
-        self._proxyFor    = xmlPrincipal.proxyFor
+        self.password          = xmlPrincipal.password
+        self._members          = xmlPrincipal.members
+        self._groups           = xmlPrincipal.groups
+        self._proxies          = xmlPrincipal.proxies
+        self._proxyFor         = xmlPrincipal.proxyFor
+        self._readOnlyProxies  = xmlPrincipal.readOnlyProxies
+        self._readOnlyProxyFor = xmlPrincipal.readOnlyProxyFor
 
     def members(self):
         for recordType, shortName in self._members:
@@ -131,10 +133,18 @@
         for recordType, shortName in self._proxies:
             yield self.service.recordWithShortName(recordType, shortName)
 
-    def proxyFor(self):
+    def proxyFor(self, read_write=True):
         for recordType, shortName in self._proxyFor:
             yield self.service.recordWithShortName(recordType, shortName)
 
+    def readOnlyProxies(self):
+        for recordType, shortName in self._readOnlyProxies:
+            yield self.service.recordWithShortName(recordType, shortName)
+
+    def readOnlyProxyFor(self, read_write=True):
+        for recordType, shortName in self._readOnlyProxyFor:
+            yield self.service.recordWithShortName(recordType, shortName)
+
     def verifyCredentials(self, credentials):
         if isinstance(credentials, UsernamePassword):
             return credentials.password == self.password

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20080518/604b9bc8/attachment-0001.htm 


More information about the calendarserver-changes mailing list