[CalendarServer-changes] [15328] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Tue Nov 17 16:56:59 PST 2015


Revision: 15328
          http://trac.calendarserver.org//changeset/15328
Author:   cdaboo at apple.com
Date:     2015-11-17 16:56:59 -0800 (Tue, 17 Nov 2015)
Log Message:
-----------
Support cross-pod scheduling between v5 and v8 servers.

Modified Paths:
--------------
    CalendarServer/trunk/conf/caldavd-test-podA.plist
    CalendarServer/trunk/conf/caldavd-test-podB.plist
    CalendarServer/trunk/conf/localservers.dtd
    CalendarServer/trunk/twistedcaldav/ical.py
    CalendarServer/trunk/twistedcaldav/test/test_icalendar.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/delivery.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/localservers.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/remoteservers.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/test/test_delivery.py
    CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/test/test_localservers.py

Modified: CalendarServer/trunk/conf/caldavd-test-podA.plist
===================================================================
--- CalendarServer/trunk/conf/caldavd-test-podA.plist	2015-11-18 00:27:31 UTC (rev 15327)
+++ CalendarServer/trunk/conf/caldavd-test-podA.plist	2015-11-18 00:56:59 UTC (rev 15328)
@@ -106,8 +106,6 @@
 	    <string>./conf/localservers-test.xml</string>
 	    <key>MaxClients</key>
 	    <integer>5</integer>
-	    <key>InboxName</key>
-	    <string>podding</string>
 	</dict>
 
     <key>Notifications</key>

Modified: CalendarServer/trunk/conf/caldavd-test-podB.plist
===================================================================
--- CalendarServer/trunk/conf/caldavd-test-podB.plist	2015-11-18 00:27:31 UTC (rev 15327)
+++ CalendarServer/trunk/conf/caldavd-test-podB.plist	2015-11-18 00:56:59 UTC (rev 15328)
@@ -106,8 +106,6 @@
 	    <string>./conf/localservers-test.xml</string>
 	    <key>MaxClients</key>
 	    <integer>5</integer>
-	    <key>InboxName</key>
-	    <string>podding</string>
 	</dict>
 
     <key>Notifications</key>

Modified: CalendarServer/trunk/conf/localservers.dtd
===================================================================
--- CalendarServer/trunk/conf/localservers.dtd	2015-11-18 00:27:31 UTC (rev 15327)
+++ CalendarServer/trunk/conf/localservers.dtd	2015-11-18 00:56:59 UTC (rev 15328)
@@ -17,7 +17,7 @@
 <!ELEMENT servers (server*) >
 
 	<!ELEMENT server (id, uri, allowed-from*, shared-secret?) >
