[CalendarServer-changes] [5239] CalendarServer/branches/users/cdaboo/shared-calendars-5187
source_changes at macosforge.org
source_changes at macosforge.org
Thu Mar 4 08:46:54 PST 2010
Revision: 5239
http://trac.macosforge.org/projects/calendarserver/changeset/5239
Author: cdaboo at apple.com
Date: 2010-03-04 08:46:51 -0800 (Thu, 04 Mar 2010)
Log Message:
-----------
Fine grained config options for different aspects of sharing. Validate userids and return multistatus for failed
responses.
Modified Paths:
--------------
CalendarServer/branches/users/cdaboo/shared-calendars-5187/conf/caldavd-apple.plist
CalendarServer/branches/users/cdaboo/shared-calendars-5187/conf/caldavd-test.plist
CalendarServer/branches/users/cdaboo/shared-calendars-5187/conf/caldavd.plist
CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/customxml.py
CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/directory/calendar.py
CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/directory/principal.py
CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/resource.py
CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/sharing.py
CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/static.py
CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/stdconfig.py
CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/test/test_sharing.py
Modified: CalendarServer/branches/users/cdaboo/shared-calendars-5187/conf/caldavd-apple.plist
===================================================================
--- CalendarServer/branches/users/cdaboo/shared-calendars-5187/conf/caldavd-apple.plist 2010-03-04 01:50:42 UTC (rev 5238)
+++ CalendarServer/branches/users/cdaboo/shared-calendars-5187/conf/caldavd-apple.plist 2010-03-04 16:46:51 UTC (rev 5239)
@@ -477,11 +477,27 @@
<key>EnablePrivateEvents</key>
<true/>
- <!-- Shared Calendars -->
- <key>EnableSharing</key>
- <true/>
+ <!-- Shared Calendars & Address Books -->
+ <key>Sharing</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ <key>AllowExternalUsers</key>
+ <false/>
+ <key>Calendars</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ <key>AllowScheduling</key>
+ <false/>
+ </dict>
+ <key>AddressBooks</key>
+ <dict>
+ <key>Enabled</key>
+ <false/>
+ </dict>
+ </dict>
-
<!--
Miscellaneous items
-->
Modified: CalendarServer/branches/users/cdaboo/shared-calendars-5187/conf/caldavd-test.plist
===================================================================
--- CalendarServer/branches/users/cdaboo/shared-calendars-5187/conf/caldavd-test.plist 2010-03-04 01:50:42 UTC (rev 5238)
+++ CalendarServer/branches/users/cdaboo/shared-calendars-5187/conf/caldavd-test.plist 2010-03-04 16:46:51 UTC (rev 5239)
@@ -669,11 +669,27 @@
<key>EnableTimezoneService</key>
<true/>
- <!-- Shared Calendars -->
- <key>EnableSharing</key>
- <true/>
+ <!-- Shared Calendars & Address Books -->
+ <key>Sharing</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ <key>AllowExternalUsers</key>
+ <false/>
+ <key>Calendars</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ <key>AllowScheduling</key>
+ <false/>
+ </dict>
+ <key>AddressBooks</key>
+ <dict>
+ <key>Enabled</key>
+ <false/>
+ </dict>
+ </dict>
-
<!--
Miscellaneous items
-->
Modified: CalendarServer/branches/users/cdaboo/shared-calendars-5187/conf/caldavd.plist
===================================================================
--- CalendarServer/branches/users/cdaboo/shared-calendars-5187/conf/caldavd.plist 2010-03-04 01:50:42 UTC (rev 5238)
+++ CalendarServer/branches/users/cdaboo/shared-calendars-5187/conf/caldavd.plist 2010-03-04 16:46:51 UTC (rev 5239)
@@ -466,9 +466,26 @@
<key>EnablePrivateEvents</key>
<true/>
- <!-- Shared Calendars -->
- <key>EnableSharing</key>
- <true/>
+ <!-- Shared Calendars & Address Books -->
+ <key>Sharing</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ <key>AllowExternalUsers</key>
+ <false/>
+ <key>Calendars</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ <key>AllowScheduling</key>
+ <false/>
+ </dict>
+ <key>AddressBooks</key>
+ <dict>
+ <key>Enabled</key>
+ <false/>
+ </dict>
+ </dict>
<!--
Modified: CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/customxml.py
===================================================================
--- CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/customxml.py 2010-03-04 01:50:42 UTC (rev 5238)
+++ CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/customxml.py 2010-03-04 16:46:51 UTC (rev 5239)
@@ -681,6 +681,7 @@
(calendarserver_namespace, "invite-deleted" ) : (0, 1),
(calendarserver_namespace, "invite-accepted" ) : (0, 1),
(calendarserver_namespace, "invite-declined" ) : (0, 1),
+ (calendarserver_namespace, "invite-invalid" ) : (0, 1),
}
class InviteAccess (davxml.WebDAVElement):
@@ -720,6 +721,10 @@
namespace = calendarserver_namespace
name = "invite-declined"
+class InviteStatusInvalid (davxml.WebDAVEmptyElement):
+ namespace = calendarserver_namespace
+ name = "invite-invalid"
+
class HostURL (davxml.WebDAVElement):
"""
The source for a shared calendar
Modified: CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/directory/calendar.py
===================================================================
--- CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/directory/calendar.py 2010-03-04 01:50:42 UTC (rev 5238)
+++ CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/directory/calendar.py 2010-03-04 16:46:51 UTC (rev 5239)
@@ -278,7 +278,7 @@
childlist += (
("freebusy", FreeBusyURLResource),
)
- if config.EnableSharing:
+ if config.Sharing.Enabled and config.Sharing.Calendars.Enabled:
childlist += (
("notification", NotificationCollectionResource),
)
Modified: CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/directory/principal.py 2010-03-04 01:50:42 UTC (rev 5238)
+++ CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/directory/principal.py 2010-03-04 16:46:51 UTC (rev 5239)
@@ -895,7 +895,7 @@
def notificationCollection(self, request):
notification = None
- if config.EnableSharing:
+ if config.Sharing.Enabled:
home = self.calendarHome()
if home is not None:
notification = home.getChild("notification")
@@ -919,7 +919,7 @@
return None
def notificationURL(self):
- if config.EnableSharing:
+ if config.Sharing.Enabled:
return self._homeChildURL("notification/")
else:
return None
Modified: CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/resource.py
===================================================================
--- CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/resource.py 2010-03-04 01:50:42 UTC (rev 5238)
+++ CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/resource.py 2010-03-04 16:46:51 UTC (rev 5239)
@@ -114,7 +114,7 @@
extra_compliance += customxml.calendarserver_principal_property_search_compliance
if config.EnableCardDAV:
extra_compliance += carddavxml.carddav_compliance
- if config.EnableSharing:
+ if config.Sharing.Enabled:
extra_compliance += customxml.calendarserver_sharing_compliance
return tuple(super(CalDAVComplianceMixIn, self).davComplianceClasses()) + extra_compliance
@@ -421,7 +421,7 @@
elif property.qname() == (dav_namespace, "resourcetype"):
if self.isCalendarCollection():
sawShare = [child for child in property.children if child.qname() == (calendarserver_namespace, "shared-owner")]
- if not config.EnableSharing:
+ if not (config.Sharing.Enabled and config.Sharing.Calendars.Enabled):
raise HTTPError(StatusResponse(
responsecode.FORBIDDEN,
"Cannot create shared calendars on this server.",
@@ -1103,7 +1103,7 @@
else:
returnValue(customxml.DropBoxHomeURL(davxml.HRef(url)))
- elif name == "notification-URL" and config.EnableSharing:
+ elif name == "notification-URL" and config.Sharing.Enabled:
url = yield self.notificationURL()
if url is None:
returnValue(None)
Modified: CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/sharing.py
===================================================================
--- CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/sharing.py 2010-03-04 01:50:42 UTC (rev 5238)
+++ CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/sharing.py 2010-03-04 16:46:51 UTC (rev 5239)
@@ -13,10 +13,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
##
-from twisted.internet.defer import succeed, inlineCallbacks, DeferredList
+from twisted.internet.defer import succeed, inlineCallbacks, DeferredList,\
+ returnValue
from twext.web2 import responsecode
from twext.web2.http import HTTPError, Response
-from twext.web2.dav.http import ErrorResponse
+from twext.web2.dav.http import ErrorResponse, MultiStatusResponse
from twext.web2.dav.util import allDataFromStream
from twext.web2.dav.element.base import PCDATAElement
from twistedcaldav.sql import AbstractSQLDatabase, db_prefix
@@ -48,7 +49,8 @@
# Build the CS:invite property from our DB
def sharedOK(isShared):
- if config.EnableSharing and isShared:
+ if config.Sharing.Enabled and isShared:
+ self.validateInvites()
return customxml.Invite(
*[record.makePropertyElement() for record in self.invitesDB().allRecords()]
)
@@ -98,6 +100,41 @@
""" Return True if this is a shared calendar collection """
return succeed(self.isSpecialCollection(customxml.Shared))
+ def validUserIDForShare(self, userid):
+ """
+ Test the user id to see if it is a valid identifier for sharing and return a "normalized"
+ form for our own use (e.g. convert mailto: to urn:uuid).
+
+ @param userid: the userid to test
+ @type userid: C{str}
+
+ @return: C{str} of normalized userid or C{None} if
+ userid is not allowed.
+ """
+
+ # First try to resolve as a principal
+ principal = self.principalForCalendarUserAddress(userid)
+ if principal:
+ return principal.principalURL()
+
+ # TODO: we do not support external users right now so this is being hard-coded
+ # off in spite of the config option.
+ #elif config.Sharing.AllowExternalUsers:
+ # return userid
+ else:
+ return None
+
+ def validateInvites(self):
+ """
+ Make sure each userid in an invite is valid - if not re-write status.
+ """
+
+ records = self.invitesDB().allRecords()
+ for record in records:
+ if self.validUserIDForShare(record.userid) is None and record.state != "INVALID":
+ record.state = "INVALID"
+ self.invitesDB().addOrUpdateRecord(record)
+
def removeVirtualShare(self, request):
""" As user of a shared calendar, unlink this calendar collection """
return succeed(False)
@@ -114,6 +151,12 @@
@param userid:
@param ace: Must be one of customxml.ReadWriteAccess or customxml.ReadAccess
"""
+
+ # Check for valid userid first
+ userid = self.validUserIDForShare(userid)
+ if userid is None:
+ return succeed(False)
+
# TODO: Check if this collection is shared, and error out if it isn't
hosturl = self.fp.path
if type(userid) is not list:
@@ -122,17 +165,29 @@
commonName = [commonName]
if type(shareName) is not list:
shareName = [shareName]
+
dl = [self.inviteSingleUserToShare(user, ace, summary, hosturl, request, cn=cn, sn=sn) for user, cn, sn in zip(userid, commonName, shareName)]
- return DeferredList(dl)
+ return DeferredList(dl).addCallback(lambda _:True)
def uninviteUserToShare(self, userid, ace, request):
""" Send out in uninvite first, and then remove this user from the share list."""
+
+ # Do not validate the userid - we want to allow invalid users to be removed because they
+ # may have been valid when added, but no longer valid now. Clients should be able to clear out
+ # anything known to be invalid.
+
# TODO: Check if this collection is shared, and error out if it isn't
if type(userid) is not list:
userid = [userid]
- return DeferredList([self.uninviteSingleUserFromShare(user, ace, request) for user in userid])
+ return DeferredList([self.uninviteSingleUserFromShare(user, ace, request) for user in userid]).addCallback(lambda _:True)
def inviteUserUpdateToShare(self, userid, aceOLD, aceNEW, summary, request, commonName="", shareName=""):
+
+ # Check for valid userid first
+ userid = self.validUserIDForShare(userid)
+ if userid is None:
+ return succeed(False)
+
hosturl = self.fp.path
if type(userid) is not list:
userid = [userid]
@@ -141,7 +196,7 @@
if type(shareName) is not list:
shareName = [shareName]
dl = [self.inviteSingleUserUpdateToShare(user, aceOLD, aceNEW, summary, hosturl, request, commonName=cn, shareName=sn) for user, cn, sn in zip(userid, commonName, shareName)]
- return DeferredList(dl)
+ return DeferredList(dl).addCallback(lambda _:True)
def inviteSingleUserToShare(self, userid, ace, summary, hosturl, request, cn="", sn=""):
@@ -168,9 +223,6 @@
return self.inviteSingleUserToShare(userid, aceNEW, summary, hosturl, request, commonName, shareName)
def xmlPOSTNoAuth(self, encoding, request):
- def _handleResponse(result):
- return Response(code=responsecode.OK)
-
def _handleErrorResponse(error):
if isinstance(error.value, HTTPError) and hasattr(error.value, "response"):
return error.value.response
@@ -259,6 +311,8 @@
removeDict[userid] = access
# Special case removing and adding the same user and treat that as an add
+ okusers = set()
+ badusers = set()
sameUseridInRemoveAndSet = [u for u in removeDict.keys() if u in setDict]
for u in sameUseridInRemoveAndSet:
removeACL = removeDict[u]
@@ -267,12 +321,38 @@
del removeDict[u]
del setDict[u]
for userid, access in removeDict.iteritems():
- yield self.uninviteUserToShare(userid, access, request)
+ result = (yield self.uninviteUserToShare(userid, access, request))
+ (okusers if result else badusers).add(userid)
for userid, (access, summary) in setDict.iteritems():
- yield self.inviteUserToShare(userid, access, summary, request)
+ result = (yield self.inviteUserToShare(userid, access, summary, request))
+ (okusers if result else badusers).add(userid)
for userid, (removeACL, newACL, summary) in updateinviteDict.iteritems():
- yield self.inviteUserUpdateToShare(userid, removeACL, newACL, summary, request)
+ result = (yield self.inviteUserUpdateToShare(userid, removeACL, newACL, summary, request))
+ (okusers if result else badusers).add(userid)
+ # Do a final validation of the entire set of invites
+ self.validateInvites()
+
+ # Create the multistatus response - only needed if some are bad
+ if badusers:
+ xml_responses = []
+ xml_responses.extend([
+ davxml.StatusResponse(davxml.HRef(userid), davxml.Status.fromResponseCode(responsecode.OK))
+ for userid in sorted(okusers)
+ ])
+ xml_responses.extend([
+ davxml.StatusResponse(davxml.HRef(userid), davxml.Status.fromResponseCode(responsecode.FORBIDDEN))
+ for userid in sorted(badusers)
+ ])
+
+ #
+ # Return response
+ #
+ returnValue(MultiStatusResponse(xml_responses))
+ else:
+ returnValue(responsecode.OK)
+
+
return self.isShared(request).addCallback(_autoShare, request).addCallback(_processInviteDoc, request)
def _getData(data):
@@ -287,7 +367,7 @@
customxml.InviteShare: _handleInvite,
}
if type(root) in xmlDocHanders:
- return xmlDocHanders[type(root)](root).addCallbacks(_handleResponse, errback=_handleErrorResponse)
+ return xmlDocHanders[type(root)](root).addErrback(_handleErrorResponse)
else:
self.log_error("Unsupported XML (%s)" % (root,))
raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (customxml.calendarserver_namespace, "valid-request-content")))
@@ -332,13 +412,14 @@
}
inviteAccessMapFromXML = dict([(v,k) for k,v in inviteAccessMapToXML.iteritems()])
-inviteAcceptMapToXML = {
+inviteStatusMapToXML = {
"NEEDS-ACTION" : customxml.InviteStatusNoResponse,
"ACCEPTED" : customxml.InviteStatusAccepted,
"DECLINED" : customxml.InviteStatusDeclined,
"DELETED" : customxml.InviteStatusDeleted,
+ "INVALID" : customxml.InviteStatusInvalid,
}
-inviteAcceptMapFromXML = dict([(v,k) for k,v in inviteAcceptMapToXML.iteritems()])
+inviteStatusMapFromXML = dict([(v,k) for k,v in inviteStatusMapToXML.iteritems()])
class Invite(object):
@@ -355,7 +436,7 @@
customxml.UID.fromString(self.inviteuid),
davxml.HRef.fromString(self.userid),
customxml.InviteAccess(inviteAccessMapToXML[self.access]()),
- inviteAcceptMapToXML[self.state](),
+ inviteStatusMapToXML[self.state](),
)
class InvitesDatabase(AbstractSQLDatabase, LoggingMixIn):
Modified: CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/static.py
===================================================================
--- CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/static.py 2010-03-04 01:50:42 UTC (rev 5238)
+++ CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/static.py 2010-03-04 16:46:51 UTC (rev 5239)
@@ -943,7 +943,7 @@
else:
FreeBusyURLFileClass = None
- if config.EnableSharing:
+ if config.Sharing.Enabled:
NotificationCollectionFileClass = NotificationCollectionFile
else:
NotificationCollectionFileClass = None
Modified: CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/stdconfig.py
===================================================================
--- CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/stdconfig.py 2010-03-04 01:50:42 UTC (rev 5238)
+++ CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/stdconfig.py 2010-03-04 16:46:51 UTC (rev 5239)
@@ -330,8 +330,20 @@
"EnableDropBox" : False, # Calendar Drop Box
"EnablePrivateEvents" : False, # Private Events
"EnableTimezoneService" : False, # Timezone service
- "EnableSharing" : False, # Sharing
+
+ "Sharing": {
+ "Enabled" : False, # Overall on/off switch
+ "AllowExternalUsers" : False, # External (non-principal) sharees allowed
+ "Calendars" : {
+ "Enabled" : False, # Calendar on/off switch
+ "AllowScheduling" : False, # Scheduling in shared calendars
+ },
+ "AddressBooks" : {
+ "Enabled" : False, # Address Books on/off switch
+ }
+ },
+
#
# Web-based administration
#
@@ -904,8 +916,8 @@
# FIXME: Use the config object instead of doing this here
#
from twistedcaldav.resource import CalDAVResource, CalendarPrincipalResource
- CalDAVResource.enableSharing(configDict.EnableSharing)
- CalendarPrincipalResource.enableSharing(configDict.EnableSharing)
+ CalDAVResource.enableSharing(configDict.Sharing.Enabled)
+ CalendarPrincipalResource.enableSharing(configDict.Sharing.Enabled)
def _updatePartitions(configDict):
#
Modified: CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/test/test_sharing.py
===================================================================
--- CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/test/test_sharing.py 2010-03-04 01:50:42 UTC (rev 5238)
+++ CalendarServer/branches/users/cdaboo/shared-calendars-5187/twistedcaldav/test/test_sharing.py 2010-03-04 16:46:51 UTC (rev 5239)
@@ -15,39 +15,55 @@
##
+from twext.web2 import responsecode
+from twext.web2.dav import davxml
+from twext.web2.http_headers import MimeType
+from twext.web2.stream import MemoryStream
+from twext.web2.test.test_server import SimpleRequest
+from twisted.internet.defer import inlineCallbacks, returnValue
+from twistedcaldav import customxml
+from twistedcaldav.config import config
+from twistedcaldav.static import CalDAVFile
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, returnValue
import os
-from twistedcaldav.config import config
-from twext.web2.test.test_server import SimpleRequest
-from twext.web2.stream import MemoryStream
-from twext.web2.http_headers import MimeType
-from twext.web2 import responsecode
class SharingTests(TestCase):
def setUp(self):
- TestCase.setUp(self)
- config.EnableSharing = True
+ super(SharingTests, self).setUp()
+ config.Sharing.Enabled = True
+ config.Sharing.Calendars.Enabled = True
collection = self.mktemp()
os.mkdir(collection)
self.resource = CalDAVFile(collection, self.site.resource)
self.resource._dead_properties = InMemoryPropertyStore()
self.site.resource.putChild("calendar", self.resource)
+
+ self.resource.validUserIDForShare = self._fakeValidUserID
+
+ def _fakeValidUserID(self, userid):
+ if userid.endswith("@example.com"):
+ return userid
+ else:
+ return None
+ def _fakeInvalidUserID(self, userid):
+ if userid.endswith("@example.net"):
+ return userid
+ else:
+ return None
+
@inlineCallbacks
- def _doPOST(self, body):
+ def _doPOST(self, body, resultcode = responsecode.OK):
request = SimpleRequest(self.site, "POST", "/calendar/")
request.headers.setHeader("content-type", MimeType("text", "xml"))
request.stream = MemoryStream(body)
response = (yield self.send(request, None))
- self.assertEqual(response.code, responsecode.OK)
+ self.assertEqual(response.code, resultcode)
+ returnValue(response)
def _clearUIDElementValue(self, xml):
@@ -359,3 +375,81 @@
customxml.InviteStatusNoResponse(),
),
))
+
+ @inlineCallbacks
+ def test_POSTaddInvalidInvitee(self):
+
+ yield self.resource.upgradeToShare(None)
+
+ response = (yield self._doPOST("""<?xml version="1.0" encoding="utf-8" ?>
+<CS:share xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/">
+ <CS:set>
+ <D:href>mailto:bogus at example.net</D:href>
+ <CS:summary>My Shared Calendar</CS:summary>
+ <CS:read-write/>
+ </CS:set>
+</CS:share>
+""",
+ responsecode.MULTI_STATUS
+ ))
+
+ self.assertEqual(
+ str(response.stream.read()).replace("\r\n", "\n"),
+ """<?xml version='1.0' encoding='UTF-8'?><multistatus xmlns='DAV:'>
+ <response>
+ <href>mailto:bogus at example.net</href>
+ <status>HTTP/1.1 403 Forbidden</status>
+ </response>
+</multistatus>"""
+ )
+
+ propInvite = (yield self.resource.readProperty(customxml.Invite, None))
+ self.assertEquals(self._clearUIDElementValue(propInvite), customxml.Invite())
+
+ @inlineCallbacks
+ def test_POSTremoveInvalidInvitee(self):
+
+ yield self.resource.upgradeToShare(None)
+
+ yield self._doPOST("""<?xml version="1.0" encoding="utf-8" ?>
+<CS:share xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/">
+ <CS:set>
+ <D:href>mailto:user01 at example.com</D:href>
+ <CS:summary>My Shared Calendar</CS:summary>
+ <CS:read-write/>
+ </CS:set>
+</CS:share>
+""")
+
+ propInvite = (yield self.resource.readProperty(customxml.Invite, None))
+ self.assertEquals(self._clearUIDElementValue(propInvite), customxml.Invite(
+ customxml.InviteUser(
+ customxml.UID.fromString(""),
+ davxml.HRef.fromString("mailto:user01 at example.com"),
+ customxml.InviteAccess(customxml.ReadWriteAccess()),
+ customxml.InviteStatusNoResponse(),
+ )
+ ))
+
+ self.resource.validUserIDForShare = self._fakeInvalidUserID
+
+ propInvite = (yield self.resource.readProperty(customxml.Invite, None))
+ self.assertEquals(self._clearUIDElementValue(propInvite), customxml.Invite(
+ customxml.InviteUser(
+ customxml.UID.fromString(""),
+ davxml.HRef.fromString("mailto:user01 at example.com"),
+ customxml.InviteAccess(customxml.ReadWriteAccess()),
+ customxml.InviteStatusInvalid(),
+ )
+ ))
+
+ yield self._doPOST("""<?xml version="1.0" encoding="utf-8" ?>
+<CS:share xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/">
+ <CS:remove>
+ <D:href>mailto:user01 at example.com</D:href>
+ </CS:remove>
+</CS:share>
+""")
+
+ propInvite = (yield self.resource.readProperty(customxml.Invite, None))
+ self.assertEquals(self._clearUIDElementValue(propInvite), customxml.Invite())
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100304/0265edd4/attachment-0001.html>
More information about the calendarserver-changes
mailing list