Code

Added the web access and email access permissions, so people can restrict
authorrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Thu, 1 Aug 2002 00:56:22 +0000 (00:56 +0000)
committerrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Thu, 1 Aug 2002 00:56:22 +0000 (00:56 +0000)
access to users who register through the email interface (for example).
Also added "security" command to the roundup-admin interface to display the
Role/Permission config for an instance.

git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@944 57a73879-2fb5-44c3-a270-3262357dd7e2

roundup/admin.py
roundup/cgi_client.py
roundup/mailgw.py
roundup/templates/classic/dbinit.py
roundup/templates/extended/dbinit.py

index 305da4e355e1e5f49fffc5715299356b207fd29e..a949e05fbd4bf3d32eae6d805631c40069b825d9 100644 (file)
@@ -16,7 +16,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: admin.py,v 1.19 2002-07-25 07:14:05 richard Exp $
+# $Id: admin.py,v 1.20 2002-08-01 00:56:22 richard Exp $
 
 import sys, os, getpass, getopt, re, UserDict, shlex, shutil
 try:
 
 import sys, os, getpass, getopt, re, UserDict, shlex, shutil
 try:
@@ -249,7 +249,6 @@ Command help:
         backends = roundup.backends.__all__
         print _('Back ends:'), ', '.join(backends)
 
         backends = roundup.backends.__all__
         print _('Back ends:'), ', '.join(backends)
 
-
     def do_install(self, instance_home, args):
         '''Usage: install [template [backend [admin password]]]
         Install a new Roundup instance.
     def do_install(self, instance_home, args):
         '''Usage: install [template [backend [admin password]]]
         Install a new Roundup instance.
@@ -981,6 +980,30 @@ Date format is "YYYY-MM-DD" eg:
         self.db.reindex()
         return 0
 
         self.db.reindex()
         return 0
 
+    def do_security(self, args):
+        '''Usage: security [Role name]
+        Display the Permissions available to one or all Roles.
+        '''
+        if len(args) == 1:
+            role = args[0]
+            try:
+                roles = [(args[0], self.db.security.role[args[0]])]
+            except KeyError:
+                print _('No such Role "%(role)s"')%locals()
+                return 1
+        else:
+            roles = self.db.security.role.items()
+        roles.sort()
+        for rolename, role in roles:
+            print _('Role "%(name)s":')%role.__dict__
+            for permission in role.permissions:
+                if permission.klass:
+                    print _(' %(description)s (%(name)s for "%(klass)s" '
+                        'only)')%permission.__dict__
+                else:
+                    print _(' %(description)s (%(name)s)')%permission.__dict__
+        return 0
+
     def run_command(self, args):
         '''Run a single command
         '''
     def run_command(self, args):
         '''Run a single command
         '''
@@ -1131,6 +1154,14 @@ if __name__ == '__main__':
 
 #
 # $Log: not supported by cvs2svn $
 
 #
 # $Log: not supported by cvs2svn $
+# Revision 1.19  2002/07/25 07:14:05  richard
+# Bugger it. Here's the current shape of the new security implementation.
+# Still to do:
+#  . call the security funcs from cgi and mailgw
+#  . change shipped templates to include correct initialisation and remove
+#    the old config vars
+# ... that seems like a lot. The bulk of the work has been done though. Honest :)
+#
 # Revision 1.18  2002/07/18 11:17:30  gmcm
 # Add Number and Boolean types to hyperdb.
 # Add conversion cases to web, mail & admin interfaces.
 # Revision 1.18  2002/07/18 11:17:30  gmcm
 # Add Number and Boolean types to hyperdb.
 # Add conversion cases to web, mail & admin interfaces.
index 632b1d4f955e3c678a371056afa1fcd77e32f6c0..94aa96212799cbfa367c54c7c321b57048dfd1ee 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: cgi_client.py,v 1.154 2002-07-31 23:57:36 richard Exp $
+# $Id: cgi_client.py,v 1.155 2002-08-01 00:56:22 richard Exp $
 
 __doc__ = """
 WWW request handler (also used in the stand-alone server).
 
 __doc__ = """
 WWW request handler (also used in the stand-alone server).
@@ -41,6 +41,8 @@ def initialiseSecurity(security):
     '''
     security.addPermission(name="Web Registration",
         description="User may register through the web")
     '''
     security.addPermission(name="Web Registration",
         description="User may register through the web")
