[security] check attributes: dispatch on the "add" action if entity was just created
authorAurelien Campeas <aurelien.campeas@logilab.fr>
Wed, 17 Dec 2014 10:55:53 +0100
changeset 10114 6f4b4567b77d
parent 10113 e1e8df594d58
child 10116 4e9738f5c798
[security] check attributes: dispatch on the "add" action if entity was just created cw_set on a just-created entity (i.e. created in the same transaction) should behave the same as setting the attribute directly on creation: check the 'add' permissions, not 'update'. Closes #4740310.
hooks/security.py
server/test/data/schema.py
server/test/unittest_security.py
--- a/hooks/security.py	Tue Dec 09 15:18:58 2014 +0100
+++ b/hooks/security.py	Wed Dec 17 10:55:53 2014 +0100
@@ -116,8 +116,9 @@
         # save back editedattrs in case the entity is reedited later in the
         # same transaction, which will lead to cw_edited being
         # overwritten
+        action = 'add' if self._cw.added_in_transaction(self.entity.eid) else 'update'
         CheckEntityPermissionOp.get_instance(self._cw).add_data(
-            (self.entity.eid, 'update', self.entity.cw_edited) )
+            (self.entity.eid, action, self.entity.cw_edited) )
 
 
 class BeforeDelEntitySecurityHook(SecurityHook):
--- a/server/test/data/schema.py	Tue Dec 09 15:18:58 2014 +0100
+++ b/server/test/data/schema.py	Wed Dec 17 10:55:53 2014 +0100
@@ -155,7 +155,11 @@
 
 
 class Old(EntityType):
-    name = String()
+    name = String(__permissions__ = {
+        'read'   : ('managers', 'users', 'guests'),
+        'add'    : ('managers', 'users', 'guests'),
+        'update' : ()
+    })
 
 
 class connait(RelationType):
--- a/server/test/unittest_security.py	Tue Dec 09 15:18:58 2014 +0100
+++ b/server/test/unittest_security.py	Wed Dec 17 10:55:53 2014 +0100
@@ -154,6 +154,15 @@
             cnx.execute("INSERT Societe X: X nom 'looogilab'")
             cnx.execute("SET X travaille S WHERE X nom 'biduuule', S nom 'looogilab'")
 
+    def test_insert_immutable_attribute_update(self):
+        with self.admin_access.repo_cnx() as cnx:
+            cnx.create_entity('Old', name=u'Babar')
+            cnx.commit()
+            # this should be equivalent
+            o = cnx.create_entity('Old')
+            o.cw_set(name=u'Celeste')
+            cnx.commit()
+
     def test_update_rql_permission(self):
         with self.admin_access.repo_cnx() as cnx:
             cnx.execute("SET A concerne S WHERE A is Affaire, S is Societe")