|
1 """functional tests for server'security |
|
2 """ |
|
3 import sys |
|
4 |
|
5 from logilab.common.testlib import unittest_main, TestCase |
|
6 from cubicweb.devtools.apptest import RepositoryBasedTC |
|
7 |
|
8 from cubicweb import Unauthorized, ValidationError |
|
9 from cubicweb.server.querier import check_read_access |
|
10 |
|
11 class BaseSecurityTC(RepositoryBasedTC): |
|
12 |
|
13 def setUp(self): |
|
14 RepositoryBasedTC.setUp(self) |
|
15 self.create_user('iaminusersgrouponly') |
|
16 self.readoriggroups = self.schema['Personne'].get_groups('read') |
|
17 self.addoriggroups = self.schema['Personne'].get_groups('add') |
|
18 |
|
19 def tearDown(self): |
|
20 RepositoryBasedTC.tearDown(self) |
|
21 self.schema['Personne'].set_groups('read', self.readoriggroups) |
|
22 self.schema['Personne'].set_groups('add', self.addoriggroups) |
|
23 |
|
24 |
|
25 class LowLevelSecurityFunctionTC(BaseSecurityTC): |
|
26 |
|
27 def test_check_read_access(self): |
|
28 rql = u'Personne U where U nom "managers"' |
|
29 rqlst = self.repo.querier._rqlhelper.parse(rql).children[0] |
|
30 origgroups = self.schema['Personne'].get_groups('read') |
|
31 self.schema['Personne'].set_groups('read', ('users', 'managers')) |
|
32 self.repo.querier._rqlhelper.compute_solutions(rqlst) |
|
33 solution = rqlst.solutions[0] |
|
34 check_read_access(self.schema, self.session.user, rqlst, solution) |
|
35 cnx = self.login('anon') |
|
36 cu = cnx.cursor() |
|
37 self.assertRaises(Unauthorized, |
|
38 check_read_access, |
|
39 self.schema, cnx.user(self.current_session()), rqlst, solution) |
|
40 self.assertRaises(Unauthorized, cu.execute, rql) |
|
41 |
|
42 def test_upassword_not_selectable(self): |
|
43 self.assertRaises(Unauthorized, |
|
44 self.execute, 'Any X,P WHERE X is EUser, X upassword P') |
|
45 self.rollback() |
|
46 cnx = self.login('iaminusersgrouponly') |
|
47 cu = cnx.cursor() |
|
48 self.assertRaises(Unauthorized, |
|
49 cu.execute, 'Any X,P WHERE X is EUser, X upassword P') |
|
50 |
|
51 |
|
52 class SecurityTC(BaseSecurityTC): |
|
53 |
|
54 def setUp(self): |
|
55 BaseSecurityTC.setUp(self) |
|
56 # implicitly test manager can add some entities |
|
57 self.execute("INSERT Affaire X: X sujet 'cool'") |
|
58 self.execute("INSERT Societe X: X nom 'logilab'") |
|
59 self.execute("INSERT Personne X: X nom 'bidule'") |
|
60 self.execute('INSERT EGroup X: X name "staff"') |
|
61 self.commit() |
|
62 |
|
63 def test_insert_security(self): |
|
64 cnx = self.login('anon') |
|
65 cu = cnx.cursor() |
|
66 cu.execute("INSERT Personne X: X nom 'bidule'") |
|
67 self.assertRaises(Unauthorized, cnx.commit) |
|
68 self.assertEquals(cu.execute('Personne X').rowcount, 1) |
|
69 |
|
70 def test_insert_rql_permission(self): |
|
71 # test user can only add une affaire related to a societe he owns |
|
72 cnx = self.login('iaminusersgrouponly') |
|
73 cu = cnx.cursor() |
|
74 cu.execute("INSERT Affaire X: X sujet 'cool'") |
|
75 self.assertRaises(Unauthorized, cnx.commit) |
|
76 # test nothing has actually been inserted |
|
77 self.restore_connection() |
|
78 self.assertEquals(self.execute('Affaire X').rowcount, 1) |
|
79 cnx = self.login('iaminusersgrouponly') |
|
80 cu = cnx.cursor() |
|
81 cu.execute("INSERT Affaire X: X sujet 'cool'") |
|
82 cu.execute("INSERT Societe X: X nom 'chouette'") |
|
83 cu.execute("SET A concerne S WHERE A sujet 'cool', S nom 'chouette'") |
|
84 cnx.commit() |
|
85 |
|
86 def test_update_security_1(self): |
|
87 cnx = self.login('anon') |
|
88 cu = cnx.cursor() |
|
89 # local security check |
|
90 cu.execute( "SET X nom 'bidulechouette' WHERE X is Personne") |
|
91 self.assertRaises(Unauthorized, cnx.commit) |
|
92 self.restore_connection() |
|
93 self.assertEquals(self.execute('Personne X WHERE X nom "bidulechouette"').rowcount, 0) |
|
94 |
|
95 def test_update_security_2(self): |
|
96 cnx = self.login('anon') |
|
97 cu = cnx.cursor() |
|
98 self.repo.schema['Personne'].set_groups('read', ('users', 'managers')) |
|
99 self.repo.schema['Personne'].set_groups('add', ('guests', 'users', 'managers')) |
|
100 self.assertRaises(Unauthorized, cu.execute, "SET X nom 'bidulechouette' WHERE X is Personne") |
|
101 #self.assertRaises(Unauthorized, cnx.commit) |
|
102 # test nothing has actually been inserted |
|
103 self.restore_connection() |
|
104 self.assertEquals(self.execute('Personne X WHERE X nom "bidulechouette"').rowcount, 0) |
|
105 |
|
106 def test_update_security_3(self): |
|
107 cnx = self.login('iaminusersgrouponly') |
|
108 cu = cnx.cursor() |
|
109 cu.execute("INSERT Personne X: X nom 'biduuule'") |
|
110 cu.execute("INSERT Societe X: X nom 'looogilab'") |
|
111 cu.execute("SET X travaille S WHERE X nom 'biduuule', S nom 'looogilab'") |
|
112 |
|
113 def test_update_rql_permission(self): |
|
114 self.execute("SET A concerne S WHERE A is Affaire, S is Societe") |
|
115 self.commit() |
|
116 # test user can only update une affaire related to a societe he owns |
|
117 cnx = self.login('iaminusersgrouponly') |
|
118 cu = cnx.cursor() |
|
119 cu.execute("SET X sujet 'pascool' WHERE X is Affaire") |
|
120 # this won't actually do anything since the selection query won't return anything |
|
121 cnx.commit() |
|
122 # to actually get Unauthorized exception, try to update an entity we can read |
|
123 cu.execute("SET X nom 'toto' WHERE X is Societe") |
|
124 self.assertRaises(Unauthorized, cnx.commit) |
|
125 cu.execute("INSERT Affaire X: X sujet 'pascool'") |
|
126 cu.execute("INSERT Societe X: X nom 'chouette'") |
|
127 cu.execute("SET A concerne S WHERE A sujet 'pascool', S nom 'chouette'") |
|
128 cu.execute("SET X sujet 'habahsicestcool' WHERE X sujet 'pascool'") |
|
129 cnx.commit() |
|
130 |
|
131 def test_delete_security(self): |
|
132 # FIXME: sample below fails because we don't detect "owner" can't delete |
|
133 # user anyway, and since no user with login == 'bidule' exists, no |
|
134 # exception is raised |
|
135 #user._groups = {'guests':1} |
|
136 #self.assertRaises(Unauthorized, |
|
137 # self.o.execute, user, "DELETE EUser X WHERE X login 'bidule'") |
|
138 # check local security |
|
139 cnx = self.login('iaminusersgrouponly') |
|
140 cu = cnx.cursor() |
|
141 self.assertRaises(Unauthorized, cu.execute, "DELETE EGroup Y WHERE Y name 'staff'") |
|
142 |
|
143 def test_delete_rql_permission(self): |
|
144 self.execute("SET A concerne S WHERE A is Affaire, S is Societe") |
|
145 self.commit() |
|
146 # test user can only dele une affaire related to a societe he owns |
|
147 cnx = self.login('iaminusersgrouponly') |
|
148 cu = cnx.cursor() |
|
149 # this won't actually do anything since the selection query won't return anything |
|
150 cu.execute("DELETE Affaire X") |
|
151 cnx.commit() |
|
152 # to actually get Unauthorized exception, try to delete an entity we can read |
|
153 self.assertRaises(Unauthorized, cu.execute, "DELETE Societe S") |
|
154 cu.execute("INSERT Affaire X: X sujet 'pascool'") |
|
155 cu.execute("INSERT Societe X: X nom 'chouette'") |
|
156 cu.execute("SET A concerne S WHERE A sujet 'pascool', S nom 'chouette'") |
|
157 cnx.commit() |
|
158 ## # this one should fail since it will try to delete two affaires, one authorized |
|
159 ## # and the other not |
|
160 ## self.assertRaises(Unauthorized, cu.execute, "DELETE Affaire X") |
|
161 cu.execute("DELETE Affaire X WHERE X sujet 'pascool'") |
|
162 cnx.commit() |
|
163 |
|
164 |
|
165 def test_insert_relation_rql_permission(self): |
|
166 cnx = self.login('iaminusersgrouponly') |
|
167 session = self.current_session() |
|
168 cu = cnx.cursor(session) |
|
169 cu.execute("SET A concerne S WHERE A is Affaire, S is Societe") |
|
170 # should raise Unauthorized since user don't own S |
|
171 # though this won't actually do anything since the selection query won't return anything |
|
172 cnx.commit() |
|
173 # to actually get Unauthorized exception, try to insert a relation were we can read both entities |
|
174 rset = cu.execute('Personne P') |
|
175 self.assertEquals(len(rset), 1) |
|
176 ent = rset.get_entity(0, 0) |
|
177 session.set_pool() # necessary |
|
178 self.assertRaises(Unauthorized, |
|
179 ent.e_schema.check_perm, session, 'update', ent.eid) |
|
180 self.assertRaises(Unauthorized, |
|
181 cu.execute, "SET P travaille S WHERE P is Personne, S is Societe") |
|
182 # test nothing has actually been inserted: |
|
183 self.assertEquals(cu.execute('Any P,S WHERE P travaille S,P is Personne, S is Societe').rowcount, 0) |
|
184 cu.execute("INSERT Societe X: X nom 'chouette'") |
|
185 cu.execute("SET A concerne S WHERE A is Affaire, S nom 'chouette'") |
|
186 cnx.commit() |
|
187 |
|
188 def test_delete_relation_rql_permission(self): |
|
189 self.execute("SET A concerne S WHERE A is Affaire, S is Societe") |
|
190 self.commit() |
|
191 cnx = self.login('iaminusersgrouponly') |
|
192 cu = cnx.cursor() |
|
193 # this won't actually do anything since the selection query won't return anything |
|
194 cu.execute("DELETE A concerne S") |
|
195 cnx.commit() |
|
196 # to actually get Unauthorized exception, try to delete a relation we can read |
|
197 self.restore_connection() |
|
198 eid = self.execute("INSERT Affaire X: X sujet 'pascool'")[0][0] |
|
199 self.execute('SET X owned_by U WHERE X eid %(x)s, U login "iaminusersgrouponly"', {'x': eid}, 'x') |
|
200 self.execute("SET A concerne S WHERE A sujet 'pascool', S is Societe") |
|
201 self.commit() |
|
202 cnx = self.login('iaminusersgrouponly') |
|
203 cu = cnx.cursor() |
|
204 self.assertRaises(Unauthorized, cu.execute, "DELETE A concerne S") |
|
205 cu.execute("INSERT Societe X: X nom 'chouette'") |
|
206 cu.execute("SET A concerne S WHERE A is Affaire, S nom 'chouette'") |
|
207 cnx.commit() |
|
208 cu.execute("DELETE A concerne S WHERE S nom 'chouette'") |
|
209 |
|
210 |
|
211 def test_user_can_change_its_upassword(self): |
|
212 ueid = self.create_user('user') |
|
213 cnx = self.login('user') |
|
214 cu = cnx.cursor() |
|
215 cu.execute('SET X upassword %(passwd)s WHERE X eid %(x)s', |
|
216 {'x': ueid, 'passwd': 'newpwd'}, 'x') |
|
217 cnx.commit() |
|
218 cnx.close() |
|
219 cnx = self.login('user', 'newpwd') |
|
220 |
|
221 def test_user_cant_change_other_upassword(self): |
|
222 ueid = self.create_user('otheruser') |
|
223 cnx = self.login('iaminusersgrouponly') |
|
224 cu = cnx.cursor() |
|
225 cu.execute('SET X upassword %(passwd)s WHERE X eid %(x)s', |
|
226 {'x': ueid, 'passwd': 'newpwd'}, 'x') |
|
227 self.assertRaises(Unauthorized, cnx.commit) |
|
228 |
|
229 # read security test |
|
230 |
|
231 def test_read_base(self): |
|
232 self.schema['Personne'].set_groups('read', ('users', 'managers')) |
|
233 cnx = self.login('anon') |
|
234 cu = cnx.cursor() |
|
235 self.assertRaises(Unauthorized, |
|
236 cu.execute, 'Personne U where U nom "managers"') |
|
237 |
|
238 def test_read_erqlexpr(self): |
|
239 eid = self.execute("INSERT Affaire X: X sujet 'cool'")[0][0] |
|
240 self.commit() |
|
241 cnx = self.login('iaminusersgrouponly') |
|
242 cu = cnx.cursor() |
|
243 rset = cu.execute('Affaire X') |
|
244 self.assertEquals(rset.rows, []) |
|
245 self.assertRaises(Unauthorized, cu.execute, 'Any X WHERE X eid %(x)s', {'x': eid}, 'x') |
|
246 # cache test |
|
247 self.assertRaises(Unauthorized, cu.execute, 'Any X WHERE X eid %(x)s', {'x': eid}, 'x') |
|
248 aff2 = cu.execute("INSERT Affaire X: X sujet 'cool'")[0][0] |
|
249 soc1 = cu.execute("INSERT Societe X: X nom 'chouette'")[0][0] |
|
250 cu.execute("SET A concerne S WHERE A is Affaire, S is Societe") |
|
251 cnx.commit() |
|
252 rset = cu.execute('Any X WHERE X eid %(x)s', {'x': aff2}, 'x') |
|
253 self.assertEquals(rset.rows, [[aff2]]) |
|
254 |
|
255 def test_read_erqlexpr_has_text1(self): |
|
256 aff1 = self.execute("INSERT Affaire X: X sujet 'cool'")[0][0] |
|
257 card1 = self.execute("INSERT Card X: X title 'cool'")[0][0] |
|
258 self.execute('SET X owned_by U WHERE X eid %(x)s, U login "iaminusersgrouponly"', {'x': card1}, 'x') |
|
259 self.commit() |
|
260 cnx = self.login('iaminusersgrouponly') |
|
261 cu = cnx.cursor() |
|
262 aff2 = cu.execute("INSERT Affaire X: X sujet 'cool', X in_state S WHERE S name 'pitetre'")[0][0] |
|
263 soc1 = cu.execute("INSERT Societe X: X nom 'chouette'")[0][0] |
|
264 cu.execute("SET A concerne S WHERE A eid %(a)s, S eid %(s)s", {'a': aff2, 's': soc1}, |
|
265 ('a', 's')) |
|
266 cnx.commit() |
|
267 self.assertRaises(Unauthorized, cu.execute, 'Any X WHERE X eid %(x)s', {'x':aff1}, 'x') |
|
268 self.failUnless(cu.execute('Any X WHERE X eid %(x)s', {'x':aff2}, 'x')) |
|
269 self.failUnless(cu.execute('Any X WHERE X eid %(x)s', {'x':card1}, 'x')) |
|
270 rset = cu.execute("Any X WHERE X has_text 'cool'") |
|
271 self.assertEquals(sorted(eid for eid, in rset.rows), |
|
272 [card1, aff2]) |
|
273 |
|
274 def test_read_erqlexpr_has_text2(self): |
|
275 self.execute("INSERT Personne X: X nom 'bidule'") |
|
276 self.execute("INSERT Societe X: X nom 'bidule'") |
|
277 self.commit() |
|
278 self.schema['Personne'].set_groups('read', ('managers',)) |
|
279 cnx = self.login('iaminusersgrouponly') |
|
280 cu = cnx.cursor() |
|
281 rset = cu.execute('Any N WHERE N has_text "bidule"') |
|
282 self.assertEquals(len(rset.rows), 1, rset.rows) |
|
283 rset = cu.execute('Any N WITH N BEING (Any N WHERE N has_text "bidule")') |
|
284 self.assertEquals(len(rset.rows), 1, rset.rows) |
|
285 |
|
286 def test_read_erqlexpr_optional_rel(self): |
|
287 self.execute("INSERT Personne X: X nom 'bidule'") |
|
288 self.execute("INSERT Societe X: X nom 'bidule'") |
|
289 self.commit() |
|
290 self.schema['Personne'].set_groups('read', ('managers',)) |
|
291 cnx = self.login('anon') |
|
292 cu = cnx.cursor() |
|
293 rset = cu.execute('Any N,U WHERE N has_text "bidule", N owned_by U?') |
|
294 self.assertEquals(len(rset.rows), 1, rset.rows) |
|
295 |
|
296 def test_read_erqlexpr_aggregat(self): |
|
297 self.execute("INSERT Affaire X: X sujet 'cool'")[0][0] |
|
298 self.commit() |
|
299 cnx = self.login('iaminusersgrouponly') |
|
300 cu = cnx.cursor() |
|
301 rset = cu.execute('Any COUNT(X) WHERE X is Affaire') |
|
302 self.assertEquals(rset.rows, [[0]]) |
|
303 cu = cnx.cursor() |
|
304 aff2 = cu.execute("INSERT Affaire X: X sujet 'cool'")[0][0] |
|
305 soc1 = cu.execute("INSERT Societe X: X nom 'chouette'")[0][0] |
|
306 cu.execute("SET A concerne S WHERE A is Affaire, S is Societe") |
|
307 cnx.commit() |
|
308 rset = cu.execute('Any COUNT(X) WHERE X is Affaire') |
|
309 self.assertEquals(rset.rows, [[1]]) |
|
310 rset = cu.execute('Any ETN, COUNT(X) GROUPBY ETN WHERE X is ET, ET name ETN') |
|
311 values = dict(rset) |
|
312 self.assertEquals(values['Affaire'], 1) |
|
313 self.assertEquals(values['Societe'], 2) |
|
314 rset = cu.execute('Any ETN, COUNT(X) GROUPBY ETN WHERE X is ET, ET name ETN WITH X BEING ((Affaire X) UNION (Societe X))') |
|
315 self.assertEquals(len(rset), 2) |
|
316 values = dict(rset) |
|
317 self.assertEquals(values['Affaire'], 1) |
|
318 self.assertEquals(values['Societe'], 2) |
|
319 |
|
320 |
|
321 def test_attribute_security(self): |
|
322 # only managers should be able to edit the 'test' attribute of Personne entities |
|
323 eid = self.execute("INSERT Personne X: X nom 'bidule', X web 'http://www.debian.org', X test TRUE")[0][0] |
|
324 self.commit() |
|
325 self.execute('SET X test FALSE WHERE X eid %(x)s', {'x': eid}, 'x') |
|
326 self.commit() |
|
327 cnx = self.login('iaminusersgrouponly') |
|
328 cu = cnx.cursor() |
|
329 cu.execute("INSERT Personne X: X nom 'bidule', X web 'http://www.debian.org', X test TRUE") |
|
330 self.assertRaises(Unauthorized, cnx.commit) |
|
331 cu.execute("INSERT Personne X: X nom 'bidule', X web 'http://www.debian.org', X test FALSE") |
|
332 self.assertRaises(Unauthorized, cnx.commit) |
|
333 eid = cu.execute("INSERT Personne X: X nom 'bidule', X web 'http://www.debian.org'")[0][0] |
|
334 cnx.commit() |
|
335 cu.execute('SET X test FALSE WHERE X eid %(x)s', {'x': eid}, 'x') |
|
336 self.assertRaises(Unauthorized, cnx.commit) |
|
337 cu.execute('SET X test TRUE WHERE X eid %(x)s', {'x': eid}, 'x') |
|
338 self.assertRaises(Unauthorized, cnx.commit) |
|
339 cu.execute('SET X web "http://www.logilab.org" WHERE X eid %(x)s', {'x': eid}, 'x') |
|
340 cnx.commit() |
|
341 cnx.close() |
|
342 |
|
343 def test_attribute_security_rqlexpr(self): |
|
344 # Note.para attribute editable by managers or if the note is in "todo" state |
|
345 eid = self.execute("INSERT Note X: X para 'bidule', X in_state S WHERE S name 'done'")[0][0] |
|
346 self.commit() |
|
347 self.execute('SET X para "truc" WHERE X eid %(x)s', {'x': eid}, 'x') |
|
348 self.commit() |
|
349 cnx = self.login('iaminusersgrouponly') |
|
350 cu = cnx.cursor() |
|
351 cu.execute("SET X para 'chouette' WHERE X eid %(x)s", {'x': eid}, 'x') |
|
352 self.assertRaises(Unauthorized, cnx.commit) |
|
353 eid2 = cu.execute("INSERT Note X: X para 'bidule'")[0][0] |
|
354 cnx.commit() |
|
355 cu.execute("SET X in_state S WHERE X eid %(x)s, S name 'done'", {'x': eid2}, 'x') |
|
356 cnx.commit() |
|
357 self.assertEquals(len(cu.execute('Any X WHERE X in_state S, S name "todo", X eid %(x)s', {'x': eid2}, 'x')), |
|
358 0) |
|
359 cu.execute("SET X para 'chouette' WHERE X eid %(x)s", {'x': eid2}, 'x') |
|
360 self.assertRaises(Unauthorized, cnx.commit) |
|
361 cu.execute("SET X in_state S WHERE X eid %(x)s, S name 'todo'", {'x': eid2}, 'x') |
|
362 cnx.commit() |
|
363 cu.execute("SET X para 'chouette' WHERE X eid %(x)s", {'x': eid2}, 'x') |
|
364 cnx.commit() |
|
365 |
|
366 def test_attribute_read_security(self): |
|
367 # anon not allowed to see users'login, but they can see users |
|
368 self.repo.schema['EUser'].set_groups('read', ('guests', 'users', 'managers')) |
|
369 self.repo.schema['login'].set_groups('read', ('users', 'managers')) |
|
370 cnx = self.login('anon') |
|
371 cu = cnx.cursor() |
|
372 rset = cu.execute('EUser X') |
|
373 self.failUnless(rset) |
|
374 x = rset.get_entity(0, 0) |
|
375 self.assertEquals(x.login, None) |
|
376 self.failUnless(x.creation_date) |
|
377 x = rset.get_entity(1, 0) |
|
378 x.complete() |
|
379 self.assertEquals(x.login, None) |
|
380 self.failUnless(x.creation_date) |
|
381 cnx.rollback() |
|
382 |
|
383 |
|
384 class BaseSchemaSecurityTC(BaseSecurityTC): |
|
385 """tests related to the base schema permission configuration""" |
|
386 |
|
387 def test_user_can_delete_object_he_created(self): |
|
388 # even if some other user have changed object'state |
|
389 cnx = self.login('iaminusersgrouponly') |
|
390 cu = cnx.cursor() |
|
391 # due to security test, affaire has to concerne a societe the user owns |
|
392 cu.execute('INSERT Societe X: X nom "ARCTIA"') |
|
393 cu.execute('INSERT Affaire X: X ref "ARCT01", X concerne S WHERE S nom "ARCTIA"') |
|
394 cnx.commit() |
|
395 self.restore_connection() |
|
396 self.execute('SET X in_state S WHERE X ref "ARCT01", S name "ben non"') |
|
397 self.commit() |
|
398 self.assertEquals(len(self.execute('TrInfo X WHERE X wf_info_for A, A ref "ARCT01"')), |
|
399 2) |
|
400 self.assertEquals(len(self.execute('TrInfo X WHERE X wf_info_for A, A ref "ARCT01",' |
|
401 'X owned_by U, U login "admin"')), |
|
402 1) # TrInfo at the above state change |
|
403 self.assertEquals(len(self.execute('TrInfo X WHERE X wf_info_for A, A ref "ARCT01",' |
|
404 'X owned_by U, U login "iaminusersgrouponly"')), |
|
405 1) # TrInfo created at creation time |
|
406 cnx = self.login('iaminusersgrouponly') |
|
407 cu = cnx.cursor() |
|
408 cu.execute('DELETE Affaire X WHERE X ref "ARCT01"') |
|
409 cnx.commit() |
|
410 self.failIf(cu.execute('Affaire X')) |
|
411 |
|
412 def test_users_and_groups_non_readable_by_guests(self): |
|
413 cnx = self.login('anon') |
|
414 anon = cnx.user(self.current_session()) |
|
415 cu = cnx.cursor() |
|
416 # anonymous user can only read itself |
|
417 rset = cu.execute('Any L WHERE X owned_by U, U login L') |
|
418 self.assertEquals(rset.rows, [['anon']]) |
|
419 rset = cu.execute('EUser X') |
|
420 self.assertEquals(rset.rows, [[anon.eid]]) |
|
421 # anonymous user can read groups (necessary to check allowed transitions for instance) |
|
422 self.assert_(cu.execute('EGroup X')) |
|
423 # should only be able to read the anonymous user, not another one |
|
424 origuser = self.session.user |
|
425 self.assertRaises(Unauthorized, |
|
426 cu.execute, 'EUser X WHERE X eid %(x)s', {'x': origuser.eid}, 'x') |
|
427 # nothing selected, nothing updated, no exception raised |
|
428 #self.assertRaises(Unauthorized, |
|
429 # cu.execute, 'SET X login "toto" WHERE X eid %(x)s', |
|
430 # {'x': self.user.eid}) |
|
431 |
|
432 rset = cu.execute('EUser X WHERE X eid %(x)s', {'x': anon.eid}, 'x') |
|
433 self.assertEquals(rset.rows, [[anon.eid]]) |
|
434 # but can't modify it |
|
435 cu.execute('SET X login "toto" WHERE X eid %(x)s', {'x': anon.eid}) |
|
436 self.assertRaises(Unauthorized, cnx.commit) |
|
437 |
|
438 def test_in_group_relation(self): |
|
439 cnx = self.login('iaminusersgrouponly') |
|
440 cu = cnx.cursor() |
|
441 rql = u"DELETE U in_group G WHERE U login 'admin'" |
|
442 self.assertRaises(Unauthorized, cu.execute, rql) |
|
443 rql = u"SET U in_group G WHERE U login 'admin', G name 'users'" |
|
444 self.assertRaises(Unauthorized, cu.execute, rql) |
|
445 |
|
446 def test_owned_by(self): |
|
447 self.execute("INSERT Personne X: X nom 'bidule'") |
|
448 self.commit() |
|
449 cnx = self.login('iaminusersgrouponly') |
|
450 cu = cnx.cursor() |
|
451 rql = u"SET X owned_by U WHERE U login 'iaminusersgrouponly', X is Personne" |
|
452 self.assertRaises(Unauthorized, cu.execute, rql) |
|
453 |
|
454 def test_bookmarked_by_guests_security(self): |
|
455 beid1 = self.execute('INSERT Bookmark B: B path "?vid=manage", B title "manage"')[0][0] |
|
456 beid2 = self.execute('INSERT Bookmark B: B path "?vid=index", B title "index", B bookmarked_by U WHERE U login "anon"')[0][0] |
|
457 self.commit() |
|
458 cnx = self.login('anon') |
|
459 cu = cnx.cursor() |
|
460 anoneid = self.current_session().user.eid |
|
461 self.assertEquals(cu.execute('Any T,P ORDERBY lower(T) WHERE B is Bookmark,B title T,B path P,' |
|
462 'B bookmarked_by U, U eid %s' % anoneid).rows, |
|
463 [['index', '?vid=index']]) |
|
464 self.assertEquals(cu.execute('Any T,P ORDERBY lower(T) WHERE B is Bookmark,B title T,B path P,' |
|
465 'B bookmarked_by U, U eid %(x)s', {'x': anoneid}).rows, |
|
466 [['index', '?vid=index']]) |
|
467 # can read others bookmarks as well |
|
468 self.assertEquals(cu.execute('Any B where B is Bookmark, NOT B bookmarked_by U').rows, |
|
469 [[beid1]]) |
|
470 self.assertRaises(Unauthorized, cu.execute,'DELETE B bookmarked_by U') |
|
471 self.assertRaises(Unauthorized, |
|
472 cu.execute, 'SET B bookmarked_by U WHERE U eid %(x)s, B eid %(b)s', |
|
473 {'x': anoneid, 'b': beid1}, 'x') |
|
474 |
|
475 |
|
476 def test_ambigous_ordered(self): |
|
477 cnx = self.login('anon') |
|
478 cu = cnx.cursor() |
|
479 names = [t for t, in cu.execute('Any N ORDERBY lower(N) WHERE X name N')] |
|
480 self.assertEquals(names, sorted(names, key=lambda x: x.lower())) |
|
481 |
|
482 def test_in_state_without_update_perm(self): |
|
483 """check a user change in_state without having update permission on the |
|
484 subject |
|
485 """ |
|
486 eid = self.execute('INSERT Affaire X: X ref "ARCT01"')[0][0] |
|
487 self.commit() |
|
488 cnx = self.login('iaminusersgrouponly') |
|
489 session = self.current_session() |
|
490 # needed to avoid check_perm error |
|
491 session.set_pool() |
|
492 # needed to remove rql expr granting update perm to the user |
|
493 self.schema['Affaire'].set_rqlexprs('update', ()) |
|
494 self.assertRaises(Unauthorized, |
|
495 self.schema['Affaire'].check_perm, session, 'update', eid) |
|
496 cu = cnx.cursor() |
|
497 cu.execute('SET X in_state S WHERE X ref "ARCT01", S name "abort"') |
|
498 cnx.commit() |
|
499 # though changing a user state (even logged user) is reserved to managers |
|
500 rql = u"SET X in_state S WHERE X eid %(x)s, S name 'deactivated'" |
|
501 # XXX wether it should raise Unauthorized or ValidationError is not clear |
|
502 # the best would probably ValidationError if the transition doesn't exist |
|
503 # from the current state but Unauthorized if it exists but user can't pass it |
|
504 self.assertRaises(ValidationError, cu.execute, rql, {'x': cnx.user(self.current_session()).eid}, 'x') |
|
505 |
|
506 if __name__ == '__main__': |
|
507 unittest_main() |