[CalendarServer-changes] [2463] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Fri May 23 16:04:09 PDT 2008
Revision: 2463
http://trac.macosforge.org/projects/calendarserver/changeset/2463
Author: wsanchez at apple.com
Date: 2008-05-23 16:04:08 -0700 (Fri, 23 May 2008)
Log Message:
-----------
Merge source:branches/users/cdaboo/read-only-directory-proxy-2425 read-only delegates in OD.
Modified Paths:
--------------
CalendarServer/trunk/conf/accounts-test.xml
CalendarServer/trunk/conf/accounts.dtd
CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py
CalendarServer/trunk/twistedcaldav/directory/calendaruserproxy.py
CalendarServer/trunk/twistedcaldav/directory/directory.py
CalendarServer/trunk/twistedcaldav/directory/principal.py
CalendarServer/trunk/twistedcaldav/directory/test/accounts.xml
CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectory.py
CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryschema.py
CalendarServer/trunk/twistedcaldav/directory/test/test_principal.py
CalendarServer/trunk/twistedcaldav/directory/xmlaccountsparser.py
CalendarServer/trunk/twistedcaldav/directory/xmlfile.py
Modified: CalendarServer/trunk/conf/accounts-test.xml
===================================================================
--- CalendarServer/trunk/conf/accounts-test.xml 2008-05-23 22:44:39 UTC (rev 2462)
+++ CalendarServer/trunk/conf/accounts-test.xml 2008-05-23 23:04:08 UTC (rev 2463)
@@ -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/trunk/conf/accounts.dtd
===================================================================
--- CalendarServer/trunk/conf/accounts.dtd 2008-05-23 22:44:39 UTC (rev 2462)
+++ CalendarServer/trunk/conf/accounts.dtd 2008-05-23 23:04:08 UTC (rev 2463)
@@ -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/trunk/twistedcaldav/directory/appleopendirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py 2008-05-23 22:44:39 UTC (rev 2462)
+++ CalendarServer/trunk/twistedcaldav/directory/appleopendirectory.py 2008-05-23 23:04:08 UTC (rev 2463)
@@ -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/trunk/twistedcaldav/directory/calendaruserproxy.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/calendaruserproxy.py 2008-05-23 22:44:39 UTC (rev 2462)
+++ CalendarServer/trunk/twistedcaldav/directory/calendaruserproxy.py 2008-05-23 23:04:08 UTC (rev 2463)
@@ -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/trunk/twistedcaldav/directory/directory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/directory.py 2008-05-23 22:44:39 UTC (rev 2462)
+++ CalendarServer/trunk/twistedcaldav/directory/directory.py 2008-05-23 23:04:08 UTC (rev 2463)
@@ -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/trunk/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/principal.py 2008-05-23 22:44:39 UTC (rev 2462)
+++ CalendarServer/trunk/twistedcaldav/directory/principal.py 2008-05-23 23:04:08 UTC (rev 2463)
@@ -477,7 +477,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:
@@ -495,7 +495,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)
@@ -510,7 +513,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 = []
@@ -613,6 +617,9 @@
def proxies(self):
return self._getRelatives("proxies")
+ def readOnlyProxies(self):
+ return self._getRelatives("readOnlyProxies")
+
def hasEditableProxyMembership(self):
return self.record.hasEditableProxyMembership()
Modified: CalendarServer/trunk/twistedcaldav/directory/test/accounts.xml
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/accounts.xml 2008-05-23 22:44:39 UTC (rev 2462)
+++ CalendarServer/trunk/twistedcaldav/directory/test/accounts.xml 2008-05-23 23:04:08 UTC (rev 2463)
@@ -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/trunk/twistedcaldav/directory/test/test_opendirectory.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectory.py 2008-05-23 22:44:39 UTC (rev 2462)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectory.py 2008-05-23 23:04:08 UTC (rev 2463)
@@ -72,6 +72,7 @@
enabledForCalendaring = True,
memberGUIDs = [],
proxyGUIDs = (),
+ readOnlyProxyGUIDs = (),
)
digestFields = {}
Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryschema.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryschema.py 2008-05-23 22:44:39 UTC (rev 2462)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_opendirectoryschema.py 2008-05-23 23:04:08 UTC (rev 2463)
@@ -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/trunk/twistedcaldav/directory/test/test_principal.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_principal.py 2008-05-23 22:44:39 UTC (rev 2462)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_principal.py 2008-05-23 23:04:08 UTC (rev 2463)
@@ -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/trunk/twistedcaldav/directory/xmlaccountsparser.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/xmlaccountsparser.py 2008-05-23 22:44:39 UTC (rev 2462)
+++ CalendarServer/trunk/twistedcaldav/directory/xmlaccountsparser.py 2008-05-23 23:04:08 UTC (rev 2463)
@@ -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/trunk/twistedcaldav/directory/xmlfile.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/xmlfile.py 2008-05-23 22:44:39 UTC (rev 2462)
+++ CalendarServer/trunk/twistedcaldav/directory/xmlfile.py 2008-05-23 23:04:08 UTC (rev 2463)
@@ -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/20080523/eb21be11/attachment-0001.htm
More information about the calendarserver-changes
mailing list