Code

add and use Reject exception (sf bug 700265)
authorrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Fri, 26 Mar 2004 00:44:11 +0000 (00:44 +0000)
committerrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Fri, 26 Mar 2004 00:44:11 +0000 (00:44 +0000)
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@2197 57a73879-2fb5-44c3-a270-3262357dd7e2

CHANGES.txt
doc/customizing.txt
roundup/cgi/actions.py
roundup/cgi/exceptions.py
roundup/exceptions.py [new file with mode: 0644]
roundup/mailgw.py

index ea8067070ce8f06d29696aafa34d03cca130c1d7..b00dbb9c70dd08e556c0913377aee4acd9922a90 100644 (file)
@@ -7,12 +7,16 @@ Feature:
 - added new auditor, emailauditor.py, that works around a bug in IE. See 
   emailauditor.py for more info.
 - added dispatcher functionality - see upgrading.txt for more info
 - added new auditor, emailauditor.py, that works around a bug in IE. See 
   emailauditor.py for more info.
 - added dispatcher functionality - see upgrading.txt for more info
+- added Reject exception which may be raised by auditors. This is trapped
+  by mailgw and may be used to veto creation of file attachments or
+  messages. (sf bug 700265)
 
 Fixed:
 - Boolean HTML templating was broken
 - Link HTML templating field() was broken
 - Fix reporting of test inclusion in postgresql test
 
 
 Fixed:
 - Boolean HTML templating was broken
 - Link HTML templating field() was broken
 - Fix reporting of test inclusion in postgresql test
 
