[CalendarServer-changes] [7295] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Thu Apr 7 11:30:27 PDT 2011


Revision: 7295
          http://trac.macosforge.org/projects/calendarserver/changeset/7295
Author:   cdaboo at apple.com
Date:     2011-04-07 11:30:26 -0700 (Thu, 07 Apr 2011)
Log Message:
-----------
Fix sharing of multiple items to the same user.

Modified Paths:
--------------
    CalendarServer/trunk/twistedcaldav/resource.py
    CalendarServer/trunk/twistedcaldav/sharing.py
    CalendarServer/trunk/twistedcaldav/storebridge.py
    CalendarServer/trunk/txdav/common/datastore/sql_legacy.py

Modified: CalendarServer/trunk/twistedcaldav/resource.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/resource.py	2011-04-07 18:28:06 UTC (rev 7294)
+++ CalendarServer/trunk/twistedcaldav/resource.py	2011-04-07 18:30:26 UTC (rev 7295)
@@ -1178,7 +1178,14 @@
                 return principal
         return None
 
+    def principalForUID(self, principalUID):
+        for principalCollection in self.principalCollections():
+            principal = principalCollection.principalForUID(principalUID)
+            if principal is not None:
+                return principal
+        return None
 
+
     @inlineCallbacks
     def vCard(self):
         """

Modified: CalendarServer/trunk/twistedcaldav/sharing.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/sharing.py	2011-04-07 18:28:06 UTC (rev 7294)
+++ CalendarServer/trunk/twistedcaldav/sharing.py	2011-04-07 18:30:26 UTC (rev 7295)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.test.test_sharing -*-
 ##
-# Copyright (c) 2010 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2011 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.
@@ -102,12 +102,6 @@
 
 
     @inlineCallbacks
-    def removeUserFromInvite(self, userid, request):
-        """ Remove a user from this shared calendar """
-        returnValue((yield self.invitesDB().removeRecordForUserID(userid)))
-
-
-    @inlineCallbacks
     def changeUserInviteState(self, request, inviteUID, principalURL, state, summary=None):
         shared = (yield self.isShared(request))
         if not shared:
@@ -116,9 +110,10 @@
                 (customxml.calendarserver_namespace, "valid-request"),
                 "Invalid share",
             ))
-            
+        
+        principalUID = principalURL.split("/")[3]
         record = yield self.invitesDB().recordForInviteUID(inviteUID)
-        if record is None or record.principalURL != principalURL:
+        if record is None or record.principalUID != principalUID:
             raise HTTPError(ErrorResponse(
                 responsecode.FORBIDDEN,
                 (customxml.calendarserver_namespace, "valid-request"),
@@ -480,13 +475,14 @@
             returnValue(False)
 
         # Look for existing invite and update its fields or create new one
-        record = yield self.invitesDB().recordForPrincipalURL(principalURL)
+        principalUID = principalURL.split("/")[3]
+        record = yield self.invitesDB().recordForPrincipalUID(principalUID)
         if record:
             record.name = cn
             record.access = inviteAccessMapFromXML[type(ace)]
             record.summary = summary
         else:
-            record = Invite(str(uuid4()), userid, principalURL, cn, inviteAccessMapFromXML[type(ace)], "NEEDS-ACTION", summary)
+            record = Invite(str(uuid4()), userid, principalUID, cn, inviteAccessMapFromXML[type(ace)], "NEEDS-ACTION", summary)
         
         # Send invite
         yield self.sendInvite(record, request)
@@ -529,7 +525,7 @@
                 yield self.sendInvite(record, request)
     
         # Remove from database
-        yield self.invitesDB().removeRecordForUserID(record.userid)
+        yield self.invitesDB().removeRecordForInviteUID(record.inviteuid)
         
         returnValue(True)            
 
@@ -802,10 +798,10 @@
 
 class Invite(object):
     
-    def __init__(self, inviteuid, userid, principalURL, common_name, access, state, summary):
+    def __init__(self, inviteuid, userid, principalUID, common_name, access, state, summary):
         self.inviteuid = inviteuid
         self.userid = userid
-        self.principalURL = principalURL
+        self.principalUID = principalUID
         self.name = common_name
         self.access = access
         self.state = state
@@ -862,9 +858,9 @@
         row = self._db_execute("select * from INVITE where USERID = :1", userid)
         return self._makeRecord(row[0]) if row else None
     
-    def recordForPrincipalURL(self, principalURL):
+    def recordForPrincipalUID(self, principalUID):
         
-        row = self._db_execute("select * from INVITE where PRINCIPALURL = :1", principalURL)
+        row = self._db_execute("select * from INVITE where PRINCIPALUID = :1", principalUID)
         return self._makeRecord(row[0]) if row else None
     
     def recordForInviteUID(self, inviteUID):
@@ -874,15 +870,11 @@
     
     def addOrUpdateRecord(self, record):
 
-        self._db_execute("""insert or replace into INVITE (INVITEUID, USERID, PRINCIPALURL, NAME, ACCESS, STATE, SUMMARY)
+        self._db_execute("""insert or replace into INVITE (INVITEUID, USERID, PRINCIPALUID, NAME, ACCESS, STATE, SUMMARY)
             values (:1, :2, :3, :4, :5, :6, :7)
-            """, record.inviteuid, record.userid, record.principalURL, record.name, record.access, record.state, record.summary,
+            """, record.inviteuid, record.userid, record.principalUID, record.name, record.access, record.state, record.summary,
         )
     
-    def removeRecordForUserID(self, userid):
-
-        self._db_execute("delete from INVITE where USERID = :1", userid)
-    
     def removeRecordForInviteUID(self, inviteUID):
 
         self._db_execute("delete from INVITE where INVITEUID = :1", inviteUID)
@@ -913,7 +905,7 @@
         # INVITE table is the primary table
         #   INVITEUID: UID for this invite
         #   USERID: identifier of invitee
-        #   PRINCIPALURL: principal-URL of invitee
+        #   PRINCIPALUID: principal-UID of invitee
         #   NAME: common name of invitee
         #   ACCESS: Access mode for share
         #   STATE: Invite response status
@@ -924,7 +916,7 @@
             create table INVITE (
                 INVITEUID      text unique,
                 USERID         text unique,
-                PRINCIPALURL   text unique,
+                PRINCIPALUID   text unique,
                 NAME           text,
                 ACCESS         text,
                 STATE          text,
@@ -940,7 +932,7 @@
         )
         q.execute(
             """
-            create index PRINCIPALURL on INVITE (PRINCIPALURL)
+            create index PRINCIPALUID on INVITE (PRINCIPALUID)
             """
         )
         q.execute(

Modified: CalendarServer/trunk/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/storebridge.py	2011-04-07 18:28:06 UTC (rev 7294)
+++ CalendarServer/trunk/twistedcaldav/storebridge.py	2011-04-07 18:30:26 UTC (rev 7295)
@@ -1455,10 +1455,11 @@
             proxyprivs = list(userprivs)
             proxyprivs.remove(davxml.Privilege(davxml.ReadACL()))
 
+            principal = self.principalForUID(record.principalUID)
             aces += (
                 # Inheritable specific access for the resource's associated principal.
                 davxml.ACE(
-                    davxml.Principal(davxml.HRef(record.principalURL)),
+                    davxml.Principal(davxml.HRef(principal.principalURL())),
                     davxml.Grant(*userprivs),
                     davxml.Protected(),
                     TwistedACLInheritable(),
@@ -1469,7 +1470,7 @@
                 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(record.principalURL, "calendar-proxy-read/"))),
+                        davxml.Principal(davxml.HRef(joinURL(principal.principalURL(), "calendar-proxy-read/"))),
                         davxml.Grant(
                             davxml.Privilege(davxml.Read()),
                             davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
@@ -1479,7 +1480,7 @@
                     ),
                     # 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(record.principalURL, "calendar-proxy-write/"))),
+                        davxml.Principal(davxml.HRef(joinURL(principal.principalURL(), "calendar-proxy-write/"))),
                         davxml.Grant(*proxyprivs),
                         davxml.Protected(),
                         TwistedACLInheritable(),

Modified: CalendarServer/trunk/txdav/common/datastore/sql_legacy.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql_legacy.py	2011-04-07 18:28:06 UTC (rev 7294)
+++ CalendarServer/trunk/txdav/common/datastore/sql_legacy.py	2011-04-07 18:30:26 UTC (rev 7295)
@@ -1,6 +1,6 @@
 # -*- test-case-name: twistedcaldav.test.test_sharing,twistedcaldav.test.test_calendarquery -*-
 ##
-# Copyright (c) 2010 Apple Inc. All rights reserved.
+# Copyright (c) 2010-2011 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.
@@ -198,21 +198,40 @@
         """
         inv = schema.INVITE
         return cls._allColumnsQuery(
-            inv.RECIPIENT_ADDRESS == Parameter("recipient"))
+            (inv.RESOURCE_ID == Parameter("resourceID")).And(inv.RECIPIENT_ADDRESS == Parameter("recipient"))
+        )
 
 
     @inlineCallbacks
     def recordForUserID(self, userid):
