[CalendarServer-changes] [11589] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Wed Aug 7 08:42:31 PDT 2013
Revision: 11589
http://trac.calendarserver.org//changeset/11589
Author: cdaboo at apple.com
Date: 2013-08-07 08:42:31 -0700 (Wed, 07 Aug 2013)
Log Message:
-----------
Make sure sharer can remove invalid sharees from shares. Add some tests for invalid sharer/sharee situations.
Modified Paths:
--------------
CalendarServer/trunk/conf/auth/augments.dtd
CalendarServer/trunk/twistedcaldav/sharing.py
CalendarServer/trunk/twistedcaldav/test/test_sharing.py
Modified: CalendarServer/trunk/conf/auth/augments.dtd
===================================================================
--- CalendarServer/trunk/conf/auth/augments.dtd 2013-08-07 00:04:36 UTC (rev 11588)
+++ CalendarServer/trunk/conf/auth/augments.dtd 2013-08-07 15:42:31 UTC (rev 11589)
@@ -16,7 +16,17 @@
<!ELEMENT augments (record*) >
- <!ELEMENT record (uid, enable, (server-id, partition-id?)?, enable-calendar?, enable-addressbook?, auto-schedule?, auto-schedule-mode?, auto-accept-group?)>
+ <!ELEMENT record (
+ uid,
+ enable,
+ (server-id, partition-id?)?,
+ enable-calendar?,
+ enable-addressbook?,
+ enable-login?,
+ auto-schedule?,
+ auto-schedule-mode?,
+ auto-accept-group?
+ )>
<!ATTLIST record repeat CDATA "1">
<!ELEMENT uid (#PCDATA)>
@@ -25,6 +35,7 @@
<!ELEMENT partition-id (#PCDATA)>
<!ELEMENT enable-calendar (#PCDATA)>
<!ELEMENT enable-addressbook (#PCDATA)>
+ <!ELEMENT enable-login (#PCDATA)>
<!ELEMENT auto-schedule (#PCDATA)>
<!ELEMENT auto-schedule-mode (#PCDATA)>
<!ELEMENT auto-accept-group (#PCDATA)>
Modified: CalendarServer/trunk/twistedcaldav/sharing.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/sharing.py 2013-08-07 00:04:36 UTC (rev 11588)
+++ CalendarServer/trunk/twistedcaldav/sharing.py 2013-08-07 15:42:31 UTC (rev 11589)
@@ -268,6 +268,9 @@
@inlineCallbacks
def removeShareeResource(self, request):
+ """
+ Called when the sharee DELETEs a shared collection.
+ """
sharee = self.principalForUID(self._share.shareeUID())
@@ -616,7 +619,7 @@
@inlineCallbacks
- def inviteSingleUserToShare(self, userid, cn, ace, summary, request): #@UnusedVariable
+ def inviteSingleUserToShare(self, userid, cn, ace, summary, request): #@UnusedVariable
# We currently only handle local users
sharee = self.principalForCalendarUserAddress(userid)
@@ -642,7 +645,7 @@
@inlineCallbacks
- def uninviteSingleUserFromShare(self, userid, aces, request): #@UnusedVariable
+ def uninviteSingleUserFromShare(self, userid, aces, request): #@UnusedVariable
# Cancel invites - we'll just use whatever userid we are given
sharee = self.principalForCalendarUserAddress(userid)
@@ -667,19 +670,23 @@
sharee = self.principalForUID(invitation.shareeUID())
if sharee:
previousInvitationStatus = invitation.status()
+ displayName = None
if self.isCalendarCollection():
shareeHomeResource = yield sharee.calendarHome(request)
- displayName = yield shareeHomeResource.removeShareByUID(request, invitation.uid())
+ if shareeHomeResource is not None:
+ displayName = yield shareeHomeResource.removeShareByUID(request, invitation.uid())
elif self.isAddressBookCollection() or self.isGroup():
shareeHomeResource = yield sharee.addressBookHome(request)
- yield shareeHomeResource.removeShareByUID(request, invitation.uid())
- displayName = None
+ if shareeHomeResource is not None:
+ yield shareeHomeResource.removeShareByUID(request, invitation.uid())
+
# If current user state is accepted then we send an invite with the new state, otherwise
# we cancel any existing invites for the user
- if previousInvitationStatus != _BIND_STATUS_ACCEPTED:
- yield self.removeInviteNotification(invitation, request)
- else:
- yield self.sendInviteNotification(invitation, request, displayName=displayName, notificationState="DELETED")
+ if shareeHomeResource is not None:
+ if previousInvitationStatus != _BIND_STATUS_ACCEPTED:
+ yield self.removeInviteNotification(invitation, request)
+ else:
+ yield self.sendInviteNotification(invitation, request, displayName=displayName, notificationState="DELETED")
# Direct shares for with valid sharee principal will already be deleted
yield self._newStoreObject.unshareWithUID(invitation.shareeUID())
@@ -687,7 +694,7 @@
returnValue(True)
- def inviteSingleUserUpdateToShare(self, userid, commonName, acesOLD, aceNEW, summary, request): #@UnusedVariable
+ def inviteSingleUserUpdateToShare(self, userid, commonName, acesOLD, aceNEW, summary, request): #@UnusedVariable
# Just update existing
return self.inviteSingleUserToShare(userid, commonName, aceNEW, summary, request)
@@ -1111,7 +1118,6 @@
@inlineCallbacks
def acceptInviteShare(self, request, hostUrl, inviteUID, displayname=None):
-
# Check for old share
oldShare = yield self._shareForUID(inviteUID, request)
Modified: CalendarServer/trunk/twistedcaldav/test/test_sharing.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_sharing.py 2013-08-07 00:04:36 UTC (rev 11588)
+++ CalendarServer/trunk/twistedcaldav/test/test_sharing.py 2013-08-07 15:42:31 UTC (rev 11589)
@@ -74,6 +74,8 @@
class FakePrincipal(DirectoryCalendarPrincipalResource):
+ invalid_names = set()
+
def __init__(self, cuaddr, test):
if cuaddr.startswith("mailto:"):
name = cuaddr[7:].split('@')[0]
@@ -92,6 +94,8 @@
@inlineCallbacks
def calendarHome(self, request):
+ if self._name in self.invalid_names:
+ returnValue(None)
a, _ignore_seg = yield self._test.calendarCollection.locateChild(request, ["__uids__"])
b, _ignore_seg = yield a.locateChild(request, [self._name])
if b is None:
@@ -216,6 +220,38 @@
returnValue(resource)
+ @inlineCallbacks
+ def _doPOSTSharerAccept(self, body, resultcode=responsecode.OK):
+ request = SimpleStoreRequest(self, "POST", "/calendars/__uids__/user02/", content=body, authid="user02")
+ request.headers.setHeader("content-type", MimeType("text", "xml"))
+ response = yield self.send(request)
+ response = IResponse(response)
+ self.assertEqual(response.code, resultcode)
+
+ if response.stream:
+ xmldata = yield allDataFromStream(response.stream)
+ doc = WebDAVDocument.fromString(xmldata)
+ returnValue(doc)
+ else:
+ returnValue(None)
+
+
+ @inlineCallbacks
+ def _getResourceSharer(self, name):
+ request = SimpleStoreRequest(self, "GET", "%s" % (name,))
+ resource = yield request.locateResource("%s" % (name,))
+ returnValue(resource)
+
+
+ def _getUIDElementValue(self, xml):
+
+ for user in xml.children:
+ for element in user.children:
+ if type(element) == customxml.UID:
+ return element.children[0].data
+ return None
+
+
def _clearUIDElementValue(self, xml):
for user in xml.children:
@@ -225,6 +261,14 @@
return xml
+ def _getHRefElementValue(self, xml):
+
+ for href in xml.root_element.children:
+ if type(href) == davxml.HRef:
+ return href.children[0].data
+ return None
+
+
@inlineCallbacks
def test_upgradeToShare(self):
@@ -781,3 +825,129 @@
access = "no-access"
childNames = yield listChildrenViaPropfind()
self.assertNotIn(sharedName, childNames)
+
+
+ @inlineCallbacks
+ def test_POSTDowngradeWithDisabledInvitee(self):
+
+ yield self.resource.upgradeToShare()
+
+ 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:user02 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("urn:uuid:user02"),
+ customxml.CommonName.fromString("USER02"),
+ customxml.InviteAccess(customxml.ReadWriteAccess()),
+ customxml.InviteStatusNoResponse(),
+ ),
+ ))
+
+ self.patch(FakePrincipal, "invalid_names", set(("user02",)))
+ yield self.resource.downgradeFromShare(norequest())
+
+
+ @inlineCallbacks
+ def test_POSTRemoveWithDisabledInvitee(self):
+
+ yield self.resource.upgradeToShare()
+
+ 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:user02 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("urn:uuid:user02"),
+ customxml.CommonName.fromString("USER02"),
+ customxml.InviteAccess(customxml.ReadWriteAccess()),
+ customxml.InviteStatusNoResponse(),
+ ),
+ ))
+
+ self.patch(FakePrincipal, "invalid_names", set(("user02",)))
+
+ 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:user02 at example.com</D:href>
+ </CS:remove>
+ </CS:share>
+ """)
+
+ isShared = self.resource.isShared()
+ self.assertFalse(isShared)
+
+ propInvite = (yield self.resource.readProperty(customxml.Invite, None))
+ self.assertEquals(propInvite, None)
+
+
+ @inlineCallbacks
+ def test_POSTShareeRemoveWithDisabledSharer(self):
+
+ yield self.resource.upgradeToShare()
+
+ 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:user02 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))
+ uid = self._getUIDElementValue(propInvite)
+ self.assertEquals(self._clearUIDElementValue(propInvite), customxml.Invite(
+ customxml.InviteUser(
+ customxml.UID.fromString(""),
+ davxml.HRef.fromString("urn:uuid:user02"),
+ customxml.CommonName.fromString("USER02"),
+ customxml.InviteAccess(customxml.ReadWriteAccess()),
+ customxml.InviteStatusNoResponse(),
+ ),
+ ))
+
+ result = (yield self._doPOSTSharerAccept("""<?xml version='1.0' encoding='UTF-8'?>
+ <invite-reply xmlns='http://calendarserver.org/ns/'>
+ <href xmlns='DAV:'>mailto:user01 at example.com</href>
+ <invite-accepted/>
+ <hosturl>
+ <href xmlns='DAV:'>/calendars/__uids__/user01/calendar/</href>
+ </hosturl>
+ <in-reply-to>%s</in-reply-to>
+ <summary>The Shared Calendar</summary>
+ <common-name>User 02</common-name>
+ <first-name>user</first-name>
+ <last-name>02</last-name>
+ </invite-reply>
+ """ % (uid,))
+ )
+ href = self._getHRefElementValue(result) + "/"
+
+ self.patch(FakePrincipal, "invalid_names", set(("user01",)))
+
+ resource = (yield self._getResourceSharer(href))
+ yield resource.removeShareeResource(SimpleStoreRequest(self, "DELETE", href))
+
+ resource = (yield self._getResourceSharer(href))
+ self.assertFalse(resource.exists())
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130807/a6a38538/attachment-0001.html>
More information about the calendarserver-changes
mailing list