From 9fdb76121879e5bc0df38c598e1896e637388e08 Mon Sep 17 00:00:00 2001 From: richard Date: Thu, 1 Aug 2002 00:56:22 +0000 Subject: [PATCH] Added the web access and email access permissions, so people can restrict 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 | 35 ++++++++++++++++++++-- roundup/cgi_client.py | 44 +++++++++++++++++++--------- roundup/mailgw.py | 17 ++++++++++- roundup/templates/classic/dbinit.py | 30 ++++++++++++++----- roundup/templates/extended/dbinit.py | 30 ++++++++++++++----- 5 files changed, 123 insertions(+), 33 deletions(-) diff --git a/roundup/admin.py b/roundup/admin.py index 305da4e..a949e05 100644 --- a/roundup/admin.py +++ b/roundup/admin.py @@ -16,7 +16,7 @@ # 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: @@ -249,7 +249,6 @@ Command help: 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. @@ -981,6 +980,30 @@ Date format is "YYYY-MM-DD" eg: 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 ''' @@ -1131,6 +1154,14 @@ if __name__ == '__main__': # # $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. diff --git a/roundup/cgi_client.py b/roundup/cgi_client.py index 632b1d4..94aa962 100644 --- a/roundup/cgi_client.py +++ b/roundup/cgi_client.py @@ -15,7 +15,7 @@ # 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). @@ -41,6 +41,8 @@ def initialiseSecurity(security): ''' 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", @@ -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. ''' - # 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 @@ -1489,29 +1492,39 @@ function help_window(helpurl, width, height) { 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 - 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 - 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) - # 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('

%s

'%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+)')): @@ -1690,6 +1703,9 @@ def parsePropsFromForm(db, cl, form, nodeid=0, num_re=re.compile('^\d+$')): # # $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. diff --git a/roundup/mailgw.py b/roundup/mailgw.py index a1c21ac..ff2346b 100644 --- a/roundup/mailgw.py +++ b/roundup/mailgw.py @@ -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. -$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") + 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 @@ -527,8 +529,12 @@ Subject was: "%s" 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) + + # no author? means we're not author 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] + # 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() @@ -843,6 +853,11 @@ def parseContent(content, keep_citations, keep_body, # # $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: diff --git a/roundup/templates/classic/dbinit.py b/roundup/templates/classic/dbinit.py index 7c2153d..71ff79a 100644 --- a/roundup/templates/classic/dbinit.py +++ b/roundup/templates/classic/dbinit.py @@ -15,7 +15,7 @@ # 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 @@ -98,6 +98,19 @@ def open(name=None): 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 @@ -117,13 +130,9 @@ def open(name=None): #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) @@ -176,6 +185,11 @@ def init(adminpw): # # $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. # diff --git a/roundup/templates/extended/dbinit.py b/roundup/templates/extended/dbinit.py index 6149c4d..d5178d9 100644 --- a/roundup/templates/extended/dbinit.py +++ b/roundup/templates/extended/dbinit.py @@ -15,7 +15,7 @@ # 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 @@ -122,6 +122,19 @@ def open(name=None): 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 @@ -141,13 +154,9 @@ def open(name=None): #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) @@ -217,6 +226,11 @@ def init(adminpw): # # $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 # -- 2.30.2