-        rows = yield self._inviteForRecipientQuery.on(self._txn,
-                                                      recipient=userid)
+        rows = yield self._inviteForRecipientQuery.on(
+            self._txn,
+            resourceID=self._collection._resourceID,
+            recipient=userid
+        )
         returnValue(self._makeInvite(rows[0]) if rows else None)
 
 
+    @classproperty
+    def _inviteForPrincipalUIDQuery(cls): #@NoSelf
+        """
+        DAL query to retrieve an invite record for a given principal UID.
+        """
+        inv = schema.INVITE
+        home = cls._homeSchema
+        return cls._allColumnsQuery(
+            (inv.RESOURCE_ID == Parameter("resourceID")).And(home.OWNER_UID == Parameter("principalUID"))
+        )
+
+
     @inlineCallbacks
-    def recordForPrincipalURL(self, principalURL):
-        for record in (yield self.allRecords()):
-            if record.principalURL == principalURL:
-                returnValue(record)
+    def recordForPrincipalUID(self, principalUID):
+        rows = yield self._inviteForPrincipalUIDQuery.on(
+            self._txn,
+            resourceID=self._collection._resourceID,
+            principalUID=principalUID
+        )
+        returnValue(self._makeInvite(rows[0]) if rows else None)
 
 
     @classproperty
