[hooks/security] Defer entity permission checks to an Operation.

Some of these checks may currently happen twice within the same transaction and be costly.

This should be semantically safe. If people rely on some internal transaction ordering to be allowed early (thus pass) while the condition wouldn't be met at precommit time, their application is broken. It however seems unlikely to happen in the real life (tm).

Closes #2932033

authorAurelien Campeas <aurelien.campeas@logilab.fr>
changesete1369f2dba79
branchdefault
phasepublic
hiddenno
parent revision#77e31ede9b04 [schema] drop very old bw compat (pre 3.5.10)
child revision#46f41c3e1443 remove 3.8 bw compat
files modified by this revision
doc/3.18.rst
hooks/security.py
# HG changeset patch
# User Aurelien Campeas <aurelien.campeas@logilab.fr>
# Date 1380899149 -7200
# Fri Oct 04 17:05:49 2013 +0200
# Node ID e1369f2dba79b3e74762f34219e5c51e1b51a502
# Parent 77e31ede9b048137999a3d5e1be5736801439fb3
[hooks/security] Defer entity permission checks to an Operation.

Some of these checks may currently happen twice within the same
transaction and be costly.

This should be semantically safe. If people rely on some internal
transaction ordering to be allowed early (thus pass) while the
condition wouldn't be met at precommit time, their application is
broken. It however seems unlikely to happen in the real life (tm).

Closes #2932033

diff --git a/doc/3.18.rst b/doc/3.18.rst
@@ -9,10 +9,13 @@
1 
2 
3  API changes
4  -----------
5 
6 +* not really an API change, but the entity permission checks are now
7 +  systematically deferred to an operation, instead of a) trying in a
8 +  hook and b) if it failed, retrying later in an operation
9 
10 
11  Deprecation
12  ---------------------
13 
diff --git a/hooks/security.py b/hooks/security.py
@@ -109,21 +109,15 @@
14  class AfterUpdateEntitySecurityHook(SecurityHook):
15      __regid__ = 'securityafterupdateentity'
16      events = ('after_update_entity',)
17 
18      def __call__(self):
19 -        try:
20 -            # check user has permission right now, if not retry at commit time
21 -            self.entity.cw_check_perm('update')
22 -            check_entity_attributes(self._cw, self.entity)
23 -        except Unauthorized:
24 -            self.entity._cw_clear_local_perm_cache('update')
25 -            # save back editedattrs in case the entity is reedited later in the
26 -            # same transaction, which will lead to cw_edited being
27 -            # overwritten
28 -            CheckEntityPermissionOp.get_instance(self._cw).add_data(
29 -                (self.entity.eid, 'update', self.entity.cw_edited) )
30 +        # save back editedattrs in case the entity is reedited later in the
31 +        # same transaction, which will lead to cw_edited being
32 +        # overwritten
33 +        CheckEntityPermissionOp.get_instance(self._cw).add_data(
34 +            (self.entity.eid, 'update', self.entity.cw_edited) )
35 
36 
37  class BeforeDelEntitySecurityHook(SecurityHook):
38      __regid__ = 'securitybeforedelentity'
39      events = ('before_delete_entity',)