[CalendarServer-changes] [8550] CalendarServer/trunk/twistedcaldav

source_changes at macosforge.org source_changes at macosforge.org
Mon Jan 16 19:25:22 PST 2012


Revision: 8550
          http://trac.macosforge.org/projects/calendarserver/changeset/8550
Author:   cdaboo at apple.com
Date:     2012-01-16 19:25:20 -0800 (Mon, 16 Jan 2012)
Log Message:
-----------
Allow existing events with large attendee lists to still be usable even when over the max limit.

Modified Paths:
--------------
    CalendarServer/trunk/twistedcaldav/method/put_common.py
    CalendarServer/trunk/twistedcaldav/test/test_validation.py

Modified: CalendarServer/trunk/twistedcaldav/method/put_common.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/method/put_common.py	2012-01-17 01:47:32 UTC (rev 8549)
+++ CalendarServer/trunk/twistedcaldav/method/put_common.py	2012-01-17 03:25:20 UTC (rev 8550)
@@ -317,7 +317,7 @@
                     ))
 
                 # Valid attendee list size check
-                result, message = self.validAttendeeListSizeCheck()
+                result, message = (yield self.validAttendeeListSizeCheck())
                 if not result:
                     log.err(message)
                     raise HTTPError(
@@ -562,22 +562,39 @@
 
         return result, message
 
+    @inlineCallbacks
     def validAttendeeListSizeCheck(self):
         """
-        Make sure that the Attendee list length is within bounds.
+        Make sure that the Attendee list length is within bounds. We don't do this check for inbox because we
+        will assume that the limit has been applied on the PUT causing the iTIP message to be created.
+        
+        FIXME: The inbox check might not take into account iSchedule stuff from outside. That needs to have
+        the max attendees check applied at the time of delivery.
         """
         result = True
         message = ""
-        if config.MaxAttendeesPerInstance:
+        if config.MaxAttendeesPerInstance and not self.isiTIP:
             uniqueAttendees = set()
             for attendee in self.calendar.getAllAttendeeProperties():
                 uniqueAttendees.add(attendee.value())
             attendeeListLength = len(uniqueAttendees)
             if attendeeListLength > config.MaxAttendeesPerInstance:
-                result = False
-                message = "Attendee list size %d is larger than allowed limit %d" % (attendeeListLength, config.MaxAttendeesPerInstance)
+                
+                # Check to see whether we are increasing the count on an existing resource
+                if self.destination.exists() and self.destinationcal:
+                    oldcalendar = (yield self.destination.iCalendarForUser(self.request))
+                    uniqueAttendees = set()
+                    for attendee in oldcalendar.getAllAttendeeProperties():
+                        uniqueAttendees.add(attendee.value())
+                    oldAttendeeListLength = len(uniqueAttendees)
+                else:
+                    oldAttendeeListLength = 0
+                
+                if attendeeListLength > oldAttendeeListLength:
+                    result = False
+                    message = "Attendee list size %d is larger than allowed limit %d" % (attendeeListLength, config.MaxAttendeesPerInstance)
 
-        return result, message
+        returnValue((result, message,))
 
     def validAccess(self):
         """

Modified: CalendarServer/trunk/twistedcaldav/test/test_validation.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_validation.py	2012-01-17 01:47:32 UTC (rev 8549)
+++ CalendarServer/trunk/twistedcaldav/test/test_validation.py	2012-01-17 03:25:20 UTC (rev 8550)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2009 Apple Inc. All rights reserved.
+# Copyright (c) 2009-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.
@@ -30,6 +30,17 @@
 from twistedcaldav.caldavxml import MaxAttendeesPerInstance
 from twistedcaldav.resource import CalDAVResource
 
+class InMemoryCalendarObjectResource(CalDAVResource):
+    
+    def exists(self):
+        return hasattr(self, "_data") and self._data is not None
+
+    def iCalendarForUser(self, user):
+        return self._data
+    
+    def setData(self, data):
+        self._data = data
+
 class TestCopyMoveValidation(TestCase):
     """
     Tests for the validation code in L{twistedcaldav.method.put_common}.
@@ -40,7 +51,7 @@
         Set up some CalDAV stuff.
         """
 
-        self.destination = CalDAVResource()
+        self.destination = InMemoryCalendarObjectResource()
         self.destination.name = lambda : '1'
         self.destinationParent = CalDAVResource()
         self.destinationParent.name = lambda : '2'
@@ -84,13 +95,14 @@
 
 
     @inlineCallbacks
-    def test_exceedMaximumAttendees(self):
+    def test_exceedMaximumAttendeesIfNew(self):
         """
         If too many attendees are specified (more than the configured maximum
         for the server), the storer raises an exception containing a
         L{MaxAttendeesPerInstance} element that reports the maximum value, as
         per U{RFC4791 section 5.2.9
         <http://www.webdav.org/specs/rfc4791.html#max-attendees-per-instance>}.
+        This test is for new resources.
         """
 
         # Get the event, and add too many attendees to it.
@@ -114,3 +126,99 @@
             self.assertEquals(int(element.text), config.MaxAttendeesPerInstance)
         else:
             self.fail("No error; validation should have failed!")
+
+
+    @inlineCallbacks
+    def test_exceedMaximumAttendeesWhenIncreasing(self):
+        """
+        If too many attendees are specified (more than the configured maximum
+        for the server), the storer raises an exception containing a
+        L{MaxAttendeesPerInstance} element that reports the maximum value, as
+        per U{RFC4791 section 5.2.9
+        <http://www.webdav.org/specs/rfc4791.html#max-attendees-per-instance>}.
+        This test is for an increase to an already over-sized resource.
+        """
+
+        self.patch(config, "MaxAttendeesPerInstance", config.MaxAttendeesPerInstance + 10)
+
+        # Get the event, and add many attendees to it - but not enough to fail.
+        self.sampleCalendar = self._getSampleCalendar()
+        eventComponent = list(self.sampleCalendar.subcomponents())[0]
+        for x in xrange(config.MaxAttendeesPerInstance - 5):
+            eventComponent.addProperty(
+                Property("ATTENDEE", "mailto:user%d at example.com" % (x+3,)))
+
+        try:
+            yield self._getStorer(self.sampleCalendar).fullValidation()
+        except HTTPError:
+            self.fail("Validation should not have failed!")
+        self.destination.setData(self.sampleCalendar.duplicate())
+
+        # Now reduce the limit and try to add an attendee.
+        config.MaxAttendeesPerInstance -= 10
+        eventComponent.addProperty(
+            Property("ATTENDEE", "mailto:user-extra at example.com"))
+        
+        try:
+            yield self._getStorer(self.sampleCalendar).fullValidation()
+        except HTTPError, err:
+            element = XML(err.response.stream.mem)[0]
+            self.assertEquals(
+                element.tag,
+                "{%s}%s" % (
+                    MaxAttendeesPerInstance.namespace,
+                    MaxAttendeesPerInstance.name
+                )
+            )
+            self.assertEquals(int(element.text), config.MaxAttendeesPerInstance)
+        else:
+            self.fail("No error; validation should have failed!")
+
+
+    @inlineCallbacks
+    def test_doNotExceedMaximumAttendeesIfAlreadyPresent(self):
+        """
+        If too many attendees are specified (more than the configured maximum
+        for the server), the storer raises an exception containing a
+        L{MaxAttendeesPerInstance} element that reports the maximum value, as
+        per U{RFC4791 section 5.2.9
+        <http://www.webdav.org/specs/rfc4791.html#max-attendees-per-instance>}.
+        This test is for no change to an already over-sized resource.
+        """
+
+        self.patch(config, "MaxAttendeesPerInstance", config.MaxAttendeesPerInstance + 10)
+
+        # Get the event, and add many attendees to it - but not enough to fail.
+        self.sampleCalendar = self._getSampleCalendar()
+        eventComponent = list(self.sampleCalendar.subcomponents())[0]
+        for x in xrange(config.MaxAttendeesPerInstance - 5):
+            eventComponent.addProperty(
+                Property("ATTENDEE", "mailto:user%d at example.com" % (x+3,)))
+
+        try:
+            yield self._getStorer(self.sampleCalendar).fullValidation()
+        except HTTPError:
+            self.fail("Validation should not have failed!")
+        self.destination.setData(self.sampleCalendar.duplicate())
+
+        # Now reduce the limit and try to store without any additional attendees.
+        config.MaxAttendeesPerInstance -= 10
+        
+        try:
+            yield self._getStorer(self.sampleCalendar).fullValidation()
+        except HTTPError:
+            self.fail("Validation should not have failed!")
+        self.destination.setData(self.sampleCalendar.duplicate())
+
+        # Now try to store with fewer attendees.
+        self.sampleCalendar = self._getSampleCalendar()
+        eventComponent = list(self.sampleCalendar.subcomponents())[0]
+        for x in xrange(config.MaxAttendeesPerInstance + 2):
+            eventComponent.addProperty(
+                Property("ATTENDEE", "mailto:user%d at example.com" % (x+3,)))
+        
+        try:
+            yield self._getStorer(self.sampleCalendar).fullValidation()
+        except HTTPError:
+            self.fail("Validation should not have failed!")
+        self.destination.setData(self.sampleCalendar.duplicate())
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120116/013d8ba2/attachment.html>


More information about the calendarserver-changes mailing list