|
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 `RQLExpression` 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 defined rights on attributes of an entity (non-final relation), |
|
98 knowing that : |
|
99 |
|
100 - to defines RQL expression, we have to use the class `ERQLExpression` |
|
101 in which X represents the entity the attribute belongs to |
|
102 |
|
103 - the permissions `add` and `delete` are equivalent. Only `add`/`read` |
|
104 are actually taken in consideration. |
|
105 |
|
106 In addition to that the entity type `EPermission` from the standard library |
|
107 allow to build very complex and dynamic security architecture. The schema of |
|
108 this entity type is as follow : :: |
|
109 |
|
110 class EPermission(MetaEntityType): |
|
111 """entity type that may be used to construct some advanced security configuration |
|
112 """ |
|
113 name = String(required=True, indexed=True, internationalizable=True, maxsize=100) |
|
114 require_group = SubjectRelation('EGroup', cardinality='+*', |
|
115 description=_('groups to which the permission is granted')) |
|
116 require_state = SubjectRelation('State', |
|
117 description=_("entity'state in which the permission is applyable")) |
|
118 # can be used on any entity |
|
119 require_permission = ObjectRelation('**', cardinality='*1', composite='subject', |
|
120 description=_("link a permission to the entity. This " |
|
121 "permission should be used in the security " |
|
122 "definition of the entity's type to be useful.")) |
|
123 |
|
124 |
|
125 Example of configuration :: |
|
126 |
|
127 |
|
128 ... |
|
129 |
|
130 class Version(EntityType): |
|
131 """a version is defining the content of a particular project's release""" |
|
132 |
|
133 permissions = {'read': ('managers', 'users', 'guests',), |
|
134 'update': ('managers', 'logilab', 'owners',), |
|
135 'delete': ('managers', ), |
|
136 'add': ('managers', 'logilab', |
|
137 ERQLExpression('X version_of PROJ, U in_group G,' |
|
138 'PROJ require_permission P, P name "add_version",' |
|
139 'P require_group G'),)} |
|
140 |
|
141 ... |
|
142 |
|
143 class version_of(RelationType): |
|
144 """link a version to its project. A version is necessarily linked to one and only one project. |
|
145 """ |
|
146 permissions = {'read': ('managers', 'users', 'guests',), |
|
147 'delete': ('managers', ), |
|
148 'add': ('managers', 'logilab', |
|
149 RRQLExpression('O require_permission P, P name "add_version",' |
|
150 'U in_group G, P require_group G'),) |
|
151 } |
|
152 inlined = True |
|
153 |
|
154 This configuration indicates that an entity `EPermission` named |
|
155 "add_version" can be associated to a project and provides rights to create |
|
156 new versions on this project to specific groups. It is important to notice that : |
|
157 |
|
158 * in such case, we have to protect both the entity type "Version" and the relation |
|
159 associating a version to a project ("version_of") |
|
160 |
|
161 * because of the genricity of the entity type `EPermission`, we have to execute |
|
162 a unification with the groups and/or the states if necessary in the expression |
|
163 ("U in_group G, P require_group G" in the above example) |
|
164 |
|
165 Use of RQL expression for reading rights |
|
166 ```````````````````````````````````````` |
|
167 |
|
168 The principles are the same but with the following restrictions : |
|
169 |
|
170 * we can not use `RRQLExpression` on relation types for reading |
|
171 |
|
172 * special relations "has_<ACTION>_permission" can not be used |
|
173 |
|
174 |
|
175 Note on the use of RQL expression for `add` permission |
|
176 `````````````````````````````````````````````````````` |
|
177 Potentially, the use of an RQL expression to add an entity or a relation |
|
178 can cause problems for the user interface, because if the expression uses |
|
179 the entity or the relation to create, then we are not able to verify the |
|
180 permissions before we actually add the entity (please note that this is |
|
181 not a problem for the RQL server at all, because the permissions checks are |
|
182 done after the creation). In such case, the permission check methods |
|
183 (check_perm, has_perm) can indicate that the user is not allowed to create |
|
184 this entity but can obtain the permission. |
|
185 To compensate this problem, it is usually necessary, for such case, |
|
186 to use an action that reflects the schema permissions but which enables |
|
187 to check properly the permissions so that it would show up if necessary. |
|
188 |