[CalendarServer-changes] [5231] CalendarServer/branches/users/cdaboo/shared-calendars-5187/ twistedcaldav
source_changes at macosforge.org
source_changes at macosforge.org
Tue Mar 2 13:23:49 PST 2010
Revision: 5231
http://trac.macosforge.org/projects/calendarserver/changeset/5231
Author: cdaboo at apple.com
Date: 2010-03-02 13:23:49 -0800 (Tue, 02 Mar 2010)
Log Message:
-----------
Split sharing pieces into their own mix-in class with tests. Add proper compliance header. Make extended
MKCOL work.
Modified Paths:
--------------
CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/customxml.py
CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/method/mkcol.py
CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/resource.py
CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/static.py
CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/test/util.py
Added Paths:
-----------
CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/sharing.py
CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/test/test_sharing.py
Modified: CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/customxml.py
===================================================================
--- CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/customxml.py 2010-03-02 21:20:30 UTC (rev 5230)
+++ CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/customxml.py 2010-03-02 21:23:49 UTC (rev 5231)
@@ -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.
@@ -28,6 +28,7 @@
from twext.web2.dav.element.base import twisted_private_namespace
from twext.web2.dav import davxml
+from twistedcaldav import caldavxml
from twistedcaldav.ical import Component as iComponent
from vobject.icalendar import utc
@@ -49,10 +50,14 @@
"calendarserver-private-comments",
)
-calendarserver_principal_property_search = (
+calendarserver_principal_property_search_compliance = (
"calendarserver-principal-property-search",
)
+calendarserver_sharing_compliance = (
+ "calendarserver-sharing",
+)
+
class TwistedCalendarAccessProperty (davxml.WebDAVTextElement):
"""
Contains the calendar access level (private events) for the resource.
@@ -806,3 +811,4 @@
davxml.ResourceType.ischeduleinbox = davxml.ResourceType(IScheduleInbox())
davxml.ResourceType.freebusyurl = davxml.ResourceType(FreeBusyURL())
davxml.ResourceType.notification = davxml.ResourceType(davxml.Collection(), Notification())
+davxml.ResourceType.sharedcalendar = davxml.ResourceType(davxml.Collection(), caldavxml.Calendar(), SharedOwner())
Modified: CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/method/mkcol.py
===================================================================
--- CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/method/mkcol.py 2010-03-02 21:20:30 UTC (rev 5230)
+++ CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/method/mkcol.py 2010-03-02 21:23:49 UTC (rev 5231)
@@ -165,11 +165,10 @@
# Now handle other properties
for property in mkcol.children[0].children[0].children:
try:
- if rtype == "calendar":
- if property.qname() == (caldavxml.caldav_namespace, "supported-calendar-component-set"):
- self.writeDeadProperty(property)
- elif not isinstance(property, davxml.ResourceType):
- yield self.writeProperty(property, request)
+ if rtype == "calendar" and property.qname() == (caldavxml.caldav_namespace, "supported-calendar-component-set"):
+ self.writeDeadProperty(property)
+ else:
+ yield self.writeProperty(property, request)
except HTTPError:
errors.add(Failure(), property)
got_an_error = True
Modified: CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/resource.py
===================================================================
--- CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/resource.py 2010-03-02 21:20:30 UTC (rev 5230)
+++ CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/resource.py 2010-03-02 21:23:49 UTC (rev 5231)
@@ -69,6 +69,7 @@
from twistedcaldav.ical import Component as iComponent
from twistedcaldav.ical import allowedComponents
from twistedcaldav.icaldav import ICalDAVResource, ICalendarPrincipalResource
+from twistedcaldav.sharing import SharingMixin
from twistedcaldav.vcard import Component as vComponent
@@ -110,9 +111,11 @@
extra_compliance += customxml.calendarserver_private_events_compliance
if config.Scheduling.CalDAV.get("EnablePrivateComments", True):
extra_compliance += customxml.calendarserver_private_comments_compliance
- extra_compliance += customxml.calendarserver_principal_property_search
+ extra_compliance += customxml.calendarserver_principal_property_search_compliance
if config.EnableCardDAV:
extra_compliance += carddavxml.carddav_compliance
+ if config.EnableSharing:
+ extra_compliance += customxml.calendarserver_sharing_compliance
return tuple(super(CalDAVComplianceMixIn, self).davComplianceClasses()) + extra_compliance
@@ -132,7 +135,7 @@
return fun
-class CalDAVResource (CalDAVComplianceMixIn, DAVResource, LoggingMixIn):
+class CalDAVResource (CalDAVComplianceMixIn, SharingMixin, DAVResource, LoggingMixIn):
"""
CalDAV resource.
@@ -277,7 +280,8 @@
isvirt = (yield self.isVirtualShare(request))
if self.isShadowableProperty(qname):
if isvirt:
- p = self.deadProperties().get(qname, uid=request.authzPrincipal.principalUID())
+ ownerPrincipal = (yield self.ownerPrincipal(request))
+ p = self.deadProperties().get(qname, uid=ownerPrincipal.principalUID())
if p is not None:
returnValue(p)
else:
@@ -285,7 +289,8 @@
returnValue(res)
elif (not self.isGlobalProperty(qname)) and isvirt:
- p = self.deadProperties().get(qname, uid=request.authzPrincipal.principalUID())
+ ownerPrincipal = (yield self.ownerPrincipal(request))
+ p = self.deadProperties().get(qname, uid=ownerPrincipal.principalUID())
if p is not None:
returnValue(p)
@@ -347,24 +352,8 @@
elif namespace == calendarserver_namespace:
if name == "invite":
shared = (yield self.isShared(request))
- if shared:
- userlist = []
- accesses = (yield self.getInviteUsers(request))
- if accesses:
- for access in accesses:
- acl = access()
- for principal, metaData in accesses[access]:
- children = []
- mailtoemail = "mailto:" + metaData["email"]
- children.append(davxml.HRef(mailtoemail))
- children.append(customxml.InviteAccess(acl))
- if "inviteStatus" in metaData and metaData["inviteStatus"]:
- children.append(shareAcceptStatesByXML[metaData["inviteStatus"]])
- else:
- children.append(customxml.InviteStatusNoResponse())
- userlist.append(customxml.InviteUser(*children))
- result = customxml.Invite(*userlist)
- returnValue(result)
+ if not shared:
+ returnValue(None)
result = (yield super(CalDAVResource, self).readProperty(property, request))
returnValue(result)
@@ -378,7 +367,8 @@
# Per-user Dav props currently only apply to a sharee's copy of a calendar
isvirt = (yield self.isVirtualShare(request))
if isvirt and (self.isShadowableProperty(property.qname()) or (not self.isGlobalProperty(property.qname()))):
- p = (yield self.deadProperties().set(property, uid=request.authzPrincipal.principalUID()))
+ ownerPrincipal = (yield self.ownerPrincipal(request))
+ p = (yield self.deadProperties().set(property, uid=ownerPrincipal.principalUID()))
returnValue(p)
res = (yield self._writeGlobalProperty(property, request))
@@ -434,7 +424,14 @@
inbox.processFreeBusyCalendar(myurl, property.children[0] == caldavxml.Opaque())
elif property.qname() == (dav_namespace, "resourcetype"):
- if self.isCalendarCollection() and config.EnableSharing:
+ if self.isCalendarCollection():
+ sawShare = [child for child in property.children if child.qname() == (calendarserver_namespace, "shared-owner")]
+ if not config.EnableSharing:
+ raise HTTPError(StatusResponse(
+ responsecode.FORBIDDEN,
+ "Cannot create shared calendars on this server.",
+ ))
+
# Check if adding or removing share
shared = (yield self.isShared(request))
sawShare = [child for child in property.children if child.qname() == (calendarserver_namespace, "shared-owner")]
@@ -963,47 +960,8 @@
"""
Quota root only ever set on calendar homes.
"""
- return None
+ return None
- ##
- # Sharing operations
- ##
-
- def upgradeToShare(self, request):
- """ Upgrade this collection to a shared state """
- return succeed(True)
-
- def downgradeFromShare(self, request):
- return succeed(True)
-
- def addUserToShare(self, userid, request, ace):
- """ Add a user to this shared calendar """
- return succeed(True)
-
- def removeUserFromShare(self, userid, request):
- """ Remove a user from this shared calendar """
- return succeed(True)
-
- def isShared(self, request):
- """ Return True if this is an owner shared calendar collection """
- succeed(False)
-
- def isVirtualShare(self, request):
- """ Return True if this is a shared calendar collection """
- succeed(False)
-
- def removeVirtualShare(self, request):
- """ As user of a shared calendar, unlink this calendar collection """
- succeed(False)
-
- def getInviteUsers(self, request):
- succeed(True)
-
- def sendNotificationOnChange(self, icalendarComponent, request, state="added"):
- """ Possibly send a push and or email notification on a change to a resource in a shared collection """
- succeed(True)
-
-
class CalendarPrincipalCollectionResource (DAVPrincipalCollectionResource, CalDAVResource):
"""
CalDAV principal collection.
Added: CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/sharing.py
===================================================================
--- CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/sharing.py (rev 0)
+++ CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/sharing.py 2010-03-02 21:23:49 UTC (rev 5231)
@@ -0,0 +1,83 @@
+##
+# Copyright (c) 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.
+# 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.
+##
+from twisted.internet.defer import succeed
+
+__all__ = [
+ "SharingMixin",
+]
+
+from twistedcaldav import customxml
+from twext.web2.dav import davxml
+
+"""
+Sharing behavior
+"""
+
+class SharingMixin(object):
+
+ def upgradeToShare(self, request):
+ """ Upgrade this collection to a shared state """
+
+ # Change resourcetype
+ rtype = self.resourceType()
+ rtype = davxml.ResourceType(*(rtype.children + (customxml.SharedOwner(),)))
+ self.writeDeadProperty(rtype)
+
+ # Create empty invite property
+ self.writeDeadProperty(customxml.Invite())
+
+ return succeed(True)
+
+ def downgradeFromShare(self, request):
+
+ # Change resource type
+ rtype = self.resourceType()
+ rtype = davxml.ResourceType(*([child for child in rtype.children if child != customxml.SharedOwner()]))
+ self.writeDeadProperty(rtype)
+
+ # Remove all invitees
+
+ # Remove invite property
+ self.removeDeadProperty(customxml.Invite)
+
+ return succeed(True)
+
+ def addUserToShare(self, userid, request, ace):
+ """ Add a user to this shared calendar """
+ return succeed(True)
+
+ def removeUserFromShare(self, userid, request):
+ """ Remove a user from this shared calendar """
+ return succeed(True)
+
+ def isShared(self, request):
+ """ Return True if this is an owner shared calendar collection """
+ return succeed(self.isSpecialCollection(customxml.SharedOwner))
+
+ def isVirtualShare(self, request):
+ """ Return True if this is a shared calendar collection """
+ return succeed(self.isSpecialCollection(customxml.Shared))
+
+ def removeVirtualShare(self, request):
+ """ As user of a shared calendar, unlink this calendar collection """
+ return succeed(False)
+
+ def getInviteUsers(self, request):
+ return succeed(True)
+
+ def sendNotificationOnChange(self, icalendarComponent, request, state="added"):
+ """ Possibly send a push and or email notification on a change to a resource in a shared collection """
+ return succeed(True)
Modified: CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/static.py
===================================================================
--- CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/static.py 2010-03-02 21:20:30 UTC (rev 5230)
+++ CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/static.py 2010-03-02 21:23:49 UTC (rev 5231)
@@ -181,12 +181,6 @@
# CalDAV
##
- def resourceType(self):
- if self.isCalendarCollection():
- return davxml.ResourceType.calendar
- else:
- return super(CalDAVFile, self).resourceType()
-
def createCalendar(self, request):
#
# request object is required because we need to validate against parent
Added: CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/test/test_sharing.py
===================================================================
--- CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/test/test_sharing.py (rev 0)
+++ CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/test/test_sharing.py 2010-03-02 21:23:49 UTC (rev 5231)
@@ -0,0 +1,66 @@
+##
+# Copyright (c) 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.
+# 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.
+##
+
+
+from twistedcaldav.test.util import InMemoryPropertyStore
+from twistedcaldav.test.util import TestCase
+from twext.web2.dav import davxml
+from twistedcaldav.static import CalDAVFile
+from twistedcaldav import customxml
+from twisted.internet.defer import inlineCallbacks
+import os
+
+
+class SharingTests(TestCase):
+ def setUp(self):
+ TestCase.setUp(self)
+ collection = self.mktemp()
+ os.mkdir(collection)
+ self.resource = CalDAVFile(collection)
+ self.resource._dead_properties = InMemoryPropertyStore()
+
+ @inlineCallbacks
+ def test_upgradeToShare(self):
+ self.resource.writeDeadProperty(davxml.ResourceType.calendar)
+ self.assertEquals(self.resource.resourceType(), davxml.ResourceType.calendar)
+ self.assertFalse(self.resource.hasDeadProperty(customxml.Invite()))
+
+ yield self.resource.upgradeToShare(None)
+
+ self.assertEquals(self.resource.resourceType(), davxml.ResourceType.sharedcalendar)
+ self.assertEquals(self.resource.readDeadProperty(customxml.Invite), customxml.Invite())
+
+ isShared = (yield self.resource.isShared(None))
+ self.assertTrue(isShared)
+ isVShared = (yield self.resource.isVirtualShare(None))
+ self.assertFalse(isVShared)
+
+ @inlineCallbacks
+ def test_downgradeFromShare(self):
+ self.resource.writeDeadProperty(davxml.ResourceType.sharedcalendar)
+ self.resource.writeDeadProperty(customxml.Invite())
+ self.assertEquals(self.resource.resourceType(), davxml.ResourceType.sharedcalendar)
+ self.assertEquals(self.resource.readDeadProperty(customxml.Invite), customxml.Invite())
+
+ yield self.resource.downgradeFromShare(None)
+
+ self.assertEquals(self.resource.resourceType(), davxml.ResourceType.calendar)
+ self.assertFalse(self.resource.hasDeadProperty(customxml.Invite()))
+
+ isShared = (yield self.resource.isShared(None))
+ self.assertFalse(isShared)
+ isVShared = (yield self.resource.isVirtualShare(None))
+ self.assertFalse(isVShared)
Modified: CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/test/util.py
===================================================================
--- CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/test/util.py 2010-03-02 21:20:30 UTC (rev 5230)
+++ CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/test/util.py 2010-03-02 21:23:49 UTC (rev 5231)
@@ -214,6 +214,9 @@
except KeyError:
pass
+ def contains(self, qname, uid=None):
+ qnameuid = qname + (uid,)
+ return qnameuid in self._properties
def list(self, uid=None, filterByUID=True):
results = self._properties.iterkeys()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100302/1f3f0553/attachment-0001.html>
More information about the calendarserver-changes
mailing list