[CalendarServer-changes] [5970] CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav
source_changes at macosforge.org
source_changes at macosforge.org
Tue Aug 3 13:44:19 PDT 2010
Revision: 5970
http://trac.macosforge.org/projects/calendarserver/changeset/5970
Author: cdaboo at apple.com
Date: 2010-08-03 13:44:19 -0700 (Tue, 03 Aug 2010)
Log Message:
-----------
Re-factor the home resource classes to have a more logic inheritance hierarchy and move common stuff
into a base class. Also get rid of auto provisioning mixin and do on-demand resource creation rather than
putChild in __init__.
Modified Paths:
--------------
CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/addressbook.py
CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/calendar.py
CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/resource.py
CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/extensions.py
CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/method/report_sync_collection.py
CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/resource.py
CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/schedule.py
CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/sharing.py
CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/storebridge.py
CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/test_multiget.py
CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/test_wrapping.py
CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/util.py
Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/addressbook.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/addressbook.py 2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/addressbook.py 2010-08-03 20:44:19 UTC (rev 5970)
@@ -20,7 +20,6 @@
__all__ = [
"uidsResourceName",
- #"DirectoryAddressBookProvisioningResource",
"DirectoryAddressBookHomeProvisioningResource",
"DirectoryAddressBookHomeTypeProvisioningResource",
"DirectoryAddressBookHomeUIDProvisioningResource",
@@ -29,21 +28,17 @@
from twext.python.log import Logger
from twext.web2 import responsecode
-from twext.web2.dav import davxml
-from twext.web2.dav.resource import TwistedACLInheritable
from twext.web2.dav.util import joinURL
from twext.web2.http import HTTPError
from twext.web2.http_headers import ETag, MimeType
-from twisted.internet.defer import succeed
-
from twistedcaldav.config import config
from twistedcaldav.directory.idirectory import IDirectoryService
+from twistedcaldav.directory.resource import DirectoryReverseProxyResource
from twistedcaldav.directory.util import transactionFromRequest
-from twistedcaldav.directory.resource import AutoProvisioningResourceMixIn,\
- DirectoryReverseProxyResource
from twistedcaldav.extensions import ReadOnlyResourceMixIn, DAVResource,\
DAVResourceWithChildrenMixin
+from twistedcaldav.resource import AddressBookHomeResource
from uuid import uuid4
@@ -61,7 +56,6 @@
)
class DirectoryAddressBookProvisioningResource (
- AutoProvisioningResourceMixIn,
ReadOnlyResourceMixIn,
CalDAVComplianceMixIn,
DAVResourceWithChildrenMixin,
@@ -101,20 +95,11 @@
#
# Create children
#
- def provisionChild(name):
- self.putChild(name, self.provisionChild(name))
-
for recordType in self.directory.recordTypes():
- provisionChild(recordType)
+ self.putChild(recordType, DirectoryAddressBookHomeTypeProvisioningResource(self, recordType))
- provisionChild(uidsResourceName)
+ self.putChild(uidsResourceName, DirectoryAddressBookHomeUIDProvisioningResource(self))
- def provisionChild(self, name):
- if name == uidsResourceName:
- return DirectoryAddressBookHomeUIDProvisioningResource(self)
-
- return DirectoryAddressBookHomeTypeProvisioningResource(self, name)
-
def url(self):
return self._url
@@ -172,7 +157,6 @@
return joinURL(self._parent.url(), self.recordType)
def locateChild(self, request, segments):
- self.provision()
name = segments[0]
if name == "":
return (self, segments[1:])
@@ -234,10 +218,6 @@
self.directory = parent.directory
self.parent = parent
-
- # TODO: better way to get this class - perhaps request from the store
- from twistedcaldav.resource import AddressBookHomeResource
- self.homeResourceClass = AddressBookHomeResource
def url(self):
return joinURL(self.parent.url(), uidsResourceName)
@@ -263,7 +243,6 @@
def homeResourceForRecord(self, record, request):
- self.provision()
transaction = transactionFromRequest(request, self.parent._newStore)
name = record.uid
@@ -279,7 +258,7 @@
assert len(name) > 4, "Directory record has an invalid GUID: %r" % (name,)
if record.locallyHosted():
- child = self.homeResourceClass(self, record, transaction)
+ child = DirectoryAddressBookHomeResource(self, record, transaction)
else:
child = DirectoryReverseProxyResource(self, record)
@@ -306,135 +285,20 @@
return self.parent.principalForRecord(record)
-class DirectoryAddressBookHomeResource (AutoProvisioningResourceMixIn, DAVResource):
+class DirectoryAddressBookHomeResource (AddressBookHomeResource):
"""
Address book home collection resource.
"""
- def __init__(self, parent, record):
+ def __init__(self, parent, record, transaction):
"""
@param path: the path to the file which will back the resource.
"""
assert parent is not None
assert record is not None
+ assert transaction is not None
- super(DirectoryAddressBookHomeResource, self).__init__()
-
self.record = record
- self.parent = parent
+ super(DirectoryAddressBookHomeResource, self).__init__(parent, record.uid, transaction)
- childlist = ()
- if config.Sharing.Enabled and config.Sharing.AddressBooks.Enabled and not config.Sharing.Calendars.Enabled:
- from twistedcaldav.notifications import NotificationCollectionResource
- childlist += (
- ("notification", NotificationCollectionResource),
- )
- for name, cls in childlist:
- child = self.provisionChild(name)
- assert isinstance(child, cls), "Child %r is not a %s: %r" % (name, cls.__name__, child)
- self.putChild(name, child)
-
- def provisionDefaultAddressBooks(self):
-
- # Disable notifications during provisioning
- if hasattr(self, "clientNotifier"):
- self.clientNotifier.disableNotify()
-
- try:
- self.provision()
-
- childName = "addressbook"
- child = self.provisionChild(childName)
-
- 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.uid, "/")
-
- def canonicalURL(self, request):
- return succeed(self.url())
- ##
- # DAV
- ##
-
- def isCollection(self):
- return True
-
- def http_COPY(self, request):
- return responsecode.FORBIDDEN
-
- ##
- # ACL
- ##
-
- def owner(self, request):
- return succeed(davxml.HRef(self.principalForRecord().principalURL()))
-
- def ownerPrincipal(self, request):
- return succeed(self.principalForRecord())
-
- def resourceOwnerPrincipal(self, request):
- return succeed(self.principalForRecord())
-
- def defaultAccessControlList(self):
- myPrincipal = self.principalForRecord()
-
- 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
-
- # Give all access to config.AdminPrincipals
- aces += config.AdminACEs
-
- return davxml.ACL(*aces)
-
- def accessControlList(self, request, inheritance=True, expanding=False, inherited_aces=None):
- # Permissions here are fixed, and are not subject to inheritance rules, etc.
- return succeed(self.defaultAccessControlList())
-
- def principalCollections(self):
- return self.parent.principalCollections()
-
def principalForRecord(self):
return self.parent.principalForRecord(self.record)
-
- ##
- # Quota
- ##
-
- def hasQuotaRoot(self, request):
- """
- @return: a C{True} if this resource has quota root, C{False} otherwise.
- """
- 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.
- """
- return config.UserQuota if config.UserQuota != 0 else None
Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/calendar.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/calendar.py 2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/calendar.py 2010-08-03 20:44:19 UTC (rev 5970)
@@ -1,6 +1,6 @@
# -*- test-case-name: twistedcaldav.directory.test.test_calendar -*-
##
-# 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.
@@ -14,7 +14,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
##
-from twistedcaldav.directory.util import transactionFromRequest
"""
Implements a directory-backed calendar hierarchy.
@@ -22,7 +21,6 @@
__all__ = [
"uidsResourceName",
- #"DirectoryCalendarProvisioningResource",
"DirectoryCalendarHomeProvisioningResource",
"DirectoryCalendarHomeTypeProvisioningResource",
"DirectoryCalendarHomeUIDProvisioningResource",
@@ -31,23 +29,20 @@
from twext.python.log import Logger
from twext.web2 import responsecode
-from twext.web2.dav import davxml
-from twext.web2.dav.resource import TwistedACLInheritable
from twext.web2.dav.util import joinURL
from twext.web2.http import HTTPError
from twext.web2.http_headers import ETag, MimeType
from twisted.internet.defer import succeed
-from twistedcaldav import caldavxml
from twistedcaldav.config import config
-from twistedcaldav.dropbox import DropBoxHomeResource
-from twistedcaldav.extensions import ReadOnlyResourceMixIn, DAVResource,\
- DAVResourceWithChildrenMixin
from twistedcaldav.directory.idirectory import IDirectoryService
+from twistedcaldav.directory.resource import DirectoryReverseProxyResource
+from twistedcaldav.directory.util import transactionFromRequest
from twistedcaldav.directory.wiki import getWikiACL
-from twistedcaldav.directory.resource import AutoProvisioningResourceMixIn,\
- DirectoryReverseProxyResource
+from twistedcaldav.extensions import ReadOnlyResourceMixIn, DAVResource,\
+ DAVResourceWithChildrenMixin
+from twistedcaldav.resource import CalendarHomeResource
from uuid import uuid4
@@ -65,7 +60,6 @@
)
class DirectoryCalendarProvisioningResource (
- AutoProvisioningResourceMixIn,
ReadOnlyResourceMixIn,
CalDAVComplianceMixIn,
DAVResourceWithChildrenMixin,
@@ -104,20 +98,11 @@
#
# Create children
#
- def provisionChild(name):
- self.putChild(name, self.provisionChild(name))
-
for recordType in self.directory.recordTypes():
- provisionChild(recordType)
+ self.putChild(recordType, DirectoryCalendarHomeTypeProvisioningResource(self, recordType))
- provisionChild(uidsResourceName)
+ self.putChild(uidsResourceName, DirectoryCalendarHomeUIDProvisioningResource(self))
- def provisionChild(self, name):
- if name == uidsResourceName:
- return DirectoryCalendarHomeUIDProvisioningResource(self)
-
- return DirectoryCalendarHomeTypeProvisioningResource(self, name)
-
def url(self):
return self._url
@@ -174,7 +159,6 @@
return joinURL(self._parent.url(), self.recordType)
def locateChild(self, request, segments):
- self.provision()
name = segments[0]
if name == "":
return (self, segments[1:])
@@ -235,10 +219,6 @@
self.directory = parent.directory
self.parent = parent
-
- # TODO: better way to get this class - perhaps request from the store
- from twistedcaldav.resource import CalendarHomeResource
- self.homeResourceClass = CalendarHomeResource
def url(self):
return joinURL(self.parent.url(), uidsResourceName)
@@ -264,7 +244,6 @@
def homeResourceForRecord(self, record, request):
- self.provision()
transaction = transactionFromRequest(request, self.parent._newStore)
name = record.uid
@@ -279,7 +258,7 @@
assert len(name) > 4, "Directory record has an invalid GUID: %r" % (name,)
if record.locallyHosted():
- child = self.homeResourceClass(self, record, transaction)
+ child = DirectoryCalendarHomeResource(self, record, transaction)
else:
child = DirectoryReverseProxyResource(self, record)
@@ -306,132 +285,22 @@
return self.parent.principalForRecord(record)
-class DirectoryCalendarHomeResource (AutoProvisioningResourceMixIn, DAVResource):
+class DirectoryCalendarHomeResource (CalendarHomeResource):
"""
Calendar home collection resource.
"""
- def __init__(self, parent, record):
+ def __init__(self, parent, record, transaction):
"""
@param path: the path to the file which will back the resource.
"""
assert parent is not None
assert record is not None
+ assert transaction is not None
- super(DirectoryCalendarHomeResource, self).__init__()
-
self.record = record
- self.parent = parent
+ super(DirectoryCalendarHomeResource, self).__init__(parent, record.uid, transaction)
- # Cache children which must be of a specific type
- from twistedcaldav.schedule import ScheduleInboxResource, ScheduleOutboxResource
- childlist = (
- ("inbox" , ScheduleInboxResource ),
- ("outbox", ScheduleOutboxResource),
- )
- if config.EnableDropBox:
- childlist += (
- ("dropbox", DropBoxHomeResource),
- )
- if config.FreeBusyURL.Enabled:
- from twistedcaldav.freebusyurl import FreeBusyURLResource
- childlist += (
- ("freebusy", FreeBusyURLResource),
- )
- if config.Sharing.Enabled and config.Sharing.Calendars.Enabled:
- from twistedcaldav.notifications import NotificationCollectionResource
- childlist += (
- ("notification", NotificationCollectionResource),
- )
- for name, cls in childlist:
- child = self.provisionChild(name)
- # assert isinstance(child, cls), "Child %r is not a %s: %r" % (name, cls.__name__, child)
- self.putChild(name, child)
-
-
- def provisionChild(self, name):
- raise NotImplementedError("Subclass must implement provisionChild()")
-
- def url(self):
- return joinURL(self.parent.url(), self.record.uid, "/")
-
- def canonicalURL(self, request):
- return succeed(self.url())
-
- ##
- # DAV
- ##
-
- def isCollection(self):
- return True
-
- def http_COPY(self, request):
- return responsecode.FORBIDDEN
-
- ##
- # ACL
- ##
-
- def owner(self, request):
- return succeed(davxml.HRef(self.principalForRecord().principalURL()))
-
- def ownerPrincipal(self, request):
- return succeed(self.principalForRecord())
-
- def resourceOwnerPrincipal(self, request):
- return succeed(self.principalForRecord())
-
- def defaultAccessControlList(self):
- myPrincipal = self.principalForRecord()
-
- 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(),
- ),
- # Inheritable CALDAV:read-free-busy access for authenticated users.
- davxml.ACE(
- davxml.Principal(davxml.Authenticated()),
- davxml.Grant(davxml.Privilege(caldavxml.ReadFreeBusy())),
- TwistedACLInheritable(),
- ),
- )
-
- # Give read access to config.ReadPrincipals
- aces += config.ReadACEs
-
- # Give all access to config.AdminPrincipals
- aces += config.AdminACEs
-
- if config.EnableProxyPrincipals:
- aces += (
- # DAV:read/DAV:read-current-user-privilege-set access for this principal's calendar-proxy-read users.
- davxml.ACE(
- davxml.Principal(davxml.HRef(joinURL(myPrincipal.principalURL(), "calendar-proxy-read/"))),
- davxml.Grant(
- davxml.Privilege(davxml.Read()),
- davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
- ),
- davxml.Protected(),
- TwistedACLInheritable(),
- ),
- # DAV:read/DAV:read-current-user-privilege-set/DAV:write access for this principal's calendar-proxy-write users.
- davxml.ACE(
- davxml.Principal(davxml.HRef(joinURL(myPrincipal.principalURL(), "calendar-proxy-write/"))),
- davxml.Grant(
- davxml.Privilege(davxml.Read()),
- davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
- davxml.Privilege(davxml.Write()),
- ),
- davxml.Protected(),
- TwistedACLInheritable(),
- ),
- )
-
- return davxml.ACL(*aces)
-
+ # Special ACLs for Wiki service
def accessControlList(self, request, inheritance=True, expanding=False, inherited_aces=None):
def gotACL(wikiACL):
if wikiACL is not None:
@@ -447,29 +316,5 @@
d.addCallback(gotACL)
return d
- def principalCollections(self):
- return self.parent.principalCollections()
-
def principalForRecord(self):
return self.parent.principalForRecord(self.record)
-
- ##
- # Quota
- ##
-
- def hasQuotaRoot(self, request):
- """
- Always get quota root value from config.
-
- @return: a C{True} if this resource has quota root, C{False} otherwise.
- """
- return config.UserQuota != 0
-
- def quotaRoot(self, request):
- """
- Always get quota root value from config.
-
- @return: a C{int} containing the maximum allowed bytes if this collection
- is quota-controlled, or C{None} if not quota controlled.
- """
- return config.UserQuota if config.UserQuota != 0 else None
Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/resource.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/resource.py 2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/directory/resource.py 2010-08-03 20:44:19 UTC (rev 5970)
@@ -13,65 +13,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.
##
-from twistedcaldav.client.reverseproxy import ReverseProxyResource
-from twext.web2.dav.util import joinURL
"""
Implements a directory-backed principal hierarchy.
"""
-__all__ = ["AutoProvisioningResourceMixIn"]
+from twext.web2.dav.util import joinURL
-from twisted.internet.defer import maybeDeferred, inlineCallbacks, returnValue
+from twistedcaldav.client.reverseproxy import ReverseProxyResource
-class AutoProvisioningResourceMixIn (object):
- """
- Adds auto-provisioning to a Resource implementation.
- """
- def provision(self):
- """
- Provision this resource by creating any required backing store, etc. that
- must be set up before the resource can be accessed normally. Specifically,
- this must have been called before anything that involves I/O happens.
- This method may be called multiple times; provisioning code should ensure that
- it handles this properly, typically by returning immediately if the resource is
- already provisioned (eg. the backing store exists).
- @return: a deferred or None.
- """
- return None
+__all__ = ["DirectoryReverseProxyResource"]
- def provisionChild(self, name):
- """
- Creates the child object with the given name.
- This is basically akin to L{File.createSimilarFile}, but here we know we're
- creating a child of this resource, and can take certain actions to ensure that
- it's prepared appropriately and is of the correct class.
- @param name: the name of the child resource.
- @return: the newly created (optionally deferred) child, or None of no resource
- is bound as a child of this resource with the given C{name}.
- """
- return None
-
- @inlineCallbacks
- def locateChild(self, request, segments):
- """
- This implementation calls L{provision}, then super's L{locateChild}, thereby
- ensuring that looked-up resources are provisioned.
- """
- yield maybeDeferred(self.provision)
-
- name = segments[0]
- if name != "":
- # If getChild() finds a child resource, return it
- child = self.getChild(name)
- if child is None:
- child = self.provisionChild(name)
- if child:
- returnValue((child, segments[1:],))
-
- result = (yield super(AutoProvisioningResourceMixIn, self).locateChild(request, segments))
- returnValue(result)
-
class DirectoryReverseProxyResource(ReverseProxyResource):
def __init__(self, parent, record):
Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/extensions.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/extensions.py 2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/extensions.py 2010-08-03 20:44:19 UTC (rev 5970)
@@ -635,7 +635,7 @@
return value
url = urllib.quote(name, '/')
- if isinstance(child, SuperDAVFile) and child.isCollection():
+ if isinstance(child, DAVResource) and child.isCollection():
url += "/"
name += "/"
@@ -710,8 +710,10 @@
# Allow live property to be overridden by dead property
if self.deadProperties().contains((dav_namespace, "resourcetype")):
return self.deadProperties().get((dav_namespace, "resourcetype"))
- return davxml.ResourceType()
+ return davxml.ResourceType(davxml.Collection()) if self.isCollection() else davxml.ResourceType()
+ def contentType(self):
+ return MimeType("httpd", "unix-directory") if self.isCollection() else None
class DAVResourceWithChildrenMixin (object):
"""
Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/method/report_sync_collection.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/method/report_sync_collection.py 2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/method/report_sync_collection.py 2010-08-03 20:44:19 UTC (rev 5970)
@@ -60,7 +60,7 @@
Return the specified properties on the specified resource.
@param request: the L{IRequest} for the current request.
@param props: a list of property elements or qname tuples for the properties of interest.
- @param resource: the L{DAVFile} for the targeted resource.
+ @param resource: the L{DAVResource} for the targeted resource.
@return: a map of OK and NOT FOUND property values.
"""
properties_by_status = {
Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/resource.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/resource.py 2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/resource.py 2010-08-03 20:44:19 UTC (rev 5970)
@@ -70,9 +70,8 @@
from twistedcaldav.customxml import calendarserver_namespace
from twistedcaldav.datafilters.peruserdata import PerUserDataFilter
from twistedcaldav.datafilters.privateevents import PrivateEventFilter
-from twistedcaldav.directory.addressbook import DirectoryAddressBookHomeResource
-from twistedcaldav.directory.calendar import DirectoryCalendarHomeResource
from twistedcaldav.directory.internal import InternalDirectoryRecord
+from twistedcaldav.dropbox import DropBoxHomeResource
from twistedcaldav.extensions import DAVResource, DAVPrincipalResource,\
PropertyNotFoundError, DAVResourceWithChildrenMixin
from twistedcaldav.ical import Component
@@ -2113,47 +2112,46 @@
"""
return None
-class CalendarHomeResource(SharedHomeMixin, DirectoryCalendarHomeResource, CalDAVResource):
+class CommonHomeResource(SharedHomeMixin, CalDAVResource):
"""
Calendar home collection resource.
"""
- def __init__(self, parent, record, transaction):
+ def __init__(self, parent, name, transaction):
"""
"""
+ self.parent = parent
+ self.name = name
self.associateWithTransaction(transaction)
+ self._provisionedChildren = {}
+ self._provisionedLinks = {}
+ self._setupProvisions()
# TODO: when calendar home gets a resourceID( ) method, remove
- # the "id=record.uid" keyword from this call:
- self.clientNotifier = ClientNotifier(self, id=record.uid)
- storeHome = transaction.calendarHomeWithUID(record.uid)
- if storeHome is not None:
- created = False
- else:
- storeHome = transaction.calendarHomeWithUID(
- record.uid, create=True
- )
- created = True
- self._newStoreCalendarHome = storeHome
+ # the "id=name" keyword from this call:
+ self.clientNotifier = ClientNotifier(self, id=name)
+ self._newStoreHome, created = self.makeNewStore()
CalDAVResource.__init__(self)
- DirectoryCalendarHomeResource.__init__(self, parent, record)
from twistedcaldav.storebridge import _NewStorePropertiesWrapper
self._dead_properties = _NewStorePropertiesWrapper(
- self._newStoreCalendarHome.properties()
+ self._newStoreHome.properties()
)
if created:
- # This is a bit of a hack. Really we ought to be always generating
- # this URL live from a back-end method that tells us what the
- # default calendar is.
- inbox = self.getChild("inbox")
- childURL = joinURL(self.url(), "calendar")
- inbox.processFreeBusyCalendar(childURL, True)
+ self.postCreateHome()
+ def _setupProvisions(self):
+ pass
+ def makeNewStore(self):
+ raise NotImplementedError
+
+ def postCreateHome(self):
+ pass
+
def liveProperties(self):
- return super(CalendarHomeResource, self).liveProperties() + (
+ return super(CommonHomeResource, self).liveProperties() + (
(customxml.calendarserver_namespace, "push-transports"),
(customxml.calendarserver_namespace, "pushkey"),
(customxml.calendarserver_namespace, "xmpp-uri"),
@@ -2166,67 +2164,85 @@
Retrieve the new-style shares DB wrapper.
"""
if not hasattr(self, "_sharesDB"):
- self._sharesDB = self._newStoreCalendarHome.retrieveOldShares()
+ self._sharesDB = self._newStoreHome.retrieveOldShares()
return self._sharesDB
+ def url(self):
+ return joinURL(self.parent.url(), self.name, "/")
+
+ def canonicalURL(self, request):
+ return succeed(self.url())
+
def exists(self):
# FIXME: tests
return True
-
-
+
+ def isCollection(self):
+ return True
+
def quotaSize(self, request):
# FIXME: tests, workingness
return succeed(0)
+ def hasQuotaRoot(self, request):
+ """
+ Always get quota root value from config.
- def provision(self):
- if config.Sharing.Enabled and config.Sharing.Calendars.Enabled and self.exists():
- self.provisionShares()
- return
+ @return: a C{True} if this resource has quota root, C{False} otherwise.
+ """
+ return config.UserQuota != 0
+
+ def quotaRoot(self, request):
+ """
+ Always get quota root value from config.
- def provisionChild(self, name):
- from twistedcaldav.storebridge import StoreScheduleInboxResource
- from twistedcaldav.storebridge import DropboxCollection
- if config.EnableDropBox:
- DropBoxHomeFileClass = DropboxCollection
- else:
- DropBoxHomeFileClass = None
+ @return: a C{int} containing the maximum allowed bytes if this collection
+ is quota-controlled, or C{None} if not quota controlled.
+ """
+ return config.UserQuota if config.UserQuota != 0 else None
- if config.FreeBusyURL.Enabled:
- from twistedcaldav.freebusyurl import FreeBusyURLResource
- FreeBusyURLResourceClass = FreeBusyURLResource
- else:
- FreeBusyURLResourceClass = None
-
- # For storebridge stuff we special case this
- if name == "notification" and config.Sharing.Enabled and config.Sharing.Calendars.Enabled:
- return self.createNotificationsCollection()
+ def canShare(self):
+ raise NotImplementedError
- from twistedcaldav.schedule import ScheduleOutboxResource
- cls = {
- "inbox" : StoreScheduleInboxResource,
- "outbox" : ScheduleOutboxResource,
- "dropbox" : DropBoxHomeFileClass,
- "freebusy" : FreeBusyURLResourceClass,
- }.get(name, None)
-
- if cls is not None:
- child = cls(self)
+ def makeChild(self, name):
+
+ # Try built-in children first
+ if name in self._provisionedChildren:
+ cls = self._provisionedChildren[name]
+ from twistedcaldav.notifications import NotificationCollectionResource
+ if cls is NotificationCollectionResource:
+ return self.createNotificationsCollection()
+ child = self._provisionedChildren[name](self)
child.clientNotifier = self.clientNotifier.clone(child,
label="collection")
+ self.putChild(name, child)
return child
- return self.makeChild(name)
+
+ # Try built-in links next
+ if name in self._provisionedLinks:
+ child = LinkResource(self, self._provisionedLinks[name])
+ self.putChild(name, child)
+ return child
+
+ # Try shares next
+ if self.canShare():
+ child = self.provisionShare(name)
+ if child:
+ return child
+ # Do normal child types
+ return self.makeRegularChild(name)
+
def createNotificationsCollection(self):
- txn = self._newStoreCalendarHome._transaction
- notifications = txn.notificationsWithUID(self._newStoreCalendarHome.uid())
+ txn = self._newStoreHome._transaction
+ notifications = txn.notificationsWithUID(self._newStoreHome.uid())
from twistedcaldav.storebridge import StoreNotificationCollectionResource
similar = StoreNotificationCollectionResource(
notifications,
- self._newStoreCalendarHome,
+ self._newStoreHome,
principalCollections = self.principalCollections(),
)
self.propagateTransaction(similar)
@@ -2234,42 +2250,17 @@
label="collection")
return similar
- def makeChild(self, name):
+ def makeRegularChild(self, name):
+ raise NotImplementedError
- newCalendar = self._newStoreCalendarHome.calendarWithName(name)
- if newCalendar is None:
- # Local imports.due to circular dependency between modules.
- from twistedcaldav.storebridge import (
- ProtoCalendarCollectionResource)
- similar = ProtoCalendarCollectionResource(
- self._newStoreCalendarHome,
- name,
- principalCollections=self.principalCollections()
- )
- else:
- from twistedcaldav.storebridge import CalendarCollectionResource
- similar = CalendarCollectionResource(
- newCalendar, self._newStoreCalendarHome,
- principalCollections=self.principalCollections()
- )
- self.propagateTransaction(similar)
- similar.clientNotifier = self.clientNotifier.clone(similar,
- label="collection")
- return similar
-
- def getChild(self, name):
- # This avoids finding case variants of put children on case-insensitive filesystems.
- if name not in self.putChildren and name.lower() in (x.lower() for x in self.putChildren):
- return None
-
- return super(CalendarHomeResource, self).getChild(name)
-
def listChildren(self):
"""
@return: a sequence of the names of all known children of this resource.
"""
- children = set(self.putChildren.keys())
- children.update(self._newStoreCalendarHome.listCalendars())
+ children = set(self._provisionedChildren.keys())
+ children.update(self._provisionedLinks.keys())
+ children.update(self.allShareNames())
+ children.update(self._newStoreHome.listChildren())
return children
def readProperty(self, property, request):
@@ -2379,105 +2370,205 @@
else:
return succeed(customxml.PubSubXMPPServerProperty())
- return super(CalendarHomeResource, self).readProperty(property, request)
+ return super(CommonHomeResource, self).readProperty(property, request)
- http_ACL = None # ACL method not supported
+ ##
+ # ACL
+ ##
-class AddressBookHomeResource (SharedHomeMixin, DirectoryAddressBookHomeResource, CalDAVResource):
- """
- Address book home collection resource.
- """
-
- def __init__(self, parent, record, transaction):
- """
- """
+ def owner(self, request):
+ return succeed(davxml.HRef(self.principalForRecord().principalURL()))
- self.associateWithTransaction(transaction)
+ def ownerPrincipal(self, request):
+ return succeed(self.principalForRecord())
- # TODO: when addressbook home gets a resourceID( ) method, remove
- # the "id=record.uid" keyword from this call:
- self.clientNotifier = ClientNotifier(self, id=record.uid)
- self._newStoreAddressBookHome = (
- transaction.addressbookHomeWithUID(record.uid, create=True)
- )
- CalDAVResource.__init__(self)
- DirectoryAddressBookHomeResource.__init__(self, parent, record)
+ def resourceOwnerPrincipal(self, request):
+ return succeed(self.principalForRecord())
- from twistedcaldav.storebridge import _NewStorePropertiesWrapper
- self._dead_properties = _NewStorePropertiesWrapper(
- self._newStoreAddressBookHome.properties()
+ def defaultAccessControlList(self):
+ myPrincipal = self.principalForRecord()
+
+ 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
- def liveProperties(self):
- return super(AddressBookHomeResource, self).liveProperties() + (
- (customxml.calendarserver_namespace, "push-transports"),
- (customxml.calendarserver_namespace, "pushkey"),
- (customxml.calendarserver_namespace, "xmpp-uri"),
- (customxml.calendarserver_namespace, "xmpp-heartbeat-uri"),
- (customxml.calendarserver_namespace, "xmpp-server"),
- )
+ # Give all access to config.AdminPrincipals
+ aces += config.AdminACEs
+
+ return davxml.ACL(*aces)
- def sharesDB(self):
- """
- Retrieve the new-style shares DB wrapper.
- """
- if not hasattr(self, "_sharesDB"):
- self._sharesDB = self._newStoreAddressBookHome.retrieveOldShares()
- return self._sharesDB
+ def accessControlList(self, request, inheritance=True, expanding=False, inherited_aces=None):
+ # Permissions here are fixed, and are not subject to inheritance rules, etc.
+ return succeed(self.defaultAccessControlList())
+ def principalCollections(self):
+ return self.parent.principalCollections()
- def exists(self):
- # FIXME: tests
- return True
-
-
- def quotaSize(self, request):
- # FIXME: tests, workingness
- return succeed(0)
+ def principalForRecord(self):
+ raise NotImplementedError("Subclass must implement principalForRecord()")
+ # Methods not supported
+ http_ACL = None
+ http_COPY = None
+ http_MOVE = None
- def provision(self):
- if config.Sharing.Enabled and config.Sharing.AddressBooks.Enabled:
- self.provisionShares()
- self.provisionLinks()
- def provisionLinks(self):
-
- if not hasattr(self, "_provisionedLinks"):
- if config.GlobalAddressBook.Enabled:
- self.putChild(
- config.GlobalAddressBook.Name,
- LinkResource(self, "/addressbooks/public/global/addressbook/"),
- )
- self._provisionedLinks = True
+class CalendarHomeResource(CommonHomeResource):
+ """
+ Calendar home collection resource.
+ """
- def provisionChild(self, name):
-
- # For storebridge stuff we special case this
- if name == "notification" and config.Sharing.Enabled and config.Sharing.AddressBooks.Enabled and not config.Sharing.Calendars.Enabled:
- return self.createNotificationsCollection()
+ def _setupProvisions(self):
- return self.makeChild(name)
+ # Cache children which must be of a specific type
+ from twistedcaldav.storebridge import StoreScheduleInboxResource
+ self._provisionedChildren["inbox"] = StoreScheduleInboxResource
- def createNotificationsCollection(self):
-
- txn = self._newStoreAddressBookHome._transaction
- notifications = txn.notificationsWithUID(self._newStoreAddressBookHome.uid())
+ from twistedcaldav.schedule import ScheduleOutboxResource
+ self._provisionedChildren["outbox"] = ScheduleOutboxResource
- from twistedcaldav.storebridge import StoreNotificationCollectionResource
- similar = StoreNotificationCollectionResource(
- notifications,
- self._newStoreAddressBookHome,
- principalCollections = self.principalCollections(),
- )
+ if config.EnableDropBox:
+ from twistedcaldav.storebridge import DropboxCollection
+ self._provisionedChildren["dropbox"] = DropboxCollection
+
+ if config.FreeBusyURL.Enabled:
+ from twistedcaldav.freebusyurl import FreeBusyURLResource
+ self._provisionedChildren["freebusy"] = FreeBusyURLResource
+
+ if config.Sharing.Enabled and config.Sharing.Calendars.Enabled:
+ from twistedcaldav.notifications import NotificationCollectionResource
+ self._provisionedChildren["notification"] = NotificationCollectionResource
+
+ def makeNewStore(self):
+ storeHome = self._associatedTransaction.calendarHomeWithUID(self.name)
+ if storeHome is not None:
+ created = False
+ else:
+ storeHome = self._associatedTransaction.calendarHomeWithUID(
+ self.name, create=True
+ )
+ created = True
+
+ return storeHome, created
+
+ def postCreateHome(self):
+ # This is a bit of a hack. Really we ought to be always generating
+ # this URL live from a back-end method that tells us what the
+ # default calendar is.
+ inbox = self.getChild("inbox")
+ childURL = joinURL(self.url(), "calendar")
+ inbox.processFreeBusyCalendar(childURL, True)
+
+ def canShare(self):
+ return config.Sharing.Enabled and config.Sharing.Calendars.Enabled and self.exists()
+
+ def makeRegularChild(self, name):
+
+ newCalendar = self._newStoreHome.calendarWithName(name)
+ if newCalendar is None:
+ # Local imports.due to circular dependency between modules.
+ from twistedcaldav.storebridge import (
+ ProtoCalendarCollectionResource)
+ similar = ProtoCalendarCollectionResource(
+ self._newStoreHome,
+ name,
+ principalCollections=self.principalCollections()
+ )
+ else:
+ from twistedcaldav.storebridge import CalendarCollectionResource
+ similar = CalendarCollectionResource(
+ newCalendar, self._newStoreHome,
+ principalCollections=self.principalCollections()
+ )
self.propagateTransaction(similar)
similar.clientNotifier = self.clientNotifier.clone(similar,
label="collection")
return similar
- def makeChild(self, name):
+ def defaultAccessControlList(self):
+ myPrincipal = self.principalForRecord()
+ 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(),
+ ),
+ # Inheritable CALDAV:read-free-busy access for authenticated users.
+ davxml.ACE(
+ davxml.Principal(davxml.Authenticated()),
+ davxml.Grant(davxml.Privilege(caldavxml.ReadFreeBusy())),
+ TwistedACLInheritable(),
+ ),
+ )
+
+ # Give read access to config.ReadPrincipals
+ aces += config.ReadACEs
+
+ # Give all access to config.AdminPrincipals
+ aces += config.AdminACEs
+
+ if config.EnableProxyPrincipals:
+ aces += (
+ # DAV:read/DAV:read-current-user-privilege-set access for this principal's calendar-proxy-read users.
+ davxml.ACE(
+ davxml.Principal(davxml.HRef(joinURL(myPrincipal.principalURL(), "calendar-proxy-read/"))),
+ davxml.Grant(
+ davxml.Privilege(davxml.Read()),
+ davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
+ ),
+ davxml.Protected(),
+ TwistedACLInheritable(),
+ ),
+ # DAV:read/DAV:read-current-user-privilege-set/DAV:write access for this principal's calendar-proxy-write users.
+ davxml.ACE(
+ davxml.Principal(davxml.HRef(joinURL(myPrincipal.principalURL(), "calendar-proxy-write/"))),
+ davxml.Grant(
+ davxml.Privilege(davxml.Read()),
+ davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
+ davxml.Privilege(davxml.Write()),
+ ),
+ davxml.Protected(),
+ TwistedACLInheritable(),
+ ),
+ )
+
+ return davxml.ACL(*aces)
+
+class AddressBookHomeResource (CommonHomeResource):
+ """
+ Address book home collection resource.
+ """
+
+ def _setupProvisions(self):
+
+ # Cache children which must be of a specific type
+ if config.Sharing.Enabled and config.Sharing.AddressBooks.Enabled and not config.Sharing.Calendars.Enabled:
+ from twistedcaldav.notifications import NotificationCollectionResource
+ self._provisionedChildren["notification"] = NotificationCollectionResource
+
+ if config.GlobalAddressBook.Enabled:
+ self._provisionedLinks[config.GlobalAddressBook.Name] = "/addressbooks/public/global/addressbook/"
+
+ def makeNewStore(self):
+ return self._associatedTransaction.addressbookHomeWithUID(self.name, create=True), False # Don't care about created
+
+ def canShare(self):
+ return config.Sharing.Enabled and config.Sharing.AddressBooks.Enabled and self.exists()
+
+ def makeRegularChild(self, name):
+
# Check for public/global path
from twistedcaldav.storebridge import (
AddressBookCollectionResource,
@@ -2492,17 +2583,17 @@
mainCls = GlobalAddressBookCollectionResource
protoCls = ProtoGlobalAddressBookCollectionResource
- newAddressBook = self._newStoreAddressBookHome.addressbookWithName(name)
+ newAddressBook = self._newStoreHome.addressbookWithName(name)
if newAddressBook is None:
# Local imports.due to circular dependency between modules.
similar = protoCls(
- self._newStoreAddressBookHome,
+ self._newStoreHome,
name,
principalCollections=self.principalCollections()
)
else:
similar = mainCls(
- newAddressBook, self._newStoreAddressBookHome,
+ newAddressBook, self._newStoreHome,
principalCollections=self.principalCollections()
)
self.propagateTransaction(similar)
@@ -2510,132 +2601,7 @@
label="collection")
return similar
- def getChild(self, name):
- # This avoids finding case variants of put children on case-insensitive filesystems.
- if name not in self.putChildren and name.lower() in (x.lower() for x in self.putChildren):
- return None
- return super(AddressBookHomeResource, self).getChild(name)
-
- def listChildren(self):
- """
- @return: a sequence of the names of all known children of this resource.
- """
- children = set(self.putChildren.keys())
- children.update(self._newStoreAddressBookHome.listAddressbooks())
- return children
-
- def readProperty(self, property, request):
- if type(property) is tuple:
- qname = property
- else:
- qname = property.qname()
-
- if qname == (customxml.calendarserver_namespace, "push-transports"):
- pubSubConfiguration = getPubSubConfiguration(config)
- if (pubSubConfiguration['enabled'] and
- getattr(self, "clientNotifier", None) is not None):
- id = self.clientNotifier.getID()
- nodeName = getPubSubPath(id, pubSubConfiguration)
- children = []
- if pubSubConfiguration['aps-bundle-id']:
- children.append(
- customxml.PubSubTransportProperty(
- customxml.PubSubSubscriptionProperty(
- davxml.HRef(
- pubSubConfiguration['subscription-url']
- ),
- ),
- customxml.PubSubAPSBundleIDProperty(
- pubSubConfiguration['aps-bundle-id']
- ),
- type="APSD",
- )
- )
- if pubSubConfiguration['xmpp-server']:
- children.append(
- customxml.PubSubTransportProperty(
- customxml.PubSubXMPPServerProperty(
- pubSubConfiguration['xmpp-server']
- ),
- customxml.PubSubXMPPURIProperty(
- getPubSubXMPPURI(id, pubSubConfiguration)
- ),
- type="XMPP",
- )
- )
-
- propVal = customxml.PubSubPushTransportsProperty(*children)
- nodeCacher = getNodeCacher()
- d = nodeCacher.waitForNode(self.clientNotifier, nodeName)
- # In either case we're going to return the value
- d.addBoth(lambda ignored: propVal)
- return d
-
-
- else:
- return succeed(customxml.PubSubPushTransportsProperty())
-
- if qname == (customxml.calendarserver_namespace, "pushkey"):
- pubSubConfiguration = getPubSubConfiguration(config)
- if pubSubConfiguration['enabled']:
- if getattr(self, "clientNotifier", None) is not None:
- id = self.clientNotifier.getID()
- nodeName = getPubSubPath(id, pubSubConfiguration)
- propVal = customxml.PubSubXMPPPushKeyProperty(nodeName)
- nodeCacher = getNodeCacher()
- d = nodeCacher.waitForNode(self.clientNotifier, nodeName)
- # In either case we're going to return the xmpp-uri value
- d.addBoth(lambda ignored: propVal)
- return d
- else:
- return succeed(customxml.PubSubXMPPPushKeyProperty())
-
-
- if qname == (customxml.calendarserver_namespace, "xmpp-uri"):
- pubSubConfiguration = getPubSubConfiguration(config)
- if pubSubConfiguration['enabled']:
- if getattr(self, "clientNotifier", None) is not None:
- id = self.clientNotifier.getID()
- nodeName = getPubSubPath(id, pubSubConfiguration)
- propVal = customxml.PubSubXMPPURIProperty(
- getPubSubXMPPURI(id, pubSubConfiguration))
- nodeCacher = getNodeCacher()
- d = nodeCacher.waitForNode(self.clientNotifier, nodeName)
- # In either case we're going to return the xmpp-uri value
- d.addBoth(lambda ignored: propVal)
- return d
- else:
- return succeed(customxml.PubSubXMPPURIProperty())
-
- 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())
-
- return super(AddressBookHomeResource, self).readProperty(property, request)
-
- http_ACL = None # ACL method not supported
-
class GlobalAddressBookResource (ReadOnlyResourceMixIn, CalDAVResource):
"""
Global address book. All we care about is making sure permissions are setup.
Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/schedule.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/schedule.py 2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/schedule.py 2010-08-03 20:44:19 UTC (rev 5970)
@@ -154,7 +154,7 @@
if not self.hasDeadProperty(property):
top = self.parent.url()
values = []
- for cal in self.parent._newStoreCalendarHome.calendars():
+ for cal in self.parent._newStoreHome.calendars():
prop = cal.properties().get(PropertyName.fromString(ScheduleCalendarTransp.sname()))
if prop == ScheduleCalendarTransp(Opaque()):
values.append(HRef(joinURL(top, cal.name())))
@@ -261,7 +261,7 @@
defaultCalendarURL = joinURL(calendarHomeURL, "calendar")
defaultCalendar = (yield request.locateResource(defaultCalendarURL))
if defaultCalendar is None or not defaultCalendar.exists():
- getter = iter(self.parent._newStoreCalendarHome.calendars())
+ getter = iter(self.parent._newStoreHome.calendars())
# FIXME: the back-end should re-provision a default calendar here.
# Really, the dead property shouldn't be necessary, and this should
# be entirely computed by a back-end method like 'defaultCalendar()'
Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/sharing.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/sharing.py 2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/sharing.py 2010-08-03 20:44:19 UTC (rev 5970)
@@ -946,15 +946,25 @@
self._sharesDB = SharedCollectionsDatabase(self)
return self._sharesDB
- def provisionShares(self):
+ def provisionShare(self, name):
- if not hasattr(self, "_provisionedShares"):
+ # Try to find a matching share
+ child = None
+ shares = self.allShares()
+ if name in shares:
from twistedcaldav.sharedcollection import SharedCollectionResource
- for share in self.sharesDB().allRecords():
- child = SharedCollectionResource(self, share)
- self.putChild(share.localname, child)
- self._provisionedShares = True
+ child = SharedCollectionResource(self, shares[name])
+ self.putChild(name, child)
+ return child
+ def allShares(self):
+ if not hasattr(self, "_allShares"):
+ self._allShares = dict([(share.localname, share) for share in self.sharesDB().allRecords()])
+ return self._allShares
+
+ def allShareNames(self):
+ return tuple(self.allShares().keys())
+
@inlineCallbacks
def acceptInviteShare(self, request, hostUrl, inviteUID, displayname=None):
Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/storebridge.py 2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/storebridge.py 2010-08-03 20:44:19 UTC (rev 5970)
@@ -297,7 +297,7 @@
def __init__(self, *a, **kw):
super(StoreScheduleInboxResource, self).__init__(*a, **kw)
self.parent.propagateTransaction(self)
- home = self.parent._newStoreCalendarHome
+ home = self.parent._newStoreHome
storage = home.calendarWithName("inbox")
if storage is None:
# raise RuntimeError("backend should be handling this for us")
@@ -308,7 +308,7 @@
storage = home.calendarWithName("inbox")
self._initializeWithCalendar(
storage,
- self.parent._newStoreCalendarHome
+ self.parent._newStoreHome
)
@@ -365,7 +365,7 @@
def __init__(self, parent, *a, **kw):
kw.update(principalCollections=parent.principalCollections())
super(DropboxCollection, self).__init__(*a, **kw)
- self._newStoreCalendarHome = parent._newStoreCalendarHome
+ self._newStoreHome = parent._newStoreHome
parent.propagateTransaction(self)
@@ -377,7 +377,7 @@
def getChild(self, name):
- calendarObject = self._newStoreCalendarHome.calendarObjectWithDropboxID(name)
+ calendarObject = self._newStoreHome.calendarObjectWithDropboxID(name)
if calendarObject is None:
return NoDropboxHere()
objectDropbox = CalendarObjectDropbox(
@@ -393,7 +393,7 @@
def listChildren(self):
l = []
- for everyCalendar in self._newStoreCalendarHome.calendars():
+ for everyCalendar in self._newStoreHome.calendars():
for everyObject in everyCalendar.calendarObjects():
l.append(everyObject.dropboxID())
return l
Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/test_multiget.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/test_multiget.py 2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/test_multiget.py 2010-08-03 20:44:19 UTC (rev 5970)
@@ -29,10 +29,10 @@
from twistedcaldav import caldavxml
from twistedcaldav import ical
from twistedcaldav.index import db_basename
-from twistedcaldav.test.util import HomeTestCase
+from twistedcaldav.test.util import TestCase
from twistedcaldav.config import config
-class CalendarMultiget (HomeTestCase):
+class CalendarMultiget (TestCase):
"""
calendar-multiget REPORT
"""
@@ -44,12 +44,14 @@
All events.
(CalDAV-access-09, section 7.6.8)
"""
+ self.createStockDirectoryService()
+ self.setupCalendars()
okuids = [r[0] for r in (os.path.splitext(f) for f in os.listdir(self.holidays_dir)) if r[1] == ".ics"]
okuids[:] = okuids[1:10]
baduids = ["12345 at example.com", "67890 at example.com"]
- return self.simple_event_multiget("/calendar_multiget_events/", okuids, baduids)
+ return self.simple_event_multiget("/calendars/users/wsanchez/calendar_multiget_events/", okuids, baduids)
def test_multiget_all_events(self):
"""
Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/test_wrapping.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/test_wrapping.py 2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/test_wrapping.py 2010-08-03 20:44:19 UTC (rev 5970)
@@ -235,7 +235,7 @@
"""
calDavFile = yield self.getResource("calendars/users/wsanchez/")
self.commit()
- self.assertIsInstance(calDavFile._newStoreCalendarHome, CalendarHome)
+ self.assertIsInstance(calDavFile._newStoreHome, CalendarHome)
@inlineCallbacks
@@ -350,7 +350,7 @@
"""
calDavFile = yield self.getResource("addressbooks/users/wsanchez/")
self.commit()
- self.assertIsInstance(calDavFile._newStoreAddressBookHome, AddressBookHome)
+ self.assertIsInstance(calDavFile._newStoreHome, AddressBookHome)
@inlineCallbacks
Modified: CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/util.py
===================================================================
--- CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/util.py 2010-08-03 02:13:55 UTC (rev 5969)
+++ CalendarServer/branches/new-store-no-caldavfile-2/twistedcaldav/test/util.py 2010-08-03 20:44:19 UTC (rev 5970)
@@ -320,7 +320,7 @@
def _defer(user):
# Commit the transaction
self.site.resource._associatedTransaction.commit()
- self.docroot = user._newStoreCalendarHome._path.path
+ self.docroot = user._newStoreHome._path.path
return self._refreshRoot().addCallback(_defer)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100803/8a103bba/attachment-0001.html>
More information about the calendarserver-changes
mailing list