+
 2004-03-24 0.7.0b1
 Major new features:
 - added postgresql backend (originally from sf patch 761740, many changes
 2004-03-24 0.7.0b1
 Major new features:
 - added postgresql backend (originally from sf patch 761740, many changes
index 27e73bbf12c7d8db46184e0480ad85a9dc30d84c..084d334836944ca5f71ef6c666508b142d368861 100644 (file)
@@ -2,7 +2,7 @@
 Customising Roundup
 ===================
 
 Customising Roundup
 ===================
 
-:Version: $Revision: 1.122 $
+:Version: $Revision: 1.123 $
 
 .. This document borrows from the ZopeBook section on ZPT. The original is at:
    http://www.zope.org/Documentation/Books/ZopeBook/current/ZPT.stx
 
 .. This document borrows from the ZopeBook section on ZPT. The original is at:
    http://www.zope.org/Documentation/Books/ZopeBook/current/ZPT.stx
@@ -586,6 +586,37 @@ to use one, copy it to the ``'detectors'`` of your tracker instance:
         db.issue.react('create', newissuecopy)
 
 
         db.issue.react('create', newissuecopy)
 
 
+Auditor or Reactor?
+-------------------
+
+Generally speaking, the following rules should be observed:
+
+**Auditors**
+  Are used for `vetoing creation of or changes to items`_. They might
+  also make automatic changes to item properties.
+**Reactors**
+  Detect changes in the database and react accordingly. They should avoid
+  making changes to the database where possible, as this could create
+  detector loops.
+
+Vetoing creation of or changes to items
+---------------------------------------
+
+Auditors may raise the ``Reject`` exception to prevent the creation of
+or changes to items in the database.  The mail gateway, for example, will
+not attach files or messages to issues when the creation of those files or
+messages are prevented through the ``Reject`` exception. It'll also not create
+users if that creation is ``Reject``'ed too.
+
+To use, simply add at the top of your auditor::
+
+   from roundup.exceptions import Reject
+
+And then when your rejection criteria have been detected, simply::
+
+   raise Reject
+
+
 Database Content
 ================
 
 Database Content
 ================
 
index 5fbbf228ef1b569ca3f8896e152a248677a02a48..42bd7ecde4ce111890b57bf924e738f3cbe89857 100755 (executable)
@@ -1,3 +1,5 @@
+#$Id: actions.py,v 1.15 2004-03-26 00:44:11 richard Exp $
+
 import re, cgi, StringIO, urllib, Cookie, time, random
 
 from roundup import hyperdb, token, date, password, rcsv
 import re, cgi, StringIO, urllib, Cookie, time, random
 
 from roundup import hyperdb, token, date, password, rcsv
@@ -837,3 +839,4 @@ class ExportCSVAction(Action):
 
         return '\n'
 
 
         return '\n'
 
+# vim: set filetype=python ts=4 sw=4 et si
index 29298952c7096fb7d75477eb5099a3227877959c..1d24fc1b3c56d631c290c5977c4fb4d343b08124 100755 (executable)
@@ -1,3 +1,9 @@
+#$Id: exceptions.py,v 1.4 2004-03-26 00:44:11 richard Exp $
+'''Exceptions for use in Roundup's web interface.
+'''
+
+__docformat__ = 'restructuredtext'
+
 import cgi
 
 class HTTPException(Exception):
 import cgi
 
 class HTTPException(Exception):
@@ -51,3 +57,4 @@ class SeriousError(Exception):
 </body></html>
 '''%cgi.escape(self.args[0])
 
 </body></html>
 '''%cgi.escape(self.args[0])
 
+# vim: set filetype=python ts=4 sw=4 et si
diff --git a/roundup/exceptions.py b/roundup/exceptions.py
new file mode 100644 (file)
index 0000000..27cc1ef
--- /dev/null
@@ -0,0 +1,19 @@
+#$Id: exceptions.py,v 1.1 2004-03-26 00:44:11 richard Exp $
+'''Exceptions for use across all Roundup components.
+'''
+
+__docformat__ = 'restructuredtext'
+
+class Reject(Exception):
+    '''An auditor may raise this exception when the current create or set
+    operation should be stopped.
+
+    It is up to the specific interface invoking the create or set to
+    handle this exception sanely. For example:
+
+    - mailgw will trap and ignore Reject for file attachments and messages
+    - cgi will trap and present the exception in a nice format
+    '''
+    pass
+
+# vim: set filetype=python ts=4 sw=4 et si
index d6768758397eb4c364676831387b613c5f43284e..47d0831099bff7579ab1f7e7fd3311c29b4d5999 100644 (file)
@@ -72,7 +72,7 @@ are calling the create() method to create a new node). If an auditor raises
 an exception, the original message is bounced back to the sender with the
 explanatory message given in the exception. 
 
 an exception, the original message is bounced back to the sender with the
 explanatory message given in the exception. 
 
-$Id: mailgw.py,v 1.145 2004-03-25 22:52:12 richard Exp $
+$Id: mailgw.py,v 1.146 2004-03-26 00:44:11 richard Exp $
 """
 __docformat__ = 'restructuredtext'
 
 """
 __docformat__ = 'restructuredtext'
 
@@ -80,7 +80,7 @@ import string, re, os, mimetools, cStringIO, smtplib, socket, binascii, quopri
 import time, random, sys
 import traceback, MimeWriter, rfc822
 
 import time, random, sys
 import traceback, MimeWriter, rfc822
 
-from roundup import hyperdb, date, password, rfc2822
+from roundup import hyperdb, date, password, rfc2822, exceptions
 from roundup.mailer import Mailer
 
 SENDMAILDEBUG = os.environ.get('SENDMAILDEBUG', '')
 from roundup.mailer import Mailer
 
 SENDMAILDEBUG = os.environ.get('SENDMAILDEBUG', '')
@@ -805,8 +805,13 @@ not find a text/plain part to use.
             for (name, mime_type, data) in attachments:
                 if not name:
                     name = "unnamed"
             for (name, mime_type, data) in attachments:
                 if not name:
                     name = "unnamed"
-                files.append(self.db.file.create(type=mime_type, name=name,
-                                                 content=data, **file_props))
+                try:
+                    fileid = self.db.file.create(type=mime_type, name=name,
+                         content=data, **file_props)
+                except exceptions.Reject:
+                    pass
+                else:
+                    files.append(fileid)
             # attach the files to the issue
             if nodeid:
                 # extend the existing files list
             # attach the files to the issue
             if nodeid:
                 # extend the existing files list
@@ -821,20 +826,23 @@ not find a text/plain part to use.
         # create the message if there's a message body (content)
         #
         if (content and properties.has_key('messages')):
         # create the message if there's a message body (content)
         #
         if (content and properties.has_key('messages')):
-            message_id = self.db.msg.create(author=author,
-                recipients=recipients, date=date.Date('.'), summary=summary,
-                content=content, files=files, messageid=messageid,
-                inreplyto=inreplyto, **msg_props)
-
-            # attach the message to the node
-            if nodeid:
-                # add the message to the node's list
-                messages = cl.get(nodeid, 'messages')
-                messages.append(message_id)
-                props['messages'] = messages
+            try:
+                message_id = self.db.msg.create(author=author,
+                    recipients=recipients, date=date.Date('.'),
+                    summary=summary, content=content, files=files,
+                    messageid=messageid, inreplyto=inreplyto, **msg_props)
+            except exceptions.Reject:
+                pass
             else:
             else:
-                # pre-load the messages list
-                props['messages'] = [message_id]
+                # attach the message to the node
+                if nodeid:
+                    # add the message to the node's list
+                    messages = cl.get(nodeid, 'messages')
+                    messages.append(message_id)
+                    props['messages'] = messages
+                else:
+                    # pre-load the messages list
+                    props['messages'] = [message_id]
 
         #
         # perform the node change / create
 
         #
         # perform the node change / create
@@ -948,10 +956,13 @@ def uidFromAddress(db, address, create=1, **user_props):
             trying = username + str(n)
 
         # create!
             trying = username + str(n)
 
         # create!
-        return db.user.create(username=trying, address=address,
-            realname=realname, roles=db.config.NEW_EMAIL_USER_ROLES,
-            password=password.Password(password.generatePassword()),
-            **user_props)
+        try:
+            return db.user.create(username=trying, address=address,
+                realname=realname, roles=db.config.NEW_EMAIL_USER_ROLES,
+                password=password.Password(password.generatePassword()),
+                **user_props)
+        except exceptions.Reject:
+            return 0
     else:
         return 0
 
     else:
         return 0