doc/book/en/B0015-define-permissions.en.txt
branchstable
changeset 4744 0772d4e29d52
parent 4743 026a89520184
child 4745 8feb5ec98a54
equal deleted inserted replaced
4743:026a89520184 4744:0772d4e29d52
     1 .. -*- coding: utf-8 -*-
       
     2 
       
     3 The security model
       
     4 ------------------
       
     5 
       
     6 The security model of `cubicWeb` is based on `Access Control List`.
       
     7 The main principles are:
       
     8 
       
     9 * users and groups of users
       
    10 * a user belongs to at least one group of user
       
    11 * permissions (read, update, create, delete)
       
    12 * permissions are assigned to groups (and not to users)
       
    13 
       
    14 For *CubicWeb* in particular:
       
    15 
       
    16 * we associate rights at the enttities/relations schema level
       
    17 * for each entity, we distinguish four kind of permissions: read,
       
    18   add, update and delete
       
    19 * for each relation, we distinguish three king of permissions: read,
       
    20   add and delete (we can not modify a relation)
       
    21 * the basic groups are: Administrators, Users and Guests
       
    22 * by default, users belongs to the group Users
       
    23 * there is a virtual group called `Owners users` to which we
       
    24   can associate only deletion and update permissions
       
    25 * we can not add users to the `Owners users` group, they are
       
    26   implicetely added to it according to the context of the objects
       
    27   they own
       
    28 * the permissions of this group are only be checked on update/deletion
       
    29   actions if all the other groups the user belongs does not provide
       
    30   those permissions
       
    31 
       
    32 
       
    33 Permissions definition
       
    34 ``````````````````````
       
    35 
       
    36 Setting permissions is done with the attribute `permissions` of entities and
       
    37 relation types. It defines a dictionary where the keys are the access types
       
    38 (action), and the values are the authorized groups or expressions.
       
    39 
       
    40 For an entity type, the possible actions are `read`, `add`, `update` and
       
    41 `delete`.
       
    42 
       
    43 For a relation type, the possible actions are `read`, `add`, and `delete`.
       
    44 
       
    45 For each access type, a tuple indicates the name of the authorized groups and/or
       
    46 one or multiple RQL expressions to satisfy to grant access. The access is
       
    47 provided once the user is in the listed groups or one of the RQL condition is
       
    48 satisfied.
       
    49 
       
    50 The standard groups are :
       
    51 
       
    52 * `guests`
       
    53 
       
    54 * `users`
       
    55 
       
    56 * `managers`
       
    57 
       
    58 * `owners` : virtual group corresponding to the entity's owner.
       
    59   This can only be used for the actions `update` and `delete` of an entity
       
    60   type.
       
    61 
       
    62 It is also possible to use specific groups if they are defined in the precreate
       
    63 of the cube (``migration/precreate.py``).
       
    64 
       
    65 
       
    66 Use of RQL expression for writing rights
       
    67 ````````````````````````````````````````
       
    68 
       
    69 It is possible to define RQL expression to provide update permission
       
    70 (`add`, `delete` and `update`) on relation and entity types.
       
    71 
       
    72 RQL expression for entity type permission :
       
    73 
       
    74 * you have to use the class `ERQLExpression`
       
    75 
       
    76 * the used expression corresponds to the WHERE statement of an RQL query
       
    77 
       
    78 * in this expression, the variables X and U are pre-defined references
       
    79   respectively on the current entity (on which the action is verified) and
       
    80   on the user who send the request
       
    81 
       
    82 * it is possible to use, in this expression, a special relation
       
    83   "has_<ACTION>_permission" where the subject is the user and the
       
    84   object is a any variable, meaning that the user needs to have
       
    85   permission to execute the action <ACTION> on the entities related
       
    86   to this variable
       
    87 
       
    88 For RQL expressions on a relation type, the principles are the same except
       
    89 for the following :
       
    90 
       
    91 * you have to use the class `RRQLExpression` in the case of a non-final relation
       
    92 
       
    93 * in the expression, the variables S, O and U are pre-defined references
       
    94   to respectively the subject and the object of the current relation (on
       
    95   which the action is being verified) and the user who executed the query
       
    96 
       
    97 * we can also define rights on attributes of an entity (non-final
       
    98   relation), knowing that :
       
    99 
       
   100   - to define RQL expression, we have to use the class
       
   101     `ERQLExpression` in which X represents the entity the attribute
       
   102     belongs to
       
   103 
       
   104   - the permissions `add` and `delete` are equivalent. Only `add`/`read`
       
   105     are actually taken in consideration.
       
   106 
       
   107 In addition to that the entity type `EPermission` from the standard library
       
   108 allows to build very complex and dynamic security architecture. The schema of
       
   109 this entity type is as follow : ::
       
   110 
       
   111     class CWPermission(EntityType):
       
   112 	"""entity type that may be used to construct some advanced security configuration
       
   113 	"""
       
   114         permissions = META_ETYPE_PERMS
       
   115 
       
   116         name = String(required=True, indexed=True, internationalizable=True, maxsize=100,
       
   117                       description=_('name or identifier of the permission'))
       
   118         label = String(required=True, internationalizable=True, maxsize=100,
       
   119                        description=_('distinct label to distinguate between other permission entity of the same name'))
       
   120         require_group = SubjectRelation('CWGroup',
       
   121                                         description=_('groups to which the permission is granted'))
       
   122 
       
   123     # explicitly add X require_permission CWPermission for each entity that should have
       
   124     # configurable security
       
   125     class require_permission(RelationType):
       
   126         """link a permission to the entity. This permission should be used in the
       
   127         security definition of the entity's type to be useful.
       
   128         """
       
   129         permissions = {
       
   130             'read':   ('managers', 'users', 'guests'),
       
   131             'add':    ('managers',),
       
   132             'delete': ('managers',),
       
   133             }
       
   134 
       
   135     class require_group(RelationType):
       
   136         """used to grant a permission to a group"""
       
   137         permissions = {
       
   138             'read':   ('managers', 'users', 'guests'),
       
   139             'add':    ('managers',),
       
   140             'delete': ('managers',),
       
   141             }
       
   142 
       
   143 
       
   144 Example of configuration ::
       
   145 
       
   146 
       
   147     ...
       
   148 
       
   149     class Version(EntityType):
       
   150 	"""a version is defining the content of a particular project's release"""
       
   151 
       
   152 	permissions = {'read':   ('managers', 'users', 'guests',),
       
   153 		       'update': ('managers', 'logilab', 'owners',),
       
   154 		       'delete': ('managers', ),
       
   155 		       'add':    ('managers', 'logilab',
       
   156 				  ERQLExpression('X version_of PROJ, U in_group G,'
       
   157 						 'PROJ require_permission P, P name "add_version",'
       
   158 						 'P require_group G'),)}
       
   159 
       
   160     ...
       
   161 
       
   162     class version_of(RelationType):
       
   163 	"""link a version to its project. A version is necessarily linked to one and only one project.
       
   164 	"""
       
   165 	permissions = {'read':   ('managers', 'users', 'guests',),
       
   166 		       'delete': ('managers', ),
       
   167 		       'add':    ('managers', 'logilab',
       
   168 				  RRQLExpression('O require_permission P, P name "add_version",'
       
   169 						 'U in_group G, P require_group G'),)
       
   170 		       }
       
   171 	inlined = True
       
   172 
       
   173 This configuration indicates that an entity `CWPermission` named
       
   174 "add_version" can be associated to a project and provides rights to create
       
   175 new versions on this project to specific groups. It is important to notice that :
       
   176 
       
   177 * in such case, we have to protect both the entity type "Version" and the relation
       
   178   associating a version to a project ("version_of")
       
   179 
       
   180 * because of the genericity of the entity type `CWPermission`, we have to execute
       
   181   a unification with the groups and/or the states if necessary in the expression
       
   182   ("U in_group G, P require_group G" in the above example)
       
   183 
       
   184 Use of RQL expression for reading rights
       
   185 ````````````````````````````````````````
       
   186 
       
   187 The principles are the same but with the following restrictions :
       
   188 
       
   189 * we can not use `RRQLExpression` on relation types for reading
       
   190 
       
   191 * special relations "has_<ACTION>_permission" can not be used
       
   192 
       
   193 
       
   194 Note on the use of RQL expression for `add` permission
       
   195 ``````````````````````````````````````````````````````
       
   196 Potentially, the use of an RQL expression to add an entity or a relation
       
   197 can cause problems for the user interface, because if the expression uses
       
   198 the entity or the relation to create, then we are not able to verify the
       
   199 permissions before we actually add the entity (please note that this is
       
   200 not a problem for the RQL server at all, because the permissions checks are
       
   201 done after the creation). In such case, the permission check methods
       
   202 (check_perm, has_perm) can indicate that the user is not allowed to create
       
   203 this entity but can obtain the permission.
       
   204 
       
   205 To compensate this problem, it is usually necessary, for such case,
       
   206 to use an action that reflects the schema permissions but which enables
       
   207 to check properly the permissions so that it would show up if necessary.
       
   208