[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