From aa5d6d741be87c239b431139c651532ded8d68bf Mon Sep 17 00:00:00 2001 From: richard Date: Fri, 20 Sep 2002 05:08:00 +0000 Subject: [PATCH] On second thought, that last checkin was dumb. The old, nasty, for-purely-historical-reasons journaltag-as-username has gone away now. The code should handle existing journaltag-as-username entries, but will use userid from now on. git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@1200 57a73879-2fb5-44c3-a270-3262357dd7e2 --- roundup/backends/back_anydbm.py | 53 ++++++++++++++------- roundup/backends/back_metakit.py | 14 ++++-- roundup/backends/rdbms_common.py | 19 ++++++-- test/test_db.py | 80 +++++++++++++++----------------- test/test_mailgw.py | 4 +- test/test_schema.py | 5 +- test/test_security.py | 5 +- 7 files changed, 106 insertions(+), 74 deletions(-) diff --git a/roundup/backends/back_anydbm.py b/roundup/backends/back_anydbm.py index ef047ba..0fdcf28 100644 --- a/roundup/backends/back_anydbm.py +++ b/roundup/backends/back_anydbm.py @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -#$Id: back_anydbm.py,v 1.82 2002-09-20 01:20:31 richard Exp $ +#$Id: back_anydbm.py,v 1.83 2002-09-20 05:08:00 richard Exp $ ''' This module defines a backend that saves the hyperdatabase in a database chosen by anydbm. It is guaranteed to always be available in python @@ -73,11 +73,21 @@ class Database(FileStorage, hyperdb.Database, roundupdb.Database): os.umask(0002) def post_init(self): - '''Called once the schema initialisation has finished.''' + ''' Called once the schema initialisation has finished. + ''' # reindex the db if necessary if self.indexer.should_reindex(): self.reindex() + # figure the "curuserid" + if self.journaltag is None: + self.curuserid = None + elif self.journaltag == 'admin': + # admin user may not exist, but always has ID 1 + self.curuserid = '1' + else: + self.curuserid = self.user.lookup(self.journaltag) + def reindex(self): for klass in self.classes.values(): for nodeid in klass.list(): @@ -237,11 +247,13 @@ class Database(FileStorage, hyperdb.Database, roundupdb.Database): if __debug__: print >>hyperdb.DEBUG, 'addnode', (self, classname, nodeid, node) - # add in the "calculated" properties (dupe so we don't affect - # calling code's node assumptions) - node = node.copy() - node['creator'] = self.journaltag - node['creation'] = node['activity'] = date.Date() + # we'll be supplied these props if we're doing an import + if not node.has_key('creator'): + # add in the "calculated" properties (dupe so we don't affect + # calling code's node assumptions) + node = node.copy() + node['creator'] = self.curuserid + node['creation'] = node['activity'] = date.Date() self.newnodes.setdefault(classname, {})[nodeid] = 1 self.cache.setdefault(classname, {})[nodeid] = node @@ -631,7 +643,7 @@ class Database(FileStorage, hyperdb.Database, roundupdb.Database): if creator: journaltag = creator else: - journaltag = self.journaltag + journaltag = self.curuserid if creation: journaldate = creation.serialise() else: @@ -949,7 +961,10 @@ class Class(hyperdb.Class): value = pwd d[propname] = value - # extract the extraneous journalling gumpf and nuke it + # add the node and journal + self.db.addnode(self.classname, newid, d) + + # extract the journalling stuff and nuke it if d.has_key('creator'): creator = d['creator'] del d['creator'] @@ -963,8 +978,6 @@ class Class(hyperdb.Class): if d.has_key('activity'): del d['activity'] - # add the node and journal - self.db.addnode(self.classname, newid, d) self.db.addjournal(self.classname, newid, 'create', d, creator, creation) return newid @@ -1020,9 +1033,19 @@ class Class(hyperdb.Class): raise ValueError, 'Journalling is disabled for this class' journal = self.db.getjournal(self.classname, nodeid) if journal: - return self.db.getjournal(self.classname, nodeid)[0][2] + num_re = re.compile('^\d+$') + value = self.db.getjournal(self.classname, nodeid)[0][2] + if num_re.match(value): + return value + else: + # old-style "username" journal tag + try: + return self.db.user.lookup(value) + except KeyError: + # user's been retired, return admin + return '1' else: - return self.db.journaltag + return self.db.curuserid # get the property (raises KeyErorr if invalid) prop = self.properties[propname] @@ -1779,9 +1802,7 @@ class Class(hyperdb.Class): d['id'] = String() d['creation'] = hyperdb.Date() d['activity'] = hyperdb.Date() - # can't be a link to user because the user might have been - # retired since the journal entry was created - d['creator'] = hyperdb.String() + d['creator'] = hyperdb.Link('user') return d def addprop(self, **properties): diff --git a/roundup/backends/back_metakit.py b/roundup/backends/back_metakit.py index 2a90a5c..d3b4b14 100755 --- a/roundup/backends/back_metakit.py +++ b/roundup/backends/back_metakit.py @@ -48,10 +48,16 @@ class _Database(hyperdb.Database): # --- defined in ping's spec def __getattr__(self, classname): if classname == 'curuserid': + if self.journaltag is None: + return None + try: self.curuserid = x = int(self.classes['user'].lookup(self.journaltag)) except KeyError: - x = 0 + if self.journaltag == 'admin': + self.curuserid = x = 1 + else: + x = 0 return x elif classname == 'transactions': return self.dirty @@ -194,7 +200,7 @@ class Class: self.privateprops = { 'id' : hyperdb.String(), 'activity' : hyperdb.Date(), 'creation' : hyperdb.Date(), - 'creator' : hyperdb.String() } + 'creator' : hyperdb.Link('user') } self.auditors = {'create': [], 'set': [], 'retire': []} # event -> list of callables self.reactors = {'create': [], 'set': [], 'retire': []} # ditto view = self.__getview() @@ -291,7 +297,7 @@ class Class: if propvalues.has_key('id'): raise KeyError, '"id" is reserved' if self.db.journaltag is None: - raise DatabaseError, 'Database open read-only' + raise hyperdb.DatabaseError, 'Database open read-only' view = self.getview(1) # node must exist & not be retired id = int(nodeid) @@ -341,7 +347,7 @@ class Class: # must be a string or None if value is not None and not isinstance(value, type('')): raise ValueError, 'property "%s" link value be a string'%( - propname) + key) # Roundup sets to "unselected" by passing None if value is None: value = 0 diff --git a/roundup/backends/rdbms_common.py b/roundup/backends/rdbms_common.py index 6ddf71a..d39234f 100644 --- a/roundup/backends/rdbms_common.py +++ b/roundup/backends/rdbms_common.py @@ -1,4 +1,4 @@ -# $Id: rdbms_common.py,v 1.8 2002-09-20 01:48:34 richard Exp $ +# $Id: rdbms_common.py,v 1.9 2002-09-20 05:08:00 richard Exp $ # standard python modules import sys, os, time, re, errno, weakref, copy @@ -115,6 +115,15 @@ class Database(FileStorage, hyperdb.Database, roundupdb.Database): # commit self.conn.commit() + # figure the "curuserid" + if self.journaltag is None: + self.curuserid = None + elif self.journaltag == 'admin': + # admin user may not exist, but always has ID 1 + self.curuserid = '1' + else: + self.curuserid = self.user.lookup(self.journaltag) + def reindex(self): for klass in self.classes.values(): for nodeid in klass.list(): @@ -461,7 +470,7 @@ class Database(FileStorage, hyperdb.Database, roundupdb.Database): # add the special props node = node.copy() node['creation'] = node['activity'] = date.Date() - node['creator'] = self.journaltag + node['creator'] = self.curuserid # default the non-multilink columns for col, prop in cl.properties.items(): @@ -769,7 +778,7 @@ class Database(FileStorage, hyperdb.Database, roundupdb.Database): if creator: journaltag = creator else: - journaltag = self.journaltag + journaltag = self.curuserid if creation: journaldate = creation.serialise() else: @@ -1199,7 +1208,7 @@ class Class(hyperdb.Class): if d.has_key('creator'): return d['creator'] else: - return self.db.journaltag + return self.db.curuserid # get the property (raises KeyErorr if invalid) prop = self.properties[propname] @@ -1788,7 +1797,7 @@ class Class(hyperdb.Class): d['id'] = String() d['creation'] = hyperdb.Date() d['activity'] = hyperdb.Date() - d['creator'] = hyperdb.String() + d['creator'] = hyperdb.Link('user') return d def addprop(self, **properties): diff --git a/test/test_db.py b/test/test_db.py index 00e67e7..c9ef868 100644 --- a/test/test_db.py +++ b/test/test_db.py @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: test_db.py,v 1.51 2002-09-20 01:20:32 richard Exp $ +# $Id: test_db.py,v 1.52 2002-09-20 05:08:00 richard Exp $ import unittest, os, shutil, time @@ -31,7 +31,7 @@ def setupSchema(db, create, module): assignable=Boolean(), age=Number(), roles=String()) user.setkey("username") file = module.FileClass(db, "file", name=String(), type=String(), - comment=String(indexme="yes")) + comment=String(indexme="yes"), fooz=Password()) issue = module.IssueClass(db, "issue", title=String(indexme="yes"), status=Link("status"), nosy=Multilink("user"), deadline=Date(), foo=Interval(), files=Multilink("file"), assignedto=Link('user')) @@ -39,6 +39,7 @@ def setupSchema(db, create, module): session.disableJournalling() db.post_init() if create: + user.create(username="admin", roles='Admin') status.create(name="unread") status.create(name="in-progress") status.create(name="testing") @@ -74,9 +75,9 @@ class anydbmDBTestCase(MyTestCase): if os.path.exists(config.DATABASE): shutil.rmtree(config.DATABASE) os.makedirs(config.DATABASE + '/files') - self.db = anydbm.Database(config, 'test') + self.db = anydbm.Database(config, 'admin') setupSchema(self.db, 1, anydbm) - self.db2 = anydbm.Database(config, 'test') + self.db2 = anydbm.Database(config, 'admin') setupSchema(self.db2, 0, anydbm) def testStringChange(self): @@ -150,8 +151,8 @@ class anydbmDBTestCase(MyTestCase): self.assertEqual(self.db.user.get('1', "assignable"), None) def testNumberChange(self): - self.db.user.create(username='foo', age=1) - self.assertEqual(1, self.db.user.get('1', 'age')) + nid = self.db.user.create(username='foo', age=1) + self.assertEqual(1, self.db.user.get(nid, 'age')) self.db.user.set('1', age=3) self.assertNotEqual(self.db.user.get('1', 'age'), 1) self.db.user.set('1', age=1.0) @@ -305,9 +306,9 @@ class anydbmDBTestCase(MyTestCase): # key property # # key must be a String - ar(TypeError, self.db.user.setkey, 'password') + ar(TypeError, self.db.file.setkey, 'fooz') # key must exist - ar(KeyError, self.db.user.setkey, 'fubar') + ar(KeyError, self.db.file.setkey, 'fubar') # # class get @@ -347,11 +348,11 @@ class anydbmDBTestCase(MyTestCase): ar(TypeError, self.db.user.create, username='foo', age='a') # invalid boolean value ar(TypeError, self.db.user.create, username='foo', assignable='true') - self.db.user.create(username='foo') + nid = self.db.user.create(username='foo') # invalid number value - ar(TypeError, self.db.user.set, '3', username='foo', age='a') + ar(TypeError, self.db.user.set, nid, username='foo', age='a') # invalid boolean value - ar(TypeError, self.db.user.set, '3', username='foo', assignable='true') + ar(TypeError, self.db.user.set, nid, username='foo', assignable='true') def testJournals(self): self.db.user.create(username="mary") @@ -364,7 +365,7 @@ class anydbmDBTestCase(MyTestCase): self.assertEqual(1, len(journal)) (nodeid, date_stamp, journaltag, action, params) = journal[0] self.assertEqual(nodeid, '1') - self.assertEqual(journaltag, 'test') + self.assertEqual(journaltag, self.db.user.lookup('admin')) self.assertEqual(action, 'create') keys = params.keys() keys.sort() @@ -385,7 +386,7 @@ class anydbmDBTestCase(MyTestCase): self.assertEqual(2, len(journal)) (nodeid, date_stamp, journaltag, action, params) = journal[1] self.assertEqual('1', nodeid) - self.assertEqual('test', journaltag) + self.assertEqual('1', journaltag) self.assertEqual('link', action) self.assertEqual(('issue', '1', 'assignedto'), params) @@ -396,7 +397,7 @@ class anydbmDBTestCase(MyTestCase): self.assertEqual(3, len(journal)) (nodeid, date_stamp, journaltag, action, params) = journal[2] self.assertEqual('1', nodeid) - self.assertEqual('test', journaltag) + self.assertEqual('1', journaltag) self.assertEqual('unlink', action) self.assertEqual(('issue', '1', 'assignedto'), params) @@ -525,11 +526,11 @@ class anydbmReadOnlyDBTestCase(MyTestCase): if os.path.exists(config.DATABASE): shutil.rmtree(config.DATABASE) os.makedirs(config.DATABASE + '/files') - db = anydbm.Database(config, 'test') + db = anydbm.Database(config, 'admin') setupSchema(db, 1, anydbm) self.db = anydbm.Database(config) setupSchema(self.db, 0, anydbm) - self.db2 = anydbm.Database(config, 'test') + self.db2 = anydbm.Database(config, 'admin') setupSchema(self.db2, 0, anydbm) def testExceptions(self): @@ -549,9 +550,9 @@ class bsddbDBTestCase(anydbmDBTestCase): if os.path.exists(config.DATABASE): shutil.rmtree(config.DATABASE) os.makedirs(config.DATABASE + '/files') - self.db = bsddb.Database(config, 'test') + self.db = bsddb.Database(config, 'admin') setupSchema(self.db, 1, bsddb) - self.db2 = bsddb.Database(config, 'test') + self.db2 = bsddb.Database(config, 'admin') setupSchema(self.db2, 0, bsddb) class bsddbReadOnlyDBTestCase(anydbmReadOnlyDBTestCase): @@ -561,11 +562,11 @@ class bsddbReadOnlyDBTestCase(anydbmReadOnlyDBTestCase): if os.path.exists(config.DATABASE): shutil.rmtree(config.DATABASE) os.makedirs(config.DATABASE + '/files') - db = bsddb.Database(config, 'test') + db = bsddb.Database(config, 'admin') setupSchema(db, 1, bsddb) self.db = bsddb.Database(config) setupSchema(self.db, 0, bsddb) - self.db2 = bsddb.Database(config, 'test') + self.db2 = bsddb.Database(config, 'admin') setupSchema(self.db2, 0, bsddb) @@ -576,9 +577,9 @@ class bsddb3DBTestCase(anydbmDBTestCase): if os.path.exists(config.DATABASE): shutil.rmtree(config.DATABASE) os.makedirs(config.DATABASE + '/files') - self.db = bsddb3.Database(config, 'test') + self.db = bsddb3.Database(config, 'admin') setupSchema(self.db, 1, bsddb3) - self.db2 = bsddb3.Database(config, 'test') + self.db2 = bsddb3.Database(config, 'admin') setupSchema(self.db2, 0, bsddb3) class bsddb3ReadOnlyDBTestCase(anydbmReadOnlyDBTestCase): @@ -588,11 +589,11 @@ class bsddb3ReadOnlyDBTestCase(anydbmReadOnlyDBTestCase): if os.path.exists(config.DATABASE): shutil.rmtree(config.DATABASE) os.makedirs(config.DATABASE + '/files') - db = bsddb3.Database(config, 'test') + db = bsddb3.Database(config, 'admin') setupSchema(db, 1, bsddb3) self.db = bsddb3.Database(config) setupSchema(self.db, 0, bsddb3) - self.db2 = bsddb3.Database(config, 'test') + self.db2 = bsddb3.Database(config, 'admin') setupSchema(self.db2, 0, bsddb3) @@ -607,7 +608,7 @@ class gadflyDBTestCase(anydbmDBTestCase): shutil.rmtree(config.DATABASE) config.GADFLY_DATABASE = ('test', config.DATABASE) os.makedirs(config.DATABASE + '/files') - self.db = gadfly.Database(config, 'test') + self.db = gadfly.Database(config, 'admin') setupSchema(self.db, 1, gadfly) def testIDGeneration(self): @@ -623,7 +624,7 @@ class gadflyReadOnlyDBTestCase(anydbmReadOnlyDBTestCase): shutil.rmtree(config.DATABASE) config.GADFLY_DATABASE = ('test', config.DATABASE) os.makedirs(config.DATABASE + '/files') - db = gadfly.Database(config, 'test') + db = gadfly.Database(config, 'admin') setupSchema(db, 1, gadfly) self.db = gadfly.Database(config) setupSchema(self.db, 0, gadfly) @@ -636,7 +637,7 @@ class sqliteDBTestCase(anydbmDBTestCase): if os.path.exists(config.DATABASE): shutil.rmtree(config.DATABASE) os.makedirs(config.DATABASE + '/files') - self.db = sqlite.Database(config, 'test') + self.db = sqlite.Database(config, 'admin') setupSchema(self.db, 1, sqlite) def testIDGeneration(self): @@ -649,7 +650,7 @@ class sqliteReadOnlyDBTestCase(anydbmReadOnlyDBTestCase): if os.path.exists(config.DATABASE): shutil.rmtree(config.DATABASE) os.makedirs(config.DATABASE + '/files') - db = sqlite.Database(config, 'test') + db = sqlite.Database(config, 'admin') setupSchema(db, 1, sqlite) self.db = sqlite.Database(config) setupSchema(self.db, 0, sqlite) @@ -664,10 +665,8 @@ class metakitDBTestCase(anydbmDBTestCase): if os.path.exists(config.DATABASE): shutil.rmtree(config.DATABASE) os.makedirs(config.DATABASE + '/files') - self.db = metakit.Database(config, 'test') + self.db = metakit.Database(config, 'admin') setupSchema(self.db, 1, metakit) - #self.db2 = metakit.Database(config, 'test') - #setupSchema(self.db2, 0, metakit) def testIDGeneration(self): id1 = self.db.issue.create(title="spam", status='1') @@ -708,12 +707,10 @@ class metakitReadOnlyDBTestCase(anydbmReadOnlyDBTestCase): if os.path.exists(config.DATABASE): shutil.rmtree(config.DATABASE) os.makedirs(config.DATABASE + '/files') - db = metakit.Database(config, 'test') + db = metakit.Database(config, 'admin') setupSchema(db, 1, metakit) self.db = metakit.Database(config) setupSchema(self.db, 0, metakit) -# self.db2 = metakit.Database(config, 'test') -# setupSchema(self.db2, 0, metakit) def suite(): l = [ @@ -722,14 +719,6 @@ def suite(): ] # return unittest.TestSuite(l) - try: - import sqlite - l.append(unittest.makeSuite(sqliteDBTestCase, 'test')) - l.append(unittest.makeSuite(sqliteReadOnlyDBTestCase, 'test')) - except: - print 'sqlite module not found, skipping gadfly DBTestCase' -# return unittest.TestSuite(l) - try: import gadfly l.append(unittest.makeSuite(gadflyDBTestCase, 'test')) @@ -737,6 +726,13 @@ def suite(): except: print 'gadfly module not found, skipping gadfly DBTestCase' + try: + import sqlite + l.append(unittest.makeSuite(sqliteDBTestCase, 'test')) + l.append(unittest.makeSuite(sqliteReadOnlyDBTestCase, 'test')) + except: + print 'sqlite module not found, skipping gadfly DBTestCase' + try: import bsddb l.append(unittest.makeSuite(bsddbDBTestCase, 'test')) diff --git a/test/test_mailgw.py b/test/test_mailgw.py index 650133f..71293a5 100644 --- a/test/test_mailgw.py +++ b/test/test_mailgw.py @@ -8,7 +8,7 @@ # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # -# $Id: test_mailgw.py,v 1.30 2002-09-12 04:21:20 richard Exp $ +# $Id: test_mailgw.py,v 1.31 2002-09-20 05:08:00 richard Exp $ import unittest, cStringIO, tempfile, os, shutil, errno, imp, sys, difflib @@ -79,7 +79,7 @@ class MailgwTestCase(unittest.TestCase, DiffHelper): # check we can load the package self.instance = instance.open(self.dirname) # and open the database - self.db = self.instance.open('sekrit') + self.db = self.instance.open('admin') self.db.user.create(username='Chef', address='chef@bork.bork.bork', roles='User') self.db.user.create(username='richard', address='richard@test', diff --git a/test/test_schema.py b/test/test_schema.py index 9ad53c8..051b07d 100644 --- a/test/test_schema.py +++ b/test/test_schema.py @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: test_schema.py,v 1.11 2002-09-12 04:21:21 richard Exp $ +# $Id: test_schema.py,v 1.12 2002-09-20 05:08:00 richard Exp $ import unittest, os, shutil @@ -43,7 +43,8 @@ class SchemaTestCase(unittest.TestCase): if os.path.exists(config.DATABASE): shutil.rmtree(config.DATABASE) os.makedirs(config.DATABASE + '/files') - self.db = back_anydbm.Database(config, 'test') + self.db = back_anydbm.Database(config, 'admin') + self.db.post_init() self.db.clear() def tearDown(self): diff --git a/test/test_security.py b/test/test_security.py index df55be4..97e759f 100644 --- a/test/test_security.py +++ b/test/test_security.py @@ -18,7 +18,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -# $Id: test_security.py,v 1.4 2002-09-10 00:19:55 richard Exp $ +# $Id: test_security.py,v 1.5 2002-09-20 05:08:00 richard Exp $ import os, unittest, shutil @@ -32,7 +32,7 @@ class PermissionTest(MyTestCase): if os.path.exists(config.DATABASE): shutil.rmtree(config.DATABASE) os.makedirs(config.DATABASE + '/files') - self.db = anydbm.Database(config, 'test') + self.db = anydbm.Database(config, 'admin') setupSchema(self.db, 1, anydbm) def testInterfaceSecurity(self): @@ -66,7 +66,6 @@ class PermissionTest(MyTestCase): self.db.security.getPermission('View', 'issue') def testDBinit(self): - self.db.user.create(username="admin", roles='Admin') self.db.user.create(username="anonymous", roles='User') def testAccessControls(self): -- 2.30.2