[CalendarServer-changes] [5469] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Mon Apr 12 13:22:36 PDT 2010
Revision: 5469
http://trac.macosforge.org/projects/calendarserver/changeset/5469
Author: cdaboo at apple.com
Date: 2010-04-12 13:22:32 -0700 (Mon, 12 Apr 2010)
Log Message:
-----------
Remove "search" and "searchall" address books, and find-shared REPORT. Fix up xmpp notifications
for address books.
Modified Paths:
--------------
CalendarServer/trunk/calendarserver/tap/test/test_caldav.py
CalendarServer/trunk/calendarserver/tap/util.py
CalendarServer/trunk/conf/carddavd-apple.plist
CalendarServer/trunk/conf/carddavd-test.plist
CalendarServer/trunk/twistedcaldav/directory/addressbook.py
CalendarServer/trunk/twistedcaldav/directory/principal.py
CalendarServer/trunk/twistedcaldav/directorybackedaddressbook.py
CalendarServer/trunk/twistedcaldav/resource.py
CalendarServer/trunk/twistedcaldav/static.py
CalendarServer/trunk/twistedcaldav/stdconfig.py
CalendarServer/trunk/twistedcaldav/test/util.py
Removed Paths:
-------------
CalendarServer/trunk/twistedcaldav/report_addressbook_findshared.py
Modified: CalendarServer/trunk/calendarserver/tap/test/test_caldav.py
===================================================================
--- CalendarServer/trunk/calendarserver/tap/test/test_caldav.py 2010-04-12 16:27:16 UTC (rev 5468)
+++ CalendarServer/trunk/calendarserver/tap/test/test_caldav.py 2010-04-12 20:22:32 UTC (rev 5469)
@@ -291,6 +291,7 @@
self.config.SSLCertificate = pemFile
self.config.Memcached.Pools.Default.ClientEnabled = False
self.config.Memcached.Pools.Default.ServerEnabled = False
+ self.config.DirectoryAddressBook.Enabled = False
self.config.SudoersFile = ""
Modified: CalendarServer/trunk/calendarserver/tap/util.py
===================================================================
--- CalendarServer/trunk/calendarserver/tap/util.py 2010-04-12 16:27:16 UTC (rev 5468)
+++ CalendarServer/trunk/calendarserver/tap/util.py 2010-04-12 20:22:32 UTC (rev 5469)
@@ -268,34 +268,22 @@
principalCollection = principalResourceClass("/principals/", directory)
- log.info("Setting up calendar collection: %r" % (calendarResourceClass,))
+ if config.EnableCalDAV:
+ log.info("Setting up calendar collection: %r" % (calendarResourceClass,))
+ calendarCollection = calendarResourceClass(
+ os.path.join(config.DocumentRoot, "calendars"),
+ directory, "/calendars/",
+ )
- calendarCollection = calendarResourceClass(
- os.path.join(config.DocumentRoot, "calendars"),
- directory, "/calendars/",
- )
-
- log.info("Setting up root resource: %r" % (rootResourceClass,))
-
- root = rootResourceClass(
- config.DocumentRoot,
- principalCollections=(principalCollection,),
- )
-
if config.EnableCardDAV:
- root.saclService = "addressbook" # XXX this needs to be dealt with
- # differently if caldav and carddav
- # are going to be in the same process
log.info("Setting up address book collection: %r" % (addressBookResourceClass,))
-
addressBookCollection = addressBookResourceClass(
os.path.join(config.DocumentRoot, "addressbooks"),
directory, "/addressbooks/"
)
directoryPath = os.path.join(config.DocumentRoot, "directory")
- doBacking = config.DirectoryAddressBook and config.EnableSearchAddressBook
- if doBacking:
+ if config.DirectoryAddressBook.Enabled:
log.info("Setting up directory address book: %r" % (directoryBackedAddressBookResourceClass,))
directoryBackedAddressBookCollection = directoryBackedAddressBookResourceClass(
@@ -315,13 +303,26 @@
if e.errno != errno.ENOENT:
log.error("Could not delete: %s : %r" % (directoryPath, e,))
+ log.info("Setting up root resource: %r" % (rootResourceClass,))
+
+ root = rootResourceClass(
+ config.DocumentRoot,
+ principalCollections=(principalCollection,),
+ )
+
+ if config.EnableCardDAV and not config.EnableCalDAV:
+ # TODO need a better way to do this when both services are enabled
+ root.saclService = "addressbook"
+
+
+ root.putChild("principals", principalCollection)
+ if config.EnableCalDAV:
+ root.putChild("calendars", calendarCollection)
+ if config.EnableCardDAV:
root.putChild('addressbooks', addressBookCollection)
- if doBacking:
+ if config.DirectoryAddressBook.Enabled:
root.putChild('directory', directoryBackedAddressBookCollection)
- root.putChild("principals", principalCollection)
- root.putChild("calendars", calendarCollection)
-
# /.well-known
if config.EnableWellKnown:
log.info("Setting up .well-known collection resource")
Modified: CalendarServer/trunk/conf/carddavd-apple.plist
===================================================================
--- CalendarServer/trunk/conf/carddavd-apple.plist 2010-04-12 16:27:16 UTC (rev 5468)
+++ CalendarServer/trunk/conf/carddavd-apple.plist 2010-04-12 20:22:32 UTC (rev 5469)
@@ -16,7 +16,7 @@
limitations under the License.
-->
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
@@ -40,18 +40,6 @@
<key>EnableCalDAV</key>
<false/>
- <key>ConfigRoot</key>
- <string>/etc/carddavd</string>
-
- <key>LogRoot</key>
- <string>/var/log/carddavd</string>
-
- <key>PIDFile</key>
- <string>carddavd.pid</string>
-
- <key>GlobalStatsSocket</key>
- <string>carddavd-stats.sock</string>
-
<key>ControlSocket</key>
<string>carddavd.sock</string>
@@ -113,10 +101,6 @@
<key>ConfigRoot</key>
<string>/etc/carddavd</string>
- <!-- Log root -->
- <key>LogRoot</key>
- <string>/var/log/carddavd</string>
-
<!-- Run root -->
<key>RunRoot</key>
<string>/var/run</string>
@@ -133,7 +117,12 @@
-->
</dict>
- <!-- User quota (in bytes) -->
+
+ <!--
+ Quotas and limits
+ -->
+
+ <!-- User quota (in bytes) [0 = no quota] -->
<key>UserQuota</key>
<integer>104857600</integer><!-- 100Mb -->
@@ -198,80 +187,8 @@
</dict>
</dict>
- <!--
- Augment service
- Augments for the directory service records to add calendar specific attributes.
-
- A variety of augment services are available for use.
- When using a partitioned server, a service that can be accessed from each host will be needed.
- -->
-
- <!-- XML File Augment Service -->
- <key>AugmentService</key>
- <dict>
- <key>type</key>
- <string>twistedcaldav.directory.augment.AugmentXMLDB</string>
-
- <key>params</key>
- <dict>
- <key>xmlFiles</key>
- <array>
- <string>augments.xml</string>
- </array>
- </dict>
- </dict>
-
- <!-- Sqlite Augment Service -->
<!--
- <key>AugmentService</key>
- <dict>
- <key>type</key>
- <string>twistedcaldav.directory.augment.AugmentSqliteDB</string>
-
- <key>params</key>
- <dict>
- <key>dbpath</key>
- <string>augments.sqlite</string>
- </dict>
- </dict>
- -->
-
- <!-- PostgreSQL Augment Service -->
- <!--
- <key>AugmentService</key>
- <dict>
- <key>type</key>
- <string>twistedcaldav.directory.augment.AugmentPostgreSQLDB</string>
-
- <key>params</key>
- <dict>
- <key>host</key>
- <string>localhost</string>
- <key>database</key>
- <string>augments</string>
- </dict>
- </dict>
- -->
-
- <!-- PostgreSQL ProxyDB Service -->
- <!--
- <key>ProxyDBService</key>
- <dict>
- <key>type</key>
- <string>twistedcaldav.directory.calendaruserproxy.ProxyPostgreSQLDB</string>
-
- <key>params</key>
- <dict>
- <key>host</key>
- <string>localhost</string>
- <key>database</key>
- <string>proxies</string>
- </dict>
- </dict>
- -->
-
- <!--
Special principals
These principals are granted special access and/or perform
@@ -290,10 +207,6 @@
<!-- <string>/principals/__uids__/983C8238-FB6B-4D92-9242-89C0A39E5F81/</string> -->
</array>
- <!-- Principals that can pose as other principals -->
- <key>SudoersFile</key>
- <string>sudoers.plist</string>
-
<!-- Create "proxy access" principals -->
<key>EnableProxyPrincipals</key>
<true/>
@@ -368,6 +281,10 @@
Logging
-->
+ <!-- Log root -->
+ <key>LogRoot</key>
+ <string>/var/log/carddavd</string>
+
<!-- Apache-style access log -->
<key>AccessLogFile</key>
<string>access.log</string>
@@ -439,7 +356,6 @@
</dict>
</dict>
-
<!--
Notifications
-->
@@ -450,6 +366,10 @@
<key>CoalesceSeconds</key>
<integer>3</integer>
+ <!-- Client service port different from caldav -->
+ <key>InternalNotificationPort</key>
+ <integer>62311</integer>
+
<key>Services</key>
<dict>
<key>XMPPNotifier</key>
@@ -568,7 +488,7 @@
<key>FreeBusyURL</key>
<dict>
<key>Enabled</key>
- <true/>
+ <false/>
<key>TimePeriod</key>
<integer>14</integer>
<key>AnonymousAccess</key>
@@ -582,15 +502,15 @@
<!-- Calendar Drop Box -->
<key>EnableDropBox</key>
- <true/>
+ <false/>
<!-- Private Events -->
<key>EnablePrivateEvents</key>
- <true/>
+ <false/>
<!-- Timezone Service -->
<key>EnableTimezoneService</key>
- <true/>
+ <false/>
<!--
@@ -607,6 +527,9 @@
<key>DirectoryAddressBook</key>
<dict>
+ <key>Enabled</key>
+ <true/>
+
<key>type</key>
<string>twistedcaldav.directory.opendirectorybacker.OpenDirectoryBackingService</string>
@@ -711,13 +634,6 @@
<!-- allow unauthenticated users to access the directory address book -->
<key>AnonymousDirectoryAddressBookAccess</key>
<false/>
-
- <!-- enable search address book in user's home -->
- <key>EnableSearchAddressBook</key>
- <false/>
-
- <!-- enable find share report -->
- <key>EnableFindSharedReport</key>
- <false/>
+
</dict>
</plist>
Modified: CalendarServer/trunk/conf/carddavd-test.plist
===================================================================
--- CalendarServer/trunk/conf/carddavd-test.plist 2010-04-12 16:27:16 UTC (rev 5468)
+++ CalendarServer/trunk/conf/carddavd-test.plist 2010-04-12 20:22:32 UTC (rev 5469)
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2006-2009 Apple Inc. All rights reserved.
+ Copyright (c) 2006-2010 Apple Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
limitations under the License.
-->
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
@@ -34,6 +34,9 @@
<key>ServerHostName</key>
<string></string> <!-- The hostname clients use when connecting -->
+ <key>EnableCalDAV</key>
+ <false/>
+
<key>EnableCardDAV</key>
<true/>
@@ -46,10 +49,11 @@
<key>SSLPort</key>
<integer>8843</integer>
- <!-- Redirect non-SSL ports to an SSL port -->
+ <!-- Redirect non-SSL ports to an SSL port (if configured for SSL) -->
<key>RedirectHTTPToHTTPS</key>
<false/>
+
<!--
Network address configuration information
@@ -75,13 +79,14 @@
<!--
Data Store
-->
+
<!-- Server root -->
<key>ServerRoot</key>
- <string>data</string>
+ <string>./data</string>
<!-- Data root -->
<key>DataRoot</key>
- <string>Data/</string>
+ <string>Data</string>
<!-- Document root -->
<key>DocumentRoot</key>
@@ -91,13 +96,9 @@
<key>ConfigRoot</key>
<string>./conf</string>
- <!-- Log root -->
- <key>LogRoot</key>
- <string>Logs</string>
-
<!-- Run root -->
<key>RunRoot</key>
- <string>Run</string>
+ <string>Logs</string>
<!-- Child aliases -->
<key>Aliases</key>
@@ -111,7 +112,12 @@
-->
</dict>
- <!-- User quota (in bytes) -->
+
+ <!--
+ Quotas and limits
+ -->
+
+ <!-- User quota (in bytes) [0 = no quota] -->
<key>UserQuota</key>
<integer>104857600</integer><!-- 100Mb -->
@@ -129,12 +135,6 @@
<key>MaxInstancesForRRULE</key>
<integer>400</integer>
- <!-- Disable resource service. -->
- <key>ResourceService</key>
- <dict>
- <key>Enabled</key>
- <false/>
- </dict>
<!--
Directory service
@@ -144,6 +144,7 @@
A variety of directory services are available for use.
-->
+
<!-- XML File Directory Service -->
<key>DirectoryService</key>
<dict>
@@ -174,15 +175,21 @@
</dict>
-->
- <!--
- Augment service
+ <!-- Resource and Location Service -->
+ <key>ResourceService</key>
+ <dict>
+ <key>Enabled</key>
+ <false/>
+ <key>type</key>
+ <string>twistedcaldav.directory.xmlfile.XMLDirectoryService</string>
+
+ <key>params</key>
+ <dict>
+ <key>xmlFile</key>
+ <string>./conf/auth/resources-test.xml</string>
+ </dict>
+ </dict>
- Augments for the directory service records to add calendar specific attributes.
-
- A variety of augment services are available for use.
- When using a partitioned server, a service that can be accessed from each host will be needed.
- -->
-
<!-- XML File Augment Service -->
<key>AugmentService</key>
<dict>
@@ -197,7 +204,7 @@
</array>
</dict>
</dict>
-
+
<!-- Sqlite Augment Service -->
<!--
<key>AugmentService</key>
@@ -208,7 +215,7 @@
<key>params</key>
<dict>
<key>dbpath</key>
- <string>/etc/carddavd/augments.sqlite</string>
+ <string>./conf/auth/augments.sqlite</string>
</dict>
</dict>
-->
@@ -260,9 +267,10 @@
</dict>
-->
- <key>ProxyLoadFromFile</key>
+ <key>ProxyLoadFromFile</key>
<string>./conf/auth/proxies-test.xml</string>
+
<!--
Special principals
@@ -284,7 +292,7 @@
<!-- Principals that can pose as other principals -->
<key>SudoersFile</key>
- <string>./conf/sudoers.plist</string>
+ <string>sudoers.plist</string>
<!-- Create "proxy access" principals -->
<key>EnableProxyPrincipals</key>
@@ -343,7 +351,7 @@
<key>Kerberos</key>
<dict>
<key>Enabled</key>
- <false/>
+ <true/>
<key>ServicePrincipal</key>
<string></string>
</dict>
@@ -370,13 +378,15 @@
Logging
-->
+ <!-- Log root -->
+ <key>LogRoot</key>
+ <string>Logs</string>
+
<!-- Apache-style access log -->
<key>AccessLogFile</key>
<string>access.log</string>
<key>RotateAccessLog</key>
<false/>
- <key>MoreAccessLogData</key>
- <true/>
<!-- Server activity log -->
<key>ErrorLogFile</key>
@@ -428,6 +438,7 @@
<key>HTTP</key>
<false/>
</dict>
+
<!-- Enable accounting for specific principals -->
<key>AccountingPrincipals</key>
<array>
@@ -486,7 +497,7 @@
<string>localhost</string>
<key>InternalNotificationPort</key>
- <integer>62309</integer>
+ <integer>62311</integer>
<key>Services</key>
<dict>
@@ -587,7 +598,7 @@
<array>
</array>
<key>Servers</key>
- <string>./conf/servertoserver-test.xml</string>
+ <string>servertoserver-test.xml</string>
</dict>
<!-- iMIP protocol options -->
@@ -637,16 +648,16 @@
</array>
</dict>
- <!-- General options for scheduling -->
- <key>Options</key>
- <dict>
+ <!-- General options for scheduling -->
+ <key>Options</key>
+ <dict>
<key>AllowGroupAsOrganizer</key>
<false/>
<key>AllowLocationAsOrganizer</key>
<false/>
<key>AllowResourceAsOrganizer</key>
<false/>
- </dict>
+ </dict>
</dict>
@@ -658,7 +669,7 @@
<key>FreeBusyURL</key>
<dict>
<key>Enabled</key>
- <true/>
+ <false/>
<key>TimePeriod</key>
<integer>14</integer>
<key>AnonymousAccess</key>
@@ -672,16 +683,36 @@
<!-- Calendar Drop Box -->
<key>EnableDropBox</key>
- <true/>
+ <false/>
<!-- Private Events -->
<key>EnablePrivateEvents</key>
- <true/>
+ <false/>
<!-- Timezone Service -->
<key>EnableTimezoneService</key>
- <true/>
+ <false/>
+ <!-- Shared Calendars & Address Books -->
+ <key>Sharing</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ <key>AllowExternalUsers</key>
+ <false/>
+ <key>Calendars</key>
+ <dict>
+ <key>Enabled</key>
+ <false/>
+ <key>AllowScheduling</key>
+ <false/>
+ </dict>
+ <key>AddressBooks</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ </dict>
+ </dict>
<!--
Miscellaneous items
@@ -703,8 +734,7 @@
<key>HTTPRetryAfter</key>
<integer>180</integer>
- <!-- A unix socket used for communication between the child and master processes.
- An empty value tells the server to use a tcp socket instead. -->
+ <!-- For child-master IPC. [empty = use tcp] -->
<key>ControlSocket</key>
<string>carddavd.sock</string>
@@ -755,8 +785,12 @@
<key>DirectoryAddressBook</key>
<dict>
+ <key>Enabled</key>
+ <true/>
+
<key>type</key>
<string>twistedcaldav.directory.xmlfile.XMLDirectoryService</string>
+
<key>params</key>
<dict>
<key>xmlFile</key>
@@ -767,18 +801,6 @@
<!-- allow unauthenticated users to access the directory address book -->
<key>AnonymousDirectoryAddressBookAccess</key>
<false/>
-
- <!-- enable search address book in user's home -->
- <key>EnableSearchAddressBook</key>
- <true/>
-
- <!-- enable searchall address book in user's home -->
- <key>EnableSearchAllAddressBook</key>
- <true/>
-
- <!-- enable find share report -->
- <key>EnableFindSharedReport</key>
- <true/>
- </dict>
+ </dict>
</plist>
Modified: CalendarServer/trunk/twistedcaldav/directory/addressbook.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/addressbook.py 2010-04-12 16:27:16 UTC (rev 5468)
+++ CalendarServer/trunk/twistedcaldav/directory/addressbook.py 2010-04-12 20:22:32 UTC (rev 5469)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2006-2009 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2010 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -27,23 +27,24 @@
"DirectoryAddressBookHomeResource",
]
-from twisted.internet.defer import succeed
+from twext.python.log import Logger
from twext.web2 import responsecode
from twext.web2.dav import davxml
-from twext.web2.http import HTTPError
+from twext.web2.dav.resource import TwistedACLInheritable
from twext.web2.dav.util import joinURL
-from twext.web2.dav.resource import TwistedACLInheritable, TwistedQuotaRootProperty
+from twext.web2.http import HTTPError
+from twisted.internet.defer import succeed
+
from twistedcaldav.config import config
-from twistedcaldav.extensions import ReadOnlyResourceMixIn, DAVResource
-from twistedcaldav.resource import CalDAVResource, SearchAddressBookResource, SearchAllAddressBookResource, CalDAVComplianceMixIn
from twistedcaldav.directory.idirectory import IDirectoryService
from twistedcaldav.directory.resource import AutoProvisioningResourceMixIn
+from twistedcaldav.extensions import ReadOnlyResourceMixIn, DAVResource
+from twistedcaldav.notifications import NotificationCollectionResource
+from twistedcaldav.resource import CalDAVResource, CalDAVComplianceMixIn
-from twistedcaldav.directory.directory import DirectoryService
+log = Logger()
-from twistedcaldav.report_addressbook_findshared import getReadWriteSharedAddressBookGroups, getReadOnlySharedAddressBookGroups, getWritersGroupForSharedAddressBookGroup
-
# Use __underbars__ convention to avoid conflicts with directory resource types.
uidsResourceName = "__uids__"
@@ -57,11 +58,7 @@
def defaultAccessControlList(self):
return config.ProvisioningResourceACL
- def accessControlList(self, request, inheritance=True, expanding=False, inherited_aces=None):
- # Permissions here are fixed, and are not subject to inherritance rules, etc.
- return succeed(self.defaultAccessControlList())
-
class DirectoryAddressBookHomeProvisioningResource (DirectoryAddressBookProvisioningResource):
"""
Resource which provisions address book home collections as needed.
@@ -178,6 +175,9 @@
# Not a listable collection
raise HTTPError(responsecode.FORBIDDEN)
+ def createSimilarFile(self, path):
+ raise HTTPError(responsecode.NOT_FOUND)
+
##
# DAV
##
@@ -185,9 +185,6 @@
def isCollection(self):
return True
- def http_COPY(self, request):
- return responsecode.FORBIDDEN
-
##
# ACL
##
@@ -263,40 +260,50 @@
self.record = record
self.parent = parent
-
- # Cache children which must be of a specific type
+
childlist = ()
- if config.EnableSearchAddressBook and config.DirectoryAddressBook:
- childlist += (("search" , SearchAddressBookResource ), )
- if config.EnableSearchAllAddressBook:
- childlist += (("searchall" , SearchAllAddressBookResource ),)
-
+ if config.Sharing.Enabled and config.Sharing.Calendars.Enabled:
+ childlist += (
+ ("notification", NotificationCollectionResource),
+ )
for name, cls in childlist:
child = self.provisionChild(name)
- assert isinstance(child, cls), "Child %r not a %s: %r" % (name, cls.__name__, child)
+ assert isinstance(child, cls), "Child %r is not a %s: %r" % (name, cls.__name__, child)
self.putChild(name, child)
-
def provisionDefaultAddressBooks(self):
- self.provision()
- childName = "addressbook"
- child = self.provisionChild(childName)
- assert isinstance(child, CalDAVResource), "Child %r is not a %s: %r" % (childName, CalDAVResource.__name__, child) #@UndefinedVariable
+ # Disable notifications during provisioning
+ if hasattr(self, "clientNotifier"):
+ self.clientNotifier.disableNotify()
- return child.createAddressBookCollection()
+ try:
+ self.provision()
+
+ childName = "addressbook"
+ child = self.provisionChild(childName)
+ assert isinstance(child, CalDAVResource), "Child %r is not a %s: %r" % (childName, CalDAVResource.__name__, child) #@UndefinedVariable
+ d = child.createAddressBookCollection()
+ except:
+ # We want to make sure to re-enable notifications, so do so
+ # if there is an immediate exception above, or via errback, below
+ if hasattr(self, "clientNotifier"):
+ self.clientNotifier.enableNotify(None)
+ raise
+
+ # Re-enable notifications
+ if hasattr(self, "clientNotifier"):
+ d.addCallback(self.clientNotifier.enableNotify)
+ d.addErrback(self.clientNotifier.enableNotify)
+
+ return d
+
def provisionChild(self, name):
raise NotImplementedError("Subclass must implement provisionChild()")
def url(self):
- return joinURL(self.parent.url(), self.record.guid)
- ##
- ## While the underlying primary location is GUID-based, we want
- ## the canonical user-facing location to be recordType &
- ## shortName-based, because that's friendlier.
- ##
- #return joinURL(self.parent.parent.getChild(self.record.recordType).url(), self.record.shortName)
+ return joinURL(self.parent.url(), self.record.uid, "/")
def canonicalURL(self, request):
return succeed(self.url())
@@ -307,6 +314,9 @@
def isCollection(self):
return True
+ def http_COPY(self, request):
+ return responsecode.FORBIDDEN
+
##
# ACL
##
@@ -314,108 +324,25 @@
def owner(self, request):
return succeed(davxml.HRef(self.principalForRecord().principalURL()))
- def _determineGroupAccessMode(self):
- """
- Determines whether this record (assumed to be a group) is provisioned in the list of read-write address books or read-only address books
- Returns:
- "ReadWrite", "ReadOnly" or None
- """
-
- members = getReadWriteSharedAddressBookGroups(self.record.service) # list of members of the "ab_readwrite" group
- if self.record in members: # membership must be explicit in the "ab_readwrite" group - no membership expansion is done
- return "ReadWrite"
-
- members = getReadOnlySharedAddressBookGroups(self.record.service) # list of members of the "ab_readonly" group
- if self.record in members: # membership must be explicit in the "ab_readonly" group - no membership expansion is done
- return "ReadOnly"
-
- return None
-
- def _getWritersURL(self):
- """
- Looks for a "-writers" group, and if found, extract the principal URL to it
- """
-
- writerRecord = getWritersGroupForSharedAddressBookGroup(self.record)
- if writerRecord == None:
- return None
-
-
- # TO-DO: Need better way to build the principal URL to the "-writers" group
- #principalURL = "/principals/__uids__/%s/" % writerRecord.guid
-
- principalURL = None
- for principalCollection in self.principalCollections(): # based on principalForCalendarUserAddress in resource.CalDAVResource
- groups = principalCollection.getChild(DirectoryService.recordType_groups) # get only the "groups" collection within the parent collection
- if groups:
- p = groups.principalForRecord(writerRecord)
- if p is not None:
- principalURL = p.principalURL()
- break
-
- return principalURL
-
def ownerPrincipal(self, request):
return succeed(self.principalForRecord())
+ def resourceOwnerPrincipal(self, request):
+ return succeed(self.principalForRecord())
+
def defaultAccessControlList(self):
myPrincipal = self.principalForRecord()
-
- if self.record.recordType != DirectoryService.recordType_groups:
- # Original ACE logic
- aces = (
- # DAV:read access for authenticated users.
- davxml.ACE(
- davxml.Principal(davxml.Authenticated()),
- davxml.Grant(
- davxml.Privilege(davxml.Read()),
- davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
- ),
- ),
- # Inheritable DAV:all access for the resource's associated principal.
- davxml.ACE(
- davxml.Principal(davxml.HRef(myPrincipal.principalURL())),
- davxml.Grant(davxml.Privilege(davxml.All())),
- davxml.Protected(),
- TwistedACLInheritable(),
- ),
- )
- else:
- # Determine access for this group (members are read-write or members are read-only)
- accMode = self._determineGroupAccessMode()
-
- aces = ()
-
- if accMode == "ReadWrite":
- aces += (davxml.ACE(
- davxml.Principal(davxml.HRef(myPrincipal.principalURL())),
- davxml.Grant(davxml.Privilege(davxml.All())),
- davxml.Protected(),
- TwistedACLInheritable(),
- ), )
- elif accMode == "ReadOnly":
- aces += (davxml.ACE(
- davxml.Principal(davxml.HRef(myPrincipal.principalURL())),
- davxml.Grant(
- davxml.Privilege(davxml.Read()),
- davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
- ),
- davxml.Protected(),
- TwistedACLInheritable(),
- ), )
-
- # Look for a "-writers" group and add those members with read-write access
- writerURL = self._getWritersURL()
- if writerURL:
- aces += (davxml.ACE(
- davxml.Principal(davxml.HRef(writerURL)),
- davxml.Grant(davxml.Privilege(davxml.All())),
- davxml.Protected(),
- TwistedACLInheritable(),
- ), )
- else:
- pass
+ aces = (
+ # Inheritable DAV:all access for the resource's associated principal.
+ davxml.ACE(
+ davxml.Principal(davxml.HRef(myPrincipal.principalURL())),
+ davxml.Grant(davxml.Privilege(davxml.All())),
+ davxml.Protected(),
+ TwistedACLInheritable(),
+ ),
+ )
+
# Give read access to config.ReadPrincipals
aces += config.ReadACEs
@@ -442,14 +369,11 @@
"""
@return: a C{True} if this resource has quota root, C{False} otherwise.
"""
- return self.hasDeadProperty(TwistedQuotaRootProperty) or config.UserQuota > 0
+ return config.UserQuota != 0
def quotaRoot(self, request):
"""
@return: a C{int} containing the maximum allowed bytes if this collection
is quota-controlled, or C{None} if not quota controlled.
"""
- if self.hasDeadProperty(TwistedQuotaRootProperty):
- return int(str(self.readDeadProperty(TwistedQuotaRootProperty)))
- else:
- return config.UserQuota if config.UserQuota > 0 else None
+ return config.UserQuota if config.UserQuota != 0 else None
Modified: CalendarServer/trunk/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/principal.py 2010-04-12 16:27:16 UTC (rev 5468)
+++ CalendarServer/trunk/twistedcaldav/directory/principal.py 2010-04-12 20:22:32 UTC (rev 5469)
@@ -48,8 +48,6 @@
from twext.web2.dav.util import joinURL
from twext.web2.dav.noneprops import NonePropertyStore
-from twistedcaldav import carddavxml
-
from twext.python.log import Logger
from twistedcaldav.authkerb import NegotiateCredentials
@@ -915,7 +913,7 @@
return None
def addressBookHomeURLs(self):
- home = self._addressBookHome()
+ home = self.addressBookHome()
if home is None:
return ()
else:
@@ -945,7 +943,7 @@
else:
return None
- def _addressBookHome(self):
+ def addressBookHome(self):
# FIXME: self.record.service.addressBookHomesCollection smells like a hack
# See AddressBookHomeProvisioningFile.__init__()
service = self.record.service
@@ -954,13 +952,6 @@
else:
return None
- def supportedReports(self): # Method added for AddressBook find-shared report support
- result = super(DirectoryCalendarPrincipalResource, self).supportedReports()
- if config.EnableCardDAV and config.EnableFindSharedReport:
- result.append(davxml.Report(carddavxml.AddressBookFindShared(),))
- return result
-
-
##
# Static
##
Modified: CalendarServer/trunk/twistedcaldav/directorybackedaddressbook.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directorybackedaddressbook.py 2010-04-12 16:27:16 UTC (rev 5468)
+++ CalendarServer/trunk/twistedcaldav/directorybackedaddressbook.py 2010-04-12 20:22:32 UTC (rev 5469)
@@ -56,13 +56,13 @@
def provisionDirectory(self):
if self.directory is None:
- directoryClass = namedClass(config.DirectoryAddressBook["type"])
+ directoryClass = namedClass(config.DirectoryAddressBook.type)
log.info("Configuring: %s:%r"
- % (config.DirectoryAddressBook["type"], config.DirectoryAddressBook["params"]))
+ % (config.DirectoryAddressBook.type, config.DirectoryAddressBook.params))
#add self as "directoryBackedAddressBook" parameter
- params = config.DirectoryAddressBook["params"].copy()
+ params = config.DirectoryAddressBook.params.copy()
params["directoryBackedAddressBook"] = self
self.directory = directoryClass(params)
Deleted: CalendarServer/trunk/twistedcaldav/report_addressbook_findshared.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/report_addressbook_findshared.py 2010-04-12 16:27:16 UTC (rev 5468)
+++ CalendarServer/trunk/twistedcaldav/report_addressbook_findshared.py 2010-04-12 20:22:32 UTC (rev 5469)
@@ -1,485 +0,0 @@
-##
-# Copyright (c) 2006-2009 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-"""
-AddressBook Server "Find Shared" Address Books report
-Based on addressbook-query report in report_addressbook_query.py
-"""
-
-__all__ = [
- "http___addressbookserver_org_ns__addressbook_findshared",
- "getReadWriteSharedAddressBookGroups",
- "getReadOnlySharedAddressBookGroups",
- "getWritersGroupForSharedAddressBookGroup",
-]
-
-from twext.python.plistlib import readPlist
-#import traceback
-
-import opendirectory
-import dsattributes
-
-from twisted.internet.defer import inlineCallbacks, returnValue
-
-from twext.python.log import Logger
-from twext.python.filepath import CachingFilePath as FilePath
-from twext.web2 import responsecode
-from twext.web2.dav import davxml
-from twext.web2.dav.http import MultiStatusResponse
-from twext.web2.dav.util import joinURL
-from twext.web2.http import HTTPError, StatusResponse
-
-from twistedcaldav import customxml
-from twistedcaldav.carddavxml import addressbookserver_namespace, carddav_namespace
-from twistedcaldav.config import config
-from twistedcaldav.stdconfig import DEFAULT_CONFIG_FILE as defaultConfigFile
-from twistedcaldav.customxml import calendarserver_namespace
-from twistedcaldav.directory.appleopendirectory import OpenDirectoryRecord
-from twistedcaldav.resource import isAddressBookCollectionResource
-
-from twistedcaldav.directory.directory import DirectoryService
-
-log = Logger()
-
-gLogLocal = 0 # Poor mans logging control for this file only
-
-
-class AddressBookAccessMode (davxml.WebDAVTextElement):
- """
- Access Mode XML element for Address Book "Find Shared" report
- """
- name = "current-addressbook-access-mode"
- namespace = addressbookserver_namespace
- protected = True
-
-
-class AddressBookGroupAddressBookInfo (davxml.WebDAVElement):
- name = "addressbook-info"
- namespace = addressbookserver_namespace
- protected = True
-
- allowed_children = { (davxml.dav_namespace, "href"): (0, None),
- (calendarserver_namespace, "getctag"): (0, None),
- (davxml.dav_namespace, "displayname"): (0, None),
- }
-
-class AddressBookGroupAddressBooks (davxml.WebDAVElement):
- """
- The list (hrefs) of address books contained within a group principal
- """
- # Code based on CalendarHomeSet()
-
- name = "current-addressbooks-set"
- namespace = addressbookserver_namespace
- protected = True
-
- allowed_children = { (AddressBookGroupAddressBookInfo.namespace, AddressBookGroupAddressBookInfo.name): (0, None),
- }
-
- _sharedABFileInfo = None
- _sharedABDict = None
-
-
-def getABSharedFileAsDictionary():
-
- try:
- # get file path
- sharedABFilePath = "SharedAddressBooks.plist"
- if config._configFile:
- configFilePath = config._configFile
- else:
- configFilePath = defaultConfigFile
- sharedABFilePath = configFilePath[:configFilePath.rfind("/")+1] + sharedABFilePath
-
- sharedABFile = FilePath(sharedABFilePath)
- sharedABFile.restat()
- fileInfo = (sharedABFile.getmtime(), sharedABFile.getsize())
- if fileInfo != AddressBookGroupAddressBooks._sharedABFileInfo:
- AddressBookGroupAddressBooks._sharedABFileInfo = fileInfo
- AddressBookGroupAddressBooks._sharedABDict = readPlist(sharedABFilePath)
-
-
- except Exception, e:
- log.msg("getABSharedFileAsDictionary(): could not read or decode %s: %r" % (sharedABFilePath, e,))
- AddressBookGroupAddressBooks._sharedABDict = None
-
- return AddressBookGroupAddressBooks._sharedABDict
-
-
-def reloadRecordFromDS(record):
- # Cause the record to be re-read from DS by forcing a cache reload on it
- if record == None:
- return
-
- log.debug("(Shared Address Book) Reloading record from DS: %s (%s)" % (record.shortNames[0], record.guid));
- guid = record.guid
- service = record.service
- service.reloadCache(record.recordType, lookup=["guid", guid], logIt=False)
- record = service.recordWithUID(guid) # reacquire record after cache reload
- return record
-
-
-def reloadGroupMembersFromDS(groupRecord):
- # This routine is mainly for purposes of adding the "-writers" group to an ACL. If the -writers group contains any nested groups, then
- # make sure that the memberships of those nested groups is up to date
- # Assumes that groupRecord itself is already current
- if groupRecord == None:
- return
-
- log.debug("(Shared Address Book) Reloading members from DS for record: %s (%s)" % (groupRecord.shortNames[0], groupRecord.guid));
-
- visitedGroups = []
- for m in groupRecord.members():
- if m.recordType == DirectoryService.recordType_groups: # only care about refreshing group members - I hope
- if m.guid in visitedGroups:
- continue
- visitedGroups.append(m.guid)
- m = reloadRecordFromDS(m) # refresh the member group
- reloadGroupMembersFromDS(m) # and any of it's children
-
- log.debug("(Shared Address Book) Completed reload of members from DS for record: %s (%s)" % (groupRecord.shortNames[0], groupRecord.guid));
-
-
-def getSharedAddressBookSpecialGroup(service, wantGroupName):
- # Used to find the "ab_readwrite", "ab_readonly" or "xx-writers" groups in the /Local/ node
-
- # Read these directory from DS because DSLocal recrods are not in principals
-
- # We now intentionally force the read to go to DS to make sure we don't have stale data (esp. between processes)
- log.debug("(Shared Address Book) Querying DS for provisioning group: %s" % wantGroupName);
-
- def _uniqueTupleFromAttribute(attribute):
- if attribute:
- if isinstance(attribute, str):
- return (attribute,)
- else:
- s = set()
- return tuple([(s.add(x), x)[1] for x in attribute if x not in s])
- else:
- return ()
-
- record = None
- attrs = [
- dsattributes.kDS1AttrGeneratedUID,
- dsattributes.kDSNAttrRecordName,
- dsattributes.kDS1AttrDistinguishedName,
- dsattributes.kDSNAttrGroupMembers,
- dsattributes.kDSNAttrNestedGroups,
- dsattributes.kDSNAttrMetaNodeLocation,
- ]
-
- try:
- localNodeDirectory = opendirectory.odInit("/Local/Default")
-
- log.debug(
- "(Shared Address Book) opendirectory.queryRecordsWithAttribute_list(%r,%r,%r,%r,%r,%r,%r)" % (
- "/Local/Default",
- dsattributes.kDSNAttrRecordName,
- wantGroupName,
- dsattributes.eDSExact,
- False,
- dsattributes.kDSStdRecordTypeGroups,
- attrs,
- )
- )
- results = opendirectory.queryRecordsWithAttribute_list(
- localNodeDirectory,
- dsattributes.kDSNAttrRecordName,
- wantGroupName,
- dsattributes.eDSExact,
- False,
- dsattributes.kDSStdRecordTypeGroups,
- attrs,
- )
-
- log.debug("(Shared Address Book) results= %r" % (results,))
-
- if len(results) > 0:
-
- recordShortName, value = results[0] #@UnusedVariable
-
- memberGUIDs = value.get(dsattributes.kDSNAttrGroupMembers)
- if memberGUIDs is None:
- memberGUIDs = ()
- elif type(memberGUIDs) is str:
- memberGUIDs = (memberGUIDs,)
- nestedGUIDs = value.get(dsattributes.kDSNAttrNestedGroups)
- if nestedGUIDs:
- if type(nestedGUIDs) is str:
- nestedGUIDs = (nestedGUIDs,)
- memberGUIDs += tuple(nestedGUIDs)
-
- record = OpenDirectoryRecord(
- service = service,
- recordType = DirectoryService.recordType_groups,
- guid = value.get(dsattributes.kDS1AttrGeneratedUID),
- nodeName = value.get(dsattributes.kDSNAttrMetaNodeLocation),
- shortNames = _uniqueTupleFromAttribute(value.get(dsattributes.kDSNAttrRecordName)),
- authIDs = (),
- fullName = value.get(dsattributes.kDS1AttrDistinguishedName),
- firstName = None,
- lastName = None,
- emailAddresses = (),
- calendarUserAddresses = (),
- autoSchedule = False,
- enabledForCalendaring = False,
- memberGUIDs = memberGUIDs,
- proxyGUIDs = (),
- readOnlyProxyGUIDs = (),
- )
-
- except opendirectory.ODError, e:
- #traceback.print_exc()
- log.err("Open Directory (node=%s) error: %s" % ("/Local/Default", str(e,)))
- except Exception, e:
- #traceback.print_exc()
- log.err("Exception while qerying DS for provisioning group: %s: r" % (wantGroupName, e,))
-
- log.debug("(Shared Address Book) record= %r" % (record,))
- return record
-
-
-
-def getSharedAddressBookGroups(service, masterGroupName):
- record = getSharedAddressBookSpecialGroup(service, masterGroupName)
- if record == None:
- return [] # don't return None since callers expect to be able to iterate the results
-
- return record.members()
-
-
-def getReadWriteSharedAddressBookGroups(service):
- return getSharedAddressBookGroups(service, "com.apple.addressbookserver.sharedABs.readwrite")
-
-
-def getReadOnlySharedAddressBookGroups(service):
- return getSharedAddressBookGroups(service, "com.apple.addressbookserver.sharedABs.readonly")
-
-
-def getWritersGroupForSharedAddressBookGroup(groupRecord):
- # Find the "-writers" record object for a given group record
- # Do not just call:
- # writerRecord = self.record.service.recordWithShortName(DirectoryService.recordType_groups, writerRecName)
- # because that will cause the DS cache to fault looking for the record name if it doesn't exist
- writerRecName = "com.apple.addressbookserver.sharedABs.writers." + groupRecord.shortNames[0]
-
- writersRec = getSharedAddressBookSpecialGroup(groupRecord.service, writerRecName)
- reloadGroupMembersFromDS(writersRec) # Make sure all group memberships are up to date
-
- return writersRec
-
-
-def groupRecordContainsMember(aGroup, wantMember):
- # Does recursive search of aGroup's members, looking for wantMember
- # Caller is responsible for insuring that "aGroup" is current before calling this routine; we'll make sure to re-read any nested groups
-
- if aGroup == None or wantMember == None:
- return False
-
- visitedGroups = []
- for m in aGroup.members():
- isGroup = m.recordType == DirectoryService.recordType_groups
- if isGroup:
- if m.guid in visitedGroups:
- continue
- visitedGroups.append(m.guid)
-
- if m.guid == wantMember.guid:
- return True
-
- if isGroup:
- # Reread the nested group information to make sure it's membership is current
- m = reloadRecordFromDS(m)
- if groupRecordContainsMember(m, wantMember):
- return True
-
- return False
-
-
-def findPrincipalForRecord(rec, principalCollections):
- for pc in principalCollections:
- recs = pc.getChild(rec.recordType)
- if recs:
- p = recs.principalForRecord(rec)
- if p:
- return p
-
- return None
-
-
-def userIsAddressBookGroupWriter(userRecord, groupRecord):
- # Check to see if the user is a member of the "-writers" record (if one exists)
-
- # Now go after the actual -writer record and insure that one exists in the local node
- writerRecord = getWritersGroupForSharedAddressBookGroup(groupRecord)
- if not writerRecord:
- return False
-
- # Check to see if the user is a member of the "-writers" record
- return groupRecordContainsMember(writerRecord, userRecord) # RECURSIVE search!
-
-
-def filterGroupsForMember(groupList, wantMember):
- # Check to see which groups in "groupList" wantMember is a member of (recursively)
- # Will only return the top level groups from groupList, not the actual group that the user is a member of
-
- list = []
- for g in groupList:
- # "g" could conceivably be a user record but then g.members() will return [] so it shouldn't be necessary to preflight
- if groupRecordContainsMember(g, wantMember):
- list.append(g)
-
- return list
-
- at inlineCallbacks
-def http___addressbookserver_org_ns__addressbook_findshared(self, request, findshared):
- """
- Generate a findshared REPORT.
- """
-
- # Verify root element
- if findshared.qname() != (addressbookserver_namespace, "addressbook-findshared"):
- raise ValueError("addressbook-findshared expected as root element, not %s." % (findshared.sname(),))
-
- # Make sure target resource is of the right type
- uriResource = yield request.locateResource(request.uri)
- if uriResource == None:
- log.err("addressbook-findshared unable to convert request URI to resource: %s" % request.uri)
- raise HTTPError(StatusResponse(responsecode.NOT_FOUND, "Unable to convert request URI to resource: %s" % request.uri))
-
- if uriResource.record.recordType != DirectoryService.recordType_users:
- log.err("addressbook-findshared request URI is not a user principal: %s" % request.uri)
- raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, "Request URI is not a user principal: %s" % request.uri))
-
- #
- # Reacquire the user record from DS to make sure it's information is up-to-date
- #
- userRecord = uriResource.record
- userRecord = reloadRecordFromDS(userRecord)
- if userRecord == None:
- raise HTTPError(StatusResponse(responsecode.NOT_FOUND, "Unable to reload user record from DS cache: %s" % request.uri))
-
- uriResource = None # Invalidate since it contains a reference to a stale "record" instance
-
- #
- # Run the report
- #
- responses = []
-
-
- #
- # Get the master lists of Address Book-enabled groups (No group expansion necessary - each group must contain leaf groups that are enabled)
- #
- readOnlyGroups = getReadOnlySharedAddressBookGroups(userRecord.service) # wrap in tuple() if we're going to use more than once since this returns a generator
- readOnlyGroups = filterGroupsForMember(readOnlyGroups, userRecord) # keep only those groups that "user" is a member of (checking nested membership)
-
- readWriteGroups = getReadWriteSharedAddressBookGroups(userRecord.service)
- readWriteGroups = filterGroupsForMember(readWriteGroups, userRecord)
-
-
- #
- # Determine which of the groups have address books enabled and what the user's access is to them
- #
- processedGroups = []
- for memberList in (readWriteGroups, readOnlyGroups): # Make sure to process R/W group access before R/O access
- isReadWriteGroup = memberList == readWriteGroups
- for g in memberList:
- if g.guid in processedGroups: # Just in case we have multiple references to the same group, process only once
- continue
- processedGroups.append(g.guid)
-
- # Reload the group from DS to make sure it's information is up-to-date
- g = reloadRecordFromDS(g)
- if g == None: # group disappeared on cache reload
- continue
-
- mode = None
- if isReadWriteGroup:
- mode = "ReadWrite"
- else:
- mode = "ReadOnly"
- if userIsAddressBookGroupWriter(userRecord, g):
- mode = "ReadWrite"
-
- if mode == None:
- continue
-
- groupPrincipalURL = None
- groupPrincipal = findPrincipalForRecord(g, self.principalCollections())
- if groupPrincipal:
- groupPrincipalURL = groupPrincipal.principalURL()
-
-
- abHome = yield groupPrincipal.readProperty((carddav_namespace, "addressbook-home-set"), request)
-
- groupDisplayName = yield groupPrincipal.readProperty((davxml.dav_namespace, "displayname"), request)
-
- groupUUID = customxml.ResourceID(g.guid)
-
- abMode = AddressBookAccessMode(mode)
-
- abInfos = []
- for home in groupPrincipal.addressBookHomeURLs():
- homeResource = yield request.locateResource(home)
- for child in homeResource.listChildren():
- props = []
- childPath = joinURL(homeResource.url(), child)
- childResource = yield request.locateResource(childPath)
- if childResource and isAddressBookCollectionResource(childResource):
- childPath = childPath + "/" # Now that we know it's a directory, append the trailing slash
- props.append(davxml.HRef(childPath))
-
- cTag = None
- try:
- cTag = yield childResource.readProperty((calendarserver_namespace, "getctag"), request)
- except:
- cTag = None
-
- if cTag is not None:
- props.append(cTag)
-
- if str(child) == "addressbook":
- sharedABFileDictionary = getABSharedFileAsDictionary()
- if sharedABFileDictionary:
- sharedABDict = sharedABFileDictionary.get("SharedAddressBooks")
- if sharedABDict:
- thisGroupsDict = sharedABDict.get(g.guid)
- if thisGroupsDict:
- displayNameString = thisGroupsDict.get("AddressBookName")
- if displayNameString:
- displayName = davxml.DisplayName.fromString(displayNameString)
- props.append(displayName)
-
-
- thisInfo = AddressBookGroupAddressBookInfo(*props)
- abInfos.append(thisInfo)
-
- groupAddressBooksProp = AddressBookGroupAddressBooks(*abInfos)
- #groupAddressBooksProp = AddressBookGroupAddressBooks(*[davxml.HRef(url) for url in groupAddressBooks])
-
- xml_status = davxml.Status.fromResponseCode(responsecode.OK)
- xml_container = davxml.PropertyContainer(groupDisplayName, groupUUID, abHome, abMode, groupAddressBooksProp)
- xml_propstat = davxml.PropertyStatus(xml_container, xml_status)
-
- propstats = []
- propstats.append(xml_propstat)
-
- xml_resource = davxml.HRef.fromString(groupPrincipalURL)
- xml_response = davxml.PropertyStatusResponse(xml_resource, *propstats)
-
- responses.append(xml_response)
-
- returnValue(MultiStatusResponse(responses))
Modified: CalendarServer/trunk/twistedcaldav/resource.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/resource.py 2010-04-12 16:27:16 UTC (rev 5468)
+++ CalendarServer/trunk/twistedcaldav/resource.py 2010-04-12 20:22:32 UTC (rev 5469)
@@ -26,8 +26,6 @@
"isCalendarCollectionResource",
"isPseudoCalendarCollectionResource",
"isAddressBookCollectionResource",
- "SearchAddressBookResource",
- "SearchAllAddressBookResource",
]
import urllib
@@ -1278,64 +1276,6 @@
return None
-
-
-
-class SearchAddressBookResource (CalDAVResource):
- """
- Search collection resource.
- """
- def __init__(self, parent):
- """
- @param parent: the parent resource of this one.
- """
- assert parent is not None
-
- CalDAVResource.__init__(self, principalCollections=parent.principalCollections())
-
- self.parent = parent
-
- def resourceType(self, request):
- return succeed(davxml.ResourceType.searchaddressbook)
-
- def renderHTTP(self, request):
- return RedirectResponse(request.unparseURL(path="/directory/"))
-
-
-class SearchAllAddressBookResource (CalDAVResource):
- """
- Search collection resource.
- """
- def __init__(self, parent):
- """
- @param parent: the parent resource of this one.
- """
- assert parent is not None
-
- CalDAVResource.__init__(self, principalCollections=parent.principalCollections())
-
- self.parent = parent
-
- def resourceType(self, request):
- return succeed(davxml.ResourceType.searchalladdressbook)
-
- def renderHTTP(self, request):
-
- # if requested path ends with "searchall", redirect it for now, redirect to "addressbook"
- #
- # in future, should combine all accessible address books
-
- matchString = "/searchall"
- if request.path[-1] == "/":
- matchString += "/"
-
- if request.path.endswith( matchString ):
- return RedirectResponse(request.unparseURL(path=request.path[:-len(matchString)] + "/addressbook/"))
- else:
- return CalDAVResource.renderHTTP(self, request)
-
-
-
class AuthenticationWrapper(SuperAuthenticationWrapper):
""" AuthenticationWrapper implementation which allows overriding
Modified: CalendarServer/trunk/twistedcaldav/static.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/static.py 2010-04-12 16:27:16 UTC (rev 5468)
+++ CalendarServer/trunk/twistedcaldav/static.py 2010-04-12 20:22:32 UTC (rev 5469)
@@ -80,7 +80,7 @@
from twistedcaldav.ical import Property as iProperty
from twistedcaldav.index import Index, IndexSchedule, SyncTokenValidException
from twistedcaldav.resource import CalDAVResource, isCalendarCollectionResource, isPseudoCalendarCollectionResource
-from twistedcaldav.resource import isAddressBookCollectionResource, SearchAddressBookResource, SearchAllAddressBookResource
+from twistedcaldav.resource import isAddressBookCollectionResource
from twistedcaldav.schedule import ScheduleInboxResource, ScheduleOutboxResource, IScheduleInboxResource
from twistedcaldav.datafilters.privateevents import PrivateEventFilter
from twistedcaldav.dropbox import DropBoxHomeResource, DropBoxCollectionResource
@@ -1374,25 +1374,6 @@
DAVFile.__init__(self, path)
DirectoryAddressBookHomeProvisioningResource.__init__(self, directory, url)
- # create with permissions
- try:
- os.mkdir(path)
- os.chmod(path, 0750)
- if config.UserName and config.GroupName:
- import pwd
- import grp
- uid = pwd.getpwnam(config.UserName)[2]
- gid = grp.getgrnam(config.GroupName)[2]
- os.chown(path, uid, gid)
-
- log.msg("Created %s" % (path,))
-
- except (OSError,), e:
- # this is caused by multiprocessor race and is harmless
- if e.errno != errno.EEXIST:
- raise
-
-
def provisionChild(self, name):
if name == uidsResourceNameAddressBook:
return AddressBookHomeUIDProvisioningFile(self.fp.child(name).path, self)
@@ -1499,6 +1480,8 @@
def liveProperties(self):
return super(AddressBookHomeFile, self).liveProperties() + (
(customxml.calendarserver_namespace, "xmpp-uri"),
+ (customxml.calendarserver_namespace, "xmpp-heartbeat-uri"),
+ (customxml.calendarserver_namespace, "xmpp-server"),
)
def __init__(self, path, parent, record):
@@ -1511,27 +1494,23 @@
def provisionChild(self, name):
- SearchAddressBookFileClass = None
- SearchAllAddressBookFileClass = None
- if config.EnableSearchAddressBook and config.DirectoryAddressBook:
- SearchAddressBookFileClass = SearchAddressBookFile
- if config.EnableSearchAllAddressBook:
- SearchAllAddressBookFileClass = SearchAllAddressBookFile
-
+ if config.Sharing.Enabled:
+ NotificationCollectionFileClass = NotificationCollectionFile
+ else:
+ NotificationCollectionFileClass = None
+
cls = {
- "search" : SearchAddressBookFileClass,
- "searchall" : SearchAllAddressBookFileClass,
+ "notification" : NotificationCollectionFileClass,
}.get(name, None)
if cls is not None:
child = cls(self.fp.child(name).path, self)
child.clientNotifier = self.clientNotifier
return child
-
return self.createSimilarFile(self.fp.child(name).path)
def createSimilarFile(self, path):
- if path == self.fp.path:
+ if self.comparePath(path):
return self
else:
similar = CalDAVFile(path, principalCollections=self.principalCollections())
@@ -1552,50 +1531,53 @@
else:
qname = property.qname()
+ def doneWaiting(result, propVal):
+ return propVal
+
if qname == (customxml.calendarserver_namespace, "xmpp-uri"):
pubSubConfiguration = getPubSubConfiguration(config)
if pubSubConfiguration['enabled']:
- return succeed(customxml.PubSubXMPPURIProperty(
- getPubSubXMPPURI(self.url(), pubSubConfiguration)))
+ if getattr(self, "clientNotifier", None) is not None:
+ url = self.url()
+ nodeName = getPubSubPath(url, pubSubConfiguration)
+ propVal = customxml.PubSubXMPPURIProperty(
+ getPubSubXMPPURI(url, pubSubConfiguration))
+ nodeCacher = getNodeCacher()
+ d = nodeCacher.waitForNode(self.clientNotifier, nodeName)
+ # In either case we're going to return the xmpp-uri value
+ d.addCallback(doneWaiting, propVal)
+ d.addErrback(doneWaiting, propVal)
+ return d
else:
return succeed(customxml.PubSubXMPPURIProperty())
- return super(AddressBookHomeFile, self).readProperty(property, request)
+ elif qname == (customxml.calendarserver_namespace, "xmpp-heartbeat-uri"):
+ pubSubConfiguration = getPubSubConfiguration(config)
+ if pubSubConfiguration['enabled']:
+ return succeed(
+ customxml.PubSubHeartbeatProperty(
+ customxml.PubSubHeartbeatURIProperty(
+ getPubSubHeartbeatURI(pubSubConfiguration)
+ ),
+ customxml.PubSubHeartbeatMinutesProperty(
+ str(pubSubConfiguration['heartrate'])
+ )
+ )
+ )
+ else:
+ return succeed(customxml.PubSubHeartbeatURIProperty())
+ elif qname == (customxml.calendarserver_namespace, "xmpp-server"):
+ pubSubConfiguration = getPubSubConfiguration(config)
+ if pubSubConfiguration['enabled']:
+ return succeed(customxml.PubSubXMPPServerProperty(
+ pubSubConfiguration['xmpp-server']))
+ else:
+ return succeed(customxml.PubSubXMPPServerProperty())
-class SearchAddressBookFile (SearchAddressBookResource, CalDAVFile):
- """
- Search collection resource.
- """
- def __init__(self, path, parent):
- SearchAddressBookResource.__init__(self, parent)
- CalDAVFile.__init__(self, path, principalCollections=parent.principalCollections())
- self.parent = parent
+ return super(AddressBookHomeFile, self).readProperty(property, request)
- def createSimilarFile(self, path):
- if path == self.fp.path:
- return self
- # FIXME: path here is similar too .../addressbooks/__uids__/us/er/user01/search/move2_1.vcf
- # so we should really redirect to /directory/move2_1.vcf or perhaps we shouldn't be here in the first place
- raise HTTPError(responsecode.NOT_FOUND)
-
-class SearchAllAddressBookFile (SearchAllAddressBookResource, CalDAVFile):
- """
- Search collection resource.
- """
- def __init__(self, path, parent):
- SearchAllAddressBookResource.__init__(self, parent)
- CalDAVFile.__init__(self, path, principalCollections=parent.principalCollections())
- self.parent = parent
-
- def createSimilarFile(self, path):
- if path == self.fp.path:
- return self
-
- # FIXME: see note above
- raise HTTPError(responsecode.NOT_FOUND)
-
class DirectoryBackedAddressBookFile (DirectoryBackedAddressBookResource, CalDAVFile):
"""
Directory-backed address book, supporting directory vcard search.
@@ -1750,11 +1732,3 @@
twistedcaldav.method.put.CalDAVFile = CalDAVFile
-#
-# Attach method to DirectoryCalendarPrincipalResource for "Find Shared Address Books" REPORT method
-#
-from twistedcaldav.directory.principal import DirectoryCalendarPrincipalResource
-from twistedcaldav import report_addressbook_findshared
-setattr(DirectoryCalendarPrincipalResource, "report_http___addressbookserver_org_ns__addressbook_findshared", report_addressbook_findshared.http___addressbookserver_org_ns__addressbook_findshared)
-
-
Modified: CalendarServer/trunk/twistedcaldav/stdconfig.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/stdconfig.py 2010-04-12 16:27:16 UTC (rev 5468)
+++ CalendarServer/trunk/twistedcaldav/stdconfig.py 2010-04-12 20:22:32 UTC (rev 5469)
@@ -152,19 +152,17 @@
"EnableCalDAV" : True, # Enable CalDAV service
"EnableCardDAV" : True, # Enable CardDAV service
- # XXX CardDAV
+ # CardDAV Features
"DirectoryAddressBook": {
- "type": "twistedcaldav.directory.opendirectorybacker.OpenDirectoryBackingService",
- "params": directoryAddressBookBackingServiceDefaultParams["twistedcaldav.directory.opendirectorybacker.OpenDirectoryBackingService"],
+ "Enabled": True,
+ "type": "twistedcaldav.directory.opendirectorybacker.OpenDirectoryBackingService",
+ "params": directoryAddressBookBackingServiceDefaultParams["twistedcaldav.directory.opendirectorybacker.OpenDirectoryBackingService"],
},
"AnonymousDirectoryAddressBookAccess": False, # Anonymous users may access directory address book
- "EnableSearchAddressBook": False,
- "EnableSearchAllAddressBook":False,
"MaxAddressBookQueryResults":1000,
"MaxAddressBookMultigetHrefs":5000,
- "EnableFindSharedReport":False,
# /XXX CardDAV
#
@@ -683,17 +681,17 @@
#
dsType = items.get("DirectoryAddressBook", {}).get("type", None)
if dsType is None:
- dsType = configDict["DirectoryAddressBook"]["type"]
+ dsType = configDict.DirectoryAddressBook.type
else:
- if dsType == configDict["DirectoryAddressBook"]["type"]:
- oldParams = configDict["DirectoryAddressBook"]["params"]
+ if dsType == configDict.DirectoryAddressBook.type:
+ oldParams = configDict.DirectoryAddressBook.params
newParams = items["DirectoryAddressBook"].get("params", {})
_mergeData(oldParams, newParams)
else:
if dsType in directoryAddressBookBackingServiceDefaultParams:
- configDict["DirectoryAddressBook"]["params"] = copy.deepcopy(directoryAddressBookBackingServiceDefaultParams[dsType])
+ configDict.DirectoryAddressBook.params = copy.deepcopy(directoryAddressBookBackingServiceDefaultParams[dsType])
else:
- configDict["DirectoryAddressBook"]["params"] = {}
+ configDict.DirectoryAddressBook.params = {}
for param in items.get("DirectoryAddressBook", {}).get("params", {}):
if param not in directoryAddressBookBackingServiceDefaultParams[dsType]:
@@ -701,9 +699,9 @@
_mergeData(configDict, items)
- for param in tuple(configDict["DirectoryAddressBook"]["params"]):
- if param not in directoryAddressBookBackingServiceDefaultParams[configDict["DirectoryAddressBook"]["type"]]:
- del configDict["DirectoryAddressBook"]["params"][param]
+ for param in tuple(configDict.DirectoryAddressBook.params):
+ if param not in directoryAddressBookBackingServiceDefaultParams[configDict.DirectoryAddressBook.type]:
+ del configDict.DirectoryAddressBook.params[param]
def _postUpdateAugmentService(configDict):
if configDict.AugmentService.type in DEFAULT_AUGMENT_PARAMS:
Modified: CalendarServer/trunk/twistedcaldav/test/util.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/util.py 2010-04-12 16:27:16 UTC (rev 5468)
+++ CalendarServer/trunk/twistedcaldav/test/util.py 2010-04-12 20:22:32 UTC (rev 5469)
@@ -74,6 +74,8 @@
ClientFactory.allowTestCache = True
memcacher.Memcacher.allowTestCache = True
+ config.DirectoryAddressBook.Enabled = False
+
def createHierarchy(self, structure, root=None):
if root is None:
root = self.mktemp()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100412/4310f30f/attachment-0001.html>
More information about the calendarserver-changes
mailing list