-		<!ATTLIST server implicit (yes|no) "yes">
+		<!ATTLIST server v5 (yes|no) "no">
 
 		<!ELEMENT id  (#PCDATA) >
 		<!ELEMENT uri (#PCDATA) >

Modified: CalendarServer/trunk/twistedcaldav/ical.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/ical.py	2015-11-18 00:27:31 UTC (rev 15327)
+++ CalendarServer/trunk/twistedcaldav/ical.py	2015-11-18 00:56:59 UTC (rev 15328)
@@ -3463,7 +3463,7 @@
 
     @inlineCallbacks
     def normalizeCalendarUserAddresses(
-        self, lookupFunction, recordFunction, toCanonical=True
+        self, lookupFunction, recordFunction, toCanonical=True, toURN_UUID=False,
     ):
         """
         Do the ORGANIZER/ATTENDEE property normalization.
@@ -3477,10 +3477,14 @@
         @param toCanonical: whether to convert to the canonical CUA form (True)
             or to the mailto: form (False)
         @type toCanonical: L{bool}
+
+        @param toURN_UUID: whether to convert to urn:x-uid to urn:uuid: for
+            compatibility with older servers
+        @type toURN_UUID: L{bool}
         """
 
         # Keep a cache of records because events with lots of recurrence overrides can contain
-        # the same attendee cu-address multuiple times
+        # the same attendee cu-address multiple times
         cache = {}
 
         for component in self.subcomponents(ignore=True):
@@ -3513,6 +3517,10 @@
                     # Always re-write value to urn:x-uid
                     prop.setValue("urn:x-uid:{uid}".format(uid=uid))
 
+                # Look for urn:x-uid: -> urn:uuid: conversion
+                elif toURN_UUID and cuaddr.startswith("urn:x-uid:"):
+                    prop.setValue(cuaddr.replace("urn:x-uid:", "urn:uuid:"))
+
                 # If it is already a non-x-uid address leave it be
                 elif (cuaddr.startswith("urn:x-uid:") or cuaddr.startswith("urn:uuid:")):
 
@@ -3910,7 +3918,7 @@
 # #
 
 @inlineCallbacks
-def normalizeCUAddress(cuaddr, lookupFunction, recordFunction, toCanonical=True):
+def normalizeCUAddress(cuaddr, lookupFunction, recordFunction, toCanonical=True, toURN_UUID=False):
     # Check that we can lookup this calendar user address - if not
     # we cannot do anything with it
     _ignore_name, uid, _ignore_cuType, cuaddrs = (yield lookupFunction(normalizeCUAddr(cuaddr), recordFunction, config))
@@ -3920,6 +3928,10 @@
         if uid:
             returnValue("urn:x-uid:{0}".format(uid,))
 
+    # Look for urn:x-uid: -> urn:uuid: conversion
+    elif toURN_UUID and cuaddr.startswith("urn:x-uid:"):
+        returnValue(cuaddr.replace("urn:x-uid:", "urn:uuid:"))
+
     # If it is already a non-x-uid address leave it be
     elif (cuaddr.startswith("urn:x-uid:") or cuaddr.startswith("urn:uuid:")):
 

Modified: CalendarServer/trunk/twistedcaldav/test/test_icalendar.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_icalendar.py	2015-11-18 00:27:31 UTC (rev 15327)
+++ CalendarServer/trunk/twistedcaldav/test/test_icalendar.py	2015-11-18 00:56:59 UTC (rev 15328)
@@ -8191,6 +8191,76 @@
 
 
     @inlineCallbacks
+    def test_normalizeCalendarUserAddressesFromCanonical_URN_UUID(self):
+        """
+        Ensure mailto is preferred, followed by path form, then http form.
+        """
+
+        data = """BEGIN:VCALENDAR
+VERSION:2.0
+DTSTART:20071114T000000Z
+BEGIN:VEVENT
+UID:12345-67890
+DTSTART:20071114T000000Z
+ATTENDEE:urn:x-uid:foo
+ATTENDEE:urn:x-uid:bar
+ATTENDEE:urn:x-uid:baz
+ATTENDEE:urn:x-uid:buz
+DTSTAMP:20071114T000000Z
+END:VEVENT
+END:VCALENDAR
+"""
+
+        component = Component.fromString(data)
+
+
+        def lookupFunction(cuaddr, ignored1, ignored2):
+            return succeed(
+                {
+                    "urn:x-uid:foo" : (
+                        "Foo",
+                        "foo",
+                        "INDIVIDUAL",
+                        ("urn:x-uid:foo", "urn:uuid:foo", "http://example.com/foo", "/foo")
+                    ),
+                    "urn:x-uid:bar" : (
+                        "Bar",
+                        "bar",
+                        "INDIVIDUAL",
+                        ("urn:x-uid:bar", "urn:uuid:bar", "mailto:bar at example.com", "http://example.com/bar", "/bar")
+                    ),
+                    "urn:x-uid:baz" : (
+                        "Baz",
+                        "baz",
+                        "INDIVIDUAL",
+                        ("urn:x-uid:baz", "urn:uuid:baz", "http://example.com/baz")
+                    ),
+                    "urn:x-uid:buz" : (
+                        "Buz",
+                        "buz",
+                        "INDIVIDUAL",
+                        ("urn:x-uid:buz", "urn:uuid:buz", "http://example.com/buz")
+                    ),
+                }[cuaddr]
+            )
+
+        yield component.normalizeCalendarUserAddresses(lookupFunction, None, toCanonical=False, toURN_UUID=True)
+
+        self.assertEquals(
+            "urn:uuid:foo",
+            component.getAttendeeProperty(("urn:uuid:foo",)).value())
+        self.assertEquals(
+            "urn:uuid:bar",
+            component.getAttendeeProperty(("urn:uuid:bar",)).value())
+        self.assertEquals(
+            "urn:uuid:baz",
+            component.getAttendeeProperty(("urn:uuid:baz",)).value())
+        self.assertEquals(
+            "urn:uuid:buz",
+            component.getAttendeeProperty(("urn:uuid:buz",)).value())
+
+
+    @inlineCallbacks
     def test_normalizeCalendarUserAddressesAndLocationChange(self):
         """
         Ensure http(s) and /path CUA values are tucked away into the property
@@ -9174,6 +9244,82 @@
             self.assertEquals(new_cuaddr, result)
 
 
+    @inlineCallbacks
+    def test_normalizeCUAddressFromCanonical_URN_UUID(self):
+        """
+        Ensure mailto is preferred, followed by path form, then http form.
+        """
+
+        data = (
+            ("urn:uuid:foo", "/foo"),
+            ("urn:uuid:bar", "mailto:bar at example.com",),
+            ("urn:uuid:baz", "http://example.com/baz",),
+            ("urn:uuid:buz", "urn:x-uid:buz",),
+            ("urn:x-uid:foo", "urn:uuid:foo"),
+            ("urn:x-uid:bar", "urn:uuid:bar",),
+            ("urn:x-uid:baz", "urn:uuid:baz",),
+            ("urn:x-uid:buz", "urn:uuid:buz",),
+        )
+
+        def lookupFunction(cuaddr, ignored1, ignored2):
+            return succeed(
+                {
+                    "urn:uuid:foo" : (
+                        "Foo",
+                        "foo",
+                        "INDIVIDUAL",
+                        ("urn:x-uid:foo", "urn:uuid:foo", "http://example.com/foo", "/foo")
+                    ),
+                    "urn:uuid:bar" : (
+                        "Bar",
+                        "bar",
+                        "INDIVIDUAL",
+                        ("urn:x-uid:bar", "urn:uuid:bar", "mailto:bar at example.com", "http://example.com/bar", "/bar")
+                    ),
+                    "urn:uuid:baz" : (
+                        "Baz",
+                        "baz",
+                        "INDIVIDUAL",
+                        ("urn:x-uid:baz", "urn:uuid:baz", "http://example.com/baz")
+                    ),
+                    "urn:uuid:buz" : (
+                        "Buz",
+                        "buz",
+                        "INDIVIDUAL",
+                        ("urn:x-uid:buz", "urn:uuid:buz",)
+                    ),
+                    "urn:x-uid:foo" : (
+                        "Foo",
+                        "foo",
+                        "INDIVIDUAL",
+                        ("urn:x-uid:foo", "urn:uuid:foo", "http://example.com/foo", "/foo")
+                    ),
+                    "urn:x-uid:bar" : (
+                        "Bar",
+                        "bar",
+                        "INDIVIDUAL",
+                        ("urn:x-uid:bar", "urn:uuid:bar", "mailto:bar at example.com", "http://example.com/bar", "/bar")
+                    ),
+                    "urn:x-uid:baz" : (
+                        "Baz",
+                        "baz",
+                        "INDIVIDUAL",
+                        ("urn:x-uid:baz", "urn:uuid:baz", "http://example.com/baz")
+                    ),
+                    "urn:x-uid:buz" : (
+                        "Buz",
+                        "buz",
+                        "INDIVIDUAL",
+                        ("urn:x-uid:buz", "urn:uuid:buz",)
+                    ),
+                }[cuaddr]
+            )
+
+        for cuaddr, result in data:
+            new_cuaddr = yield normalizeCUAddress(cuaddr, lookupFunction, None, toCanonical=False, toURN_UUID=True)
+            self.assertEquals(new_cuaddr, result)
+
+
     def test_hasPropertyWithParameterMatch(self):
 
         data = (

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/delivery.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/delivery.py	2015-11-18 00:27:31 UTC (rev 15327)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/delivery.py	2015-11-18 00:56:59 UTC (rev 15328)
@@ -193,7 +193,7 @@
         if serverURI not in self.otherServers:
             self.otherServers[serverURI] = IScheduleServerRecord(
                 uri=joinURL(serverURI, config.Servers.InboxName),
-                unNormalizeAddresses=not recipient.record.server().isImplicit,
+                rewriteCUAddresses=recipient.record.server().v5,
                 moreHeaders=[recipient.record.server().secretHeader(), ],
                 podding=True,
             )
@@ -379,13 +379,28 @@
 
         # The Originator must be the ORGANIZER (for a request) or ATTENDEE (for a reply)
         originator = self.scheduler.organizer.cuaddr if self.scheduler.isiTIPRequest else self.scheduler.attendee
-        if self.server.unNormalizeAddresses:
-            originator = yield normalizeCUAddress(originator, normalizationLookup, self.scheduler.txn.directoryService().recordWithCalendarUserAddress, toCanonical=False)
+        if self.server.rewriteCUAddresses:
+            originator = yield normalizeCUAddress(
+                originator,
+                normalizationLookup,
+                self.scheduler.txn.directoryService().recordWithCalendarUserAddress,
+                toCanonical=False,
+                toURN_UUID=self.server.podding(),
+            )
         self.headers.addRawHeader("Originator", utf8String(originator))
         self.sign_headers.append("Originator")
 
         for recipient in self.recipients:
-            self.headers.addRawHeader("Recipient", utf8String(recipient.cuaddr))
+            cuaddr = recipient.cuaddr
+            if self.server.rewriteCUAddresses and self.server.podding():
+                cuaddr = yield normalizeCUAddress(
+                    cuaddr,
+                    normalizationLookup,
+                    self.scheduler.txn.directoryService().recordWithCalendarUserAddress,
+                    toCanonical=False,
+                    toURN_UUID=True,
+                )
+            self.headers.addRawHeader("Recipient", utf8String(cuaddr))
 
         # Only one Recipient header as they get concatenated in ischedule-relaxed canonicalization
         self.sign_headers.append("Recipient")
@@ -434,11 +449,13 @@
             # Need to remap cuaddrs from urn:uuid
             normalizedCalendar = self.scheduler.calendar.duplicate()
             self.original_organizer = normalizedCalendar.getOrganizer()
-            if self.server.unNormalizeAddresses:
+            if self.server.rewriteCUAddresses:
                 yield normalizedCalendar.normalizeCalendarUserAddresses(
                     normalizationLookup,
                     self.scheduler.txn.directoryService().recordWithCalendarUserAddress,
-                    toCanonical=False)
+                    toCanonical=False,
+                    toURN_UUID=self.server.podding(),
+                )
 
             # For VFREEBUSY we need to strip out ATTENDEEs that do not match the recipient list
             if self.scheduler.isfreebusy:
@@ -524,7 +541,7 @@
             calendar_data = response.childOfType(CalendarData)
             if calendar_data:
                 calendar_data = str(calendar_data)
-                if self.server.unNormalizeAddresses and self.original_organizer is not None:
+                if self.server.rewriteCUAddresses and self.original_organizer is not None:
                     # Need to restore original ORGANIZER value if it got unnormalized
                     calendar = Component.fromString(calendar_data)
                     organizers = calendar.getAllPropertiesInAnyComponent("ORGANIZER", depth=1)

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/localservers.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/localservers.py	2015-11-18 00:27:31 UTC (rev 15327)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/localservers.py	2015-11-18 00:56:59 UTC (rev 15328)
@@ -148,7 +148,7 @@
         self.ips = set()
         self.allowed_from_ips = set()
         self.shared_secret = sharedSecret
-        self.isImplicit = True
+        self.v5 = False   # Needs old style urn:uuid cu-address
 
 
     def details(self):
@@ -274,7 +274,7 @@
 ELEMENT_URI = "uri"
 ELEMENT_ALLOWED_FROM = "allowed-from"
 ELEMENT_SHARED_SECRET = "shared-secret"
-ATTR_IMPLICIT = "implicit"
+ATTR_V5 = "v5"
 ATTR_VALUE_YES = "yes"
 ATTR_VALUE_NO = "no"
 
@@ -299,7 +299,7 @@
                 raise RuntimeError("Unknown server type: '{}' in servers file: '{}'".format(child.tag, xmlFile,))
 
             server = Server()
-            server.isImplicit = child.get(ATTR_IMPLICIT, ATTR_VALUE_YES) == ATTR_VALUE_YES
+            server.v5 = child.get(ATTR_V5, ATTR_VALUE_NO) == ATTR_VALUE_YES
 
             for node in child:
                 if node.tag == ELEMENT_ID:

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/remoteservers.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/remoteservers.py	2015-11-18 00:27:31 UTC (rev 15327)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/remoteservers.py	2015-11-18 00:56:59 UTC (rev 15328)
@@ -138,7 +138,7 @@
     """
     Contains server-to-server details.
     """
-    def __init__(self, uri=None, unNormalizeAddresses=True, moreHeaders=[], podding=False):
+    def __init__(self, uri=None, rewriteCUAddresses=True, moreHeaders=[], podding=False):
         """
         @param recordType: record type for directory entry.
         """
@@ -148,7 +148,7 @@
         self.allow_to = True
         self.domains = []
         self.client_hosts = []
-        self.unNormalizeAddresses = unNormalizeAddresses
+        self.rewriteCUAddresses = rewriteCUAddresses
         self.moreHeaders = moreHeaders
         self._podding = podding
 

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/test/test_delivery.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/test/test_delivery.py	2015-11-18 00:27:31 UTC (rev 15327)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/test/test_delivery.py	2015-11-18 00:56:59 UTC (rev 15328)
@@ -20,11 +20,17 @@
 from twisted.trial import unittest
 from twistedcaldav.stdconfig import config
 from txdav.caldav.datastore.scheduling.ischedule import utils
-from txdav.caldav.datastore.scheduling.ischedule.delivery import ScheduleViaISchedule
+from txdav.caldav.datastore.scheduling.ischedule.delivery import ScheduleViaISchedule, \
+    IScheduleRequest
+from txdav.caldav.datastore.scheduling.ischedule.remoteservers import IScheduleServerRecord
+from txdav.caldav.datastore.scheduling.cuaddress import CalendarUser
+from txdav.common.datastore.test.util import CommonCommonTests
+import txweb2.dav.test.util
+from twistedcaldav.ical import Component
 
-class CalDAV (unittest.TestCase):
+class TestiSchedule (unittest.TestCase):
     """
-    txdav.caldav.datastore.scheduling.caldav tests
+    txdav.caldav.datastore.scheduling.ischedule tests
     """
 
     def tearDown(self):
@@ -71,3 +77,219 @@
         self.patch(config.Scheduling.iSchedule, "Enabled", False)
         result = yield ScheduleViaISchedule.matchCalendarUserAddress("mailto:user at example.com")
         self.assertFalse(result)
+
+
+
+class TestIScheduleRequest (CommonCommonTests, txweb2.dav.test.util.TestCase):
+    """
+    txdav.caldav.datastore.scheduling.ischedule tests
+    """
+
+    class FakeScheduler(object):
+        def __init__(self, txn, organizer, caldata=None):
+            self.txn = txn
+            self.organizer = CalendarUser(organizer)
+            self.calendar = Component.fromString(caldata) if caldata else None
+            self.isiTIPRequest = True
+            self.isfreebusy = False
+
+
+    @inlineCallbacks
+    def setUp(self):
+        yield super(TestIScheduleRequest, self).setUp()
+        yield self.buildStoreAndDirectory()
+
+
+    @inlineCallbacks
+    def test_prepareHeaders_podding(self):
+        """
+        Make sure Originator header is properly re-written.
+        """
+
+        txn = self.transactionUnderTest()
+        server = IScheduleServerRecord("https://calendar.example.com", rewriteCUAddresses=False, podding=True)
+        request = IScheduleRequest(
+            self.FakeScheduler(txn, "urn:x-uid:user01"),
+            server,
+            (CalendarUser("urn:x-uid:user02"),),
+            None, False,
+        )
+        _ignore_ssl, host, port, _ignore_path = server.details()
+        yield request._prepareHeaders(host, port, "VEVENT", "REQUEST")
+        yield txn.commit()
+
+        self.assertEqual(request.headers.getRawHeaders("Originator")[0], "urn:x-uid:user01")
+        self.assertEqual(request.headers.getRawHeaders("Recipient")[0], "urn:x-uid:user02")
+
+
+    @inlineCallbacks
+    def test_prepareHeaders_podding_with_rewrite(self):
+        """
+        Make sure Originator header is properly re-written.
+        """
+
+        txn = self.transactionUnderTest()
+        server = IScheduleServerRecord("https://calendar.example.com", rewriteCUAddresses=True, podding=True)
+        request = IScheduleRequest(
+            self.FakeScheduler(txn, "urn:x-uid:user01"),
+            server,
+            (CalendarUser("urn:x-uid:user02"),),
+            None, False,
+        )
+        _ignore_ssl, host, port, _ignore_path = server.details()
+        yield request._prepareHeaders(host, port, "VEVENT", "REQUEST")
+        yield txn.commit()
+
+        self.assertEqual(request.headers.getRawHeaders("Originator")[0], "urn:uuid:user01")
+        self.assertEqual(request.headers.getRawHeaders("Recipient")[0], "urn:uuid:user02")
+
+
+    @inlineCallbacks
+    def test_prepareHeaders_nopodding_with_rewrite(self):
+        """
+        Make sure Originator header is properly re-written.
+        """
+
+        txn = self.transactionUnderTest()
+        server = IScheduleServerRecord("https://calendar.example.com", rewriteCUAddresses=True, podding=False)
+        request = IScheduleRequest(
+            self.FakeScheduler(txn, "urn:x-uid:user01"),
+            server,
+            (CalendarUser("mailto:user02 at example.com"),),
+            None, False,
+        )
+        _ignore_ssl, host, port, _ignore_path = server.details()
+        yield request._prepareHeaders(host, port, "VEVENT", "REQUEST")
+        yield txn.commit()
+
+        self.assertEqual(request.headers.getRawHeaders("Originator")[0], "mailto:user01 at example.com")
+        self.assertEqual(request.headers.getRawHeaders("Recipient")[0], "mailto:user02 at example.com")
+
+
+    @inlineCallbacks
+    def test_prepareData_podding(self):
+        """
+        Make sure Originator header is properly re-written.
+        """
+
+        txn = self.transactionUnderTest()
+        server = IScheduleServerRecord("https://calendar.example.com", rewriteCUAddresses=False, podding=True)
+        request = IScheduleRequest(
+            self.FakeScheduler(
+                txn, "urn:x-uid:user01",
+                """BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART:20060101T100000Z
+DURATION:PT1H
+SUMMARY:event 1
+UID:deadlocked
+ORGANIZER:urn:x-uid:user01
+ATTENDEE;PARTSTAT=ACCEPTED:urn:x-uid:user01
+ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:urn:x-uid:user02
+END:VEVENT
+END:VCALENDAR
+""",
+            ),
+            server,
+            (), None, False,
+        )
+        yield request._prepareData()
+        yield txn.commit()
+
+        ical = Component.fromString(request.data)
+        self.assertEqual(ical.masterComponent().getOrganizer(), "urn:x-uid:user01")
+        self.assertEqual(
+            set([attendee.value() for attendee in ical.getAllAttendeeProperties()]),
+            set(("urn:x-uid:user01", "urn:x-uid:user02")),
+        )
+
+
+    @inlineCallbacks
+    def test_prepareData_podding_with_rewrite(self):
+        """
+        Make sure Originator header is properly re-written.
+        """
+
+        txn = self.transactionUnderTest()
+        server = IScheduleServerRecord("https://calendar.example.com", rewriteCUAddresses=True, podding=True)
+        request = IScheduleRequest(
+            self.FakeScheduler(
+                txn, "urn:x-uid:user01",
+                """BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART:20060101T100000Z
+DURATION:PT1H
+SUMMARY:event 1
+UID:deadlocked
+ORGANIZER:urn:x-uid:user01
+ATTENDEE;PARTSTAT=ACCEPTED:urn:x-uid:user01
+ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:urn:x-uid:user02
+END:VEVENT
+END:VCALENDAR
+""",
+            ),
+            server,
+            (), None, False,
+        )
+        yield request._prepareData()
+        yield txn.commit()
+
+        ical = Component.fromString(request.data)
+        self.assertEqual(ical.masterComponent().getOrganizer(), "urn:uuid:user01")
+        self.assertEqual(
+            set([attendee.value() for attendee in ical.getAllAttendeeProperties()]),
+            set(("urn:uuid:user01", "urn:uuid:user02")),
+        )
+
+
+    @inlineCallbacks
+    def test_prepareData_nopodding_with_rewrite(self):
+        """
+        Make sure Originator header is properly re-written.
+        """
+
+        txn = self.transactionUnderTest()
+        server = IScheduleServerRecord("https://calendar.example.com", rewriteCUAddresses=True, podding=False)
+        request = IScheduleRequest(
+            self.FakeScheduler(
+                txn, "urn:x-uid:user01",
+                """BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART:20060101T100000Z
+DURATION:PT1H
+SUMMARY:event 1
+UID:deadlocked
+ORGANIZER:urn:x-uid:user01
+ATTENDEE;PARTSTAT=ACCEPTED:urn:x-uid:user01
+ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:urn:x-uid:user02
+END:VEVENT
+END:VCALENDAR
+""",
+            ),
+            server,
+            (), None, False,
+        )
+        yield request._prepareData()
+        yield txn.commit()
+
+        ical = Component.fromString(request.data)
+        self.assertEqual(ical.masterComponent().getOrganizer(), "mailto:user01 at example.com")
+        self.assertEqual(
+            set([attendee.value() for attendee in ical.getAllAttendeeProperties()]),
+            set(("mailto:user01 at example.com", "mailto:user02 at example.com")),
+        )

Modified: CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/test/test_localservers.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/test/test_localservers.py	2015-11-18 00:27:31 UTC (rev 15327)
+++ CalendarServer/trunk/txdav/caldav/datastore/scheduling/ischedule/test/test_localservers.py	2015-11-18 00:56:59 UTC (rev 15328)
@@ -59,6 +59,26 @@
 </servers>
 """
 
+    data_v5 = """<?xml version="1.0" encoding="utf-8"?>
+<servers>
+  <server>
+    <id>00001</id>
+    <uri>http://caldav1.example.com:8008</uri>
+    <allowed-from>127.0.0.1</allowed-from>
+    <shared-secret>foobar</shared-secret>
+  </server>
+  <server v5='yes'>
+    <id>00002</id>
+    <uri>https://caldav2.example.com:8843</uri>
+  </server>
+  <server v5='no'>
+    <id>00003</id>
+    <uri>https://caldav3.example.com:8943</uri>
+  </server>
+</servers>
+"""
+
+
     def _setupServers(self, data=data1):
         self.patch(config, "ServerHostName", "caldav1.example.com")
         self.patch(config, "HTTPPort", 8008)
@@ -178,3 +198,12 @@
 
         request = SimpleRequest(None, "POST", "/ischedule")
         self.assertTrue(servers.getServerById("00002").checkSharedSecret(request.headers))
+
+
+    def test_urn_uuid(self):
+
+        servers = self._setupServers(self.data_v5)
+
+        self.assertFalse(servers.getServerById("00001").v5)
+        self.assertTrue(servers.getServerById("00002").v5)
+        self.assertFalse(servers.getServerById("00003").v5)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20151117/c157e236/attachment-0001.html>


More information about the calendarserver-changes mailing list