263 card1 = self.execute("INSERT Card X: X title 'cool'")[0][0] |
263 card1 = self.execute("INSERT Card X: X title 'cool'")[0][0] |
264 self.execute('SET X owned_by U WHERE X eid %(x)s, U login "iaminusersgrouponly"', {'x': card1}, 'x') |
264 self.execute('SET X owned_by U WHERE X eid %(x)s, U login "iaminusersgrouponly"', {'x': card1}, 'x') |
265 self.commit() |
265 self.commit() |
266 cnx = self.login('iaminusersgrouponly') |
266 cnx = self.login('iaminusersgrouponly') |
267 cu = cnx.cursor() |
267 cu = cnx.cursor() |
268 aff2 = cu.execute("INSERT Affaire X: X sujet 'cool', X in_state S WHERE S name 'pitetre'")[0][0] |
268 aff2 = cu.execute("INSERT Affaire X: X sujet 'cool'")[0][0] |
269 soc1 = cu.execute("INSERT Societe X: X nom 'chouette'")[0][0] |
269 soc1 = cu.execute("INSERT Societe X: X nom 'chouette'")[0][0] |
270 cu.execute("SET A concerne S WHERE A eid %(a)s, S eid %(s)s", {'a': aff2, 's': soc1}, |
270 cu.execute("SET A concerne S WHERE A eid %(a)s, S eid %(s)s", {'a': aff2, 's': soc1}, |
271 ('a', 's')) |
271 ('a', 's')) |
272 cnx.commit() |
272 cnx.commit() |
273 self.assertRaises(Unauthorized, cu.execute, 'Any X WHERE X eid %(x)s', {'x':aff1}, 'x') |
273 self.assertRaises(Unauthorized, cu.execute, 'Any X WHERE X eid %(x)s', {'x':aff1}, 'x') |
345 cnx.commit() |
345 cnx.commit() |
346 cnx.close() |
346 cnx.close() |
347 |
347 |
348 def test_attribute_security_rqlexpr(self): |
348 def test_attribute_security_rqlexpr(self): |
349 # Note.para attribute editable by managers or if the note is in "todo" state |
349 # Note.para attribute editable by managers or if the note is in "todo" state |
350 eid = self.execute("INSERT Note X: X para 'bidule', X in_state S WHERE S name 'done'")[0][0] |
350 note = self.execute("INSERT Note X: X para 'bidule'").get_entity(0, 0) |
351 self.commit() |
351 self.commit() |
352 self.execute('SET X para "truc" WHERE X eid %(x)s', {'x': eid}, 'x') |
352 note.fire_transition('markasdone') |
353 self.commit() |
353 self.execute('SET X para "truc" WHERE X eid %(x)s', {'x': note.eid}, 'x') |
354 cnx = self.login('iaminusersgrouponly') |
354 self.commit() |
355 cu = cnx.cursor() |
355 cnx = self.login('iaminusersgrouponly') |
356 cu.execute("SET X para 'chouette' WHERE X eid %(x)s", {'x': eid}, 'x') |
356 cu = cnx.cursor() |
357 self.assertRaises(Unauthorized, cnx.commit) |
357 cu.execute("SET X para 'chouette' WHERE X eid %(x)s", {'x': note.eid}, 'x') |
358 eid2 = cu.execute("INSERT Note X: X para 'bidule'")[0][0] |
358 self.assertRaises(Unauthorized, cnx.commit) |
359 cnx.commit() |
359 note2 = cu.execute("INSERT Note X: X para 'bidule'").get_entity(0, 0) |
360 cu.execute("SET X in_state S WHERE X eid %(x)s, S name 'done'", {'x': eid2}, 'x') |
360 cnx.commit() |
361 cnx.commit() |
361 note2.fire_transition('markasdone') |
362 self.assertEquals(len(cu.execute('Any X WHERE X in_state S, S name "todo", X eid %(x)s', {'x': eid2}, 'x')), |
362 cnx.commit() |
|
363 self.assertEquals(len(cu.execute('Any X WHERE X in_state S, S name "todo", X eid %(x)s', {'x': note2.eid}, 'x')), |
363 0) |
364 0) |
364 cu.execute("SET X para 'chouette' WHERE X eid %(x)s", {'x': eid2}, 'x') |
365 cu.execute("SET X para 'chouette' WHERE X eid %(x)s", {'x': note2.eid}, 'x') |
365 self.assertRaises(Unauthorized, cnx.commit) |
366 self.assertRaises(Unauthorized, cnx.commit) |
366 cu.execute("SET X in_state S WHERE X eid %(x)s, S name 'todo'", {'x': eid2}, 'x') |
367 note2.fire_transition('redoit') |
367 cnx.commit() |
368 cnx.commit() |
368 cu.execute("SET X para 'chouette' WHERE X eid %(x)s", {'x': eid2}, 'x') |
369 cu.execute("SET X para 'chouette' WHERE X eid %(x)s", {'x': note2.eid}, 'x') |
369 cnx.commit() |
370 cnx.commit() |
370 |
371 |
371 def test_attribute_read_security(self): |
372 def test_attribute_read_security(self): |
372 # anon not allowed to see users'login, but they can see users |
373 # anon not allowed to see users'login, but they can see users |
373 self.repo.schema['CWUser'].set_groups('read', ('guests', 'users', 'managers')) |
374 self.repo.schema['CWUser'].set_groups('read', ('guests', 'users', 'managers')) |
396 # due to security test, affaire has to concerne a societe the user owns |
397 # due to security test, affaire has to concerne a societe the user owns |
397 cu.execute('INSERT Societe X: X nom "ARCTIA"') |
398 cu.execute('INSERT Societe X: X nom "ARCTIA"') |
398 cu.execute('INSERT Affaire X: X ref "ARCT01", X concerne S WHERE S nom "ARCTIA"') |
399 cu.execute('INSERT Affaire X: X ref "ARCT01", X concerne S WHERE S nom "ARCTIA"') |
399 cnx.commit() |
400 cnx.commit() |
400 self.restore_connection() |
401 self.restore_connection() |
401 self.execute('SET X in_state S WHERE X ref "ARCT01", S name "ben non"') |
402 affaire = self.execute('Any X WHERE X ref "ARCT01"').get_entity(0, 0) |
|
403 affaire.fire_transition('abort') |
402 self.commit() |
404 self.commit() |
403 self.assertEquals(len(self.execute('TrInfo X WHERE X wf_info_for A, A ref "ARCT01"')), |
405 self.assertEquals(len(self.execute('TrInfo X WHERE X wf_info_for A, A ref "ARCT01"')), |
404 2) |
406 1) |
405 self.assertEquals(len(self.execute('TrInfo X WHERE X wf_info_for A, A ref "ARCT01",' |
407 self.assertEquals(len(self.execute('TrInfo X WHERE X wf_info_for A, A ref "ARCT01",' |
406 'X owned_by U, U login "admin"')), |
408 'X owned_by U, U login "admin"')), |
407 1) # TrInfo at the above state change |
409 1) # TrInfo at the above state change |
408 self.assertEquals(len(self.execute('TrInfo X WHERE X wf_info_for A, A ref "ARCT01",' |
|
409 'X owned_by U, U login "iaminusersgrouponly"')), |
|
410 1) # TrInfo created at creation time |
|
411 cnx = self.login('iaminusersgrouponly') |
410 cnx = self.login('iaminusersgrouponly') |
412 cu = cnx.cursor() |
411 cu = cnx.cursor() |
413 cu.execute('DELETE Affaire X WHERE X ref "ARCT01"') |
412 cu.execute('DELETE Affaire X WHERE X ref "ARCT01"') |
414 cnx.commit() |
413 cnx.commit() |
415 self.failIf(cu.execute('Affaire X')) |
414 self.failIf(cu.execute('Affaire X')) |
497 # needed to remove rql expr granting update perm to the user |
496 # needed to remove rql expr granting update perm to the user |
498 self.schema['Affaire'].set_rqlexprs('update', ()) |
497 self.schema['Affaire'].set_rqlexprs('update', ()) |
499 self.assertRaises(Unauthorized, |
498 self.assertRaises(Unauthorized, |
500 self.schema['Affaire'].check_perm, session, 'update', eid) |
499 self.schema['Affaire'].check_perm, session, 'update', eid) |
501 cu = cnx.cursor() |
500 cu = cnx.cursor() |
502 cu.execute('SET X in_state S WHERE X ref "ARCT01", S name "ben non"') |
501 self.schema['Affaire'].set_groups('read', ('users',)) |
503 cnx.commit() |
502 try: |
504 # though changing a user state (even logged user) is reserved to managers |
503 aff = cu.execute('Any X WHERE X ref "ARCT01"').get_entity(0, 0) |
505 rql = u"SET X in_state S WHERE X eid %(x)s, S name 'deactivated'" |
504 aff.fire_transition('abort') |
506 # XXX wether it should raise Unauthorized or ValidationError is not clear |
505 cnx.commit() |
507 # the best would probably ValidationError if the transition doesn't exist |
506 # though changing a user state (even logged user) is reserved to managers |
508 # from the current state but Unauthorized if it exists but user can't pass it |
507 user = cnx.user(self.current_session()) |
509 self.assertRaises(ValidationError, cu.execute, rql, {'x': cnx.user(self.session).eid}, 'x') |
508 # XXX wether it should raise Unauthorized or ValidationError is not clear |
|
509 # the best would probably ValidationError if the transition doesn't exist |
|
510 # from the current state but Unauthorized if it exists but user can't pass it |
|
511 self.assertRaises(ValidationError, user.fire_transition, 'deactivate') |
|
512 finally: |
|
513 self.schema['Affaire'].set_groups('read', ('managers',)) |
510 |
514 |
511 def test_trinfo_security(self): |
515 def test_trinfo_security(self): |
512 aff = self.execute('INSERT Affaire X: X ref "ARCT01"').get_entity(0, 0) |
516 aff = self.execute('INSERT Affaire X: X ref "ARCT01"').get_entity(0, 0) |
513 self.commit() |
517 self.commit() |
|
518 aff.fire_transition('abort') |
|
519 self.commit() |
514 # can change tr info comment |
520 # can change tr info comment |
515 self.execute('SET TI comment %(c)s WHERE TI wf_info_for X, X ref "ARCT01"', |
521 self.execute('SET TI comment %(c)s WHERE TI wf_info_for X, X ref "ARCT01"', |
516 {'c': u'creation'}) |
522 {'c': u'bouh!'}) |
517 self.commit() |
523 self.commit() |
518 aff.clear_related_cache('wf_info_for', 'object') |
524 aff.clear_related_cache('wf_info_for', 'object') |
519 self.assertEquals(aff.latest_trinfo().comment, 'creation') |
525 trinfo = aff.latest_trinfo() |
|
526 self.assertEquals(trinfo.comment, 'bouh!') |
520 # but not from_state/to_state |
527 # but not from_state/to_state |
521 self.execute('SET X in_state S WHERE X ref "ARCT01", S name "ben non"') |
|
522 self.commit() |
|
523 aff.clear_related_cache('wf_info_for', role='object') |
528 aff.clear_related_cache('wf_info_for', role='object') |
524 trinfo = aff.latest_trinfo() |
|
525 self.assertRaises(Unauthorized, |
529 self.assertRaises(Unauthorized, |
526 self.execute, 'SET TI from_state S WHERE TI eid %(ti)s, S name "ben non"', |
530 self.execute, 'SET TI from_state S WHERE TI eid %(ti)s, S name "ben non"', |
527 {'ti': trinfo.eid}, 'ti') |
531 {'ti': trinfo.eid}, 'ti') |
528 self.assertRaises(Unauthorized, |
532 self.assertRaises(Unauthorized, |
529 self.execute, 'SET TI to_state S WHERE TI eid %(ti)s, S name "pitetre"', |
533 self.execute, 'SET TI to_state S WHERE TI eid %(ti)s, S name "pitetre"', |