diff --git a/ChangeLog b/ChangeLog index 00f83764c..8b383cc2e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2012-05-09 Jean Raby + + * SoObjects/Appointments/SOGoAppointmentObject.m (PUTAction): + Delete bitrotten code that could end up duplicating attendees. + Behavior exposed by the new caldav tests + + * Tests/Integration/config.py.in + * Tests/Integration/test-caldav-scheduling.py + * Tests/Integration/test-ical.py + * Tests/Integration/test-davacl.py: + Use an unprivileged webdavclient where possible. + This would have uncovered the resources calendar autocreation bug. + + * Tests/Integration/test-caldav-scheduling.py: + New tests to excercise somewhat fragile code in dav autoscheduling. + 2012-05-09 Jean Raby * SoObject/SOGo/SOGoParentFolder.m (_createPersonalFolder): diff --git a/Documentation/SOGo Installation Guide.odt b/Documentation/SOGo Installation Guide.odt index d2e057c27..c9f49e63a 100644 Binary files a/Documentation/SOGo Installation Guide.odt and b/Documentation/SOGo Installation Guide.odt differ diff --git a/SoObjects/Appointments/SOGoAppointmentObject.m b/SoObjects/Appointments/SOGoAppointmentObject.m index 50f02bc98..37924103b 100644 --- a/SoObjects/Appointments/SOGoAppointmentObject.m +++ b/SoObjects/Appointments/SOGoAppointmentObject.m @@ -1891,16 +1891,6 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent // one from the request. [rq setContent: [[[newEvent parent] versitString] dataUsingEncoding: [rq contentEncoding]]]; } - - // A RECURRENCE-ID was removed so there has to be a change in the master event - // We could also have an EXDATE added in the master component of the attendees - // so we always compare the MASTER event. - if (!master) - { - newEvent = [newEvents objectAtIndex: 0]; - oldEvent = [oldEvents objectAtIndex: 0]; - [self _handleUpdatedEvent: newEvent fromOldEvent: oldEvent]; - } } // // else => attendee is responding diff --git a/Tests/Integration/config.py.in b/Tests/Integration/config.py.in index 149dff65d..0de6d4a4f 100644 --- a/Tests/Integration/config.py.in +++ b/Tests/Integration/config.py.in @@ -1,16 +1,24 @@ -# setup: username must be super-user or have read-access to PUBLIC events in -# both attendee and delegate's personal calendar +# setup: 4 user are needed: username, superuser, attendee1, attendee1_delegate +# superuser must be a sogo superuser... hostname = "localhost" port = "80" username = "myuser" password = "mypass" +superuser = "super" +superuser_password="pass" + subscriber_username = "otheruser" subscriber_password = "otherpass" attendee1 = "user@domain.com" -attendee1_delegate = "otheruser@domain.com" +attendee1_username = "user" +attendee1_password = "pass" + +attendee1_delegate = "user2@domain.com" +attendee1_delegate_username = "sogo2" +attendee1_delegate_password = "sogo" resource_no_overbook = "res" resource_can_overbook = "res-nolimit" diff --git a/Tests/Integration/test-caldav-scheduling.py b/Tests/Integration/test-caldav-scheduling.py index 559bd9753..513b6e19e 100755 --- a/Tests/Integration/test-caldav-scheduling.py +++ b/Tests/Integration/test-caldav-scheduling.py @@ -1,10 +1,15 @@ #!/usr/bin/python -# setup: username must be super-user or have read-access to PUBLIC events in -# both attendee and delegate's personal calendar +# setup: 4 users are needed: username, attendee1_username, +# attendee1_delegate_username and superuser. +# when writing new tests, avoid using superuser when not absolutely needed from config import hostname, port, username, password, \ - attendee1, attendee1_delegate, \ + superuser, superuser_password, \ + attendee1, attendee1_username, \ + attendee1_password, \ + attendee1_delegate, attendee1_delegate_username, \ + attendee1_delegate_password, \ resource_no_overbook, resource_can_overbook import datetime @@ -98,10 +103,17 @@ class CalDAVPropertiesTest(unittest.TestCase): % (proppatch.response["status"], proppatch.response["body"])) -class CalDAVITIPDelegationTest(unittest.TestCase): +class CalDAVSchedulingTest(unittest.TestCase): def setUp(self): + self.superuser_client = webdavlib.WebDAVClient(hostname, port, + superuser, superuser_password) self.client = webdavlib.WebDAVClient(hostname, port, username, password) + self.attendee1_client = webdavlib.WebDAVClient(hostname, port, + attendee1_username, attendee1_password) + self.attendee1_delegate_client = webdavlib.WebDAVClient(hostname, port, + attendee1_delegate_username, attendee1_password) + utility = utilities.TestUtility(self, self.client) (self.user_name, self.user_email) = utility.fetchUserInfo(username) (self.attendee1_name, self.attendee1_email) = utility.fetchUserInfo(attendee1) @@ -117,14 +129,14 @@ class CalDAVITIPDelegationTest(unittest.TestCase): def tearDown(self): self._deleteEvent(self.client, "%stest-delegation.ics" % self.user_calendar, None) - self._deleteEvent(self.client, + self._deleteEvent(self.attendee1_client, "%stest-delegation.ics" % self.attendee1_calendar, None) - self._deleteEvent(self.client, + self._deleteEvent(self.attendee1_delegate_client, "%stest-delegation.ics" % self.attendee1_delegate_calendar, None) self._deleteEvent(self.client, "%stest-add-attendee.ics" % self.user_calendar, None) - self._deleteEvent(self.client, + self._deleteEvent(self.attendee1_client, "%stest-add-attendee.ics" % self.attendee1_calendar, None) self._deleteEvent(self.client, "%stest-no-overbook.ics" % self.user_calendar, None) @@ -135,9 +147,13 @@ class CalDAVITIPDelegationTest(unittest.TestCase): self._deleteEvent(self.client, "%stest-can-overbook-overlap.ics" % self.user_calendar, None) self._deleteEvent(self.client, - "%stest-remove-attendee.ics" % self.user_calendar, None) + "%stest-rrule-exception-invitation-dance.ics" % self.user_calendar, None) + self._deleteEvent(self.attendee1_client, + "%stest-rrule-exception-invitation-dance.ics" % self.attendee1_calendar, None) self._deleteEvent(self.client, - "%stest-remove-attendee-no-org.ics" % self.user_calendar, None) + "%stest-rrule-invitation-deleted-exdate-dance.ics" % self.user_calendar, None) + self._deleteEvent(self.attendee1_client, + "%stest-rrule-invitation-deleted-exdate-dance.ics" % self.attendee1_calendar, None) def _newEvent(self, summary="test event", uid="test", transp=0): transparency = ("OPAQUE", "TRANSPARENT") @@ -156,7 +172,7 @@ class CalDAVITIPDelegationTest(unittest.TestCase): vevent.add('dtstamp').value = now vevent.add('last-modified').value = now vevent.add('created').value = now - + vevent.add('class').value = "PUBLIC" vevent.add('sequence').value = "0" return newCal @@ -242,6 +258,41 @@ class CalDAVITIPDelegationTest(unittest.TestCase): % (email, compared_attendees[email], attendees[email])) + def testAddAttendee(self): + """ add attendee after event creation """ + + # make sure the event doesn't exist + ics_name = "test-add-attendee.ics" + self._deleteEvent(self.client, + "%s%s" % (self.user_calendar,ics_name), None) + self._deleteEvent(self.attendee1_client, + "%s%s" % (self.attendee1_calendar,ics_name), None) + + # 1. create an event in the organiser's calendar + event = self._newEvent(summary="Test add attendee", uid="Test add attendee") + organizer = event.vevent.add('organizer') + organizer.cn_param = self.user_name + organizer.value = self.user_email + self._putEvent(self.client, "%s%s" % (self.user_calendar, ics_name), event) + + # 2. add an attendee + event.add("method").value = "REQUEST" + attendee = event.vevent.add('attendee') + attendee.cn_param = self.attendee1_name + attendee.rsvp_param = "TRUE" + attendee.partstat_param = "NEEDS-ACTION" + attendee.value = self.attendee1_email + self._putEvent(self.client, "%s%s" % (self.user_calendar, ics_name), event, + exp_status=204) + + + # 3. verify that the attendee has the event + attendee_event = self._getEvent(self.attendee1_client, "%s%s" % (self.attendee1_calendar, ics_name)) + + # 4. make sure the received event match the original one + # XXX is this enough? + self.assertEquals(event.vevent.uid, attendee_event.vevent.uid) + def testUninviteAttendee(self): """ Remove attendee after event creation """ @@ -249,7 +300,7 @@ class CalDAVITIPDelegationTest(unittest.TestCase): ics_name = "test-remove-attendee.ics" self._deleteEvent(self.client, "%s%s" % (self.user_calendar,ics_name), None) - self._deleteEvent(self.client, + self._deleteEvent(self.attendee1_client, "%s%s" % (self.attendee1_calendar,ics_name), None) # 1. create an event in the organiser's calendar @@ -275,7 +326,7 @@ class CalDAVITIPDelegationTest(unittest.TestCase): exp_status=204) # 3. verify that the attendee has the event - attendee_event = self._getEvent(self.client, "%s%s" % (self.attendee1_calendar, ics_name)) + attendee_event = self._getEvent(self.attendee1_client, "%s%s" % (self.attendee1_calendar, ics_name)) # 4. make sure the received event match the original one self.assertEquals(event.vevent.uid, attendee_event.vevent.uid) @@ -287,92 +338,42 @@ class CalDAVITIPDelegationTest(unittest.TestCase): exp_status=204) # 6. verify that the attendee doesn't have the event anymore - attendee_event = self._getEvent(self.client, "%s%s" % (self.attendee1_calendar, ics_name), 404) + attendee_event = self._getEvent(self.attendee1_client, "%s%s" % (self.attendee1_calendar, ics_name), 404) - def testUninviteAttendeeNoOrganizer(self): - """ Remove attendee and organizer after event creation """ + def testAddAttendee(self): + """ add attendee after event creation """ # make sure the event doesn't exist - ics_name = "test-remove-attendee-no-org.ics" + ics_name = "test-add-attendee.ics" self._deleteEvent(self.client, "%s%s" % (self.user_calendar,ics_name), None) self._deleteEvent(self.client, "%s%s" % (self.attendee1_calendar,ics_name), None) # 1. create an event in the organiser's calendar - event = self._newEvent(summary="Test uninvite attendee no org", uid="Test uninvite attendee no org") - # keep a copy around for updates without other attributes - plainEvent = vobject.iCalendar() - plainEvent.copy(event) - + event = self._newEvent(summary="Test add attendee", uid="Test add attendee") organizer = event.vevent.add('organizer') organizer.cn_param = self.user_name organizer.value = self.user_email - self._putEvent(self.client, "%s%s" % (self.user_calendar, ics_name), event) - # 2. add an attendee - event.add("method").value = "REQUEST" attendee = event.vevent.add('attendee') attendee.cn_param = self.attendee1_name attendee.rsvp_param = "TRUE" attendee.partstat_param = "NEEDS-ACTION" attendee.value = self.attendee1_email self._putEvent(self.client, "%s%s" % (self.user_calendar, ics_name), event, - exp_status=204) + exp_status=204) + # 3. verify that the attendee has the event - attendee_event = self._getEvent(self.client, "%s%s" % (self.attendee1_calendar, ics_name)) - + attendee_event = self._getEvent(self.attendee1_client, "%s%s" % (self.attendee1_calendar, ics_name)) + # 4. make sure the received event match the original one + # XXX is this enough? self.assertEquals(event.vevent.uid, attendee_event.vevent.uid) - # 5. put the event back without attendee or organizer - now = datetime.datetime.now(dateutil.tz.gettz("America/Montreal")) - plainEvent.vevent.last_modified.value = now - self._putEvent(self.client, "%s%s" % (self.user_calendar, ics_name), plainEvent, - exp_status=204) - - # 6. verify that the attendee doesn't have the event anymore - attendee_event = self._getEvent(self.client, "%s%s" % (self.attendee1_calendar, ics_name), 404) - - - def testAddAttendee(self): - """ add attendee after event creation """ - - # make sure the event doesn't exist - ics_name = "test-add-attendee.ics" - self._deleteEvent(self.client, - "%s%s" % (self.user_calendar,ics_name), None) - self._deleteEvent(self.client, - "%s%s" % (self.attendee1_calendar,ics_name), None) - - # 1. create an event in the organiser's calendar - event = self._newEvent(summary="Test add attendee", uid="Test add attendee") - organizer = event.vevent.add('organizer') - organizer.cn_param = self.user_name - organizer.value = self.user_email - self._putEvent(self.client, "%s%s" % (self.user_calendar, ics_name), event) - - # 2. add an attendee - event.add("method").value = "REQUEST" - attendee = event.vevent.add('attendee') - attendee.cn_param = self.attendee1_name - attendee.rsvp_param = "TRUE" - attendee.partstat_param = "NEEDS-ACTION" - attendee.value = self.attendee1_email - self._putEvent(self.client, "%s%s" % (self.user_calendar, ics_name), event, - exp_status=204) - - - # 3. verify that the attendee has the event - attendee_event = self._getEvent(self.client, "%s%s" % (self.attendee1_calendar, ics_name)) - - # 4. make sure the received event match the original one - # XXX is this enough? - self.assertEquals(event.vevent.uid, attendee_event.vevent.uid) - def testResourceNoOverbook(self): """ try to overbook a resource """ @@ -450,15 +451,219 @@ class CalDAVITIPDelegationTest(unittest.TestCase): self._putEvent(self.client, "%s%s" % (self.user_calendar, ob_ics_name), event) + def testRruleExceptionInvitationDance(self): + """ RRULE exception invitation dance """ + + # This workflow is based on what lightning 1.2.1 does + # create a reccurring event + # add an exception + # invite bob to the exception: + # bob is declined in the master event + # bob needs-action in the exception + # bob accepts + # bob is declined in the master event + # bob is accepted in the exception + # the organizer 'uninvites' bob + # the event disappears from bob's calendar + # bob isn't in the master+exception event + + ics_name = "test-rrule-exception-invitation-dance.ics" + self._deleteEvent(self.client, + "%s%s" % (self.user_calendar, ics_name), None) + self._deleteEvent(self.attendee1_client, + "%s%s" % (self.attendee1_calendar, ics_name), None) + + # 1. create a recurring event in the organiser's calendar + summary="Test reccuring exception invite cancel" + uid="Test-recurring-exception-invite-cancel" + event = self._newEvent(summary, uid) + event.vevent.add('rrule').value = "FREQ=DAILY;COUNT=5" + + self._putEvent(self.client, "%s%s" % (self.user_calendar, ics_name), event) + + # read the event back from the server + org_ev = self._getEvent(self.client, "%s%s" % (self.user_calendar, ics_name)) + + # 2. Add an exception to the master event and invite attendee1 to it + now = datetime.datetime.now(dateutil.tz.gettz("America/Montreal")) + org_ev.vevent.last_modified.value = now + orig_dtstart = org_ev.vevent.dtstart.value + orig_dtend = org_ev.vevent.dtend.value + + ev_exception = org_ev.add("vevent") + ev_exception.add('created').value = now + ev_exception.add('last-modified').value = now + ev_exception.add('dtstamp').value = now + ev_exception.add('uid').value = uid + ev_exception.add('summary').value = summary + # out of laziness, add the exception for the first occurence of the event + recurrence_id = orig_dtstart + ev_exception.add('recurrence-id').value = recurrence_id + + ev_exception.add('transp').value = "OPAQUE" + ev_exception.add('description').value = "Exception" + ev_exception.add('sequence').value = "1" + ev_exception.add('dtstart').value = orig_dtstart + ev_exception.add('dtend').value = orig_dtend + + # 2.1 Add attendee1 and organizer to the exception + organizer = ev_exception.add('organizer') + organizer.cn_param = self.user_name + organizer.partstat_param = "ACCEPTED" + organizer.value = self.user_email + attendee = ev_exception.add('attendee') + attendee.cn_param = self.attendee1_name + attendee.rsvp_param = "TRUE" + attendee.role_param = "REQ-PARTICIPANT" + attendee.partstat_param = "NEEDS-ACTION" + attendee.value = self.attendee1_email + + self._putEvent(self.client, "%s%s" % (self.user_calendar, ics_name), org_ev, + exp_status=204) + + # 3. Make sure the attendee got the event + attendee_ev = self._getEvent(self.attendee1_client, "%s%s" % (self.attendee1_calendar, ics_name)) + + for ev in attendee_ev.vevent_list: + try: + if (ev.recurrence_id.value): + attendee_ev_exception = ev + except: + attendee_ev_master = ev + + # make sure sogo doesn't duplicate attendees - yes, we've seen that + self.assertEquals(len(attendee_ev_master.attendee_list), 1) + self.assertEquals(len(attendee_ev_exception.attendee_list), 1) + + # 4. The master event must contain the invitation, declined + self.assertEquals(attendee_ev_master.attendee.partstat_param, "DECLINED") + + # 5. The exception event contain the invitation, NEEDS-ACTION + self.assertEquals(attendee_ev_exception.attendee.partstat_param, "NEEDS-ACTION") + + # 6. attendee accepts invitation + attendee_ev_exception.attendee.partstat_param = "ACCEPTED" + self._putEvent(self.attendee1_client, "%s%s" % (self.attendee1_calendar, ics_name), + attendee_ev, exp_status=204) + + # fetch the organizer's event + org_ev = self._getEvent(self.client, "%s%s" % (self.user_calendar, ics_name)) + for ev in org_ev.vevent_list: + try: + if (ev.recurrence_id.value): + org_ev_exception = ev + except: + org_ev_master = ev + + # make sure sogo doesn't duplicate attendees + self.assertEquals(len(org_ev_master.attendee_list), 1) + self.assertEquals(len(org_ev_exception.attendee_list), 1) + + # 7. Make sure organizer got the accept for the exception and + # that the attendee is still declined in the master + self.assertEquals(org_ev_exception.attendee.partstat_param, "ACCEPTED") + self.assertEquals(org_ev_master.attendee.partstat_param, "DECLINED") + + # 8. delete the attendee from the master event (uninvite) + # The event should be deleted from the attendee's calendar + del org_ev_exception.attendee + del org_ev_master.attendee + self._putEvent(self.client, "%s%s" % (self.user_calendar, ics_name), + org_ev, exp_status=204) + + self._getEvent(self.client, "%s%s" % (self.attendee1_calendar, ics_name), + exp_status=404) + + # now be happy + + def testRruleInvitationDeleteExdate(self): + """RRULE invitation delete exdate dance""" + + # Workflow: + # Create an recurring event and invite Bob + # Add an exdate to the master event + # Verify that the exdate has propagated to Bob's calendar + # Add an exdate to bob's version of the event + # Verify that an exception has been created in the org's calendar + # and that bob is 'declined' + + ics_name = "test-rrule-invitation-deleted-exdate-dance.ics" + self._deleteEvent(self.client, + "%s%s" % (self.user_calendar, ics_name), None) + self._deleteEvent(self.attendee1_client, + "%s%s" % (self.attendee1_calendar, ics_name), None) + + # 1. create a recurring event in the organiser's calendar + summary="Test-rrule-invitation-deleted-exdate-dance" + uid=summary + event = self._newEvent(summary, uid) + event.vevent.add('rrule').value = "FREQ=DAILY;COUNT=5" + organizer = event.vevent.add('organizer') + organizer.cn_param = self.user_name + organizer.partstat_param = "ACCEPTED" + organizer.value = self.user_email + attendee = event.vevent.add('attendee') + attendee.cn_param = self.attendee1_name + attendee.rsvp_param = "TRUE" + attendee.role_param = "REQ-PARTICIPANT" + attendee.partstat_param = "NEEDS-ACTION" + attendee.value = self.attendee1_email + + self._putEvent(self.client, "%s%s" % (self.user_calendar, ics_name), event) + + # 2. Make sure the attendee got it + self._getEvent(self.attendee1_client, "%s%s" % (self.attendee1_calendar, ics_name)) + + # 3. Add exdate to master event + org_ev=self._getEvent(self.client, "%s%s" % (self.user_calendar, ics_name)) + orig_dtstart = org_ev.vevent.dtstart.value + # exdate is a list in vobject.icalendar + org_exdate = [orig_dtstart.astimezone(dateutil.tz.gettz("UTC"))] + org_ev.vevent.add('exdate').value = org_exdate + self._putEvent(self.client, "%s%s" % (self.user_calendar, ics_name), org_ev, exp_status=204) + + # 4. make sure the attendee has the exdate + attendee_ev = self._getEvent(self.attendee1_client, "%s%s" % + (self.attendee1_calendar, ics_name)) + self.assertEqual(org_exdate, attendee_ev.vevent.exdate.value) + + # 5. Create an exdate in the attendee's calendar + new_exdate = orig_dtstart + datetime.timedelta(days=2) + attendee_exdate = [new_exdate.astimezone(dateutil.tz.gettz("UTC"))] + attendee_ev.vevent.add('exdate').value = attendee_exdate + now = datetime.datetime.now(dateutil.tz.gettz("America/Montreal")) + attendee_ev.vevent.last_modified.value = now + self._putEvent(self.attendee1_client, "%s%s" % (self.attendee1_calendar, ics_name), + attendee_ev, exp_status=204) + + # 6. Make sure the attendee is: + # needs-action in master event + # declined in the new exception created by the exdate above + org_ev=self._getEvent(self.client, "%s%s" % (self.user_calendar, ics_name)) + for ev in org_ev.vevent_list: + try: + if (ev.recurrence_id.value == attendee_exdate[0]): + org_ev_exception = ev + except: + org_ev_master = ev + + self.assertTrue(org_ev_exception) + # make sure sogo doesn't duplicate attendees + self.assertEquals(len(org_ev_master.attendee_list), 1) + self.assertEquals(len(org_ev_exception.attendee_list), 1) + + self.assertEqual(org_ev_master.attendee.partstat_param, "NEEDS-ACTION"); + self.assertEqual(org_ev_exception.attendee.partstat_param, "DECLINED"); + def testInvitationDelegation(self): """ invitation delegation """ # the invitation must not exist self._deleteEvent(self.client, "%stest-delegation.ics" % self.user_calendar, None) - self._deleteEvent(self.client, + self._deleteEvent(self.attendee1_client, "%stest-delegation.ics" % self.attendee1_calendar, None) - self._deleteEvent(self.client, + self._deleteEvent(self.attendee1_delegate_client, "%stest-delegation.ics" % self.attendee1_delegate_calendar, None) @@ -482,7 +687,7 @@ class CalDAVITIPDelegationTest(unittest.TestCase): "%stest-delegation.ics" % self.user_calendar, invitation) - att_inv = self._getEvent(self.client, + att_inv = self._getEvent(self.attendee1_client, "%stest-delegation.ics" % self.attendee1_calendar) self._compareAttendees(att_inv, invitation) @@ -502,19 +707,19 @@ class CalDAVITIPDelegationTest(unittest.TestCase): delegate.partstat_param = "NEEDS-ACTION" delegate.value = self.attendee1_delegate_email - self._postEvent(self.client, + self._postEvent(self.attendee1_client, self.attendee1_calendar, invitation, self.attendee1_email, [self.attendee1_delegate_email]) invitation.method.value = "REPLY" - self._postEvent(self.client, + self._postEvent(self.attendee1_client, self.attendee1_calendar, invitation, self.attendee1_email, [self.user_email]) del invitation.method - self._putEvent(self.client, + self._putEvent(self.attendee1_client, "%stest-delegation.ics" % self.attendee1_calendar, invitation, 204) - del_inv = self._getEvent(self.client, + del_inv = self._getEvent(self.attendee1_delegate_client, "%stest-delegation.ics" % self.attendee1_delegate_calendar) self._compareAttendees(del_inv, invitation) @@ -528,18 +733,18 @@ class CalDAVITIPDelegationTest(unittest.TestCase): invitation.add("method").value = "REPLY" delegate.partstat_param = "ACCEPTED" - self._postEvent(self.client, + self._postEvent(self.attendee1_delegate_client, self.attendee1_delegate_calendar, invitation, self.attendee1_delegate_email, [self.user_email, self.attendee1_email]) del invitation.method - self._putEvent(self.client, + self._putEvent(self.attendee1_delegate_client, "%stest-delegation.ics" % self.attendee1_delegate_calendar, invitation, 204) org_inv = self._getEvent(self.client, "%stest-delegation.ics" % self.user_calendar) self._compareAttendees(org_inv, invitation) - att_inv = self._getEvent(self.client, + att_inv = self._getEvent(self.attendee1_client, "%stest-delegation.ics" % self.attendee1_calendar) self._compareAttendees(att_inv, invitation) @@ -551,7 +756,7 @@ class CalDAVITIPDelegationTest(unittest.TestCase): cancellation.copy(invitation) cancellation.add("method").value = "CANCEL" cancellation.vevent.sequence.value = "1" - self._postEvent(self.client, + self._postEvent(self.attendee1_client, self.attendee1_calendar, cancellation, self.attendee1_email, [self.attendee1_delegate_email]) @@ -560,12 +765,12 @@ class CalDAVITIPDelegationTest(unittest.TestCase): del attendee1.delegated_to_param invitation.add("method").value = "REPLY" invitation.vevent.remove(delegate) - self._postEvent(self.client, + self._postEvent(self.attendee1_client, self.attendee1_calendar, invitation, self.attendee1_email, [self.user_email]) del invitation.method - self._putEvent(self.client, + self._putEvent(self.attendee1_client, "%stest-delegation.ics" % self.attendee1_calendar, invitation, 204) @@ -573,7 +778,7 @@ class CalDAVITIPDelegationTest(unittest.TestCase): "%stest-delegation.ics" % self.user_calendar) self._compareAttendees(org_inv, invitation) - del_inv = self._getEvent(self.client, + del_inv = self._getEvent(self.attendee1_delegate_client, "%stest-delegation.ics" % self.attendee1_delegate_calendar, 404) # 5. org updates inv. @@ -595,7 +800,7 @@ class CalDAVITIPDelegationTest(unittest.TestCase): "%stest-delegation.ics" % self.user_calendar, invitation, 204) - att_inv = self._getEvent(self.client, + att_inv = self._getEvent(self.attendee1_client, "%stest-delegation.ics" % self.attendee1_calendar) self._compareAttendees(att_inv, invitation) @@ -613,22 +818,22 @@ class CalDAVITIPDelegationTest(unittest.TestCase): delegate.partstat_param = "NEEDS-ACTION" delegate.value = self.attendee1_delegate_email - self._postEvent(self.client, + self._postEvent(self.attendee1_client, self.attendee1_calendar, invitation, self.attendee1_email, [self.attendee1_delegate_email]) invitation.method.value = "REPLY" - self._postEvent(self.client, + self._postEvent(self.attendee1_client, self.attendee1_calendar, invitation, self.attendee1_email, [self.user_email]) del invitation.method - self._putEvent(self.client, + self._putEvent(self.attendee1_client, "%stest-delegation.ics" % self.attendee1_calendar, invitation, 204) org_inv = self._getEvent(self.client, "%stest-delegation.ics" % self.user_calendar) self._compareAttendees(org_inv, invitation) - del_inv = self._getEvent(self.client, + del_inv = self._getEvent(self.attendee1_delegate_client, "%stest-delegation.ics" % self.attendee1_delegate_calendar) self._compareAttendees(del_inv, invitation) @@ -638,19 +843,19 @@ class CalDAVITIPDelegationTest(unittest.TestCase): invitation.add("method").value = "REPLY" delegate.partstat_param = "ACCEPTED" - self._postEvent(self.client, + self._postEvent(self.attendee1_delegate_client, self.attendee1_delegate_calendar, invitation, self.attendee1_delegate_email, [self.user_email, self.attendee1_email]) del invitation.method - self._putEvent(self.client, + self._putEvent(self.attendee1_delegate_client, "%stest-delegation.ics" % self.attendee1_delegate_calendar, invitation, 204) org_inv = self._getEvent(self.client, "%stest-delegation.ics" % self.user_calendar) self._compareAttendees(org_inv, invitation) - att_inv = self._getEvent(self.client, + att_inv = self._getEvent(self.attendee1_client, "%stest-delegation.ics" % self.attendee1_calendar) self._compareAttendees(att_inv, invitation) @@ -674,10 +879,10 @@ class CalDAVITIPDelegationTest(unittest.TestCase): "%stest-delegation.ics" % self.user_calendar, invitation, 204) - att_inv = self._getEvent(self.client, + att_inv = self._getEvent(self.attendee1_client, "%stest-delegation.ics" % self.attendee1_calendar) self._compareAttendees(att_inv, invitation) - del_inv = self._getEvent(self.client, + del_inv = self._getEvent(self.attendee1_client, "%stest-delegation.ics" % self.attendee1_calendar) self._compareAttendees(del_inv, invitation) @@ -702,9 +907,9 @@ class CalDAVITIPDelegationTest(unittest.TestCase): "%stest-delegation.ics" % self.user_calendar, invitation, 204) - att_inv = self._getEvent(self.client, + att_inv = self._getEvent(self.attendee1_client, "%stest-delegation.ics" % self.attendee1_calendar, 404) - del_inv = self._getEvent(self.client, + del_inv = self._getEvent(self.attendee1_delegate_client, "%stest-delegation.ics" % self.attendee1_delegate_calendar, 404) if __name__ == "__main__": diff --git a/Tests/Integration/test-davacl.py b/Tests/Integration/test-davacl.py index d1fddc6a0..0a8ecd787 100755 --- a/Tests/Integration/test-davacl.py +++ b/Tests/Integration/test-davacl.py @@ -1,6 +1,7 @@ #!/usr/bin/python -from config import hostname, port, username, password, subscriber_username, subscriber_password +from config import hostname, port, username, password, subscriber_username, subscriber_password, \ + superuser, superuser_password import sys import unittest @@ -25,7 +26,7 @@ import utilities class DAVCalendarSuperUserAclTest(unittest.TestCase): def __init__(self, arg): self.client = webdavlib.WebDAVClient(hostname, port, - username, password) + superuser, superuser_password) self.resource = "/SOGo/dav/%s/Calendar/test-dav-superuser-acl/" % subscriber_username self.filename = "suevent.ics" self.url = "%s%s" % (self.resource, self.filename) @@ -949,6 +950,8 @@ class DAVPublicAccessTest(unittest.TestCase): class DAVCalendarPublicAclTest(unittest.TestCase): def setUp(self): self.createdRsrc = None + self.superuser_client = webdavlib.WebDAVClient(hostname, port, + superuser, superuser_password) self.client = webdavlib.WebDAVClient(hostname, port, username, password) self.subscriber_client = webdavlib.WebDAVClient(hostname, port, @@ -959,7 +962,7 @@ class DAVCalendarPublicAclTest(unittest.TestCase): def tearDown(self): if self.createdRsrc is not None: delete = webdavlib.WebDAVDELETE(self.createdRsrc) - self.client.execute(delete) + self.superuser_client.execute(delete) def testCollectionAccessNormalUser(self): """normal user access to (non-)shared resource from su""" @@ -1091,7 +1094,7 @@ class DAVCalendarPublicAclTest(unittest.TestCase): for rsrc in [ 'personal', 'test-dav-acl' ]: resource = '%s%s/' % (parentColl, rsrc) mkcol = webdavlib.WebDAVMKCOL(resource) - self.client.execute(mkcol) + self.superuser_client.execute(mkcol) acl_utility = utilities.TestCalendarACLUtility(self, self.subscriber_client, resource) diff --git a/Tests/Integration/test-ical.py b/Tests/Integration/test-ical.py index 8c9c76871..6f128de7c 100755 --- a/Tests/Integration/test-ical.py +++ b/Tests/Integration/test-ical.py @@ -1,6 +1,9 @@ #!/usr/bin/python -from config import hostname, port, username, password, subscriber_username +# FIXME: we should avoid using superuser if possible + +from config import hostname, port, username, password, subscriber_username, \ + superuser, superuser_password import unittest import sogotests @@ -48,7 +51,7 @@ class iCalTest(unittest.TestCase): for x in members ] props = { "{DAV:}group-member-set": membersHref } proppatch = webdavlib.WebDAVPROPPATCH(resource, props) - client = webdavlib.WebDAVClient(hostname, port, username, password) + client = webdavlib.WebDAVClient(hostname, port, superuser, superuser_password) client.user_agent = "DAVKit/4.0.1 (730); CalendarStore/4.0.1 (973); iCal/4.0.1 (1374); Mac OS X/10.6.2 (10C540)" client.execute(proppatch) self.assertEquals(proppatch.response["status"], 207, @@ -60,7 +63,7 @@ class iCalTest(unittest.TestCase): resource = '/SOGo/dav/%s/' % user propfind = webdavlib.WebDAVPROPFIND(resource, ["{DAV:}group-membership"], 0) - client = webdavlib.WebDAVClient(hostname, port, username, password) + client = webdavlib.WebDAVClient(hostname, port, superuser, superuser_password) client.user_agent = "DAVKit/4.0.1 (730); CalendarStore/4.0.1 (973); iCal/4.0.1 (1374); Mac OS X/10.6.2 (10C540)" client.execute(propfind) @@ -73,7 +76,7 @@ class iCalTest(unittest.TestCase): resource = '/SOGo/dav/%s/' % user prop = "{http://calendarserver.org/ns/}calendar-proxy-%s-for" % perm propfind = webdavlib.WebDAVPROPFIND(resource, [prop], 0) - client = webdavlib.WebDAVClient(hostname, port, username, password) + client = webdavlib.WebDAVClient(hostname, port, superuser, superuser_password) client.user_agent = "DAVKit/4.0.1 (730); CalendarStore/4.0.1 (973); iCal/4.0.1 (1374); Mac OS X/10.6.2 (10C540)" client.execute(propfind) @@ -136,7 +139,7 @@ class iCalTest(unittest.TestCase): def testCalendarProxy2(self): """calendar-proxy as used from SOGo""" - client = webdavlib.WebDAVClient(hostname, port, username, password) + client = webdavlib.WebDAVClient(hostname, port, superuser, superuser_password) client.user_agent = "DAVKit/4.0.1 (730); CalendarStore/4.0.1 (973); iCal/4.0.1 (1374); Mac OS X/10.6.2 (10C540)" personal_resource = "/SOGo/dav/%s/Calendar/personal/" % username dav_utility = utilities.TestCalendarACLUtility(self,