# HG changeset patch # User Paul Boddie # Date 1442074526 -7200 # Node ID 575ed0737946c27eef0f974dd9d5fcc9216b66e3 # Parent 9ea0dc9bca564e4a1252c7ae0d1d8634b4a8007b Added support for different organiser replacement preferences. diff -r 9ea0dc9bca56 -r 575ed0737946 docs/preferences.txt --- a/docs/preferences.txt Sat Sep 12 18:13:10 2015 +0200 +++ b/docs/preferences.txt Sat Sep 12 18:15:26 2015 +0200 @@ -73,6 +73,27 @@ summary-only deliver only a summary of the message + summary-wraps-message deliver a summary that includes the original message + as an attachment + +organiser_replacement +--------------------- + +Default: attendee +Alternatives: (see below) + +Indicate whether the organiser of an event can be replaced and the nature of +any replacement: + + any any identity, regardless of whether it is already + present or even previously unknown, may become the + organiser + + attendee any new organiser must be a previously-recognised + attendee + + never forbid the replacement of an event's organiser + participating ------------- diff -r 9ea0dc9bca56 -r 575ed0737946 imiptools/client.py --- a/imiptools/client.py Sat Sep 12 18:13:10 2015 +0200 +++ b/imiptools/client.py Sat Sep 12 18:15:26 2015 +0200 @@ -39,6 +39,13 @@ default_window_size = 100 def __init__(self, user, messenger=None, store=None, publisher=None, preferences_dir=None): + + """ + Initialise a calendar client with the current 'user', plus any + 'messenger', 'store' and 'publisher' objects, indicating any specific + 'preferences_dir'. + """ + self.user = user self.messenger = messenger self.store = store or imip_store.FileStore() @@ -90,6 +97,10 @@ prefs = self.get_preferences() return prefs and prefs.get("event_refreshing") == "always" or False + def allow_organiser_replacement(self): + prefs = self.get_preferences() + return prefs and prefs.get("organiser_replacement", "attendee") or False + def have_manager(self): return MANAGER_INTERFACE @@ -337,6 +348,36 @@ # Object-related tests. + def is_recognised_organiser(self, organiser): + + """ + Return whether the given 'organiser' is recognised from + previously-received details. If no stored details exist, True is + returned. + """ + + obj = self.get_stored_object_version() + if obj: + stored_organiser = get_uri(obj.get_value("ORGANIZER")) + return stored_organiser == organiser + else: + return True + + def is_recognised_attendee(self, attendee): + + """ + Return whether the given 'attendee' is recognised from + previously-received details. If no stored details exist, True is + returned. + """ + + obj = self.get_stored_object_version() + if obj: + stored_attendees = uri_dict(obj.get_value_map("ATTENDEE")) + return stored_attendees.has_key(attendee) + else: + return True + def get_attendance(self, user=None, obj=None): """ diff -r 9ea0dc9bca56 -r 575ed0737946 imiptools/handlers/__init__.py --- a/imiptools/handlers/__init__.py Sat Sep 12 18:13:10 2015 +0200 +++ b/imiptools/handlers/__init__.py Sat Sep 12 18:15:26 2015 +0200 @@ -157,10 +157,17 @@ # Test against any previously-received organiser details. - obj = self.get_stored_object_version() - if obj: - stored_organiser = get_uri(obj.get_value("ORGANIZER")) - if stored_organiser != organiser: + if not self.is_recognised_organiser(organiser): + replacement = self.allow_organiser_replacement() + + # Allow any organiser as a replacement where indicated. + + if replacement == "any": + pass + + # Allow any recognised attendee as a replacement where indicated. + + elif replacement != "attendee" or not self.is_recognised_attendee(organiser): return None return organiser_item diff -r 9ea0dc9bca56 -r 575ed0737946 tests/templates/event-request-imposter-attendee.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/templates/event-request-imposter-attendee.txt Sat Sep 12 18:15:26 2015 +0200 @@ -0,0 +1,36 @@ +Content-Type: multipart/alternative; boundary="===============0047278175==" +MIME-Version: 1.0 +From: harvey.horse@example.com +To: resource-room-confroom@example.com +Subject: Invitation! + +--===============0047278175== +Content-Type: text/plain; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit + +This message contains an event. The organiser is not the real organiser but is an attendee. + +--===============0047278175== +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Content-Type: text/calendar; charset="us-ascii"; method="REQUEST" + +BEGIN:VCALENDAR +PRODID:-//imip-agent/test//EN +METHOD:REQUEST +VERSION:2.0 +BEGIN:VEVENT +ORGANIZER:mailto:harvey.horse@example.com +ATTENDEE;ROLE=CHAIR:mailto:paul.boddie@example.com +ATTENDEE;RSVP=TRUE:mailto:resource-room-confroom@example.com +ATTENDEE;RSVP=TRUE:mailto:harvey.horse@example.com +DTSTAMP:20141125T004600Z +DTSTART;TZID=Europe/Oslo:20141126T161500 +DTEND;TZID=Europe/Oslo:20141126T170000 +SUMMARY:Meeting at 4:30pm +UID:event1@example.com +END:VEVENT +END:VCALENDAR + +--===============0047278175==-- diff -r 9ea0dc9bca56 -r 575ed0737946 tests/templates/event-request-imposter.txt --- a/tests/templates/event-request-imposter.txt Sat Sep 12 18:13:10 2015 +0200 +++ b/tests/templates/event-request-imposter.txt Sat Sep 12 18:15:26 2015 +0200 @@ -24,6 +24,7 @@ ORGANIZER:mailto:vincent.vole@example.com ATTENDEE;ROLE=CHAIR:mailto:paul.boddie@example.com ATTENDEE;RSVP=TRUE:mailto:resource-room-confroom@example.com +ATTENDEE;RSVP=TRUE:mailto:harvey.horse@example.com DTSTAMP:20141125T004600Z DTSTART;TZID=Europe/Oslo:20141126T163000 DTEND;TZID=Europe/Oslo:20141126T170000 diff -r 9ea0dc9bca56 -r 575ed0737946 tests/templates/event-request.txt --- a/tests/templates/event-request.txt Sat Sep 12 18:13:10 2015 +0200 +++ b/tests/templates/event-request.txt Sat Sep 12 18:15:26 2015 +0200 @@ -22,6 +22,7 @@ BEGIN:VEVENT ORGANIZER:mailto:paul.boddie@example.com ATTENDEE;ROLE=CHAIR:mailto:paul.boddie@example.com +ATTENDEE;RSVP=TRUE:mailto:harvey.horse@example.com ATTENDEE;RSVP=TRUE:mailto:resource-room-confroom@example.com DTSTAMP:20141125T004600Z DTSTART;TZID=Europe/Oslo:20141126T160000 diff -r 9ea0dc9bca56 -r 575ed0737946 tests/test_resource_invitation.sh --- a/tests/test_resource_invitation.sh Sat Sep 12 18:13:10 2015 +0200 +++ b/tests/test_resource_invitation.sh Sat Sep 12 18:15:26 2015 +0200 @@ -58,24 +58,6 @@ && echo "Success" \ || echo "Failed" - "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/event-request-imposter.txt" 2>> $ERROR \ -| "$SHOWMAIL" \ -> out2i.tmp - - ! grep -q 'METHOD:REPLY' out2i.tmp \ -&& echo "Success" \ -|| echo "Failed" - - "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/fb-request.txt" 2>> $ERROR \ -| "$SHOWMAIL" \ -> out3i.tmp - - grep -q 'METHOD:REPLY' out3i.tmp \ -&& grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T150000Z/20141126T160000Z' out3i.tmp \ -&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T153000Z/20141126T160000Z' out3i.tmp \ -&& echo "Success" \ -|| echo "Failed" - "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/event-request-conflict.txt" 2>> $ERROR \ | "$SHOWMAIL" \ > out4.tmp diff -r 9ea0dc9bca56 -r 575ed0737946 tests/test_resource_invitation_imposter.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test_resource_invitation_imposter.sh Sat Sep 12 18:15:26 2015 +0200 @@ -0,0 +1,194 @@ +#!/bin/sh + +THIS_DIR=`dirname $0` + +TEMPLATES="$THIS_DIR/templates" +RESOURCE_SCRIPT="$THIS_DIR/../imip_resource.py" +SHOWMAIL="$THIS_DIR/../tools/showmail.py" +STORE=/tmp/store +STATIC=/tmp/static +PREFS=/tmp/prefs +ARGS="-S $STORE -P $STATIC -p $PREFS -d" +USER="mailto:resource-room-confroom@example.com" +ERROR=err.tmp + +rm -r $STORE +rm -r $STATIC +rm -r $PREFS +rm $ERROR +rm out*.tmp + +mkdir -p "$PREFS/$USER" +echo 'Europe/Oslo' > "$PREFS/$USER/TZID" +echo 'share' > "$PREFS/$USER/freebusy_sharing" +echo 'never' > "$PREFS/$USER/organiser_replacement" + + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/fb-request-all.txt" 2>> $ERROR \ +| "$SHOWMAIL" \ +> out0.tmp + + grep -q 'METHOD:REPLY' out0.tmp \ +&& ! grep -q '^FREEBUSY' out0.tmp \ +&& echo "Success" \ +|| echo "Failed" + + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/fb-request.txt" 2>> $ERROR \ +| "$SHOWMAIL" \ +> out1.tmp + + grep -q 'METHOD:REPLY' out1.tmp \ +&& ! grep -q '^FREEBUSY' out1.tmp \ +&& echo "Success" \ +|| echo "Failed" + + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/event-request.txt" 2>> $ERROR \ +| "$SHOWMAIL" \ +> out2.tmp + + grep -q 'METHOD:REPLY' out2.tmp \ +&& grep -q 'ATTENDEE;PARTSTAT=ACCEPTED' out2.tmp \ +&& echo "Success" \ +|| echo "Failed" + + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/fb-request.txt" 2>> $ERROR \ +| "$SHOWMAIL" \ +> out3.tmp + + grep -q 'METHOD:REPLY' out3.tmp \ +&& grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T150000Z/20141126T160000Z' out3.tmp \ +&& echo "Success" \ +|| echo "Failed" + +# Try to change to an unrecognised organiser. + + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/event-request-imposter.txt" 2>> $ERROR \ +| "$SHOWMAIL" \ +> out4.tmp + + ! grep -q 'METHOD:REPLY' out4.tmp \ +&& echo "Success" \ +|| echo "Failed" + + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/fb-request.txt" 2>> $ERROR \ +| "$SHOWMAIL" \ +> out5.tmp + + grep -q 'METHOD:REPLY' out5.tmp \ +&& grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T150000Z/20141126T160000Z' out5.tmp \ +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T153000Z/20141126T160000Z' out5.tmp \ +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T151500Z/20141126T160000Z' out5.tmp \ +&& echo "Success" \ +|| echo "Failed" + +# Try to change to an attendee as organiser. + + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/event-request-imposter-attendee.txt" 2>> $ERROR \ +| "$SHOWMAIL" \ +> out6.tmp + + ! grep -q 'METHOD:REPLY' out6.tmp \ +&& echo "Success" \ +|| echo "Failed" + + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/fb-request.txt" 2>> $ERROR \ +| "$SHOWMAIL" \ +> out7.tmp + + grep -q 'METHOD:REPLY' out7.tmp \ +&& grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T150000Z/20141126T160000Z' out7.tmp \ +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T153000Z/20141126T160000Z' out7.tmp \ +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T151500Z/20141126T160000Z' out7.tmp \ +&& echo "Success" \ +|| echo "Failed" + +# Change the policy. + +echo 'attendee' > "$PREFS/$USER/organiser_replacement" + +# Try to change to an attendee as organiser. + + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/event-request-imposter-attendee.txt" 2>> $ERROR \ +| "$SHOWMAIL" \ +> out8.tmp + + grep -q 'METHOD:REPLY' out8.tmp \ +&& echo "Success" \ +|| echo "Failed" + + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/fb-request.txt" 2>> $ERROR \ +| "$SHOWMAIL" \ +> out9.tmp + + grep -q 'METHOD:REPLY' out9.tmp \ +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T150000Z/20141126T160000Z' out9.tmp \ +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T153000Z/20141126T160000Z' out9.tmp \ +&& grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T151500Z/20141126T160000Z' out9.tmp \ +&& echo "Success" \ +|| echo "Failed" + +# Try to change to an unrecognised organiser. + + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/event-request-imposter.txt" 2>> $ERROR \ +| "$SHOWMAIL" \ +> out10.tmp + + ! grep -q 'METHOD:REPLY' out10.tmp \ +&& echo "Success" \ +|| echo "Failed" + + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/fb-request.txt" 2>> $ERROR \ +| "$SHOWMAIL" \ +> out11.tmp + + grep -q 'METHOD:REPLY' out11.tmp \ +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T150000Z/20141126T160000Z' out11.tmp \ +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T153000Z/20141126T160000Z' out11.tmp \ +&& grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T151500Z/20141126T160000Z' out11.tmp \ +&& echo "Success" \ +|| echo "Failed" + +# Change the policy. + +echo 'any' > "$PREFS/$USER/organiser_replacement" + +# Try to change to an unrecognised organiser. + + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/event-request-imposter.txt" 2>> $ERROR \ +| "$SHOWMAIL" \ +> out12.tmp + + grep -q 'METHOD:REPLY' out12.tmp \ +&& echo "Success" \ +|| echo "Failed" + + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/fb-request.txt" 2>> $ERROR \ +| "$SHOWMAIL" \ +> out13.tmp + + grep -q 'METHOD:REPLY' out13.tmp \ +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T150000Z/20141126T160000Z' out13.tmp \ +&& grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T153000Z/20141126T160000Z' out13.tmp \ +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T151500Z/20141126T160000Z' out13.tmp \ +&& echo "Success" \ +|| echo "Failed" + +# Try to change to an attendee as organiser. + + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/event-request-imposter-attendee.txt" 2>> $ERROR \ +| "$SHOWMAIL" \ +> out14.tmp + + grep -q 'METHOD:REPLY' out14.tmp \ +&& echo "Success" \ +|| echo "Failed" + + "$RESOURCE_SCRIPT" $ARGS < "$TEMPLATES/fb-request.txt" 2>> $ERROR \ +| "$SHOWMAIL" \ +> out15.tmp + + grep -q 'METHOD:REPLY' out15.tmp \ +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T150000Z/20141126T160000Z' out15.tmp \ +&& ! grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T153000Z/20141126T160000Z' out15.tmp \ +&& grep -q 'FREEBUSY;FBTYPE=BUSY:20141126T151500Z/20141126T160000Z' out15.tmp \ +&& echo "Success" \ +|| echo "Failed"