[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