server/test/unittest_security.py
changeset 2773 b2530e3e0afb
parent 2608 21856eda34f6
child 2968 0e3460341023
equal deleted inserted replaced
2767:58c519e5a31f 2773:b2530e3e0afb
     2 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
     2 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
     3 """
     3 """
     4 import sys
     4 import sys
     5 
     5 
     6 from logilab.common.testlib import unittest_main, TestCase
     6 from logilab.common.testlib import unittest_main, TestCase
     7 from cubicweb.devtools.apptest import RepositoryBasedTC
     7 from cubicweb.devtools.testlib import CubicWebTC
     8 
     8 
     9 from cubicweb import Unauthorized, ValidationError
     9 from cubicweb import Unauthorized, ValidationError
    10 from cubicweb.server.querier import check_read_access
    10 from cubicweb.server.querier import check_read_access
    11 
    11 
    12 class BaseSecurityTC(RepositoryBasedTC):
    12 class BaseSecurityTC(CubicWebTC):
    13 
    13 
    14     def setUp(self):
    14     def setUp(self):
    15         RepositoryBasedTC.setUp(self)
    15         CubicWebTC.setUp(self)
    16         self.create_user('iaminusersgrouponly')
    16         self.create_user('iaminusersgrouponly')
    17         self.readoriggroups = self.schema['Personne'].get_groups('read')
    17         self.readoriggroups = self.schema['Personne'].get_groups('read')
    18         self.addoriggroups = self.schema['Personne'].get_groups('add')
    18         self.addoriggroups = self.schema['Personne'].get_groups('add')
    19 
    19 
    20     def tearDown(self):
    20     def tearDown(self):
    21         RepositoryBasedTC.tearDown(self)
    21         CubicWebTC.tearDown(self)
    22         self.schema['Personne'].set_groups('read', self.readoriggroups)
    22         self.schema['Personne'].set_groups('read', self.readoriggroups)
    23         self.schema['Personne'].set_groups('add', self.addoriggroups)
    23         self.schema['Personne'].set_groups('add', self.addoriggroups)
    24 
    24 
    25 
    25 
    26 class LowLevelSecurityFunctionTC(BaseSecurityTC):
    26 class LowLevelSecurityFunctionTC(BaseSecurityTC):
    35         check_read_access(self.schema, self.session.user, rqlst, solution)
    35         check_read_access(self.schema, self.session.user, rqlst, solution)
    36         cnx = self.login('anon')
    36         cnx = self.login('anon')
    37         cu = cnx.cursor()
    37         cu = cnx.cursor()
    38         self.assertRaises(Unauthorized,
    38         self.assertRaises(Unauthorized,
    39                           check_read_access,
    39                           check_read_access,
    40                           self.schema, cnx.user(self.current_session()), rqlst, solution)
    40                           self.schema, cnx.user(self.session), rqlst, solution)
    41         self.assertRaises(Unauthorized, cu.execute, rql)
    41         self.assertRaises(Unauthorized, cu.execute, rql)
    42 
    42 
    43     def test_upassword_not_selectable(self):
    43     def test_upassword_not_selectable(self):
    44         self.assertRaises(Unauthorized,
    44         self.assertRaises(Unauthorized,
    45                           self.execute, 'Any X,P WHERE X is CWUser, X upassword P')
    45                           self.execute, 'Any X,P WHERE X is CWUser, X upassword P')
   163         cnx.commit()
   163         cnx.commit()
   164 
   164 
   165 
   165 
   166     def test_insert_relation_rql_permission(self):
   166     def test_insert_relation_rql_permission(self):
   167         cnx = self.login('iaminusersgrouponly')
   167         cnx = self.login('iaminusersgrouponly')
   168         session = self.current_session()
   168         session = self.session
   169         cu = cnx.cursor(session)
   169         cu = cnx.cursor(session)
   170         cu.execute("SET A concerne S WHERE A is Affaire, S is Societe")
   170         cu.execute("SET A concerne S WHERE A is Affaire, S is Societe")
   171         # should raise Unauthorized since user don't own S
   171         # should raise Unauthorized since user don't own S
   172         # though this won't actually do anything since the selection query won't return anything
   172         # though this won't actually do anything since the selection query won't return anything
   173         cnx.commit()
   173         cnx.commit()
   208         cnx.commit()
   208         cnx.commit()
   209         cu.execute("DELETE A concerne S WHERE S nom 'chouette'")
   209         cu.execute("DELETE A concerne S WHERE S nom 'chouette'")
   210 
   210 
   211 
   211 
   212     def test_user_can_change_its_upassword(self):
   212     def test_user_can_change_its_upassword(self):
   213         ueid = self.create_user('user')
   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'}, 'x')
   218         cnx.commit()
   218         cnx.commit()
   219         cnx.close()
   219         cnx.close()
   220         cnx = self.login('user', 'newpwd')
   220         cnx = self.login('user', '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')
   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'}, 'x')
   228         self.assertRaises(Unauthorized, cnx.commit)
   228         self.assertRaises(Unauthorized, cnx.commit)
   414         cnx.commit()
   414         cnx.commit()
   415         self.failIf(cu.execute('Affaire X'))
   415         self.failIf(cu.execute('Affaire X'))
   416 
   416 
   417     def test_users_and_groups_non_readable_by_guests(self):
   417     def test_users_and_groups_non_readable_by_guests(self):
   418         cnx = self.login('anon')
   418         cnx = self.login('anon')
   419         anon = cnx.user(self.current_session())
   419         anon = cnx.user(self.session)
   420         cu = cnx.cursor()
   420         cu = cnx.cursor()
   421         # anonymous user can only read itself
   421         # anonymous user can only read itself
   422         rset = cu.execute('Any L WHERE X owned_by U, U login L')
   422         rset = cu.execute('Any L WHERE X owned_by U, U login L')
   423         self.assertEquals(rset.rows, [['anon']])
   423         self.assertEquals(rset.rows, [['anon']])
   424         rset = cu.execute('CWUser X')
   424         rset = cu.execute('CWUser X')
   425         self.assertEquals(rset.rows, [[anon.eid]])
   425         self.assertEquals(rset.rows, [[anon.eid]])
   426         # anonymous user can read groups (necessary to check allowed transitions for instance)
   426         # anonymous user can read groups (necessary to check allowed transitions for instance)
   427         self.assert_(cu.execute('CWGroup X'))
   427         self.assert_(cu.execute('CWGroup X'))
   428         # should only be able to read the anonymous user, not another one
   428         # should only be able to read the anonymous user, not another one
   429         origuser = self.session.user
   429         origuser = self.adminsession.user
   430         self.assertRaises(Unauthorized,
   430         self.assertRaises(Unauthorized,
   431                           cu.execute, 'CWUser X WHERE X eid %(x)s', {'x': origuser.eid}, 'x')
   431                           cu.execute, 'CWUser X WHERE X eid %(x)s', {'x': origuser.eid}, 'x')
   432         # nothing selected, nothing updated, no exception raised
   432         # nothing selected, nothing updated, no exception raised
   433         #self.assertRaises(Unauthorized,
   433         #self.assertRaises(Unauthorized,
   434         #                  cu.execute, 'SET X login "toto" WHERE X eid %(x)s',
   434         #                  cu.execute, 'SET X login "toto" WHERE X eid %(x)s',
   460         beid1 = self.execute('INSERT Bookmark B: B path "?vid=manage", B title "manage"')[0][0]
   460         beid1 = self.execute('INSERT Bookmark B: B path "?vid=manage", B title "manage"')[0][0]
   461         beid2 = self.execute('INSERT Bookmark B: B path "?vid=index", B title "index", B bookmarked_by U WHERE U login "anon"')[0][0]
   461         beid2 = self.execute('INSERT Bookmark B: B path "?vid=index", B title "index", B bookmarked_by U WHERE U login "anon"')[0][0]
   462         self.commit()
   462         self.commit()
   463         cnx = self.login('anon')
   463         cnx = self.login('anon')
   464         cu = cnx.cursor()
   464         cu = cnx.cursor()
   465         anoneid = self.current_session().user.eid
   465         anoneid = self.session.user.eid
   466         self.assertEquals(cu.execute('Any T,P ORDERBY lower(T) WHERE B is Bookmark,B title T,B path P,'
   466         self.assertEquals(cu.execute('Any T,P ORDERBY lower(T) WHERE B is Bookmark,B title T,B path P,'
   467                                      'B bookmarked_by U, U eid %s' % anoneid).rows,
   467                                      'B bookmarked_by U, U eid %s' % anoneid).rows,
   468                           [['index', '?vid=index']])
   468                           [['index', '?vid=index']])
   469         self.assertEquals(cu.execute('Any T,P ORDERBY lower(T) WHERE B is Bookmark,B title T,B path P,'
   469         self.assertEquals(cu.execute('Any T,P ORDERBY lower(T) WHERE B is Bookmark,B title T,B path P,'
   470                                      'B bookmarked_by U, U eid %(x)s', {'x': anoneid}).rows,
   470                                      'B bookmarked_by U, U eid %(x)s', {'x': anoneid}).rows,
   489         subject
   489         subject
   490         """
   490         """
   491         eid = self.execute('INSERT Affaire X: X ref "ARCT01"')[0][0]
   491         eid = self.execute('INSERT Affaire X: X ref "ARCT01"')[0][0]
   492         self.commit()
   492         self.commit()
   493         cnx = self.login('iaminusersgrouponly')
   493         cnx = self.login('iaminusersgrouponly')
   494         session = self.current_session()
   494         session = self.session
   495         # needed to avoid check_perm error
   495         # needed to avoid check_perm error
   496         session.set_pool()
   496         session.set_pool()
   497         # needed to remove rql expr granting update perm to the user
   497         # needed to remove rql expr granting update perm to the user
   498         self.schema['Affaire'].set_rqlexprs('update', ())
   498         self.schema['Affaire'].set_rqlexprs('update', ())
   499         self.assertRaises(Unauthorized,
   499         self.assertRaises(Unauthorized,
   504         # though changing a user state (even logged user) is reserved to managers
   504         # though changing a user state (even logged user) is reserved to managers
   505         rql = u"SET X in_state S WHERE X eid %(x)s, S name 'deactivated'"
   505         rql = u"SET X in_state S WHERE X eid %(x)s, S name 'deactivated'"
   506         # XXX wether it should raise Unauthorized or ValidationError is not clear
   506         # XXX wether it should raise Unauthorized or ValidationError is not clear
   507         # the best would probably ValidationError if the transition doesn't exist
   507         # the best would probably ValidationError if the transition doesn't exist
   508         # from the current state but Unauthorized if it exists but user can't pass it
   508         # from the current state but Unauthorized if it exists but user can't pass it
   509         self.assertRaises(ValidationError, cu.execute, rql, {'x': cnx.user(self.current_session()).eid}, 'x')
   509         self.assertRaises(ValidationError, cu.execute, rql, {'x': cnx.user(self.session).eid}, 'x')
   510 
   510 
   511     def test_trinfo_security(self):
   511     def test_trinfo_security(self):
   512         aff = self.execute('INSERT Affaire X: X ref "ARCT01"').get_entity(0, 0)
   512         aff = self.execute('INSERT Affaire X: X ref "ARCT01"').get_entity(0, 0)
   513         self.commit()
   513         self.commit()
   514         # can change tr info comment
   514         # can change tr info comment