+    security.addPermission(name="Web Access",
+        description="User may access the web interface")
 
     # doing Role stuff through the web - make sure Admin can
     p = security.addPermission(name="Web Roles",
 
     # doing Role stuff through the web - make sure Admin can
     p = security.addPermission(name="Web Roles",
@@ -1407,8 +1409,9 @@ function help_window(helpurl, width, height) {
     def opendb(self, user):
         ''' Open the database - but include the definition of the sessions db.
         '''
     def opendb(self, user):
         ''' Open the database - but include the definition of the sessions db.
         '''
-        # open the db
-        self.db = self.instance.open(user)
+        # open the db if the user has changed
+        if not hasattr(self, 'db') or user != self.db.journaltag:
+            self.db = self.instance.open(user)
 
     def main(self):
         ''' Wrap the request and handle unauthorised requests
 
     def main(self):
         ''' Wrap the request and handle unauthorised requests
@@ -1489,29 +1492,39 @@ function help_window(helpurl, width, height) {
                 return
             # figure the resulting page
             action = self.form['__destination_url'].value
                 return
             # figure the resulting page
             action = self.form['__destination_url'].value
-            if not action:
-                action = 'index'
-            self.do_action(action)
-            return
 
         # allow anonymous people to register
 
         # allow anonymous people to register
-        if action == 'newuser_action':
+        elif action == 'newuser_action':
             # try to add the user
             if not self.newuser_action():
                 return
             # figure the resulting page
             action = self.form['__destination_url'].value
             # try to add the user
             if not self.newuser_action():
                 return
             # figure the resulting page
             action = self.form['__destination_url'].value
-            if not action:
-                action = 'index'
+
+        # ok, now we have figured out who the user is, make sure the user
+        # has permission to use this interface
+        userid = self.db.user.lookup(self.user)
+        if not self.db.security.hasPermission('Web Access', userid):
+            raise Unauthorised, \
+                _("You do not have permission to access this interface.")
 
         # re-open the database for real, using the user
         self.opendb(self.user)
 
 
         # re-open the database for real, using the user
         self.opendb(self.user)
 
-        # just a regular action
-        self.do_action(action)
+        # make sure we have a sane action
+        if not action:
+            action = 'index'
 
 
-        # commit all changes to the database
-        self.db.commit()
+        # just a regular action
+        try:
+            self.do_action(action)
+        except Unauthorised, message:
+            # if unauth is raised here, then a page header will have 
+            # been displayed
+            self.write('<p class="system-msg">%s</p>'%message)
+        else:
+            # commit all changes to the database
+            self.db.commit()
 
     def do_action(self, action, dre=re.compile(r'([^\d]+)(\d+)'),
             nre=re.compile(r'new(\w+)'), sre=re.compile(r'search(\w+)')):
 
     def do_action(self, action, dre=re.compile(r'([^\d]+)(\d+)'),
             nre=re.compile(r'new(\w+)'), sre=re.compile(r'search(\w+)')):
@@ -1690,6 +1703,9 @@ def parsePropsFromForm(db, cl, form, nodeid=0, num_re=re.compile('^\d+$')):
 
 #
 # $Log: not supported by cvs2svn $
 
 #
 # $Log: not supported by cvs2svn $
+# Revision 1.154  2002/07/31 23:57:36  richard
+#  . web forms may now unset Link values (like assignedto)
+#
 # Revision 1.153  2002/07/31 22:40:50  gmcm
 # Fixes to the search form and saving queries.
 # Fixes to  sorting in back_metakit.py.
 # Revision 1.153  2002/07/31 22:40:50  gmcm
 # Fixes to the search form and saving queries.
 # Fixes to  sorting in back_metakit.py.
index a1c21ac82da78bfa4ec7dc39131ee57f315baea9..ff2346bfd5b7602271854a572e3bfdcba693a4d9 100644 (file)
@@ -73,7 +73,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.79 2002-07-26 08:26:59 richard Exp $
+$Id: mailgw.py,v 1.80 2002-08-01 00:56:22 richard Exp $
 '''
 
 
 '''
 
 
@@ -104,6 +104,8 @@ def initialiseSecurity(security):
     '''
     newid = security.addPermission(name="Email Registration",
         description="Anonymous may register through e-mail")
     '''
     newid = security.addPermission(name="Email Registration",
         description="Anonymous may register through e-mail")
+    security.addPermission(name="Email Access",
+        description="User may use the email interface")
 
 class Message(mimetools.Message):
     ''' subclass mimetools.Message so we can retrieve the parts of the
 
 class Message(mimetools.Message):
     ''' subclass mimetools.Message so we can retrieve the parts of the
@@ -527,8 +529,12 @@ Subject was: "%s"
         if not self.db.security.hasPermission('Email Registration', anonid):
             create = 0
 
         if not self.db.security.hasPermission('Email Registration', anonid):
             create = 0
 
+        # ok, now figure out who the author is - create a new user if the
+        # "create" flag is true
         author = uidFromAddress(self.db, message.getaddrlist('from')[0],
             create=create)
         author = uidFromAddress(self.db, message.getaddrlist('from')[0],
             create=create)
+
+        # no author? means we're not author
         if not author:
             raise Unauthorized, '''
 You are not a registered user.
         if not author:
             raise Unauthorized, '''
 You are not a registered user.
@@ -536,6 +542,10 @@ You are not a registered user.
 Unknown address: %s
 '''%message.getaddrlist('from')[0][1]
 
 Unknown address: %s
 '''%message.getaddrlist('from')[0][1]
 
+        # make sure the author has permission to use the email interface
+        if not self.db.security.hasPermission('Email Access', author):
+            raise Unauthorized, 'You are not permitted to access this tracker.'
+
         # the author may have been created - make sure the change is
         # committed before we reopen the database
         self.db.commit()
         # the author may have been created - make sure the change is
         # committed before we reopen the database
         self.db.commit()
@@ -843,6 +853,11 @@ def parseContent(content, keep_citations, keep_body,
 
 #
 # $Log: not supported by cvs2svn $
 
 #
 # $Log: not supported by cvs2svn $
+# Revision 1.79  2002/07/26 08:26:59  richard
+# Very close now. The cgi and mailgw now use the new security API. The two
+# templates have been migrated to that setup. Lots of unit tests. Still some
+# issue in the web form for editing Roles assigned to users.
+#
 # Revision 1.78  2002/07/25 07:14:06  richard
 # Bugger it. Here's the current shape of the new security implementation.
 # Still to do:
 # Revision 1.78  2002/07/25 07:14:06  richard
 # Bugger it. Here's the current shape of the new security implementation.
 # Still to do:
index 7c2153ddf5e5c2ada0db13b21c82fe4cdee4ac09..71ff79ac44a6d799f0d1685a5d066f5734343e6a 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: dbinit.py,v 1.21 2002-07-26 08:26:59 richard Exp $
+# $Id: dbinit.py,v 1.22 2002-08-01 00:56:22 richard Exp $
 
 import os
 
 
 import os
 
@@ -98,6 +98,19 @@ def open(name=None):
         db.security.addPermission(name="View", klass=cl,
             description="User is allowed to access "+cl)
 
         db.security.addPermission(name="View", klass=cl,
             description="User is allowed to access "+cl)
 
+    # Assign the access and edit permissions for issue, file and message
+    # to regular users now
+    for cl in 'issue', 'file', 'msg':
+        p = db.security.getPermission('View', cl)
+        db.security.addPermissionToRole('User', p)
+        p = db.security.getPermission('Edit', cl)
+        db.security.addPermissionToRole('User', p)
+    # and give the regular users access to the web and email interface
+    p = db.security.getPermission('Web Access')
+    db.security.addPermissionToRole('User', p)
+    p = db.security.getPermission('Email Access')
+    db.security.addPermissionToRole('User', p)
+
     # Assign the appropriate permissions to the anonymous user's Anonymous
     # Role. Choices here are:
     # - Allow anonymous users to register through the web
     # Assign the appropriate permissions to the anonymous user's Anonymous
     # Role. Choices here are:
     # - Allow anonymous users to register through the web
@@ -117,13 +130,9 @@ def open(name=None):
     #p = db.security.getPermission('Edit', 'issue')
     #db.security.addPermissionToRole('Anonymous', p)
 
     #p = db.security.getPermission('Edit', 'issue')
     #db.security.addPermissionToRole('Anonymous', p)
 
-    # Assign the access and edit permissions for issue, file and message
-    # to regular users now
-    for cl in 'issue', 'file', 'msg':
-        p = db.security.getPermission('View', cl)
-        db.security.addPermissionToRole('User', p)
-        p = db.security.getPermission('Edit', cl)
-        db.security.addPermissionToRole('User', p)
+    # oh, g'wan, let anonymous access the web interface too
+    p = db.security.getPermission('Web Access')
+    db.security.addPermissionToRole('Anonymous', p)
 
     import detectors
     detectors.init(db)
 
     import detectors
     detectors.init(db)
@@ -176,6 +185,11 @@ def init(adminpw):
 
 #
 # $Log: not supported by cvs2svn $
 
 #
 # $Log: not supported by cvs2svn $
+# Revision 1.21  2002/07/26 08:26:59  richard
+# Very close now. The cgi and mailgw now use the new security API. The two
+# templates have been migrated to that setup. Lots of unit tests. Still some
+# issue in the web form for editing Roles assigned to users.
+#
 # Revision 1.20  2002/07/17 12:39:10  gmcm
 # Saving, running & editing queries.
 #
 # Revision 1.20  2002/07/17 12:39:10  gmcm
 # Saving, running & editing queries.
 #
index 6149c4dc5d8d9bf26408b4eb568703357dd85134..d5178d9a455178594bcfd129125a8b25d12fcded 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: dbinit.py,v 1.24 2002-07-26 08:27:00 richard Exp $
+# $Id: dbinit.py,v 1.25 2002-08-01 00:56:22 richard Exp $
 
 import os
 
 
 import os
 
@@ -122,6 +122,19 @@ def open(name=None):
         db.security.addPermission(name="View", klass=cl,
             description="User is allowed to access "+cl)
 
         db.security.addPermission(name="View", klass=cl,
             description="User is allowed to access "+cl)
 
+    # Assign the access and edit permissions for issue, file and message
+    # to regular users now
+    for cl in 'issue', 'support', 'file', 'msg':
+        p = db.security.getPermission('View', cl)
+        db.security.addPermissionToRole('User', p)
+        p = db.security.getPermission('Edit', cl)
+        db.security.addPermissionToRole('User', p)
+    # and give the regular users access to the web and email interface
+    p = db.security.getPermission('Web Access')
+    db.security.addPermissionToRole('User', p)
+    p = db.security.getPermission('Email Access')
+    db.security.addPermissionToRole('User', p)
+
     # Assign the appropriate permissions to the anonymous user's Anonymous
     # Role. Choices here are:
     # - Allow anonymous users to register through the web
     # Assign the appropriate permissions to the anonymous user's Anonymous
     # Role. Choices here are:
     # - Allow anonymous users to register through the web
@@ -141,13 +154,9 @@ def open(name=None):
     #p = db.security.getPermission('Edit', 'issue')
     #db.security.addPermissionToRole('Anonymous', p)
 
     #p = db.security.getPermission('Edit', 'issue')
     #db.security.addPermissionToRole('Anonymous', p)
 
-    # Assign the access and edit permissions for issue, file and message
-    # to regular users now
-    for cl in 'issue', 'support', 'file', 'msg':
-        p = db.security.getPermission('View', cl)
-        db.security.addPermissionToRole('User', p)
-        p = db.security.getPermission('Edit', cl)
-        db.security.addPermissionToRole('User', p)
+    # oh, g'wan, let anonymous access the web interface too
+    p = db.security.getPermission('Web Access')
+    db.security.addPermissionToRole('Anonymous', p)
 
     import detectors
     detectors.init(db)
 
     import detectors
     detectors.init(db)
@@ -217,6 +226,11 @@ def init(adminpw):
 
 #
 # $Log: not supported by cvs2svn $
 
 #
 # $Log: not supported by cvs2svn $
+# Revision 1.24  2002/07/26 08:27:00  richard
+# Very close now. The cgi and mailgw now use the new security API. The two
+# templates have been migrated to that setup. Lots of unit tests. Still some
+# issue in the web form for editing Roles assigned to users.
+#
 # Revision 1.23  2002/07/14 02:05:54  richard
 # . all storage-specific code (ie. backend) is now implemented by the backends
 #
 # Revision 1.23  2002/07/14 02:05:54  richard
 # . all storage-specific code (ie. backend) is now implemented by the backends
 #