1 #
2 # Copyright (C) 2007 Stefan Seefeld
3 # All rights reserved.
4 # For license terms see the file COPYING.txt.
5 #
7 import unittest, os, shutil, errno, sys, difflib, cgi, re
9 from roundup.cgi.exceptions import *
10 from roundup import init, instance, password, hyperdb, date
11 from roundup.xmlrpc import RoundupInstance
12 from roundup.backends import list_backends
14 import db_test_base
16 NEEDS_INSTANCE = 1
18 class TestCase(unittest.TestCase):
20 backend = None
22 def setUp(self):
23 self.dirname = '_test_xmlrpc'
24 # set up and open a tracker
25 self.instance = db_test_base.setupTracker(self.dirname, self.backend)
27 # open the database
28 self.db = self.instance.open('admin')
29 self.joeid = 'user' + self.db.user.create(username='joe',
30 password=password.Password('random'), address='random@home.org',
31 realname='Joe Random', roles='User')
33 self.db.commit()
34 self.db.close()
35 self.db = self.instance.open('joe')
36 self.server = RoundupInstance(self.db, self.instance.actions, None)
38 def tearDown(self):
39 self.db.close()
40 try:
41 shutil.rmtree(self.dirname)
42 except OSError, error:
43 if error.errno not in (errno.ENOENT, errno.ESRCH): raise
45 def testAccess(self):
46 # Retrieve all three users.
47 results = self.server.list('user', 'id')
48 self.assertEqual(len(results), 3)
50 # Obtain data for 'joe'.
51 results = self.server.display(self.joeid)
52 self.assertEqual(results['username'], 'joe')
53 self.assertEqual(results['realname'], 'Joe Random')
55 def testChange(self):
56 # Reset joe's 'realname'.
57 results = self.server.set(self.joeid, 'realname=Joe Doe')
58 results = self.server.display(self.joeid, 'realname')
59 self.assertEqual(results['realname'], 'Joe Doe')
61 # check we can't change admin's details
62 self.assertRaises(Unauthorised, self.server.set, 'user1', 'realname=Joe Doe')
64 def testCreate(self):
65 results = self.server.create('issue', 'title=foo')
66 issueid = 'issue' + results
67 results = self.server.display(issueid, 'title')
68 self.assertEqual(results['title'], 'foo')
70 def testFileCreate(self):
71 results = self.server.create('file', 'content=hello\r\nthere')
72 fileid = 'file' + results
73 results = self.server.display(fileid, 'content')
74 self.assertEqual(results['content'], 'hello\r\nthere')
76 def testAction(self):
77 # As this action requires special previledges, we temporarily switch
78 # to 'admin'
79 self.db.setCurrentUser('admin')
80 users_before = self.server.list('user')
81 try:
82 tmp = 'user' + self.db.user.create(username='tmp')
83 self.server.action('retire', tmp)
84 finally:
85 self.db.setCurrentUser('joe')
86 users_after = self.server.list('user')
87 self.assertEqual(users_before, users_after)
89 def testAuthDeniedEdit(self):
90 # Wrong permissions (caught by roundup security module).
91 self.assertRaises(Unauthorised, self.server.set,
92 'user1', 'realname=someone')
94 def testAuthDeniedCreate(self):
95 self.assertRaises(Unauthorised, self.server.create,
96 'user', {'username': 'blah'})
98 def testAuthAllowedEdit(self):
99 self.db.setCurrentUser('admin')
100 try:
101 try:
102 self.server.set('user2', 'realname=someone')
103 except Unauthorised, err:
104 self.fail('raised %s'%err)
105 finally:
106 self.db.setCurrentUser('joe')
108 def testAuthAllowedCreate(self):
109 self.db.setCurrentUser('admin')
110 try:
111 try:
112 self.server.create('user', 'username=blah')
113 except Unauthorised, err:
114 self.fail('raised %s'%err)
115 finally:
116 self.db.setCurrentUser('joe')
118 def testAuthFilter(self):
119 # this checks if we properly check for search permissions
120 self.db.security.permissions = {}
121 self.db.security.addRole(name='User')
122 self.db.security.addRole(name='Project')
123 self.db.security.addPermissionToRole('User', 'Web Access')
124 self.db.security.addPermissionToRole('Project', 'Web Access')
125 # Allow viewing keyword
126 p = self.db.security.addPermission(name='View', klass='keyword')
127 self.db.security.addPermissionToRole('User', p)
128 # Allow viewing interesting things (but not keyword) on issue
129 # But users might only view issues where they are on nosy
130 # (so in the real world the check method would be better)
131 p = self.db.security.addPermission(name='View', klass='issue',
132 properties=("title", "status"), check=lambda x,y,z: True)
133 self.db.security.addPermissionToRole('User', p)
134 # Allow role "Project" access to whole issue
135 p = self.db.security.addPermission(name='View', klass='issue')
136 self.db.security.addPermissionToRole('Project', p)
137 # Allow all access to status:
138 p = self.db.security.addPermission(name='View', klass='status')
139 self.db.security.addPermissionToRole('User', p)
140 self.db.security.addPermissionToRole('Project', p)
142 keyword = self.db.keyword
143 status = self.db.status
144 issue = self.db.issue
146 d1 = keyword.create(name='d1')
147 d2 = keyword.create(name='d2')
148 open = status.create(name='open')
149 closed = status.create(name='closed')
150 issue.create(title='i1', status=open, keyword=[d2])
151 issue.create(title='i2', status=open, keyword=[d1])
152 issue.create(title='i2', status=closed, keyword=[d1])
154 chef = self.db.user.create(username = 'chef', roles='User, Project')
155 joe = self.db.user.lookup('joe')
157 # Conditionally allow view of whole issue (check is False here,
158 # this might check for keyword owner in the real world)
159 p = self.db.security.addPermission(name='View', klass='issue',
160 check=lambda x,y,z: False)
161 self.db.security.addPermissionToRole('User', p)
162 # Allow user to search for issue.status
163 p = self.db.security.addPermission(name='Search', klass='issue',
164 properties=("status",))
165 self.db.security.addPermissionToRole('User', p)
167 keyw = {'keyword':self.db.keyword.lookup('d1')}
168 stat = {'status':self.db.status.lookup('open')}
169 keygroup = keysort = [('+', 'keyword')]
170 self.db.commit()
172 # Filter on keyword ignored for role 'User':
173 r = self.server.filter('issue', None, keyw)
174 self.assertEqual(r, ['1', '2', '3'])
175 # Filter on status works for all:
176 r = self.server.filter('issue', None, stat)
177 self.assertEqual(r, ['1', '2'])
178 # Sorting and grouping for class User fails:
179 r = self.server.filter('issue', None, {}, sort=keysort)
180 self.assertEqual(r, ['1', '2', '3'])
181 r = self.server.filter('issue', None, {}, group=keygroup)
182 self.assertEqual(r, ['1', '2', '3'])
184 self.db.close()
185 self.db = self.instance.open('chef')
186 self.server = RoundupInstance(self.db, self.instance.actions, None)
188 # Filter on keyword works for role 'Project':
189 r = self.server.filter('issue', None, keyw)
190 self.assertEqual(r, ['2', '3'])
191 # Filter on status works for all:
192 r = self.server.filter('issue', None, stat)
193 self.assertEqual(r, ['1', '2'])
194 # Sorting and grouping for class Project works:
195 r = self.server.filter('issue', None, {}, sort=keysort)
196 self.assertEqual(r, ['2', '3', '1'])
197 r = self.server.filter('issue', None, {}, group=keygroup)
198 self.assertEqual(r, ['2', '3', '1'])
200 def test_suite():
201 suite = unittest.TestSuite()
202 for l in list_backends():
203 dct = dict(backend = l)
204 subcls = type(TestCase)('TestCase_%s'%l, (TestCase,), dct)
205 suite.addTest(unittest.makeSuite(subcls))
206 return suite
208 if __name__ == '__main__':
209 runner = unittest.TextTestRunner()
210 unittest.main(testRunner=runner)