[CalendarServer-changes] [10183] CalendarServer/branches/users/gaya/sharedgroups

source_changes at macosforge.org source_changes at macosforge.org
Mon Dec 17 15:18:07 PST 2012


Revision: 10183
          http://trac.calendarserver.org//changeset/10183
Author:   gaya at apple.com
Date:     2012-12-17 15:18:07 -0800 (Mon, 17 Dec 2012)
Log Message:
-----------
merge from trunk

Modified Paths:
--------------
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/logAnalysis.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/applepush.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/test/test_applepush.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tap/caldav.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tap/test/test_caldav.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/dbinspect.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/push.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/web2/channel/http.py
    CalendarServer/branches/users/gaya/sharedgroups/twext/web2/test/test_http.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/customxml.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/icaldiff.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/implicit.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/itip.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/test/test_icaldiff.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/stdconfig.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_13_to_14.sql
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_13_to_14.sql
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/test/test_migrate.py

Removed Paths:
-------------
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/test_timezone.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/timezone.py
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/test/test_methodDescriptor.py

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/logAnalysis.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/logAnalysis.py	2012-12-17 23:16:54 UTC (rev 10182)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/logAnalysis.py	2012-12-17 23:18:07 UTC (rev 10183)
@@ -332,18 +332,22 @@
 
 
 