@@ -245,9 +264,8 @@
             _BIND_MODE_READ: "read-only",
             _BIND_MODE_WRITE: "read-write"
         }[bindMode]
-        principalURL = "/principals/__uids__/%s/" % (ownerUID,)
         return Invite(
-            inviteuid, userid, principalURL, common_name,
+            inviteuid, userid, ownerUID, common_name,
             access, state, summary
         )
 
@@ -265,11 +283,11 @@
 
 
     @classproperty
-    def _idsForRecipient(cls): #@NoSelf
+    def _idsForInviteUID(cls): #@NoSelf
         inv = schema.INVITE
         return Select([inv.RESOURCE_ID, inv.HOME_RESOURCE_ID],
                       From=inv,
-                      Where=inv.RECIPIENT_ADDRESS == Parameter("recipient"))
+                      Where=inv.INVITE_UID == Parameter("inviteuid"))
 
 
     @classproperty
@@ -278,9 +296,8 @@
         DAL query to update an invitation for a given recipient.
         """
         inv = schema.INVITE
-        return Update({inv.NAME: Parameter("name"),
-                       inv.INVITE_UID: Parameter("uid")},
-                      Where=inv.RECIPIENT_ADDRESS == Parameter("recipient"))
+        return Update({inv.NAME: Parameter("name")},
+                      Where=inv.INVITE_UID == Parameter("uid"))
 
 
     @classproperty
@@ -327,13 +344,9 @@
             "DECLINED": _BIND_STATUS_DECLINED,
             "INVALID": _BIND_STATUS_INVALID,
         }[record.state]
-        # principalURL is derived from a directory record's principalURL() so
-        # it will always contain the UID.  The form is '/principals/__uids__/x'
-        # (and may contain a trailing slash).
-        principalUID = record.principalURL.split("/")[3]
-        shareeHome = yield self._getHomeWithUID(principalUID)
-        rows = yield self._idsForRecipient.on(self._txn,
-                                              recipient=record.userid)
+        shareeHome = yield self._getHomeWithUID(record.principalUID)
+        rows = yield self._idsForInviteUID.on(self._txn,
+                                              inviteuid=record.inviteuid)
         if rows:
             [[resourceID, homeResourceID]] = rows
             yield self._updateBindQuery.on(
@@ -342,8 +355,7 @@
                 resourceID=resourceID, homeID=homeResourceID
             )
             yield self._updateInviteQuery.on(
-                self._txn, name=record.name, uid=record.inviteuid,
-                recipient=record.userid
+                self._txn, name=record.name, uid=record.inviteuid
             )
         else:
             yield self._insertInviteQuery.on(
@@ -379,20 +391,6 @@
 
 
     @classproperty
-    def _deleteBindByRecipient(cls): #@NoSelf
-        inv = schema.INVITE
-        return cls._deleteOneBindQuery(
-            inv.RECIPIENT_ADDRESS == Parameter("recipient"))
-
-
-    @classproperty
-    def _deleteInviteByRecipient(cls): #@NoSelf
-        inv = schema.INVITE
-        return cls._deleteOneInviteQuery(
-            inv.RECIPIENT_ADDRESS == Parameter("recipient"))
-
-
-    @classproperty
     def _deleteBindByUID(cls): #@NoSelf
         inv = schema.INVITE
         return cls._deleteOneBindQuery(inv.INVITE_UID == Parameter("uid"))
@@ -405,12 +403,6 @@
 
 
     @inlineCallbacks
-    def removeRecordForUserID(self, userid):
-        yield self._deleteBindByRecipient.on(self._txn, recipient=userid)
-        yield self._deleteInviteByRecipient.on(self._txn, recipient=userid)
-
-
-    @inlineCallbacks
     def removeRecordForInviteUID(self, inviteUID):
         yield self._deleteBindByUID.on(self._txn, uid=inviteUID)
         yield self._deleteInviteByUID.on(self._txn, uid=inviteUID)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20110407/23104ca4/attachment-0001.html>


More information about the calendarserver-changes mailing list