# HG changeset patch # User Paul Boddie # Date 1387285898 -3600 # Node ID f4c4380dc038878adc6aab6a9849f4b6cc766e44 # Parent 85e8ce50de99be177569f034ce2378a874206229 Fixed the recipient dictionary format so that different recipient types can be represented properly. Introduced filtering to avoid showing irrelevant recipients for certain operations. Tidied up the HTTP responses when certain operations cannot be performed. diff -r 85e8ce50de99 -r f4c4380dc038 MoinMessageSupport.py --- a/MoinMessageSupport.py Thu Nov 14 18:43:10 2013 +0100 +++ b/MoinMessageSupport.py Tue Dec 17 14:11:38 2013 +0100 @@ -118,6 +118,8 @@ homedir = self.get_homedir() if not homedir: + writeHeaders(request, "text/plain", getMetadata(self.page), "403 Forbidden") + request.write("This site is not configured for this request.") return gpg = GPG(homedir) @@ -260,7 +262,7 @@ getattr(request.cfg, "moinmessage_gpg_relays_page", "MoinMessageRelayDict"), request) -def get_recipients(request, main=False): +def get_recipients(request, main=False, sending=True, fetching=True): """ Return the recipients dictionary by first obtaining the page in which it @@ -270,6 +272,10 @@ When 'main' is specified and set to a true value, only a dictionary under the site root is consulted. + When 'sending' or 'fetching' is specified and set to a false value, any + recipients of the indicated type will be excluded from the result of this + function. + The name of the subpage is defined by the configuration setting 'moinmessage_gpg_recipients_page', which if absent is set to "MoinMessageRecipientsDict". @@ -285,9 +291,9 @@ if homewiki == "Self": recipients = getWikiDict("%s/%s" % (homepage, subpage), request) if recipients: - return recipients + return filter_recipients(recipients, sending, fetching) - return getWikiDict(subpage, request) + return filter_recipients(getWikiDict(subpage, request), sending, fetching) def get_username_for_fingerprint(request, fingerprint): @@ -310,7 +316,7 @@ else: return None -def get_recipient_details(request, recipient, main=False): +def get_recipient_details(request, recipient, main=False, fetching=False): """ Using the 'request', return a dictionary of details for the specified @@ -319,6 +325,10 @@ When 'main' is specified and set to a true value, only the recipients dictionary under the site root is consulted. + + When 'fetching' is specified and set to a true value, the recipient need + not have a "type" or "location" defined, but it must have a "fingerprint" + defined. """ _ = request.getText @@ -333,15 +343,35 @@ parameters = parseDictEntry(recipient_details, ("type", "location", "fingerprint",)) - if not parameters.has_key("type"): + type = parameters.get("type") + location = parameters.get("location") + fingerprint = parameters.get("fingerprint") + + if type in (None, "none") and not fetching: raise MoinMessageBadRecipient, _("The recipient details are missing a destination type.") - if not parameters.has_key("location"): + if type not in (None, "none") and not location: raise MoinMessageBadRecipient, _("The recipient details are missing a location for sent messages.") - if parameters["type"] in ("url", "relay") and not parameters.has_key("fingerprint"): + if type in ("url", "relay", None, "none") and not fingerprint: raise MoinMessageBadRecipient, _("The recipient details are missing a fingerprint for sending messages.") return parameters +def filter_recipients(recipients, sending, fetching): + + """ + Return a copy of the given 'recipients' dictionary retaining all entries + that apply to the given 'sending' and 'fetching' criteria. + """ + + result = {} + for recipient, parameters in recipients.items(): + if not fetching and parameters.get("type") in (None, "none"): + continue + if not sending and not parameters.get("fingerprint"): + continue + result[recipient] = parameters + return result + # vim: tabstop=4 expandtab shiftwidth=4 diff -r 85e8ce50de99 -r f4c4380dc038 README.txt --- a/README.txt Thu Nov 14 18:43:10 2013 +0100 +++ b/README.txt Tue Dec 17 14:11:38 2013 +0100 @@ -238,8 +238,12 @@ must be defined in the relays mapping (see below) and yield a URL that can accept MoinMessage content. -Where a type of "url" or "relay" has been given, a fingerprint must accompany -this information in order to encrypt messages sent to the specified resource. +Where the type is "none" or omitted completely, the recipient is any user that +is allowed to fetch messages from the wiki. + +Where a type of "url", "relay" or "none" has been given (or if the type is +omitted), a fingerprint must accompany this information in order to encrypt +messages sent to the specified resource. Each fingerprint corresponds to a key used by the wiki to encrypt messages and by the remote site (as identified by the URL) to decrypt messages. diff -r 85e8ce50de99 -r f4c4380dc038 actions/FetchMessages.py --- a/actions/FetchMessages.py Thu Nov 14 18:43:10 2013 +0100 +++ b/actions/FetchMessages.py Tue Dec 17 14:11:38 2013 +0100 @@ -9,7 +9,8 @@ from MoinSupport import getMetadata, writeHeaders, parseDictEntry from MoinMessage import Message, GPG from MoinMessageSupport import MoinMessageAction, \ - get_signing_users, get_recipients + get_signing_users, get_recipient_details, \ + MoinMessageRecipientError from email.mime.text import MIMEText from email.parser import Parser from itertools import islice @@ -34,12 +35,14 @@ # NOTE: Could employ a more accurate content type. if not content.get_content_type() == "text/plain": - writeHeaders(request, "text/plain", getMetadata(self.page), "403 Forbidden") + writeHeaders(request, "text/plain", getMetadata(self.page), "415 Unsupported Media Type") request.write("The content does not appear to be a request for messages.") return homedir = self.get_homedir() if not homedir: + writeHeaders(request, "text/plain", getMetadata(self.page), "403 Forbidden") + request.write("This site is not configured for this request.") return gpg = GPG(homedir) @@ -57,18 +60,11 @@ # Get the recipient details. - recipients = get_recipients(request) - if not recipient or not recipients or not recipients.has_key(recipient): + try: + parameters = get_recipient_details(request, recipient, fetching=True) + except MoinMessageRecipientError, exc: writeHeaders(request, "text/plain", getMetadata(self.page), "403 Forbidden") - request.write("The recipient does not appear to be registered for message delivery.") - return - - recipient_details = recipients[recipient] - parameters = parseDictEntry(recipient_details, ("type", "location", "fingerprint",)) - - if not parameters.has_key("fingerprint"): - writeHeaders(request, "text/plain", getMetadata(self.page), "403 Forbidden") - request.write("The recipient does not appear to be registered for message delivery.") + request.write(exc.message) return # Obtain commands from the payload, returning a collection of messages. @@ -170,7 +166,6 @@ writeHeaders(request, "text/plain", getMetadata(self.page)) request.write(message.as_string()) - return 1, None # Action function. diff -r 85e8ce50de99 -r f4c4380dc038 actions/SendMessage.py --- a/actions/SendMessage.py Thu Nov 14 18:43:10 2013 +0100 +++ b/actions/SendMessage.py Tue Dec 17 14:11:38 2013 +0100 @@ -72,7 +72,7 @@ # Get a list of potential recipients. - recipients = get_recipients(request) + recipients = get_recipients(request, fetching=False) # Prepare the recipients list, selecting the specified recipients.