-versionClients = (
+osClients = (
     "Mac OS X/",
     "iOS/",
+)
+
+versionClients = (
     "iCal/",
     "iPhone/",
-    "CalendarAgent",
+    "CalendarAgent/",
     "Calendar/",
     "CoreDAV/",
     "Safari/",
-    "dataaccessd",
+    "dataaccessd/",
+    "Preferences/",
     "curl/",
-    "DAVKit",
+    "DAVKit/",
 )
 
 quickclients = (
@@ -358,16 +362,27 @@
 def getAdjustedClientName(stats):
 
     userAgent = stats["userAgent"]
-    for client in versionClients:
+    os = ""
+    for client in osClients:
         index = userAgent.find(client)
         if index != -1:
             l = len(client)
-            endex = userAgent[index + l:].find(' ', index)
-            return userAgent[index:] if endex == -1 else userAgent[index:endex + l]
+            endex = userAgent.find(' ', index + l)
+            os = (userAgent[index:] if endex == -1 else userAgent[index:endex]) + " "
 
+    for client in versionClients:
+        index = userAgent.find(client)
+        if index != -1:
+            if os:
+                return os + client[:-1]
+            else:
+                l = len(client)
+                endex = userAgent.find(' ', index + l)
+                return os + (userAgent[index:] if endex == -1 else userAgent[index:endex])
+
     for quick, result in quickclients:
         index = userAgent.find(quick)
         if index != -1:
-            return result
+            return os + result
 
     return userAgent[:20]

Deleted: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/test_timezone.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/test_timezone.py	2012-12-17 23:16:54 UTC (rev 10182)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/test_timezone.py	2012-12-17 23:18:07 UTC (rev 10183)
@@ -1,66 +0,0 @@
-##
-# Copyright (c) 2012 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.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-from twistedcaldav.test.util import TestCase
-from twistedcaldav.config import config
-import calendarserver.platform.darwin.timezone
-import twistedcaldav.timezones
-from calendarserver.platform.darwin.timezone import getLocalTimezone, DEFAULT_TIMEZONE
-
-class DefaultTimezoneTests(TestCase):
-
-    def stubLookup(self):
-        return self._storedLookup
-
-    def stubHasTZ(self, ignored):
-        return self._storedHasTZ.pop()
-
-    def setUp(self):
-        self.patch(calendarserver.platform.darwin.timezone,
-            "lookupSystemTimezone", self.stubLookup)
-        self.patch(twistedcaldav.timezones,
-            "hasTZ", self.stubHasTZ)
-
-    def test_getLocalTimezone(self):
-
-        # Empty config, system timezone known = use system timezone
-        self.patch(config, "DefaultTimezone", "")
-        self._storedLookup = "America/New_York"
-        self._storedHasTZ = [True]
-        self.assertEquals(getLocalTimezone(), "America/New_York")
-
-        # Empty config, system timezone unknown = use DEFAULT_TIMEZONE
-        self.patch(config, "DefaultTimezone", "")
-        self._storedLookup = "Unknown/Unknown"
-        self._storedHasTZ = [False]
-        self.assertEquals(getLocalTimezone(), DEFAULT_TIMEZONE)
-
-        # Known config value = use config value
-        self.patch(config, "DefaultTimezone", "America/New_York")
-        self._storedHasTZ = [True]
-        self.assertEquals(getLocalTimezone(), "America/New_York")
-
-        # Unknown config value, system timezone known = use system timezone
-        self.patch(config, "DefaultTimezone", "Unknown/Unknown")
-        self._storedLookup = "America/New_York"
-        self._storedHasTZ = [True, False]
-        self.assertEquals(getLocalTimezone(), "America/New_York")
-
-        # Unknown config value, system timezone unknown = use DEFAULT_TIMEZONE
-        self.patch(config, "DefaultTimezone", "Unknown/Unknown")
-        self._storedLookup = "Unknown/Unknown"
-        self._storedHasTZ = [False, False]
-        self.assertEquals(getLocalTimezone(), DEFAULT_TIMEZONE)

Deleted: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/timezone.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/timezone.py	2012-12-17 23:16:54 UTC (rev 10182)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/platform/darwin/timezone.py	2012-12-17 23:18:07 UTC (rev 10183)
@@ -1,51 +0,0 @@
-##
-# Copyright (c) 2012 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.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-
-from twistedcaldav.config import config
-import twistedcaldav.timezones
-
-DEFAULT_TIMEZONE = "America/Los_Angeles"
-
-try:
-    from Foundation import NSTimeZone
-    def lookupSystemTimezone():
-        return NSTimeZone.localTimeZone().name().encode("utf-8")
-
-except:
-    def lookupSystemTimezone():
-        return ""
-
-
-def getLocalTimezone():
-    """
-    Returns the default timezone for the server.  The order of precedence is:
-    config.DefaultTimezone, lookupSystemTimezone( ), DEFAULT_TIMEZONE.
-    Also, if neither of the first two values in that list are in the timezone
-    database, DEFAULT_TIMEZONE is returned.
-
-    @return: The server's local timezone name
-    @rtype: C{str}
-    """
-    if config.DefaultTimezone:
-        if twistedcaldav.timezones.hasTZ(config.DefaultTimezone):
-            return config.DefaultTimezone
-
-    systemTimezone = lookupSystemTimezone()
-    if twistedcaldav.timezones.hasTZ(systemTimezone):
-        return systemTimezone
-
-    return DEFAULT_TIMEZONE

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/applepush.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/applepush.py	2012-12-17 23:16:54 UTC (rev 10182)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/applepush.py	2012-12-17 23:18:07 UTC (rev 10183)
@@ -798,6 +798,9 @@
 
         userAgent = request.headers.getHeader("user-agent", "-")
         host = request.remoteAddr.host
+        fwdHeaders = request.headers.getRawHeaders("x-forwarded-for", [])
+        if fwdHeaders:
+            host = fwdHeaders[0]
 
         if not (key and token):
             code = responsecode.BAD_REQUEST

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/test/test_applepush.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/test/test_applepush.py	2012-12-17 23:16:54 UTC (rev 10182)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/push/test/test_applepush.py	2012-12-17 23:18:07 UTC (rev 10183)
@@ -96,9 +96,9 @@
         yield txn.addAPNSubscription(token, key2, timestamp2, uid, userAgent, ipAddr)
 
         subscriptions = (yield txn.apnSubscriptionsBySubscriber(uid))
-        self.assertTrue([token, key1, timestamp1] in subscriptions)
-        self.assertTrue([token, key2, timestamp2] in subscriptions)
-        self.assertTrue([token2, key1, timestamp1] in subscriptions)
+        self.assertTrue([token, key1, timestamp1, userAgent, ipAddr] in subscriptions)
+        self.assertTrue([token, key2, timestamp2, userAgent, ipAddr] in subscriptions)
+        self.assertTrue([token2, key1, timestamp1, userAgent, ipAddr] in subscriptions)
 
         # Verify an update to a subscription with a different uid takes on
         # the new uid
@@ -106,10 +106,10 @@
         uid2 = "D8FFB335-9D36-4CE8-A3B9-D1859E38C0DA"
         yield txn.addAPNSubscription(token, key2, timestamp3, uid2, userAgent, ipAddr)
         subscriptions = (yield txn.apnSubscriptionsBySubscriber(uid))
-        self.assertTrue([token, key1, timestamp1] in subscriptions)
-        self.assertFalse([token, key2, timestamp3] in subscriptions)
+        self.assertTrue([token, key1, timestamp1, userAgent, ipAddr] in subscriptions)
+        self.assertFalse([token, key2, timestamp3, userAgent, ipAddr] in subscriptions)
         subscriptions = (yield txn.apnSubscriptionsBySubscriber(uid2))
-        self.assertTrue([token, key2, timestamp3] in subscriptions)
+        self.assertTrue([token, key2, timestamp3, userAgent, ipAddr] in subscriptions)
         # Change it back
         yield txn.addAPNSubscription(token, key2, timestamp2, uid, userAgent, ipAddr)
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tap/caldav.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tap/caldav.py	2012-12-17 23:16:54 UTC (rev 10182)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tap/caldav.py	2012-12-17 23:18:07 UTC (rev 10183)
@@ -874,6 +874,22 @@
             def requestFactory(*args, **kw):
                 return SSLRedirectRequest(site=underlyingSite, *args, **kw)
 
+        # Add the Strict-Transport-Security header to all secured requests
+        # if enabled.
+        if config.StrictTransportSecuritySeconds:
+            previousRequestFactory = requestFactory
+            def requestFactory(*args, **kw):
+                request = previousRequestFactory(*args, **kw)
+                def responseFilter(ignored, response):
+                    ignored, secure = request.chanRequest.getHostInfo()
+                    if secure:
+                        response.headers.addRawHeader("Strict-Transport-Security",
+                            "max-age={max_age:d}"
+                            .format(max_age=config.StrictTransportSecuritySeconds))
+                    return response
+                request.addResponseFilter(responseFilter)
+                return request
+
         httpFactory = LimitingHTTPFactory(
             requestFactory,
             maxRequests=config.MaxRequests,
@@ -894,6 +910,9 @@
         connectionService.setName(CalDAVService.connectionServiceName)
         connectionService.setServiceParent(service)
 
+        # For calendarserver.tap.test.test_caldav.BaseServiceMakerTests.getSite():
+        connectionService.underlyingSite = underlyingSite
+
         if config.InheritFDs or config.InheritSSLFDs:
             # Inherit sockets to call accept() on them individually.
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tap/test/test_caldav.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tap/test/test_caldav.py	2012-12-17 23:16:54 UTC (rev 10182)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tap/test/test_caldav.py	2012-12-17 23:18:07 UTC (rev 10183)
@@ -380,9 +380,10 @@
                 # NOTE: in a database 'single' configuration, PostgresService
                 # will prevent the HTTP services from actually getting added to
                 # the hierarchy until the hierarchy has started.
-                lambda x: hasattr(x, 'args')
+                # 'underlyingSite' assigned in caldav.py
+                lambda x: hasattr(x, 'underlyingSite')
             ):
-            return listeningService.args[1].protocolArgs['requestFactory']
+            return listeningService.underlyingSite
         raise RuntimeError("No site found.")
 
 

Deleted: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/test/test_methodDescriptor.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/test/test_methodDescriptor.py	2012-12-17 23:16:54 UTC (rev 10182)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/test/test_methodDescriptor.py	2012-12-17 23:18:07 UTC (rev 10183)
@@ -1,67 +0,0 @@
-##
-# Copyright (c) 2012 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.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-from twisted.trial.unittest import TestCase
-from calendarserver.methodDescriptor import getAdjustedMethodName
-
-class MethodDescriptor(TestCase):
-    """
-    Tests for L{getAdjustedMethodName}.
-    """
-    def test_getAdjustedMethodName(self):
-        """
-        L{getAdjustedMethodName} returns the appropriate method.
-        """
-
-        data = (
-            ("PROPFIND", "/calendars/users/user01/", {}, "PROPFIND Calendar Home",),
-            ("PROPFIND", "/calendars/users/user01/", {"cached": "1"}, "PROPFIND cached Calendar Home",),
-            ("PROPFIND", "/calendars/users/user01/ABC/", {}, "PROPFIND Calendar",),
-            ("PROPFIND", "/calendars/users/user01/inbox/", {}, "PROPFIND Inbox",),
-            ("PROPFIND", "/addressbooks/users/user01/", {}, "PROPFIND Adbk Home",),
-            ("PROPFIND", "/addressbooks/users/user01/", {"cached": "1"}, "PROPFIND cached Adbk Home",),
-            ("PROPFIND", "/addressbooks/users/user01/ABC/", {}, "PROPFIND Adbk",),
-            ("PROPFIND", "/addressbooks/users/user01/inbox/", {}, "PROPFIND Adbk",),
-            ("PROPFIND", "/principals/users/user01/", {}, "PROPFIND Principals",),
-            ("PROPFIND", "/principals/users/user01/", {"cached": "1"}, "PROPFIND cached Principals",),
-            ("PROPFIND", "/.well-known/caldav", {}, "PROPFIND",),
-
-            ("REPORT(CalDAV:sync-collection)", "/calendars/users/user01/ABC/", {}, "REPORT cal-sync",),
-            ("REPORT(CalDAV:calendar-query)", "/calendars/users/user01/ABC/", {}, "REPORT cal-query",),
-
-            ("POST", "/calendars/users/user01/", {}, "POST Calendar Home",),
-            ("POST", "/calendars/users/user01/outbox/", {"recipients": "1"}, "POST Freebusy",),
-            ("POST", "/calendars/users/user01/outbox/", {}, "POST Outbox",),
-            ("POST", "/apns", {}, "POST apns",),
-
-            ("PUT", "/calendars/users/user01/calendar/1.ics", {}, "PUT ics",),
-            ("PUT", "/calendars/users/user01/calendar/1.ics", {"itip.requests": "1"}, "PUT Organizer",),
-            ("PUT", "/calendars/users/user01/calendar/1.ics", {"itip.reply": "1"}, "PUT Attendee",),
-
-            ("GET", "/calendars/users/user01/", {}, "GET Calendar Home",),
-            ("GET", "/calendars/users/user01/calendar/", {}, "GET Calendar",),
-            ("GET", "/calendars/users/user01/calendar/1.ics", {}, "GET ics",),
-
-            ("DELETE", "/calendars/users/user01/", {}, "DELETE Calendar Home",),
-            ("DELETE", "/calendars/users/user01/calendar/", {}, "DELETE Calendar",),
-            ("DELETE", "/calendars/users/user01/calendar/1.ics", {}, "DELETE ics",),
-            ("DELETE", "/calendars/users/user01/inbox/1.ics", {}, "DELETE inbox ics",),
-
-            ("ACL", "/calendars/users/user01/", {}, "ACL",),
-        )
-
-        for method, uri, extras, result in data:
-            self.assertEqual(getAdjustedMethodName(method, uri, extras), result, "Failed getAdjustedMethodName: %s" % (result,))

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/dbinspect.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/dbinspect.py	2012-12-17 23:16:54 UTC (rev 10182)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/dbinspect.py	2012-12-17 23:18:07 UTC (rev 10183)
@@ -779,6 +779,7 @@
 
             schema.ADDRESSBOOK_OBJECT_REVISIONS,
 
+            schema.ADDRESSBOOK,
             schema.ABO_MEMBERS,
             schema.ADDRESSBOOK_OBJECT,
             #schema.ADDRESSBOOK_BIND, - cascades

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/push.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/push.py	2012-12-17 23:16:54 UTC (rev 10182)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/push.py	2012-12-17 23:18:07 UTC (rev 10183)
@@ -154,8 +154,8 @@
             (yield txn.commit())
             if subscriptions:
                 byKey = { }
-                for token, key, timestamp in subscriptions:
-                    byKey.setdefault(key, []).append((token, timestamp))
+                for token, key, timestamp, userAgent, ipAddr in subscriptions:
+                    byKey.setdefault(key, []).append((token, timestamp, userAgent, ipAddr))
                 for key, tokens in byKey.iteritems():
                     print
                     protocol, host, path = key.strip("/").split("/", 2)
@@ -176,8 +176,9 @@
                         print "...is subscribed to %s's %s home" % (user, resource),
                         # print "   (key: %s)\n" % (key,)
                     print "with %d device(s):" % (len(tokens),)
-                    for token, timestamp in tokens:
-                        print " %s  %ss ago" % (token, int(time.time()) - timestamp)
+                    for token, timestamp, userAgent, ipAddr in tokens:
+                        print " %s\n   '%s' from %s\n   %s" % (token, userAgent, ipAddr,
+                            time.strftime("on %a, %d %b %Y at %H:%M:%S %z(%Z)", time.localtime(timestamp)))
             else:
                 print " ...is not subscribed to anything."
         else:

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/web2/channel/http.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/web2/channel/http.py	2012-12-17 23:16:54 UTC (rev 10182)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/web2/channel/http.py	2012-12-17 23:18:07 UTC (rev 10183)
@@ -76,26 +76,11 @@
         self.transport.loseConnection()
 
 
-
 class SSLRedirectRequest(Request):
     """
     An L{SSLRedirectRequest} prevents processing if the request is over plain
     HTTP; instead, it redirects to HTTPS.
-
-    If the request is already secured, it instead sets the
-    Strict-Transport-Security header as documented by the U{HTTP Strict
-    Transport Security specification
-    <http://tools.ietf.org/html/draft-ietf-websec-strict-transport-sec-02>}.
-
-    @ivar maxAge: the number of seconds that a client must wait after receiving
-        an HTTPS response, before they may attempt to make an HTTP request
-        again.
-
-    @type maxAge: C{int}
     """
-
-    maxAge = 600
-
     def process(self):
         ignored, secure = self.chanRequest.getHostInfo()
         if not secure:
@@ -116,15 +101,6 @@
             return super(SSLRedirectRequest, self).process()
 
 
-    def writeResponse(self, response):
-        """
-        Response filter to add HSTS header.
-        """
-        response.headers.addRawHeader("Strict-Transport-Security",
-                                      "max-age={max_age:d}"
-                                      .format(max_age=self.maxAge))
-        return super(SSLRedirectRequest, self).writeResponse(response)
-
 # >%
 
 PERSIST_NO_PIPELINE, PERSIST_PIPELINE = (1,2)

Modified: CalendarServer/branches/users/gaya/sharedgroups/twext/web2/test/test_http.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twext/web2/test/test_http.py	2012-12-17 23:16:54 UTC (rev 10182)
+++ CalendarServer/branches/users/gaya/sharedgroups/twext/web2/test/test_http.py	2012-12-17 23:18:07 UTC (rev 10183)
@@ -742,18 +742,6 @@
         cxn.client.loseConnection()
         self.assertDone(cxn)
 
-
-    def test_http1_1_sts(self):
-        """
-        L{SSLRedirectRequest} uses strict transport security, and will set the
-        appropriate header.
-        """
-        self.requestClass = TestSSLRedirectRequest
-        return self.testHTTP1_1_chunking(
-            "Strict-Transport-Security: max-age=600"
-        )
-
-
     def testHTTP1_1_expect_continue(self):
         cxn = self.connect()
         cmds = [[]]

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/customxml.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/customxml.py	2012-12-17 23:16:54 UTC (rev 10182)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/customxml.py	2012-12-17 23:18:07 UTC (rev 10183)
@@ -59,7 +59,6 @@
     "calendarserver-principal-search",
 )
 
-
 calendarserver_sharing_compliance = (
     "calendarserver-sharing",
 )
@@ -69,7 +68,11 @@
     "calendarserver-sharing-no-scheduling",
 )
 
