hooks/security.py
author Rémi Cardona <remi.cardona@logilab.fr>
Tue, 22 Sep 2015 15:24:58 +0200
changeset 10730 874ac29b515d
parent 10548 2b398e58ea73
child 10907 9ae707db5265
permissions -rw-r--r--
[py3k] unicode → six.text_type
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
9981
7099bbd685aa [hooks/security] allow edition of attributes with permissive permissions
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9536
diff changeset
     1
# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4999
diff changeset
     2
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4999
diff changeset
     3
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4999
diff changeset
     4
# This file is part of CubicWeb.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4999
diff changeset
     5
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4999
diff changeset
     6
# CubicWeb is free software: you can redistribute it and/or modify it under the
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4999
diff changeset
     7
# terms of the GNU Lesser General Public License as published by the Free
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4999
diff changeset
     8
# Software Foundation, either version 2.1 of the License, or (at your option)
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4999
diff changeset
     9
# any later version.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4999
diff changeset
    10
#
5424
8ecbcbff9777 replace logilab-common by CubicWeb in disclaimer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5421
diff changeset
    11
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4999
diff changeset
    12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4999
diff changeset
    13
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4999
diff changeset
    14
# details.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4999
diff changeset
    15
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4999
diff changeset
    16
# You should have received a copy of the GNU Lesser General Public License along
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4999
diff changeset
    17
# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    18
"""Security hooks: check permissions to add/delete/update entities according to
9612
24460d4d64bf [hooks/security] let's use a connection, not a session
Julien Cristau <julien.cristau@logilab.fr>
parents: 9543
diff changeset
    19
the connected user
5813
0b250d72fcfa [transaction w/ separated web/repo processes] the dbapi should explicitly specify a transaction id to avoid confusion when web server / repository run in separated processes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5670
diff changeset
    20
"""
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    21
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    22
__docformat__ = "restructuredtext en"
9395
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9254
diff changeset
    23
from warnings import warn
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    24
8190
2a3c1b787688 [vreg] move base registry implementation to logilab.common. Closes #1916014
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6426
diff changeset
    25
from logilab.common.registry import objectify_predicate
2a3c1b787688 [vreg] move base registry implementation to logilab.common. Closes #1916014
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6426
diff changeset
    26
9129
6c4ae3a06619 [hooks/security] Streamline attributes default permission check.
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8239
diff changeset
    27
from yams import buildobjs
6c4ae3a06619 [hooks/security] Streamline attributes default permission check.
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8239
diff changeset
    28
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    29
from cubicweb import Unauthorized
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
    30
from cubicweb.server import BEFORE_ADD_RELATIONS, ON_COMMIT_ADD_RELATIONS, hook
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
    31
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    32
9395
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9254
diff changeset
    33
9612
24460d4d64bf [hooks/security] let's use a connection, not a session
Julien Cristau <julien.cristau@logilab.fr>
parents: 9543
diff changeset
    34
