Mercurial > p > roundup > code
changeset 3973:85cbaa50eba1
xml-rpc security checks and tests across all backends [SF#1907211]
also add some leap year tests
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Fri, 07 Mar 2008 01:11:55 +0000 |
| parents | eee76dd4a09f |
| children | ff089ebe95d1 |
| files | CHANGES.txt roundup/xmlrpc.py test/db_test_base.py test/test_dates.py test/test_xmlrpc.py |
| diffstat | 5 files changed, 82 insertions(+), 58 deletions(-) [+] |
line wrap: on
line diff
--- a/CHANGES.txt Fri Mar 07 00:35:47 2008 +0000 +++ b/CHANGES.txt Fri Mar 07 01:11:55 2008 +0000 @@ -4,6 +4,7 @@ 2008-03-01 1.4.5 Fixed: - 'Make a Copy' failed with more than one person in nosy list (sf #1906147) +- xml-rpc security checks and tests across all backends (sf #1907211) 2008-03-01 1.4.4
--- a/roundup/xmlrpc.py Fri Mar 07 00:35:47 2008 +0000 +++ b/roundup/xmlrpc.py Fri Mar 07 01:11:55 2008 +0000 @@ -63,13 +63,10 @@ def close(self): """Close the database, after committing any changes, if needed.""" - if getattr(self, 'db'): - try: - if self.db.transactions: - self.db.commit() - finally: - self.db.close() - + try: + self.db.commit() + finally: + self.db.close() def get_class(self, classname): """Return the class for the given classname.""" @@ -94,7 +91,7 @@ if value: try: props[key] = hyperdb.rawToHyperdb(self.db, cl, None, - key, value) + key, value) except hyperdb.HyperdbValueError, message: raise UsageError, message else: @@ -115,51 +112,53 @@ def list(self, username, password, classname, propname=None): r = RoundupRequest(self.tracker, username, password) - cl = r.get_class(classname) - if not propname: - propname = cl.labelprop() - def has_perm(itemid): - return True - r.db.security.hasPermission('View', r.userid, classname, - itemid=itemid, property=propname) - result = [cl.get(id, propname) for id in cl.list() - if has_perm(id)] - r.close() + try: + cl = r.get_class(classname) + if not propname: + propname = cl.labelprop() + result = [cl.get(itemid, propname) + for itemid in cl.list() + if r.db.security.hasPermission('View', r.userid, + classname, propname, itemid) + ] + finally: + r.close() return result def display(self, username, password, designator, *properties): r = RoundupRequest(self.tracker, username, password) - classname, itemid = hyperdb.splitDesignator(designator) - - if not r.db.security.hasPermission('View', r.userid, classname, - itemid=itemid): - raise Unauthorised('Permission to view %s denied'%designator) - - cl = r.get_class(classname) - props = properties and list(properties) or cl.properties.keys() - props.sort() - result = [(property, cl.get(itemid, property)) for property in props] - r.close() + try: + classname, itemid = hyperdb.splitDesignator(designator) + cl = r.get_class(classname) + props = properties and list(properties) or cl.properties.keys() + props.sort() + for p in props: + if not r.db.security.hasPermission('View', r.userid, + classname, p, itemid): + raise Unauthorised('Permission to view %s of %s denied'% + (p, designator)) + result = [(prop, cl.get(itemid, prop)) for prop in props] + finally: + r.close() return dict(result) def create(self, username, password, classname, *args): r = RoundupRequest(self.tracker, username, password) + try: + if not r.db.security.hasPermission('Create', r.userid, classname): + raise Unauthorised('Permission to create %s denied'%classname) - if not r.db.security.hasPermission('Create', r.userid, classname): - raise Unauthorised('Permission to create %s denied'%classname) - - cl = r.get_class(classname) + cl = r.get_class(classname) - # convert types - props = r.props_from_args(cl, args) + # convert types + props = r.props_from_args(cl, args) - # check for the key property - key = cl.getkey() - if key and not props.has_key(key): - raise UsageError, 'you must provide the "%s" property.'%key + # check for the key property + key = cl.getkey() + if key and not props.has_key(key): + raise UsageError, 'you must provide the "%s" property.'%key - # do the actual create - try: + # do the actual create try: result = cl.create(**props) except (TypeError, IndexError, ValueError), message: @@ -170,19 +169,17 @@ def set(self, username, password, designator, *args): r = RoundupRequest(self.tracker, username, password) - classname, itemid = hyperdb.splitDesignator(designator) - - if not r.db.security.hasPermission('Edit', r.userid, classname, - itemid=itemid): - raise Unauthorised('Permission to edit %s denied'%designator) - - cl = r.get_class(classname) - - # convert types - props = r.props_from_args(cl, args) try: + classname, itemid = hyperdb.splitDesignator(designator) + cl = r.get_class(classname) + props = r.props_from_args(cl, args) # convert types + for p in props.iterkeys (): + if not r.db.security.hasPermission('Edit', r.userid, + classname, p, itemid): + raise Unauthorised('Permission to edit %s of %s denied'% + (p, designator)) try: - cl.set(itemid, **props) + return cl.set(itemid, **props) except (TypeError, IndexError, ValueError), message: raise UsageError, message finally:
--- a/test/db_test_base.py Fri Mar 07 00:35:47 2008 +0000 +++ b/test/db_test_base.py Fri Mar 07 01:11:55 2008 +0000 @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: db_test_base.py,v 1.96 2008-02-07 03:28:34 richard Exp $ +# $Id: db_test_base.py,v 1.97 2008-03-07 01:11:55 richard Exp $ import unittest, os, shutil, errno, imp, sys, time, pprint, sets, base64, os.path @@ -62,6 +62,7 @@ tracker = instance.open(dirname) if tracker.exists(): tracker.nuke() + init.write_select_db(dirname, backend) tracker.init(password.Password('sekrit')) return tracker @@ -293,7 +294,7 @@ l = [u1,u2]; l.sort() m = self.db.issue.get(nid, "nosy"); m.sort() self.assertEqual(l, m) - + # XXX one day, maybe... # def testMultilinkOrdering(self): @@ -329,6 +330,18 @@ c = self.db.issue.get(nid, "deadline") self.assertEqual(c, d) + def testDateLeapYear(self): + nid = self.db.issue.create(title='spam', status='1', + deadline=date.Date('2008-02-29')) + self.assertEquals(str(self.db.issue.get(nid, 'deadline')), + '2008-02-29.00:00:00') + self.db.issue.set(nid, deadline=date.Date('2008-02-29')) + self.assertEquals(str(self.db.issue.get(nid, 'deadline')), + '2008-02-29.00:00:00') + self.assertEquals(self.db.issue.filter(None, {'deadline': '2008-02-29'}), + [nid]) + + def testDateUnset(self): for commit in (0,1): nid = self.db.issue.create(title="spam", status='1')
--- a/test/test_dates.py Fri Mar 07 00:35:47 2008 +0000 +++ b/test/test_dates.py Fri Mar 07 01:11:55 2008 +0000 @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: test_dates.py,v 1.44 2007-12-23 00:23:23 richard Exp $ +# $Id: test_dates.py,v 1.45 2008-03-07 01:11:55 richard Exp $ from __future__ import nested_scopes import unittest @@ -68,6 +68,9 @@ ae(str(Date('1900-02-01')), '1900-02-01.00:00:00') ae(str(Date('1800-07-15')), '1800-07-15.00:00:00') + def testLeapYear(self): + self.assertEquals(str(Date('2008-02-29')), '2008-02-29.00:00:00') + def testDateError(self): self.assertRaises(ValueError, Date, "12") # Date cannot handle dates before year 1
--- a/test/test_xmlrpc.py Fri Mar 07 00:35:47 2008 +0000 +++ b/test/test_xmlrpc.py Fri Mar 07 01:11:55 2008 +0000 @@ -9,16 +9,20 @@ from roundup.cgi.exceptions import * from roundup import init, instance, password, hyperdb, date from roundup.xmlrpc import RoundupServer +from roundup.backends import list_backends import db_test_base NEEDS_INSTANCE = 1 class TestCase(unittest.TestCase): + + backend = None + def setUp(self): self.dirname = '_test_xmlrpc' # set up and open a tracker - self.instance = db_test_base.setupTracker(self.dirname) + self.instance = db_test_base.setupTracker(self.dirname, self.backend) # open the database self.db = self.instance.open('admin') @@ -55,6 +59,10 @@ 'realname') self.assertEqual(results['realname'], 'Joe Doe') + # check we can't change admin's details + self.assertRaises(Unauthorised, self.server.set, 'joe', 'random', + 'user1', 'realname=Joe Doe') + def testCreate(self): results = self.server.create('joe', 'random', 'issue', 'title=foo') issueid = 'issue' + results @@ -89,10 +97,12 @@ def test_suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestCase)) + for l in list_backends(): + dct = dict(backend = l) + subcls = type(TestCase)('TestCase_%s'%l, (TestCase,), dct) + suite.addTest(unittest.makeSuite(subcls)) return suite if __name__ == '__main__': runner = unittest.TextTestRunner() unittest.main(testRunner=runner) -
