<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[12121] CalendarServer/branches/users/cdaboo/cross-pod-sharing</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.calendarserver.org//changeset/12121">12121</a></dd>
<dt>Author</dt> <dd>cdaboo@apple.com</dd>
<dt>Date</dt> <dd>2013-12-17 11:25:31 -0800 (Tue, 17 Dec 2013)</dd>
</dl>
<h3>Log Message</h3>
<pre>Checkpoint: more tests done.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServerbranchesuserscdaboocrosspodsharingtwistedcaldavdirectoryresourcepy">CalendarServer/branches/users/cdaboo/cross-pod-sharing/twistedcaldav/directory/resource.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboocrosspodsharingtwistedcaldavstorebridgepy">CalendarServer/branches/users/cdaboo/cross-pod-sharing/twistedcaldav/storebridge.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboocrosspodsharingtxdavcaldavdatastoresqlpy">CalendarServer/branches/users/cdaboo/cross-pod-sharing/txdav/caldav/datastore/sql.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboocrosspodsharingtxdavcarddavdatastoresqlpy">CalendarServer/branches/users/cdaboo/cross-pod-sharing/txdav/carddav/datastore/sql.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboocrosspodsharingtxdavcommondatastorepoddingconduitpy">CalendarServer/branches/users/cdaboo/cross-pod-sharing/txdav/common/datastore/podding/conduit.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboocrosspodsharingtxdavcommondatastorepoddingtesttest_conduitpy">CalendarServer/branches/users/cdaboo/cross-pod-sharing/txdav/common/datastore/podding/test/test_conduit.py</a></li>
<li><a href="#CalendarServerbranchesuserscdaboocrosspodsharingtxdavcommondatastoresqlpy">CalendarServer/branches/users/cdaboo/cross-pod-sharing/txdav/common/datastore/sql.py</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServerbranchesuserscdaboocrosspodsharingtwistedcaldavdirectoryresourcepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/cross-pod-sharing/twistedcaldav/directory/resource.py (12120 => 12121)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/cross-pod-sharing/twistedcaldav/directory/resource.py        2013-12-17 19:23:03 UTC (rev 12120)
+++ CalendarServer/branches/users/cdaboo/cross-pod-sharing/twistedcaldav/directory/resource.py        2013-12-17 19:25:31 UTC (rev 12121)
</span><span class="lines">@@ -22,6 +22,8 @@
</span><span class="cx">
</span><span class="cx"> from twistedcaldav.client.reverseproxy import ReverseProxyResource
</span><span class="cx">
</span><ins>+from twisted.internet.defer import succeed
+
</ins><span class="cx"> __all__ = ["DirectoryReverseProxyResource"]
</span><span class="cx">
</span><span class="cx"> class DirectoryReverseProxyResource(ReverseProxyResource):
</span><span class="lines">@@ -35,3 +37,32 @@
</span><span class="cx">
</span><span class="cx"> def url(self):
</span><span class="cx"> return joinURL(self.parent.url(), self.record.uid)
</span><ins>+
+
+ def hasQuota(self, request):
+ return succeed(False)
+
+
+ def hasQuotaRoot(self, request):
+ return succeed(False)
+
+
+ def quotaRootResource(self, request):
+ """
+ Return the quota root for this resource.
+
+ @return: L{DAVResource} or C{None}
+ """
+
+ return succeed(None)
+
+
+ def checkPrivileges(
+ self, request, privileges, recurse=False,
+ principal=None, inherited_aces=None
+ ):
+ return succeed(None)
+
+
+ def hasProperty(self, property, request):
+ return succeed(False)
</ins></span></pre></div>
<a id="CalendarServerbranchesuserscdaboocrosspodsharingtwistedcaldavstorebridgepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/cross-pod-sharing/twistedcaldav/storebridge.py (12120 => 12121)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/cross-pod-sharing/twistedcaldav/storebridge.py        2013-12-17 19:23:03 UTC (rev 12120)
+++ CalendarServer/branches/users/cdaboo/cross-pod-sharing/twistedcaldav/storebridge.py        2013-12-17 19:25:31 UTC (rev 12121)
</span><span class="lines">@@ -1123,7 +1123,7 @@
</span><span class="cx"> isowner = (yield self.isOwner(request))
</span><span class="cx"> accessPrincipal = (yield self.resourceOwnerPrincipal(request))
</span><span class="cx">
</span><del>- for name, _ignore_uid, _ignore_type in (yield maybeDeferred(self.index().bruteForceSearch)):
</del><ins>+ for name in (yield self._newStoreObject.listObjectResources()):
</ins><span class="cx"> try:
</span><span class="cx"> child = yield request.locateChildResource(self, name)
</span><span class="cx"> except TypeError:
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboocrosspodsharingtxdavcaldavdatastoresqlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/cross-pod-sharing/txdav/caldav/datastore/sql.py (12120 => 12121)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/cross-pod-sharing/txdav/caldav/datastore/sql.py        2013-12-17 19:23:03 UTC (rev 12120)
+++ CalendarServer/branches/users/cdaboo/cross-pod-sharing/txdav/caldav/datastore/sql.py        2013-12-17 19:25:31 UTC (rev 12121)
</span><span class="lines">@@ -1294,6 +1294,37 @@
</span><span class="cx"> yield self.setDefaultAlarm("empty", False, False)
</span><span class="cx">
</span><span class="cx">
</span><ins>+ def getInviteCopyProperties(self):
+ """
+ Get a dictionary of property name/values (as strings) for properties that are shadowable and
+ need to be copied to a sharee's collection when an external (cross-pod) share is created.
+ Sub-classes should override to expose the properties they care about.
+ """
+ props = {}
+ for elem in (element.DisplayName, caldavxml.CalendarDescription, caldavxml.CalendarTimeZone, customxml.CalendarColor,):
+ if PropertyName.fromElement(elem) in self.properties():
+ props[elem.sname()] = str(self.properties()[PropertyName.fromElement(elem)])
+ return props
+
+
+ def setInviteCopyProperties(self, props):
+ """
+ Copy a set of shadowable properties (as name/value strings) onto this shared resource when
+ a cross-pod invite is processed. Sub-classes should override to expose the properties they
+ care about.
+ """
+ # Initialize these for all shares
+ for elem in (caldavxml.CalendarDescription, caldavxml.CalendarTimeZone,):
+ if PropertyName.fromElement(elem) not in self.properties() and elem.sname() in props:
+ self.properties()[PropertyName.fromElement(elem)] = elem.fromString(props[elem.sname()])
+
+ # Only initialize these for direct shares
+ if self.direct():
+ for elem in (element.DisplayName, customxml.CalendarColor,):
+ if PropertyName.fromElement(elem) not in self.properties() and elem.sname() in props:
+ self.properties()[PropertyName.fromElement(elem)] = elem.fromString(props[elem.sname()])
+
+
</ins><span class="cx"> # FIXME: this is DAV-ish. Data store calendar objects don't have
</span><span class="cx"> # mime types. -wsv
</span><span class="cx"> def contentType(self):
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboocrosspodsharingtxdavcarddavdatastoresqlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/cross-pod-sharing/txdav/carddav/datastore/sql.py (12120 => 12121)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/cross-pod-sharing/txdav/carddav/datastore/sql.py        2013-12-17 19:23:03 UTC (rev 12120)
+++ CalendarServer/branches/users/cdaboo/cross-pod-sharing/txdav/carddav/datastore/sql.py        2013-12-17 19:25:31 UTC (rev 12121)
</span><span class="lines">@@ -568,6 +568,37 @@
</span><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><ins>+ def getInviteCopyProperties(self):
+ """
+ Get a dictionary of property name/values (as strings) for properties that are shadowable and
+ need to be copied to a sharee's collection when an external (cross-pod) share is created.
+ Sub-classes should override to expose the properties they care about.
+ """
+ props = {}
+ for elem in (element.DisplayName, carddavxml.AddressBookDescription,):
+ if PropertyName.fromElement(elem) in self.properties():
+ props[elem.sname()] = str(self.properties()[PropertyName.fromElement(elem)])
+ return props
+
+
+ def setInviteCopyProperties(self, props):
+ """
+ Copy a set of shadowable properties (as name/value strings) onto this shared resource when
+ a cross-pod invite is processed. Sub-classes should override to expose the properties they
+ care about.
+ """
+ # Initialize these for all shares
+ for elem in (carddavxml.AddressBookDescription,):
+ if PropertyName.fromElement(elem) not in self.properties() and elem.sname() in props:
+ self.properties()[PropertyName.fromElement(elem)] = elem.fromString(props[elem.sname()])
+
+ # Only initialize these for direct shares
+ if self.direct():
+ for elem in (element.DisplayName,):
+ if PropertyName.fromElement(elem) not in self.properties() and elem.sname() in props:
+ self.properties()[PropertyName.fromElement(elem)] = elem.fromString(props[elem.sname()])
+
+
</ins><span class="cx"> def contentType(self):
</span><span class="cx"> """
</span><span class="cx"> The content type of addressbook objects is text/vcard.
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboocrosspodsharingtxdavcommondatastorepoddingconduitpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/cross-pod-sharing/txdav/common/datastore/podding/conduit.py (12120 => 12121)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/cross-pod-sharing/txdav/common/datastore/podding/conduit.py        2013-12-17 19:23:03 UTC (rev 12120)
+++ CalendarServer/branches/users/cdaboo/cross-pod-sharing/txdav/common/datastore/podding/conduit.py        2013-12-17 19:25:31 UTC (rev 12121)
</span><span class="lines">@@ -163,7 +163,7 @@
</span><span class="cx"> #
</span><span class="cx">
</span><span class="cx"> @inlineCallbacks
</span><del>- def send_shareinvite(self, txn, homeType, ownerUID, ownerID, ownerName, shareeUID, shareUID, bindMode, summary, supported_components):
</del><ins>+ def send_shareinvite(self, txn, homeType, ownerUID, ownerID, ownerName, shareeUID, shareUID, bindMode, summary, copy_properties, supported_components):
</ins><span class="cx"> """
</span><span class="cx"> Send a sharing invite cross-pod message.
</span><span class="cx">
</span><span class="lines">@@ -183,6 +183,8 @@
</span><span class="cx"> @type bindMode: C{str}
</span><span class="cx"> @param summary: sharing message
</span><span class="cx"> @type summary: C{str}
</span><ins>+ @param copy_properties: C{str} name/value for properties to be copied
+ @type copy_properties: C{dict}
</ins><span class="cx"> @param supported_components: supproted components, may be C{None}
</span><span class="cx"> @type supported_components: C{str}
</span><span class="cx"> """
</span><span class="lines">@@ -199,6 +201,7 @@
</span><span class="cx"> "share_id": shareUID,
</span><span class="cx"> "mode": bindMode,
</span><span class="cx"> "summary": summary,
</span><ins>+ "properties": copy_properties,
</ins><span class="cx"> }
</span><span class="cx"> if supported_components is not None:
</span><span class="cx"> action["supported-components"] = supported_components
</span><span class="lines">@@ -232,6 +235,7 @@
</span><span class="cx"> message["share_id"],
</span><span class="cx"> message["mode"],
</span><span class="cx"> message["summary"],
</span><ins>+ message["properties"],
</ins><span class="cx"> supported_components=message.get("supported-components")
</span><span class="cx"> )
</span><span class="cx"> except ExternalShareFailed as e:
</span><span class="lines">@@ -507,7 +511,7 @@
</span><span class="cx"> #
</span><span class="cx">
</span><span class="cx"> @inlineCallbacks
</span><del>- def _simple_send(self, actionName, shareeView, objectResource=None, args=None, kwargs=None):
</del><ins>+ def _simple_send(self, actionName, shareeView, objectResource=None, transform=None, args=None, kwargs=None):
</ins><span class="cx"> """
</span><span class="cx"> A simple send operation that returns a value.
</span><span class="cx">
</span><span class="lines">@@ -532,7 +536,7 @@
</span><span class="cx"> action["keywords"] = kwargs
</span><span class="cx"> result = yield self.sendRequest(shareeView._txn, recipient, action)
</span><span class="cx"> if result["result"] == "ok":
</span><del>- returnValue(result["value"])
</del><ins>+ returnValue(result["value"] if transform is None else transform(result["value"], shareeView, objectResource))
</ins><span class="cx"> elif result["result"] == "exception":
</span><span class="cx"> raise namedClass(result["class"])(result["message"])
</span><span class="cx">
</span><span class="lines">@@ -652,12 +656,17 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> @staticmethod
</span><del>- def _result_string(value, shareeView, objectResource):
</del><ins>+ def _to_tuple(value, shareeView, objectResource):
+ return tuple(value)
+
+
+ @staticmethod
+ def _to_string(value, shareeView, objectResource):
</ins><span class="cx"> return str(value)
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> @staticmethod
</span><del>- def _result_externalize(value, shareeView, objectResource):
</del><ins>+ def _to_externalize(value, shareeView, objectResource):
</ins><span class="cx"> if isinstance(value, shareeView._objectResourceClass):
</span><span class="cx"> value = value.externalize()
</span><span class="cx"> elif value is not None:
</span><span class="lines">@@ -666,34 +675,34 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> @classmethod
</span><del>- def _make_simple_homechild_action(cls, action, method):
</del><ins>+ def _make_simple_homechild_action(cls, action, method, transform_recv=None, transform_send=None):
</ins><span class="cx"> setattr(
</span><span class="cx"> cls,
</span><span class="cx"> "send_{}".format(action),
</span><span class="cx"> lambda self, shareeView, *args, **kwargs:
</span><del>- self._simple_send(action, shareeView, args=args, kwargs=kwargs)
</del><ins>+ self._simple_send(action, shareeView, transform=transform_send, args=args, kwargs=kwargs)
</ins><span class="cx"> )
</span><span class="cx"> setattr(
</span><span class="cx"> cls,
</span><span class="cx"> "recv_{}".format(action),
</span><span class="cx"> lambda self, txn, message:
</span><del>- self._simple_recv(txn, action, message, method)
</del><ins>+ self._simple_recv(txn, action, message, method, transform=transform_recv)
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> @classmethod
</span><del>- def _make_simple_object_action(cls, action, method, transform_result=None):
</del><ins>+ def _make_simple_object_action(cls, action, method, transform_recv=None, transform_send=None):
</ins><span class="cx"> setattr(
</span><span class="cx"> cls,
</span><span class="cx"> "send_{}".format(action),
</span><span class="cx"> lambda self, shareeView, objectResource, *args, **kwargs:
</span><del>- self._simple_send(action, shareeView, objectResource, args=args, kwargs=kwargs)
</del><ins>+ self._simple_send(action, shareeView, objectResource, transform=transform_send, args=args, kwargs=kwargs)
</ins><span class="cx"> )
</span><span class="cx"> setattr(
</span><span class="cx"> cls,
</span><span class="cx"> "recv_{}".format(action),
</span><span class="cx"> lambda self, txn, message:
</span><del>- self._simple_recv(txn, action, message, method, onHomeChild=False, transform=transform_result)
</del><ins>+ self._simple_recv(txn, action, message, method, onHomeChild=False, transform=transform_recv)
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -701,15 +710,15 @@
</span><span class="cx"> PoddingConduit._make_simple_homechild_action("countobjects", "countObjectResources")
</span><span class="cx"> PoddingConduit._make_simple_homechild_action("listobjects", "listObjectResources")
</span><span class="cx"> PoddingConduit._make_simple_homechild_action("synctoken", "syncToken")
</span><del>-PoddingConduit._make_simple_homechild_action("resourcenamessincerevision", "resourceNamesSinceRevision")
</del><ins>+PoddingConduit._make_simple_homechild_action("resourcenamessincerevision", "resourceNamesSinceRevision", transform_send=PoddingConduit._to_tuple)
</ins><span class="cx"> PoddingConduit._make_simple_homechild_action("resourceuidforname", "resourceUIDForName")
</span><span class="cx"> PoddingConduit._make_simple_homechild_action("resourcenameforuid", "resourceNameForUID")
</span><span class="cx">
</span><span class="cx"> # Calls on L{CommonObjectResource} objects
</span><del>-PoddingConduit._make_simple_object_action("loadallobjects", "loadAllObjects", transform_result=PoddingConduit._result_externalize)
-PoddingConduit._make_simple_object_action("loadallobjectswithnames", "loadAllObjectsWithNames", transform_result=PoddingConduit._result_externalize)
-PoddingConduit._make_simple_object_action("objectwith", "objectWith", transform_result=PoddingConduit._result_externalize)
-PoddingConduit._make_simple_object_action("create", "create", transform_result=PoddingConduit._result_externalize)
</del><ins>+PoddingConduit._make_simple_object_action("loadallobjects", "loadAllObjects", transform_recv=PoddingConduit._to_externalize)
+PoddingConduit._make_simple_object_action("loadallobjectswithnames", "loadAllObjectsWithNames", transform_recv=PoddingConduit._to_externalize)
+PoddingConduit._make_simple_object_action("objectwith", "objectWith", transform_recv=PoddingConduit._to_externalize)
+PoddingConduit._make_simple_object_action("create", "create", transform_recv=PoddingConduit._to_externalize)
</ins><span class="cx"> PoddingConduit._make_simple_object_action("setcomponent", "setComponent")
</span><del>-PoddingConduit._make_simple_object_action("component", "component", transform_result=PoddingConduit._result_string)
</del><ins>+PoddingConduit._make_simple_object_action("component", "component", transform_recv=PoddingConduit._to_string)
</ins><span class="cx"> PoddingConduit._make_simple_object_action("remove", "remove")
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboocrosspodsharingtxdavcommondatastorepoddingtesttest_conduitpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/cross-pod-sharing/txdav/common/datastore/podding/test/test_conduit.py (12120 => 12121)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/cross-pod-sharing/txdav/common/datastore/podding/test/test_conduit.py        2013-12-17 19:23:03 UTC (rev 12120)
+++ CalendarServer/branches/users/cdaboo/cross-pod-sharing/txdav/common/datastore/podding/test/test_conduit.py        2013-12-17 19:25:31 UTC (rev 12121)
</span><span class="lines">@@ -439,13 +439,13 @@
</span><span class="cx"> calendar1 = yield self.calendarUnderTest(home="user01", name="calendar")
</span><span class="cx"> token1_2 = yield calendar1.syncToken()
</span><span class="cx"> names1 = yield calendar1.resourceNamesSinceToken(token1_1)
</span><del>- self.assertEqual(names1, (["1.ics"], [],))
</del><ins>+ self.assertEqual(names1, ([u"1.ics"], [],))
</ins><span class="cx"> yield self.commit()
</span><span class="cx">
</span><span class="cx"> shared = yield self.calendarUnderTest(txn=self.newOtherTransaction(), home="puser01", name="shared-calendar")
</span><span class="cx"> token2_2 = yield shared.syncToken()
</span><span class="cx"> names2 = yield shared.resourceNamesSinceToken(token2_1)
</span><del>- self.assertEqual(names2, (["1.ics"], [],))
</del><ins>+ self.assertEqual(names2, ([u"1.ics"], [],))
</ins><span class="cx"> yield self.otherCommit()
</span><span class="cx">
</span><span class="cx"> calendar1 = yield self.calendarUnderTest(home="user01", name="calendar")
</span><span class="lines">@@ -458,13 +458,13 @@
</span><span class="cx"> calendar1 = yield self.calendarUnderTest(home="user01", name="calendar")
</span><span class="cx"> token1_3 = yield calendar1.syncToken()
</span><span class="cx"> names1 = yield calendar1.resourceNamesSinceToken(token1_2)
</span><del>- self.assertEqual(names1, ([], ["1.ics"],))
</del><ins>+ self.assertEqual(names1, ([], [u"1.ics"],))
</ins><span class="cx"> yield self.commit()
</span><span class="cx">
</span><span class="cx"> shared = yield self.calendarUnderTest(txn=self.newOtherTransaction(), home="puser01", name="shared-calendar")
</span><span class="cx"> token2_3 = yield shared.syncToken()
</span><span class="cx"> names2 = yield shared.resourceNamesSinceToken(token2_2)
</span><del>- self.assertEqual(names2, ([], ["1.ics"],))
</del><ins>+ self.assertEqual(names2, ([], [u"1.ics"],))
</ins><span class="cx"> yield self.otherCommit()
</span><span class="cx">
</span><span class="cx"> calendar1 = yield self.calendarUnderTest(home="user01", name="calendar")
</span><span class="lines">@@ -518,17 +518,17 @@
</span><span class="cx"> yield self.commit()
</span><span class="cx">
</span><span class="cx"> calendar1 = yield self.calendarUnderTest(home="user01", name="calendar")
</span><del>- uid = yield calendar1.resourceNameForUID("uid1")
- self.assertEqual(uid, "1.ics")
- uid = yield calendar1.resourceNameForUID("uid2")
- self.assertTrue(uid is None)
</del><ins>+ name = yield calendar1.resourceNameForUID("uid1")
+ self.assertEqual(name, "1.ics")
+ name = yield calendar1.resourceNameForUID("uid2")
+ self.assertTrue(name is None)
</ins><span class="cx"> yield self.commit()
</span><span class="cx">
</span><span class="cx"> shared = yield self.calendarUnderTest(txn=self.newOtherTransaction(), home="puser01", name="shared-calendar")
</span><del>- uid = yield shared.resourceNameForUID("uid1")
- self.assertEqual(uid, "1.ics")
- uid = yield shared.resourceNameForUID("uid2")
- self.assertTrue(uid is None)
</del><ins>+ name = yield shared.resourceNameForUID("uid1")
+ self.assertEqual(name, "1.ics")
+ name = yield shared.resourceNameForUID("uid2")
+ self.assertTrue(name is None)
</ins><span class="cx"> yield self.otherCommit()
</span><span class="cx">
</span><span class="cx">
</span></span></pre></div>
<a id="CalendarServerbranchesuserscdaboocrosspodsharingtxdavcommondatastoresqlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/cdaboo/cross-pod-sharing/txdav/common/datastore/sql.py (12120 => 12121)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/cdaboo/cross-pod-sharing/txdav/common/datastore/sql.py        2013-12-17 19:23:03 UTC (rev 12120)
+++ CalendarServer/branches/users/cdaboo/cross-pod-sharing/txdav/common/datastore/sql.py        2013-12-17 19:25:31 UTC (rev 12121)
</span><span class="lines">@@ -1479,7 +1479,7 @@
</span><span class="cx"> # External (cross-pod) sharing - entry point is the sharee's home collection.
</span><span class="cx"> #
</span><span class="cx"> @inlineCallbacks
</span><del>- def processExternalInvite(self, ownerUID, ownerRID, ownerName, shareUID, bindMode, summary, supported_components=None):
</del><ins>+ def processExternalInvite(self, ownerUID, ownerRID, ownerName, shareUID, bindMode, summary, copy_invite_properties, supported_components=None):
</ins><span class="cx"> """
</span><span class="cx"> External invite received.
</span><span class="cx"> """
</span><span class="lines">@@ -1513,11 +1513,13 @@
</span><span class="cx">
</span><span class="cx"> # Now carry out the share operation
</span><span class="cx"> if bindMode == _BIND_MODE_DIRECT:
</span><del>- yield ownerView.directShareWithUser(self.uid(), shareName=shareUID)
</del><ins>+ shareeView = yield ownerView.directShareWithUser(self.uid(), shareName=shareUID)
</ins><span class="cx"> else:
</span><del>- yield ownerView.inviteUserToShare(self.uid(), bindMode, summary, shareName=shareUID)
</del><ins>+ shareeView = yield ownerView.inviteUserToShare(self.uid(), bindMode, summary, shareName=shareUID)
</ins><span class="cx">
</span><ins>+ shareeView.setInviteCopyProperties(copy_invite_properties)
</ins><span class="cx">
</span><ins>+
</ins><span class="cx"> @inlineCallbacks
</span><span class="cx"> def processExternalUninvite(self, ownerUID, ownerRID, shareUID):
</span><span class="cx"> """
</span><span class="lines">@@ -2630,7 +2632,7 @@
</span><span class="cx"> def revisionFromToken(self, token):
</span><span class="cx"> if token is None:
</span><span class="cx"> return 0
</span><del>- elif isinstance(token, str):
</del><ins>+ elif isinstance(token, str) or isinstance(token, unicode):
</ins><span class="cx"> _ignore_uuid, revision = token.split("_", 1)
</span><span class="cx"> return int(revision)
</span><span class="cx"> else:
</span><span class="lines">@@ -3342,6 +3344,7 @@
</span><span class="cx"> shareeView.shareUID(),
</span><span class="cx"> shareeView.shareMode(),
</span><span class="cx"> shareeView.shareMessage(),
</span><ins>+ self.getInviteCopyProperties(),
</ins><span class="cx"> supported_components=self.getSupportedComponents() if hasattr(self, "getSupportedComponents") else None,
</span><span class="cx"> )
</span><span class="cx">
</span><span class="lines">@@ -3807,6 +3810,24 @@
</span><span class="cx"> return self._bindMessage
</span><span class="cx">
</span><span class="cx">
</span><ins>+ def getInviteCopyProperties(self):
+ """
+ Get a dictionary of property name/values (as strings) for properties that are shadowable and
+ need to be copied to a sharee's collection when an external (cross-pod) share is created.
+ Sub-classes should override to expose the properties they care about.
+ """
+ return {}
+
+
+ def setInviteCopyProperties(self, props):
+ """
+ Copy a set of shadowable properties (as name/value strings) onto this shared resource when
+ a cross-pod invite is processed. Sub-classes should override to expose the properties they
+ care about.
+ """
+ pass
+
+
</ins><span class="cx"> @classmethod
</span><span class="cx"> def metadataColumns(cls):
</span><span class="cx"> """
</span></span></pre>
</div>
</div>
</body>
</html>