def check_entity_attributes(cnx, entity, action, editedattrs=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    35
    eid = entity.eid
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    36
    eschema = entity.e_schema
9981
7099bbd685aa [hooks/security] allow edition of attributes with permissive permissions
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9536
diff changeset
    37
    if action == 'delete':
7099bbd685aa [hooks/security] allow edition of attributes with permissive permissions
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9536
diff changeset
    38
        eschema.check_perm(session, action, eid=eid)
7099bbd685aa [hooks/security] allow edition of attributes with permissive permissions
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9536
diff changeset
    39
        return
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5449
diff changeset
    40
    # ._cw_skip_security_attributes is there to bypass security for attributes
8238
087bb529035c [spelling] fix dictionnary -> dictionary typo
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6426
diff changeset
    41
    # set by hooks by modifying the entity's dictionary
4577
049d92fc8614 [security] we should save back edited_attributes in case of multiple modification of an entity during the same transaction
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4570
diff changeset
    42
    if editedattrs is None:
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
    43
        editedattrs = entity.cw_edited
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
    44
    dontcheck = editedattrs.skip_security
9981
7099bbd685aa [hooks/security] allow edition of attributes with permissive permissions
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9536
diff changeset
    45
    etypechecked = False
2647
b0a2e779845c enable server side entity caching, 25% speedup on codenaf insertion. ALL CW TESTS OK
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    46
    for attr in editedattrs:
4999
221f76e14eea don't update dontcheck until everything went fine:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4970
diff changeset
    47
        if attr in dontcheck:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    48
            continue
9521
9eb810333b0f [hooks/security, devtools/fill] silence yams 0.38.0 warnings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9129
diff changeset
    49
        rdef = eschema.rdef(attr, takefirst=True)
9129
6c4ae3a06619 [hooks/security] Streamline attributes default permission check.
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8239
diff changeset
    50
        if rdef.final: # non final relation are checked by standard hooks
9395
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9254
diff changeset
    51
            perms = rdef.permissions.get(action)
9129
6c4ae3a06619 [hooks/security] Streamline attributes default permission check.
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8239
diff changeset
    52
            # comparison below works because the default update perm is:
6c4ae3a06619 [hooks/security] Streamline attributes default permission check.
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8239
diff changeset
    53
            #
9395
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9254
diff changeset
    54
            #  ('managers', ERQLExpression(Any X WHERE U has_update_permission X,
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9254
diff changeset
    55
            #                              X eid %(x)s, U eid %(u)s))
9129
6c4ae3a06619 [hooks/security] Streamline attributes default permission check.
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8239
diff changeset
    56
            #
6c4ae3a06619 [hooks/security] Streamline attributes default permission check.
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8239
diff changeset
    57
            # is deserialized in this order (groups first), and ERQLExpression
9395
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9254
diff changeset
    58
            # implements comparison by rql expression.
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9254
diff changeset
    59
            if perms == buildobjs.DEFAULT_ATTRPERMS[action]:
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9254
diff changeset
    60
                # The default rule is to delegate to the entity
9981
7099bbd685aa [hooks/security] allow edition of attributes with permissive permissions
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9536
diff changeset
    61
                # rule. This needs to be checked only once.
7099bbd685aa [hooks/security] allow edition of attributes with permissive permissions
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9536
diff changeset
    62
                if not etypechecked:
7099bbd685aa [hooks/security] allow edition of attributes with permissive permissions
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9536
diff changeset
    63
                    entity.cw_check_perm(action)
7099bbd685aa [hooks/security] allow edition of attributes with permissive permissions
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9536
diff changeset
    64
                    etypechecked = True
9129
6c4ae3a06619 [hooks/security] Streamline attributes default permission check.
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8239
diff changeset
    65
                continue
9395
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9254
diff changeset
    66
            if perms == ():
9412
8aa6c923d6c0 [security] Add comment to check_entity_attributes shortcut
Julien Cristau <julien.cristau@logilab.fr>
parents: 9395
diff changeset
    67
                # That means an immutable attribute; as an optimization, avoid
8aa6c923d6c0 [security] Add comment to check_entity_attributes shortcut
Julien Cristau <julien.cristau@logilab.fr>
parents: 9395
diff changeset
    68
                # going through check_perm.
9395
96dba2efd16d [hooks/security] provide attribute "add" permission
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9254
diff changeset
    69
                raise Unauthorized(action, str(rdef))
9612
24460d4d64bf [hooks/security] let's use a connection, not a session
Julien Cristau <julien.cristau@logilab.fr>
parents: 9543
diff changeset
    70
            rdef.check_perm(cnx, action, eid=eid)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 479
diff changeset
    71
10153
85cbf16fbb57 [security] Test case and fix for an INSERT security hole
Julien Cristau <julien.cristau@logilab.fr>
parents: 9981
diff changeset
    72
    if action == 'add' and not etypechecked:
85cbf16fbb57 [security] Test case and fix for an INSERT security hole
Julien Cristau <julien.cristau@logilab.fr>
parents: 9981
diff changeset
    73
        # think about cnx.create_entity('Foo')
85cbf16fbb57 [security] Test case and fix for an INSERT security hole
Julien Cristau <julien.cristau@logilab.fr>
parents: 9981
diff changeset
    74
        # the standard metadata were inserted by a hook
85cbf16fbb57 [security] Test case and fix for an INSERT security hole
Julien Cristau <julien.cristau@logilab.fr>
parents: 9981
diff changeset
    75
        # with a bypass ... we conceptually need to check
85cbf16fbb57 [security] Test case and fix for an INSERT security hole
Julien Cristau <julien.cristau@logilab.fr>
parents: 9981
diff changeset
    76
        # the eid attribute at *creation* time
85cbf16fbb57 [security] Test case and fix for an INSERT security hole
Julien Cristau <julien.cristau@logilab.fr>
parents: 9981
diff changeset
    77
        entity.cw_check_perm(action)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 479
diff changeset
    78
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 479
diff changeset
    79
6426
541659c39f6a [hook/operation] nicer api to achieve same result as set_operation, as described in #1253630
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6142
diff changeset
    80
class CheckEntityPermissionOp(hook.DataOperationMixIn, hook.LateOperation):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    81
    def precommit_event(self):
9612
24460d4d64bf [hooks/security] let's use a connection, not a session
Julien Cristau <julien.cristau@logilab.fr>
parents: 9543
diff changeset
    82
        cnx = self.cnx
6426
541659c39f6a [hook/operation] nicer api to achieve same result as set_operation, as described in #1253630
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6142
diff changeset
    83
        for eid, action, edited in self.get_data():
9612
24460d4d64bf [hooks/security] let's use a connection, not a session
Julien Cristau <julien.cristau@logilab.fr>
parents: 9543
diff changeset
    84
            entity = cnx.entity_from_eid(eid)
24460d4d64bf [hooks/security] let's use a connection, not a session
Julien Cristau <julien.cristau@logilab.fr>
parents: 9543
diff changeset
    85
            check_entity_attributes(cnx, entity, action, edited)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 479
diff changeset
    86
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 479
diff changeset
    87
6426
541659c39f6a [hook/operation] nicer api to achieve same result as set_operation, as described in #1253630
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6142
diff changeset
    88
class CheckRelationPermissionOp(hook.DataOperationMixIn, hook.LateOperation):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    89
    def precommit_event(self):
9612
24460d4d64bf [hooks/security] let's use a connection, not a session
Julien Cristau <julien.cristau@logilab.fr>
parents: 9543
diff changeset
    90
        cnx = self.cnx
6426
541659c39f6a [hook/operation] nicer api to achieve same result as set_operation, as described in #1253630
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6142
diff changeset
    91
        for action, rschema, eidfrom, eidto in self.get_data():
9612
24460d4d64bf [hooks/security] let's use a connection, not a session
Julien Cristau <julien.cristau@logilab.fr>
parents: 9543
diff changeset
    92
            rdef = rschema.rdef(cnx.entity_metas(eidfrom)['type'],
24460d4d64bf [hooks/security] let's use a connection, not a session
Julien Cristau <julien.cristau@logilab.fr>
parents: 9543
diff changeset
    93
                                cnx.entity_metas(eidto)['type'])
24460d4d64bf [hooks/security] let's use a connection, not a session
Julien Cristau <julien.cristau@logilab.fr>
parents: 9543
diff changeset
    94
            rdef.check_perm(cnx, action, fromeid=eidfrom, toeid=eidto)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 479
diff changeset
    95
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
    96
8190
2a3c1b787688 [vreg] move base registry implementation to logilab.common. Closes #1916014
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6426
diff changeset
    97
@objectify_predicate
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4577
diff changeset
    98
def write_security_enabled(cls, req, **kwargs):
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4577
diff changeset
    99
    if req is None or not req.write_security:
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4577
diff changeset
   100
        return 0
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4577
diff changeset
   101
    return 1
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4577
diff changeset
   102
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   103
class SecurityHook(hook.Hook):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   104
    __abstract__ = True
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   105
    category = 'security'
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4577
diff changeset
   106
    __select__ = hook.Hook.__select__ & write_security_enabled()
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   107
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   108
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   109
class AfterAddEntitySecurityHook(SecurityHook):
3376
f5c69485381f [appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2968
diff changeset
   110
    __regid__ = 'securityafteraddentity'
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   111
    events = ('after_add_entity',)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   112
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   113
    def __call__(self):
6426
541659c39f6a [hook/operation] nicer api to achieve same result as set_operation, as described in #1253630
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6142
diff changeset
   114
        CheckEntityPermissionOp.get_instance(self._cw).add_data(
541659c39f6a [hook/operation] nicer api to achieve same result as set_operation, as described in #1253630
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6142
diff changeset
   115
            (self.entity.eid, 'add', self.entity.cw_edited) )
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   116
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   117
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   118
class AfterUpdateEntitySecurityHook(SecurityHook):
3376
f5c69485381f [appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2968
diff changeset
   119
    __regid__ = 'securityafterupdateentity'
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   120
    events = ('after_update_entity',)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   121
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   122
    def __call__(self):
9254
e1369f2dba79 [hooks/security] Defer entity permission checks to an Operation.
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9129
diff changeset
   123
        # save back editedattrs in case the entity is reedited later in the
e1369f2dba79 [hooks/security] Defer entity permission checks to an Operation.
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9129
diff changeset
   124
        # same transaction, which will lead to cw_edited being
e1369f2dba79 [hooks/security] Defer entity permission checks to an Operation.
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9129
diff changeset
   125
        # overwritten
10114
6f4b4567b77d [security] check attributes: dispatch on the "add" action if entity was just created
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9984
diff changeset
   126
        action = 'add' if self._cw.added_in_transaction(self.entity.eid) else 'update'
9254
e1369f2dba79 [hooks/security] Defer entity permission checks to an Operation.
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9129
diff changeset
   127
        CheckEntityPermissionOp.get_instance(self._cw).add_data(
10114
6f4b4567b77d [security] check attributes: dispatch on the "add" action if entity was just created
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9984
diff changeset
   128
            (self.entity.eid, action, self.entity.cw_edited) )
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   129
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   130
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   131
class BeforeDelEntitySecurityHook(SecurityHook):
3376
f5c69485381f [appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2968
diff changeset
   132
    __regid__ = 'securitybeforedelentity'
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   133
    events = ('before_delete_entity',)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   134
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   135
    def __call__(self):
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5449
diff changeset
   136
        self.entity.cw_check_perm('delete')
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   137
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 479
diff changeset
   138
10388
90fcddcce166 when some inlined relation is set using cw_edited, its security shouldn't be checked.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10156
diff changeset
   139
def skip_inlined_relation_security(cnx, rschema, eid):
90fcddcce166 when some inlined relation is set using cw_edited, its security shouldn't be checked.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10156
diff changeset
   140
    """return True if security for the given inlined relation should be skipped,
90fcddcce166 when some inlined relation is set using cw_edited, its security shouldn't be checked.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10156
diff changeset
   141
    in case where the relation has been set through modification of
90fcddcce166 when some inlined relation is set using cw_edited, its security shouldn't be checked.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10156
diff changeset
   142
    `entity.cw_edited` in a hook
90fcddcce166 when some inlined relation is set using cw_edited, its security shouldn't be checked.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10156
diff changeset
   143
    """
90fcddcce166 when some inlined relation is set using cw_edited, its security shouldn't be checked.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10156
diff changeset
   144
    assert rschema.inlined
90fcddcce166 when some inlined relation is set using cw_edited, its security shouldn't be checked.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10156
diff changeset
   145
    try:
10547
a05a698a12af [hook] don't open-code Connection.entity_cache
Julien Cristau <julien.cristau@logilab.fr>
parents: 10388
diff changeset
   146
        entity = cnx.entity_cache(eid)
10388
90fcddcce166 when some inlined relation is set using cw_edited, its security shouldn't be checked.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10156
diff changeset
   147
    except KeyError:
90fcddcce166 when some inlined relation is set using cw_edited, its security shouldn't be checked.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10156
diff changeset
   148
        return False
10548
2b398e58ea73 [hook] remove assumption about entity cache vs cw_edited
Julien Cristau <julien.cristau@logilab.fr>
parents: 10547
diff changeset
   149
    edited = getattr(entity, 'cw_edited', None)
2b398e58ea73 [hook] remove assumption about entity cache vs cw_edited
Julien Cristau <julien.cristau@logilab.fr>
parents: 10547
diff changeset
   150
    if edited is None:
2b398e58ea73 [hook] remove assumption about entity cache vs cw_edited
Julien Cristau <julien.cristau@logilab.fr>
parents: 10547
diff changeset
   151
        return False
2b398e58ea73 [hook] remove assumption about entity cache vs cw_edited
Julien Cristau <julien.cristau@logilab.fr>
parents: 10547
diff changeset
   152
    return rschema.type in edited.skip_security
10388
90fcddcce166 when some inlined relation is set using cw_edited, its security shouldn't be checked.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10156
diff changeset
   153
90fcddcce166 when some inlined relation is set using cw_edited, its security shouldn't be checked.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10156
diff changeset
   154
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   155
class BeforeAddRelationSecurityHook(SecurityHook):
3376
f5c69485381f [appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2968
diff changeset
   156
    __regid__ = 'securitybeforeaddrelation'
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   157
    events = ('before_add_relation',)
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   158
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   159
    def __call__(self):
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   160
        if self.rtype in BEFORE_ADD_RELATIONS:
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920 2895
diff changeset
   161
            nocheck = self._cw.transaction_data.get('skip-security', ())
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920 2895
diff changeset
   162
            if (self.eidfrom, self.rtype, self.eidto) in nocheck:
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920 2895
diff changeset
   163
                return
2847
c2ee28f4d4b1 use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   164
            rschema = self._cw.repo.schema[self.rtype]
10388
90fcddcce166 when some inlined relation is set using cw_edited, its security shouldn't be checked.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10156
diff changeset
   165
            if rschema.inlined and skip_inlined_relation_security(
90fcddcce166 when some inlined relation is set using cw_edited, its security shouldn't be checked.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10156
diff changeset
   166
                    self._cw, rschema, self.eidfrom):
90fcddcce166 when some inlined relation is set using cw_edited, its security shouldn't be checked.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10156
diff changeset
   167
                return
9469
032825bbacab [multi-sources-removal] Drop entities.source column
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9395
diff changeset
   168
            rdef = rschema.rdef(self._cw.entity_metas(self.eidfrom)['type'],
032825bbacab [multi-sources-removal] Drop entities.source column
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9395
diff changeset
   169
                                self._cw.entity_metas(self.eidto)['type'])
4190
742e3eb16f81 fix bad merge
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4048
diff changeset
   170
            rdef.check_perm(self._cw, 'add', fromeid=self.eidfrom, toeid=self.eidto)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   171
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   172
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   173
class AfterAddRelationSecurityHook(SecurityHook):
3376
f5c69485381f [appobjects] use __regid__ instead of __id__, more explicit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2968
diff changeset
   174
    __regid__ = 'securityafteraddrelation'
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   175
    events = ('after_add_relation',)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   176
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   177
    def __call__(self):
10388
90fcddcce166 when some inlined relation is set using cw_edited, its security shouldn't be checked.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10156
diff changeset
   178
        if self.rtype not in BEFORE_ADD_RELATIONS:
2968
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920 2895
diff changeset
   179
            nocheck = self._cw.transaction_data.get('skip-security', ())
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920 2895
diff changeset
   180
            if (self.eidfrom, self.rtype, self.eidto) in nocheck:
0e3460341023 somewhat painful backport of 3.5 branch, should mostly be ok
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920 2895
diff changeset
   181
                return
2847
c2ee28f4d4b1 use ._cw instead of .cw_req
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2835
diff changeset
   182
            rschema = self._cw.repo.schema[self.rtype]
10388
90fcddcce166 when some inlined relation is set using cw_edited, its security shouldn't be checked.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10156
diff changeset
   183
            if rschema.inlined and skip_inlined_relation_security(
90fcddcce166 when some inlined relation is set using cw_edited, its security shouldn't be checked.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10156
diff changeset
   184
                    self._cw, rschema, self.eidfrom):
90fcddcce166 when some inlined relation is set using cw_edited, its security shouldn't be checked.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10156
diff changeset
   185
                return
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   186
            if self.rtype in ON_COMMIT_ADD_RELATIONS:
6426
541659c39f6a [hook/operation] nicer api to achieve same result as set_operation, as described in #1253630
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6142
diff changeset
   187
                CheckRelationPermissionOp.get_instance(self._cw).add_data(
541659c39f6a [hook/operation] nicer api to achieve same result as set_operation, as described in #1253630
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6142
diff changeset
   188
                    ('add', rschema, self.eidfrom, self.eidto) )
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   189
            else:
9469
032825bbacab [multi-sources-removal] Drop entities.source column
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9395
diff changeset
   190
                rdef = rschema.rdef(self._cw.entity_metas(self.eidfrom)['type'],
032825bbacab [multi-sources-removal] Drop entities.source column
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9395
diff changeset
   191
                                    self._cw.entity_metas(self.eidto)['type'])
4003
b9436fe77c9e fix bad merge
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 3890
diff changeset
   192
                rdef.check_perm(self._cw, 'add', fromeid=self.eidfrom, toeid=self.eidto)
2835
04034421b072 [hooks] major refactoring:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   193
4048
12c4f7e2bed6 had been involontarly dropped
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4003
diff changeset
   194
12c4f7e2bed6 had been involontarly dropped
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4003
diff changeset
   195
class BeforeDeleteRelationSecurityHook(SecurityHook):
12c4f7e2bed6 had been involontarly dropped
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4003
diff changeset
   196
    __regid__ = 'securitybeforedelrelation'
12c4f7e2bed6 had been involontarly dropped
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4003
diff changeset
   197
    events = ('before_delete_relation',)
12c4f7e2bed6 had been involontarly dropped
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4003
diff changeset
   198
12c4f7e2bed6 had been involontarly dropped
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4003
diff changeset
   199
    def __call__(self):
12c4f7e2bed6 had been involontarly dropped
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4003
diff changeset
   200
        nocheck = self._cw.transaction_data.get('skip-security', ())
12c4f7e2bed6 had been involontarly dropped
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4003
diff changeset
   201
        if (self.eidfrom, self.rtype, self.eidto) in nocheck:
12c4f7e2bed6 had been involontarly dropped
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4003
diff changeset
   202
            return
12c4f7e2bed6 had been involontarly dropped
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4003
diff changeset
   203
        rschema = self._cw.repo.schema[self.rtype]
10388
90fcddcce166 when some inlined relation is set using cw_edited, its security shouldn't be checked.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10156
diff changeset
   204
        if rschema.inlined and skip_inlined_relation_security(
90fcddcce166 when some inlined relation is set using cw_edited, its security shouldn't be checked.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10156
diff changeset
   205
                self._cw, rschema, self.eidfrom):
90fcddcce166 when some inlined relation is set using cw_edited, its security shouldn't be checked.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10156
diff changeset
   206
            return
9469
032825bbacab [multi-sources-removal] Drop entities.source column
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9395
diff changeset
   207
        rdef = rschema.rdef(self._cw.entity_metas(self.eidfrom)['type'],
032825bbacab [multi-sources-removal] Drop entities.source column
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9395
diff changeset
   208
                            self._cw.entity_metas(self.eidto)['type'])
4190
742e3eb16f81 fix bad merge
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4048
diff changeset
   209
        rdef.check_perm(self._cw, 'delete', fromeid=self.eidfrom, toeid=self.eidto)
4048
12c4f7e2bed6 had been involontarly dropped
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4003
diff changeset
   210