+calendarserver_partstat_changes_compliance = (
+    "calendarserver-partstat-changes",
+)
 
+
 @registerElement
 class TwistedCalendarSupportedComponents (WebDAVTextElement):
     """

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/icaldiff.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/icaldiff.py	2012-12-17 23:16:54 UTC (rev 10182)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/icaldiff.py	2012-12-17 23:18:07 UTC (rev 10183)
@@ -14,17 +14,19 @@
 # limitations under the License.
 ##
 
+from difflib import unified_diff
+
+from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.period import PyCalendarPeriod
+
 from twext.python.log import Logger
 
+from twistedcaldav import accounting
+from twistedcaldav.config import config
 from twistedcaldav.ical import Component, Property
 from twistedcaldav.scheduling.cuaddress import normalizeCUAddr
 from twistedcaldav.scheduling.itip import iTipGenerator
-from twistedcaldav import accounting
 
-from difflib import unified_diff
-from pycalendar.period import PyCalendarPeriod
-from pycalendar.datetime import PyCalendarDateTime
-
 """
 Class that handles diff'ing two calendar objects.
 """
@@ -483,7 +485,13 @@
 
         if serverAttendee.parameterValue("PARTSTAT", "NEEDS-ACTION") != clientAttendee.parameterValue("PARTSTAT", "NEEDS-ACTION"):
             serverAttendee.setParameter("PARTSTAT", clientAttendee.parameterValue("PARTSTAT", "NEEDS-ACTION"))
+
+            # If PARTSTAT was changed by the attendee, add a timestamp if needed
+            if config.Scheduling.Options.TimestampAttendeePartStatChanges:
+                serverAttendee.setParameter("X-CALENDARSERVER-DTSTAMP", PyCalendarDateTime.getNowUTC().getText())
+
             replyNeeded = True
+
         if serverAttendee.parameterValue("RSVP", "FALSE") != clientAttendee.parameterValue("RSVP", "FALSE"):
             if clientAttendee.parameterValue("RSVP", "FALSE") == "FALSE":
                 try:

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/implicit.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/implicit.py	2012-12-17 23:16:54 UTC (rev 10182)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/implicit.py	2012-12-17 23:18:07 UTC (rev 10183)
@@ -437,6 +437,9 @@
                 "Only one organizer allowed in scheduling object resource",
             ))
 
+        # Coerce any local with SCHEDULE-AGENT=CLIENT
+        yield self.coerceAttendeeScheduleAgent()
+
         # Get the ATTENDEEs
         self.attendeesByInstance = self.calendar.getAttendeesByInstance(True, onlyScheduleAgentServer=True)
         self.instances = set(self.calendar.getComponentInstances())
@@ -875,6 +878,26 @@
 
 
     @inlineCallbacks
+    def coerceAttendeeScheduleAgent(self):
+        """
+        Do not allow SCHEDULE-AGENT=CLIENT/NONE for attendees hosted by this server. Coerce to
+        SCHEDULE-AGENT=SERVER.
+        """
+
+        coerced = {}
+        for attendee in self.calendar.getAllAttendeeProperties():
+            if attendee.parameterValue("SCHEDULE-AGENT", "SERVER").upper() == "CLIENT":
+                cuaddr = attendee.value()
+                if cuaddr not in coerced:
+                    attendeePrincipal = self.resource.principalForCalendarUserAddress(cuaddr)
+                    attendeeAddress = (yield addressmapping.mapper.getCalendarUser(cuaddr, attendeePrincipal))
+                    local_attendee = type(attendeeAddress) in (LocalCalendarUser, PartitionedCalendarUser, OtherServerCalendarUser,)
+                    coerced[cuaddr] = local_attendee
+                if coerced[cuaddr]:
+                    attendee.removeParameter("SCHEDULE-AGENT")
+
+
+    @inlineCallbacks
     def scheduleWithAttendees(self):
 
         # First process cancelled attendees

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/itip.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/itip.py	2012-12-17 23:16:54 UTC (rev 10182)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/itip.py	2012-12-17 23:18:07 UTC (rev 10183)
@@ -117,12 +117,15 @@
             completeds = current_master.properties("COMPLETED")
             organizer = current_master.getProperty("ORGANIZER")
             organizer_schedule_status = organizer.parameterValue("SCHEDULE-STATUS", None) if organizer else None
+            attendee = current_master.getAttendeeProperty((recipient,))
+            attendee_dtstamp = attendee.parameterValue("X-CALENDARSERVER-DTSTAMP") if attendee else None
         else:
             master_valarms = ()
             private_comments = ()
             transps = ()
             completeds = ()
             organizer_schedule_status = None
+            attendee_dtstamp = None
 
         if itip_message.masterComponent() is not None:
 
@@ -143,11 +146,15 @@
                 organizer = master_component.getProperty("ORGANIZER")
                 if organizer:
                     organizer.setParameter("SCHEDULE-STATUS", organizer_schedule_status)
+            if attendee_dtstamp:
+                attendee = master_component.getAttendeeProperty((recipient,))
+                if attendee:
+                    attendee.setParameter("X-CALENDARSERVER-DTSTAMP", attendee_dtstamp)
 
             # Now try to match recurrences in the new calendar
             for component in tuple(new_calendar.subcomponents()):
                 if component.name() != "VTIMEZONE" and component.getRecurrenceIDUTC() is not None:
-                    iTipProcessing.transferItems(calendar, master_valarms, private_comments, transps, completeds, organizer_schedule_status, component, recipient)
+                    iTipProcessing.transferItems(calendar, master_valarms, private_comments, transps, completeds, organizer_schedule_status, attendee_dtstamp, component, recipient)
 
             # Now try to match recurrences from the old calendar
             for component in calendar.subcomponents():
@@ -158,7 +165,7 @@
                         new_component = new_calendar.deriveInstance(rid, allowCancelled=allowCancelled)
                         if new_component:
                             new_calendar.addComponent(new_component)
-                            iTipProcessing.transferItems(calendar, master_valarms, private_comments, transps, completeds, organizer_schedule_status, new_component, recipient)
+                            iTipProcessing.transferItems(calendar, master_valarms, private_comments, transps, completeds, organizer_schedule_status, attendee_dtstamp, new_component, recipient)
 
             # Replace the entire object
             return new_calendar, rids
@@ -175,7 +182,7 @@
                         calendar.addComponent(component)
                 else:
                     component = component.duplicate()
-                    missingDeclined = iTipProcessing.transferItems(calendar, master_valarms, private_comments, transps, completeds, organizer_schedule_status, component, recipient, remove_matched=True)
+                    missingDeclined = iTipProcessing.transferItems(calendar, master_valarms, private_comments, transps, completeds, organizer_schedule_status, attendee_dtstamp, component, recipient, remove_matched=True)
                     if not missingDeclined:
                         calendar.addComponent(component)
                         if recipient:
@@ -486,7 +493,7 @@
 
 
     @staticmethod
-    def transferItems(from_calendar, master_valarms, private_comments, transps, completeds, organizer_schedule_status, to_component, recipient, remove_matched=False):
+    def transferItems(from_calendar, master_valarms, private_comments, transps, completeds, organizer_schedule_status, attendee_dtstamp, to_component, recipient, remove_matched=False):
         """
         Transfer properties from a calendar to a component by first trying to match the component in the original calendar and
         use the properties from that, or use the values provided as arguments (which have been derived from the original calendar's
@@ -524,6 +531,8 @@
                 if matched.hasProperty(Component.HIDDEN_INSTANCE_PROPERTY):
                     to_component.addProperty(Property(Component.HIDDEN_INSTANCE_PROPERTY, "T"))
 
+            if attendee and attendee_dtstamp:
+                attendee.setParameter("X-CALENDARSERVER-DTSTAMP", attendee_dtstamp)
         else:
             # Check for incoming DECLINED
             attendee = to_component.getAttendeeProperty((recipient,))
@@ -540,6 +549,10 @@
                 organizer = to_component.getProperty("ORGANIZER")
                 if organizer:
                     organizer.setParameter("SCHEDULE-STATUS", organizer_schedule_status)
+            if attendee_dtstamp:
+                attendee = to_component.getAttendeeProperty((recipient,))
+                if attendee:
+                    attendee.setParameter("X-CALENDARSERVER-DTSTAMP", attendee_dtstamp)
 
         return False
 
@@ -843,7 +856,7 @@
         itip.removeXProperties(keep_properties=keep_properties)
 
         # Property Parameters
-        itip.removePropertyParameters("ATTENDEE", ("SCHEDULE-AGENT", "SCHEDULE-STATUS", "SCHEDULE-FORCE-SEND",))
+        itip.removePropertyParameters("ATTENDEE", ("SCHEDULE-AGENT", "SCHEDULE-STATUS", "SCHEDULE-FORCE-SEND", "X-CALENDARSERVER-DTSTAMP",))
         itip.removePropertyParameters("ORGANIZER", ("SCHEDULE-AGENT", "SCHEDULE-STATUS", "SCHEDULE-FORCE-SEND",))
 
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/test/test_icaldiff.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/test/test_icaldiff.py	2012-12-17 23:16:54 UTC (rev 10182)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/scheduling/test/test_icaldiff.py	2012-12-17 23:18:07 UTC (rev 10183)
@@ -20,6 +20,7 @@
 from difflib import unified_diff
 
 import itertools
+import re
 
 class ICalDiff (twistedcaldav.test.util.TestCase):
     """
@@ -558,7 +559,7 @@
 DTSTART:20080601T120000Z
 DTEND:20080601T130000Z
 ATTENDEE:mailto:user1 at example.com
-ATTENDEE;PARTSTAT=ACCEPTED:mailto:user2 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED;X-CALENDARSERVER-DTSTAMP=XXXXXXXXTXXXXXXZ:mailto:user2 at example.com
 ORGANIZER;CN=User 01:mailto:user1 at example.com
 END:VEVENT
 END:VCALENDAR
@@ -1180,7 +1181,11 @@
                 diffResult[0],
                 diffResult[1],
                 tuple(sorted(diffResult[2])),
-                str(diffResult[3]).replace("\r", "") if diffResult[3] else None,
+                re.sub(
+                    "X-CALENDARSERVER-DTSTAMP=[^Z]+",
+                    "X-CALENDARSERVER-DTSTAMP=XXXXXXXXTXXXXXX",
+                    str(diffResult[3]).replace("\r", "").replace("\n ", "")
+                ) if diffResult[3] else None,
             )
             self.assertEqual(diffResult, result, msg="%s: actual result: (%s)" % (description, ", ".join([str(i).replace("\r", "") for i in diffResult]),))
 
@@ -1566,7 +1571,7 @@
 RECURRENCE-ID:20080602T120000Z
 DTSTART:20080602T123000Z
 DTEND:20080602T130000Z
-ATTENDEE;PARTSTAT=ACCEPTED;RSVP=TRUE:mailto:user2 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED;RSVP=TRUE;X-CALENDARSERVER-DTSTAMP=XXXXXXXXTXXXXXXZ:mailto:user2 at example.com
 ORGANIZER:mailto:user1 at example.com
 END:VEVENT
 BEGIN:VEVENT
@@ -1575,7 +1580,7 @@
 DTSTART:20080604T120000Z
 DTEND:20080604T130000Z
 ATTENDEE:mailto:user1 at example.com
-ATTENDEE;PARTSTAT=DECLINED;RSVP=TRUE:mailto:user2 at example.com
+ATTENDEE;PARTSTAT=DECLINED;RSVP=TRUE;X-CALENDARSERVER-DTSTAMP=XXXXXXXXTXXXXXXZ:mailto:user2 at example.com
 ORGANIZER;CN=User 01:mailto:user1 at example.com
 END:VEVENT
 END:VCALENDAR
@@ -1678,7 +1683,11 @@
                 diffResult[0],
                 diffResult[1],
                 tuple(sorted(diffResult[2])),
-                str(diffResult[3]).replace("\r", "") if diffResult[3] else None,
+                re.sub(
+                    "X-CALENDARSERVER-DTSTAMP=[^Z]+",
+                    "X-CALENDARSERVER-DTSTAMP=XXXXXXXXTXXXXXX",
+                    str(diffResult[3]).replace("\r", "").replace("\n ", "")
+                ) if diffResult[3] else None,
             )
             self.assertEqual(diffResult, result, msg="%s: actual result: (%s)" % (description, ", ".join([str(i).replace("\r", "") for i in diffResult]),))
 
@@ -2715,7 +2724,7 @@
 DTSTART:20080601T120000Z
 DTEND:20080601T130000Z
 ATTENDEE:mailto:user1 at example.com
-ATTENDEE;PARTSTAT=ACCEPTED:mailto:user2 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED;X-CALENDARSERVER-DTSTAMP=XXXXXXXXTXXXXXXZ:mailto:user2 at example.com
 ORGANIZER;CN=User 01:mailto:user1 at example.com
 END:VEVENT
 END:VCALENDAR
@@ -2760,7 +2769,7 @@
 DTSTART:20080601T130000Z
 DTEND:20080601T140000Z
 ATTENDEE:mailto:user1 at example.com
-ATTENDEE;PARTSTAT=ACCEPTED:mailto:user2 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED;X-CALENDARSERVER-DTSTAMP=XXXXXXXXTXXXXXXZ:mailto:user2 at example.com
 ORGANIZER;CN=User 01:mailto:user1 at example.com
 END:VEVENT
 END:VCALENDAR
@@ -2805,7 +2814,7 @@
 DTSTART:20080601T130000Z
 DTEND:20080601T140000Z
 ATTENDEE:mailto:user1 at example.com
-ATTENDEE;PARTSTAT=ACCEPTED:mailto:user2 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED;X-CALENDARSERVER-DTSTAMP=XXXXXXXXTXXXXXXZ:mailto:user2 at example.com
 ORGANIZER;CN=User 01:mailto:user1 at example.com
 END:VEVENT
 END:VCALENDAR
@@ -2868,7 +2877,7 @@
 DTSTART:20080601T120000Z
 DTEND:20080601T130000Z
 ATTENDEE:mailto:user1 at example.com
-ATTENDEE;PARTSTAT=ACCEPTED:mailto:user2 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED;X-CALENDARSERVER-DTSTAMP=XXXXXXXXTXXXXXXZ:mailto:user2 at example.com
 ORGANIZER;CN=User 01:mailto:user1 at example.com
 END:VEVENT
 BEGIN:VEVENT
@@ -2877,7 +2886,7 @@
 DTSTART:20080602T120000Z
 DTEND:20080602T130000Z
 ATTENDEE:mailto:user1 at example.com
-ATTENDEE;PARTSTAT=ACCEPTED;RSVP=TRUE:mailto:user2 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED;RSVP=TRUE;X-CALENDARSERVER-DTSTAMP=XXXXXXXXTXXXXXXZ:mailto:user2 at example.com
 ORGANIZER;CN=User 01:mailto:user1 at example.com
 END:VEVENT
 END:VCALENDAR
@@ -2940,7 +2949,7 @@
 DTSTART:20080601T140000Z
 DTEND:20080601T150000Z
 ATTENDEE:mailto:user1 at example.com
-ATTENDEE;PARTSTAT=ACCEPTED:mailto:user2 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED;X-CALENDARSERVER-DTSTAMP=XXXXXXXXTXXXXXXZ:mailto:user2 at example.com
 ORGANIZER;CN=User 01:mailto:user1 at example.com
 END:VEVENT
 BEGIN:VEVENT
@@ -2949,7 +2958,7 @@
 DTSTART:20080602T120000Z
 DTEND:20080602T130000Z
 ATTENDEE:mailto:user1 at example.com
-ATTENDEE;PARTSTAT=ACCEPTED:mailto:user2 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED;X-CALENDARSERVER-DTSTAMP=XXXXXXXXTXXXXXXZ:mailto:user2 at example.com
 ORGANIZER;CN=User 01:mailto:user1 at example.com
 END:VEVENT
 END:VCALENDAR
@@ -3066,7 +3075,7 @@
 DTSTART:20080601T120000Z
 DTEND:20080601T130000Z
 ATTENDEE:mailto:user1 at example.com
-ATTENDEE;PARTSTAT=ACCEPTED:mailto:user2 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED;X-CALENDARSERVER-DTSTAMP=XXXXXXXXTXXXXXXZ:mailto:user2 at example.com
 ORGANIZER;CN=User 01:mailto:user1 at example.com
 END:VEVENT
 END:VCALENDAR
@@ -3134,7 +3143,7 @@
 DTSTART:20080601T120000Z
 DTEND:20080601T130000Z
 ATTENDEE:mailto:user1 at example.com
-ATTENDEE;PARTSTAT=ACCEPTED:mailto:user2 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED;X-CALENDARSERVER-DTSTAMP=XXXXXXXXTXXXXXXZ:mailto:user2 at example.com
 ORGANIZER;CN=User 01:mailto:user1 at example.com
 END:VEVENT
 END:VCALENDAR
@@ -3203,7 +3212,7 @@
 DTSTART:20080601T120000Z
 DTEND:20080601T130000Z
 ATTENDEE:mailto:user1 at example.com
-ATTENDEE;PARTSTAT=ACCEPTED:mailto:user2 at example.com
+ATTENDEE;PARTSTAT=ACCEPTED;X-CALENDARSERVER-DTSTAMP=XXXXXXXXTXXXXXXZ:mailto:user2 at example.com
 ORGANIZER;CN=User 01:mailto:user1 at example.com
 END:VEVENT
 END:VCALENDAR
@@ -3218,7 +3227,11 @@
                 diffResult[0],
                 diffResult[1],
                 tuple(sorted(diffResult[2])),
-                str(diffResult[3]).replace("\r", "") if diffResult[3] else None,
+                re.sub(
+                    "X-CALENDARSERVER-DTSTAMP=[^Z]+",
+                    "X-CALENDARSERVER-DTSTAMP=XXXXXXXXTXXXXXX",
+                    str(diffResult[3]).replace("\r", "").replace("\n ", "")
+                ) if diffResult[3] else None,
             )
             self.assertEqual(diffResult, result, msg="%s: actual result: (%s)" % (description, ", ".join([str(i).replace("\r", "") for i in diffResult]),))
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/stdconfig.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/stdconfig.py	2012-12-17 23:16:54 UTC (rev 10182)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/stdconfig.py	2012-12-17 23:18:07 UTC (rev 10183)
@@ -250,6 +250,8 @@
     "RedirectHTTPToHTTPS" : False, # If True, all nonSSL requests redirected to an SSL Port
     "SSLMethod" : "SSLv3_METHOD", # SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD
     "SSLCiphers" : "ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM",
+    "StrictTransportSecuritySeconds" : 7 * 24 * 60 * 60, # max-age value for
+        # Strict-Transport-Security header; set to 0 to disable header.
 
     #
     # Network address configuration information
@@ -692,7 +694,8 @@
             "UIDLockTimeoutSeconds"               : 60, # Time for implicit UID lock timeout
             "UIDLockExpirySeconds"                : 300, # Expiration time for UID lock,
             "V1Compatibility"                     : False, # Allow /path-based CUAs in scheduling replies
-            "PrincipalHostAliases"                : [], # Hostnames matched in http(s) CUAs
+            "PrincipalHostAliases"                : [], # Host names matched in http(s) CUAs
+            "TimestampAttendeePartStatChanges"    : True, # Add a time stamp when an Attendee changes their PARTSTAT
 
             "DelegeteRichFreeBusy"                : True, # Delegates can get extra info in a freebusy request
             "RoomResourceRichFreeBusy"            : True, # Any user can get extra info for rooms/resources in a freebusy request
@@ -1534,6 +1537,8 @@
             compliance += caldavxml.caldav_default_alarms_compliance
         if configDict.EnableManagedAttachments:
             compliance += caldavxml.caldav_managed_attachments_compliance
+        if configDict.Scheduling.Options.TimestampAttendeePartStatChanges:
+            compliance += customxml.calendarserver_partstat_changes_compliance
     else:
         compliance = ()
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_13_to_14.sql
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_13_to_14.sql	2012-12-17 23:16:54 UTC (rev 10182)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_13_to_14.sql	2012-12-17 23:18:07 UTC (rev 10183)
@@ -23,10 +23,18 @@
 drop table INVITE;
 
 alter table CALENDAR_BIND
- drop column SEEN_BY_OWNER, SEEN_BY_SHAREE;
-
+ drop column SEEN_BY_OWNER;
+alter table CALENDAR_BIND
+ drop column SEEN_BY_SHAREE;
+alter table CALENDAR_BIND
+ modify (ADDRESSBOOK_RESOURCE_NAME not null);
+ 
 alter table ADDRESSBOOK_BIND
- drop column SEEN_BY_OWNER, SEEN_BY_SHAREE;
+ drop column SEEN_BY_OWNER;
+alter table ADDRESSBOOK_BIND
+ drop column SEEN_BY_SHAREE;
+alter table ADDRESSBOOK_BIND
+ modify (ADDRESSBOOK_RESOURCE_NAME not null);
 
 -- Now update the version
 -- No data upgrades

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_13_to_14.sql
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_13_to_14.sql	2012-12-17 23:16:54 UTC (rev 10182)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_13_to_14.sql	2012-12-17 23:18:07 UTC (rev 10183)
@@ -26,11 +26,17 @@
  drop column SEEN_BY_OWNER;
 alter table CALENDAR_BIND
  drop column SEEN_BY_SHAREE;
+alter table CALENDAR_BIND
+ alter column CALENDAR_RESOURCE_NAME 
+  set not null;
 
 alter table ADDRESSBOOK_BIND
  drop column SEEN_BY_OWNER;
 alter table ADDRESSBOOK_BIND
  drop column SEEN_BY_SHAREE;
+alter table ADDRESSBOOK_BIND
+ alter column ADDRESSBOOK_RESOURCE_NAME
+  set not null;
 
 -- Now update the version
 -- No data upgrades

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/test/test_migrate.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/test/test_migrate.py	2012-12-17 23:16:54 UTC (rev 10182)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/upgrade/test/test_migrate.py	2012-12-17 23:18:07 UTC (rev 10183)
@@ -405,9 +405,8 @@
         """
         Create an upgrade service.
         """
-        #FIXME: not parallel
         return UpgradeToDatabaseService(
             self.fileStore, self.sqlStore, self.stubService,
-            parallel=0, spawner=StubSpawner()
+            parallel=2, spawner=StubSpawner()
         )
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20121217/26dcb9e9/attachment-0001.html>


More information about the calendarserver-changes mailing list