server/test/unittest_security.py
changeset 5174 78438ad513ca
parent 4915 d657b89df9f4
child 5423 e15abfdcce38
equal deleted inserted replaced
5173:73760bbb66bd 5174:78438ad513ca
   195         cu.execute("DELETE A concerne S")
   195         cu.execute("DELETE A concerne S")
   196         cnx.commit()
   196         cnx.commit()
   197         # to actually get Unauthorized exception, try to delete a relation we can read
   197         # to actually get Unauthorized exception, try to delete a relation we can read
   198         self.restore_connection()
   198         self.restore_connection()
   199         eid = self.execute("INSERT Affaire X: X sujet 'pascool'")[0][0]
   199         eid = self.execute("INSERT Affaire X: X sujet 'pascool'")[0][0]
   200         self.execute('SET X owned_by U WHERE X eid %(x)s, U login "iaminusersgrouponly"', {'x': eid}, 'x')
   200         self.execute('SET X owned_by U WHERE X eid %(x)s, U login "iaminusersgrouponly"', {'x': eid})
   201         self.execute("SET A concerne S WHERE A sujet 'pascool', S is Societe")
   201         self.execute("SET A concerne S WHERE A sujet 'pascool', S is Societe")
   202         self.commit()
   202         self.commit()
   203         cnx = self.login('iaminusersgrouponly')
   203         cnx = self.login('iaminusersgrouponly')
   204         cu = cnx.cursor()
   204         cu = cnx.cursor()
   205         self.assertRaises(Unauthorized, cu.execute, "DELETE A concerne S")
   205         self.assertRaises(Unauthorized, cu.execute, "DELETE A concerne S")
   212     def test_user_can_change_its_upassword(self):
   212     def test_user_can_change_its_upassword(self):
   213         ueid = self.create_user('user').eid
   213         ueid = self.create_user('user').eid
   214         cnx = self.login('user')
   214         cnx = self.login('user')
   215         cu = cnx.cursor()
   215         cu = cnx.cursor()
   216         cu.execute('SET X upassword %(passwd)s WHERE X eid %(x)s',
   216         cu.execute('SET X upassword %(passwd)s WHERE X eid %(x)s',
   217                    {'x': ueid, 'passwd': 'newpwd'}, 'x')
   217                    {'x': ueid, 'passwd': 'newpwd'})
   218         cnx.commit()
   218         cnx.commit()
   219         cnx.close()
   219         cnx.close()
   220         cnx = self.login('user', password='newpwd')
   220         cnx = self.login('user', password='newpwd')
   221 
   221 
   222     def test_user_cant_change_other_upassword(self):
   222     def test_user_cant_change_other_upassword(self):
   223         ueid = self.create_user('otheruser').eid
   223         ueid = self.create_user('otheruser').eid
   224         cnx = self.login('iaminusersgrouponly')
   224         cnx = self.login('iaminusersgrouponly')
   225         cu = cnx.cursor()
   225         cu = cnx.cursor()
   226         cu.execute('SET X upassword %(passwd)s WHERE X eid %(x)s',
   226         cu.execute('SET X upassword %(passwd)s WHERE X eid %(x)s',
   227                    {'x': ueid, 'passwd': 'newpwd'}, 'x')
   227                    {'x': ueid, 'passwd': 'newpwd'})
   228         self.assertRaises(Unauthorized, cnx.commit)
   228         self.assertRaises(Unauthorized, cnx.commit)
   229 
   229 
   230     # read security test
   230     # read security test
   231 
   231 
   232     def test_read_base(self):
   232     def test_read_base(self):
   241         self.commit()
   241         self.commit()
   242         cnx = self.login('iaminusersgrouponly')
   242         cnx = self.login('iaminusersgrouponly')
   243         cu = cnx.cursor()
   243         cu = cnx.cursor()
   244         rset = cu.execute('Affaire X')
   244         rset = cu.execute('Affaire X')
   245         self.assertEquals(rset.rows, [])
   245         self.assertEquals(rset.rows, [])
   246         self.assertRaises(Unauthorized, cu.execute, 'Any X WHERE X eid %(x)s', {'x': eid}, 'x')
   246         self.assertRaises(Unauthorized, cu.execute, 'Any X WHERE X eid %(x)s', {'x': eid})
   247         # cache test
   247         # cache test
   248         self.assertRaises(Unauthorized, cu.execute, 'Any X WHERE X eid %(x)s', {'x': eid}, 'x')
   248         self.assertRaises(Unauthorized, cu.execute, 'Any X WHERE X eid %(x)s', {'x': eid})
   249         aff2 = cu.execute("INSERT Affaire X: X sujet 'cool'")[0][0]
   249         aff2 = cu.execute("INSERT Affaire X: X sujet 'cool'")[0][0]
   250         soc1 = cu.execute("INSERT Societe X: X nom 'chouette'")[0][0]
   250         soc1 = cu.execute("INSERT Societe X: X nom 'chouette'")[0][0]
   251         cu.execute("SET A concerne S WHERE A is Affaire, S is Societe")
   251         cu.execute("SET A concerne S WHERE A is Affaire, S is Societe")
   252         cnx.commit()
   252         cnx.commit()
   253         rset = cu.execute('Any X WHERE X eid %(x)s', {'x': aff2}, 'x')
   253         rset = cu.execute('Any X WHERE X eid %(x)s', {'x': aff2})
   254         self.assertEquals(rset.rows, [[aff2]])
   254         self.assertEquals(rset.rows, [[aff2]])
   255         # more cache test w/ NOT eid
   255         # more cache test w/ NOT eid
   256         rset = cu.execute('Affaire X WHERE NOT X eid %(x)s', {'x': eid}, 'x')
   256         rset = cu.execute('Affaire X WHERE NOT X eid %(x)s', {'x': eid})
   257         self.assertEquals(rset.rows, [[aff2]])
   257         self.assertEquals(rset.rows, [[aff2]])
   258         rset = cu.execute('Affaire X WHERE NOT X eid %(x)s', {'x': aff2}, 'x')
   258         rset = cu.execute('Affaire X WHERE NOT X eid %(x)s', {'x': aff2})
   259         self.assertEquals(rset.rows, [])
   259         self.assertEquals(rset.rows, [])
   260         # test can't update an attribute of an entity that can't be readen
   260         # test can't update an attribute of an entity that can't be readen
   261         self.assertRaises(Unauthorized, cu.execute, 'SET X sujet "hacked" WHERE X eid %(x)s', {'x': eid}, 'x')
   261         self.assertRaises(Unauthorized, cu.execute, 'SET X sujet "hacked" WHERE X eid %(x)s', {'x': eid})
   262 
   262 
   263 
   263 
   264     def test_entity_created_in_transaction(self):
   264     def test_entity_created_in_transaction(self):
   265         affschema = self.schema['Affaire']
   265         affschema = self.schema['Affaire']
   266         origperms = affschema.permissions['read']
   266         origperms = affschema.permissions['read']
   268         try:
   268         try:
   269             cnx = self.login('iaminusersgrouponly')
   269             cnx = self.login('iaminusersgrouponly')
   270             cu = cnx.cursor()
   270             cu = cnx.cursor()
   271             aff2 = cu.execute("INSERT Affaire X: X sujet 'cool'")[0][0]
   271             aff2 = cu.execute("INSERT Affaire X: X sujet 'cool'")[0][0]
   272             # entity created in transaction are readable *by eid*
   272             # entity created in transaction are readable *by eid*
   273             self.failUnless(cu.execute('Any X WHERE X eid %(x)s', {'x':aff2}, 'x'))
   273             self.failUnless(cu.execute('Any X WHERE X eid %(x)s', {'x':aff2}))
   274             # XXX would be nice if it worked
   274             # XXX would be nice if it worked
   275             rset = cu.execute("Affaire X WHERE X sujet 'cool'")
   275             rset = cu.execute("Affaire X WHERE X sujet 'cool'")
   276             self.assertEquals(len(rset), 0)
   276             self.assertEquals(len(rset), 0)
   277         finally:
   277         finally:
   278             affschema.set_action_permissions('read', origperms)
   278             affschema.set_action_permissions('read', origperms)
   279             cnx.close()
   279             cnx.close()
   280 
   280 
   281     def test_read_erqlexpr_has_text1(self):
   281     def test_read_erqlexpr_has_text1(self):
   282         aff1 = self.execute("INSERT Affaire X: X sujet 'cool'")[0][0]
   282         aff1 = self.execute("INSERT Affaire X: X sujet 'cool'")[0][0]
   283         card1 = self.execute("INSERT Card X: X title 'cool'")[0][0]
   283         card1 = self.execute("INSERT Card X: X title 'cool'")[0][0]
   284         self.execute('SET X owned_by U WHERE X eid %(x)s, U login "iaminusersgrouponly"', {'x': card1}, 'x')
   284         self.execute('SET X owned_by U WHERE X eid %(x)s, U login "iaminusersgrouponly"', {'x': card1})
   285         self.commit()
   285         self.commit()
   286         cnx = self.login('iaminusersgrouponly')
   286         cnx = self.login('iaminusersgrouponly')
   287         cu = cnx.cursor()
   287         cu = cnx.cursor()
   288         aff2 = cu.execute("INSERT Affaire X: X sujet 'cool'")[0][0]
   288         aff2 = cu.execute("INSERT Affaire X: X sujet 'cool'")[0][0]
   289         soc1 = cu.execute("INSERT Societe X: X nom 'chouette'")[0][0]
   289         soc1 = cu.execute("INSERT Societe X: X nom 'chouette'")[0][0]
   290         cu.execute("SET A concerne S WHERE A eid %(a)s, S eid %(s)s", {'a': aff2, 's': soc1},
   290         cu.execute("SET A concerne S WHERE A eid %(a)s, S eid %(s)s", {'a': aff2, 's': soc1})
   291                    ('a', 's'))
   291         cnx.commit()
   292         cnx.commit()
   292         self.assertRaises(Unauthorized, cu.execute, 'Any X WHERE X eid %(x)s', {'x':aff1})
   293         self.assertRaises(Unauthorized, cu.execute, 'Any X WHERE X eid %(x)s', {'x':aff1}, 'x')
   293         self.failUnless(cu.execute('Any X WHERE X eid %(x)s', {'x':aff2}))
   294         self.failUnless(cu.execute('Any X WHERE X eid %(x)s', {'x':aff2}, 'x'))
   294         self.failUnless(cu.execute('Any X WHERE X eid %(x)s', {'x':card1}))
   295         self.failUnless(cu.execute('Any X WHERE X eid %(x)s', {'x':card1}, 'x'))
       
   296         rset = cu.execute("Any X WHERE X has_text 'cool'")
   295         rset = cu.execute("Any X WHERE X has_text 'cool'")
   297         self.assertEquals(sorted(eid for eid, in rset.rows),
   296         self.assertEquals(sorted(eid for eid, in rset.rows),
   298                           [card1, aff2])
   297                           [card1, aff2])
   299 
   298 
   300     def test_read_erqlexpr_has_text2(self):
   299     def test_read_erqlexpr_has_text2(self):
   345 
   344 
   346     def test_attribute_security(self):
   345     def test_attribute_security(self):
   347         # only managers should be able to edit the 'test' attribute of Personne entities
   346         # only managers should be able to edit the 'test' attribute of Personne entities
   348         eid = self.execute("INSERT Personne X: X nom 'bidule', X web 'http://www.debian.org', X test TRUE")[0][0]
   347         eid = self.execute("INSERT Personne X: X nom 'bidule', X web 'http://www.debian.org', X test TRUE")[0][0]
   349         self.commit()
   348         self.commit()
   350         self.execute('SET X test FALSE WHERE X eid %(x)s', {'x': eid}, 'x')
   349         self.execute('SET X test FALSE WHERE X eid %(x)s', {'x': eid})
   351         self.commit()
   350         self.commit()
   352         cnx = self.login('iaminusersgrouponly')
   351         cnx = self.login('iaminusersgrouponly')
   353         cu = cnx.cursor()
   352         cu = cnx.cursor()
   354         cu.execute("INSERT Personne X: X nom 'bidule', X web 'http://www.debian.org', X test TRUE")
   353         cu.execute("INSERT Personne X: X nom 'bidule', X web 'http://www.debian.org', X test TRUE")
   355         self.assertRaises(Unauthorized, cnx.commit)
   354         self.assertRaises(Unauthorized, cnx.commit)
   356         cu.execute("INSERT Personne X: X nom 'bidule', X web 'http://www.debian.org', X test FALSE")
   355         cu.execute("INSERT Personne X: X nom 'bidule', X web 'http://www.debian.org', X test FALSE")
   357         self.assertRaises(Unauthorized, cnx.commit)
   356         self.assertRaises(Unauthorized, cnx.commit)
   358         eid = cu.execute("INSERT Personne X: X nom 'bidule', X web 'http://www.debian.org'")[0][0]
   357         eid = cu.execute("INSERT Personne X: X nom 'bidule', X web 'http://www.debian.org'")[0][0]
   359         cnx.commit()
   358         cnx.commit()
   360         cu.execute('SET X test FALSE WHERE X eid %(x)s', {'x': eid}, 'x')
   359         cu.execute('SET X test FALSE WHERE X eid %(x)s', {'x': eid})
   361         self.assertRaises(Unauthorized, cnx.commit)
   360         self.assertRaises(Unauthorized, cnx.commit)
   362         cu.execute('SET X test TRUE WHERE X eid %(x)s', {'x': eid}, 'x')
   361         cu.execute('SET X test TRUE WHERE X eid %(x)s', {'x': eid})
   363         self.assertRaises(Unauthorized, cnx.commit)
   362         self.assertRaises(Unauthorized, cnx.commit)
   364         cu.execute('SET X web "http://www.logilab.org" WHERE X eid %(x)s', {'x': eid}, 'x')
   363         cu.execute('SET X web "http://www.logilab.org" WHERE X eid %(x)s', {'x': eid})
   365         cnx.commit()
   364         cnx.commit()
   366         cnx.close()
   365         cnx.close()
   367 
   366 
   368     def test_attribute_security_rqlexpr(self):
   367     def test_attribute_security_rqlexpr(self):
   369         # Note.para attribute editable by managers or if the note is in "todo" state
   368         # Note.para attribute editable by managers or if the note is in "todo" state
   370         note = self.execute("INSERT Note X: X para 'bidule'").get_entity(0, 0)
   369         note = self.execute("INSERT Note X: X para 'bidule'").get_entity(0, 0)
   371         self.commit()
   370         self.commit()
   372         note.fire_transition('markasdone')
   371         note.fire_transition('markasdone')
   373         self.execute('SET X para "truc" WHERE X eid %(x)s', {'x': note.eid}, 'x')
   372         self.execute('SET X para "truc" WHERE X eid %(x)s', {'x': note.eid})
   374         self.commit()
   373         self.commit()
   375         cnx = self.login('iaminusersgrouponly')
   374         cnx = self.login('iaminusersgrouponly')
   376         cu = cnx.cursor()
   375         cu = cnx.cursor()
   377         cu.execute("SET X para 'chouette' WHERE X eid %(x)s", {'x': note.eid}, 'x')
   376         cu.execute("SET X para 'chouette' WHERE X eid %(x)s", {'x': note.eid})
   378         self.assertRaises(Unauthorized, cnx.commit)
   377         self.assertRaises(Unauthorized, cnx.commit)
   379         note2 = cu.execute("INSERT Note X: X para 'bidule'").get_entity(0, 0)
   378         note2 = cu.execute("INSERT Note X: X para 'bidule'").get_entity(0, 0)
   380         cnx.commit()
   379         cnx.commit()
   381         note2.fire_transition('markasdone')
   380         note2.fire_transition('markasdone')
   382         cnx.commit()
   381         cnx.commit()
   383         self.assertEquals(len(cu.execute('Any X WHERE X in_state S, S name "todo", X eid %(x)s', {'x': note2.eid}, 'x')),
   382         self.assertEquals(len(cu.execute('Any X WHERE X in_state S, S name "todo", X eid %(x)s', {'x': note2.eid})),
   384                           0)
   383                           0)
   385         cu.execute("SET X para 'chouette' WHERE X eid %(x)s", {'x': note2.eid}, 'x')
   384         cu.execute("SET X para 'chouette' WHERE X eid %(x)s", {'x': note2.eid})
   386         self.assertRaises(Unauthorized, cnx.commit)
   385         self.assertRaises(Unauthorized, cnx.commit)
   387         note2.fire_transition('redoit')
   386         note2.fire_transition('redoit')
   388         cnx.commit()
   387         cnx.commit()
   389         cu.execute("SET X para 'chouette' WHERE X eid %(x)s", {'x': note2.eid}, 'x')
   388         cu.execute("SET X para 'chouette' WHERE X eid %(x)s", {'x': note2.eid})
   390         cnx.commit()
   389         cnx.commit()
   391 
   390 
   392     def test_attribute_read_security(self):
   391     def test_attribute_read_security(self):
   393         # anon not allowed to see users'login, but they can see users
   392         # anon not allowed to see users'login, but they can see users
   394         self.repo.schema['CWUser'].set_action_permissions('read', ('guests', 'users', 'managers'))
   393         self.repo.schema['CWUser'].set_action_permissions('read', ('guests', 'users', 'managers'))
   445         # anonymous user can read groups (necessary to check allowed transitions for instance)
   444         # anonymous user can read groups (necessary to check allowed transitions for instance)
   446         self.assert_(cu.execute('CWGroup X'))
   445         self.assert_(cu.execute('CWGroup X'))
   447         # should only be able to read the anonymous user, not another one
   446         # should only be able to read the anonymous user, not another one
   448         origuser = self.adminsession.user
   447         origuser = self.adminsession.user
   449         self.assertRaises(Unauthorized,
   448         self.assertRaises(Unauthorized,
   450                           cu.execute, 'CWUser X WHERE X eid %(x)s', {'x': origuser.eid}, 'x')
   449                           cu.execute, 'CWUser X WHERE X eid %(x)s', {'x': origuser.eid})
   451         # nothing selected, nothing updated, no exception raised
   450         # nothing selected, nothing updated, no exception raised
   452         #self.assertRaises(Unauthorized,
   451         #self.assertRaises(Unauthorized,
   453         #                  cu.execute, 'SET X login "toto" WHERE X eid %(x)s',
   452         #                  cu.execute, 'SET X login "toto" WHERE X eid %(x)s',
   454         #                  {'x': self.user.eid})
   453         #                  {'x': self.user.eid})
   455 
   454 
   456         rset = cu.execute('CWUser X WHERE X eid %(x)s', {'x': anon.eid}, 'x')
   455         rset = cu.execute('CWUser X WHERE X eid %(x)s', {'x': anon.eid})
   457         self.assertEquals(rset.rows, [[anon.eid]])
   456         self.assertEquals(rset.rows, [[anon.eid]])
   458         # but can't modify it
   457         # but can't modify it
   459         cu.execute('SET X login "toto" WHERE X eid %(x)s', {'x': anon.eid})
   458         cu.execute('SET X login "toto" WHERE X eid %(x)s', {'x': anon.eid})
   460         self.assertRaises(Unauthorized, cnx.commit)
   459         self.assertRaises(Unauthorized, cnx.commit)
   461 
   460 
   492         self.assertEquals(cu.execute('Any B where B is Bookmark, NOT B bookmarked_by U').rows,
   491         self.assertEquals(cu.execute('Any B where B is Bookmark, NOT B bookmarked_by U').rows,
   493                           [[beid1]])
   492                           [[beid1]])
   494         self.assertRaises(Unauthorized, cu.execute,'DELETE B bookmarked_by U')
   493         self.assertRaises(Unauthorized, cu.execute,'DELETE B bookmarked_by U')
   495         self.assertRaises(Unauthorized,
   494         self.assertRaises(Unauthorized,
   496                           cu.execute, 'SET B bookmarked_by U WHERE U eid %(x)s, B eid %(b)s',
   495                           cu.execute, 'SET B bookmarked_by U WHERE U eid %(x)s, B eid %(b)s',
   497                           {'x': anoneid, 'b': beid1}, 'x')
   496                           {'x': anoneid, 'b': beid1})
   498 
   497 
   499 
   498 
   500     def test_ambigous_ordered(self):
   499     def test_ambigous_ordered(self):
   501         cnx = self.login('anon')
   500         cnx = self.login('anon')
   502         cu = cnx.cursor()
   501         cu = cnx.cursor()
   549         self.assertEquals(trinfo.comment, 'bouh!')
   548         self.assertEquals(trinfo.comment, 'bouh!')
   550         # but not from_state/to_state
   549         # but not from_state/to_state
   551         aff.clear_related_cache('wf_info_for', role='object')
   550         aff.clear_related_cache('wf_info_for', role='object')
   552         self.assertRaises(Unauthorized,
   551         self.assertRaises(Unauthorized,
   553                           self.execute, 'SET TI from_state S WHERE TI eid %(ti)s, S name "ben non"',
   552                           self.execute, 'SET TI from_state S WHERE TI eid %(ti)s, S name "ben non"',
   554                           {'ti': trinfo.eid}, 'ti')
   553                           {'ti': trinfo.eid})
   555         self.assertRaises(Unauthorized,
   554         self.assertRaises(Unauthorized,
   556                           self.execute, 'SET TI to_state S WHERE TI eid %(ti)s, S name "pitetre"',
   555                           self.execute, 'SET TI to_state S WHERE TI eid %(ti)s, S name "pitetre"',
   557                           {'ti': trinfo.eid}, 'ti')
   556                           {'ti': trinfo.eid})
   558 
   557 
   559 if __name__ == '__main__':
   558 if __name__ == '__main__':
   560     unittest_main()
   559     unittest_main()