doc/book/en/development/datamodel/definition.rst
changeset 4459 f628abfb3a6c
parent 4449 0411dca43e05
parent 4452 5d6dec2c4650
child 4464 437cc57f7474
equal deleted inserted replaced
4458:6151849f41e0 4459:f628abfb3a6c
     1 .. -*- coding: utf-8 -*-
     1  .. -*- coding: utf-8 -*-
     2 
     2 
     3 Yams *schema*
     3 Yams *schema*
     4 -------------
     4 -------------
     5 
     5 
     6 The **schema** is the core piece of a *CubicWeb* instance as it defines
     6 The **schema** is the core piece of a *CubicWeb* instance as it defines
   224 For *CubicWeb* in particular:
   224 For *CubicWeb* in particular:
   225 
   225 
   226 * we associate rights at the enttities/relations schema level
   226 * we associate rights at the enttities/relations schema level
   227 * for each entity, we distinguish four kind of permissions: read,
   227 * for each entity, we distinguish four kind of permissions: read,
   228   add, update and delete
   228   add, update and delete
   229 * for each relation, we distinguish three king of permissions: read,
   229 * for each relation, we distinguish three kinds of permissions: read,
   230   add and delete (we can not modify a relation)
   230   add and delete (we can not modify a relation)
   231 * the basic groups are: Administrators, Users and Guests
   231 * the basic groups are: Administrators, Users and Guests
   232 * by default, users belongs to the group Users
   232 * by default, users belong to the group Users
   233 * there is a virtual group called `Owners users` to which we
   233 * there is a virtual group called `Owners` to which we
   234   can associate only deletion and update permissions
   234   can associate only deletion and update permissions
   235 * we can not add users to the `Owners users` group, they are
   235 * we can not add users to the `Owners` group, they are
   236   implicetely added to it according to the context of the objects
   236   implicitly added to it according to the context of the objects
   237   they own
   237   they own
   238 * the permissions of this group are only be checked on update/deletion
   238 * the permissions of this group are only checked on update/deletion
   239   actions if all the other groups the user belongs does not provide
   239   actions if all the other groups the user belongs to does not provide
   240   those permissions
   240   those permissions
   241 
   241 
   242 Setting permissions is done with the attribute `__permissions__` of entities and
   242 Setting permissions is done with the attribute `__permissions__` of entities and
   243 relation types. It defines a dictionary where the keys are the access types
   243 relation types. It defines a dictionary where the keys are the access types
   244 (action), and the values are the authorized groups or expressions.
   244 (action), and the values are the authorized groups or expressions.
   248 
   248 
   249 For a relation type, the possible actions are `read`, `add`, and `delete`.
   249 For a relation type, the possible actions are `read`, `add`, and `delete`.
   250 
   250 
   251 For each access type, a tuple indicates the name of the authorized groups and/or
   251 For each access type, a tuple indicates the name of the authorized groups and/or
   252 one or multiple RQL expressions to satisfy to grant access. The access is
   252 one or multiple RQL expressions to satisfy to grant access. The access is
   253 provided once the user is in the listed groups or one of the RQL condition is
   253 provided if the user is in one of the listed groups or one of if the RQL condition
   254 satisfied.
   254 is satisfied.
   255 
   255 
   256 The standard user groups
   256 The standard user groups
   257 ````````````````````````
   257 ````````````````````````
   258 
   258 
   259 * `guests`
   259 * `guests`
   269 It is also possible to use specific groups if they are defined in the precreate
   269 It is also possible to use specific groups if they are defined in the precreate
   270 of the cube (``migration/precreate.py``).
   270 of the cube (``migration/precreate.py``).
   271 
   271 
   272 
   272 
   273 Use of RQL expression for write permissions
   273 Use of RQL expression for write permissions
   274 ```````````````````````````````````````````
   274  ```````````````````````````````````````````
   275 It is possible to define RQL expression to provide update permission
   275 It is possible to define RQL expression to provide update permission
   276 (`add`, `delete` and `update`) on relation and entity types.
   276 (`add`, `delete` and `update`) on relation and entity types.
   277 
   277 
   278 RQL expression for entity type permission :
   278 RQL expression for entity type permission :
   279 
   279 
   285   respectively on the current entity (on which the action is verified) and
   285   respectively on the current entity (on which the action is verified) and
   286   on the user who send the request
   286   on the user who send the request
   287 
   287 
   288 * it is possible to use, in this expression, a special relation
   288 * it is possible to use, in this expression, a special relation
   289   "has_<ACTION>_permission" where the subject is the user and the
   289   "has_<ACTION>_permission" where the subject is the user and the
   290   object is a any variable, meaning that the user needs to have
   290   object is any variable, meaning that the user needs to have
   291   permission to execute the action <ACTION> on the entities related
   291   permission to execute the action <ACTION> on the entities related
   292   to this variable
   292   to this variable
   293 
   293 
   294 For RQL expressions on a relation type, the principles are the same except
   294 For RQL expressions on a relation type, the principles are the same except
   295 for the following :
   295 for the following :
   309   - the permissions `add` and `delete` are equivalent. Only `add`/`read`
   309   - the permissions `add` and `delete` are equivalent. Only `add`/`read`
   310     are actually taken in consideration.
   310     are actually taken in consideration.
   311 
   311 
   312 :Note on the use of RQL expression for `add` permission:
   312 :Note on the use of RQL expression for `add` permission:
   313 
   313 
   314   Potentially, the use of an RQL expression to add an entity or a relation
   314   Potentially, the use of an RQL expression to add an entity or a
   315   can cause problems for the user interface, because if the expression uses
   315   relation can cause problems for the user interface, because if the
   316   the entity or the relation to create, then we are not able to verify the
   316   expression uses the entity or the relation to create, then we are
   317   permissions before we actually add the entity (please note that this is
   317   not able to verify the permissions before we actually add the entity
   318   not a problem for the RQL server at all, because the permissions checks are
   318   (please note that this is not a problem for the RQL server at all,
   319   done after the creation). In such case, the permission check methods
   319   because the permissions checks are done after the creation). In such
   320   (check_perm, has_perm) can indicate that the user is not allowed to create
   320   case, the permission check methods (CubicWebEntitySchema.check_perm
       
   321   and has_perm) can indicate that the user is not allowed to create
   321   this entity but can obtain the permission.
   322   this entity but can obtain the permission.
   322   To compensate this problem, it is usually necessary, for such case,
   323   To compensate this problem, it is usually necessary, for such case,
   323   to use an action that reflects the schema permissions but which enables
   324   to use an action that reflects the schema permissions but which enables
   324   to check properly the permissions so that it would show up if necessary.
   325   to check properly the permissions so that it would show up if necessary.
   325 
   326 
   443 `ObjectRelation`) is all we need.
   444 `ObjectRelation`) is all we need.
   444 
   445 
   445 
   446 
   446 Definition of permissions
   447 Definition of permissions
   447 ~~~~~~~~~~~~~~~~~~~~~~~~~~
   448 ~~~~~~~~~~~~~~~~~~~~~~~~~~
   448 
   449 The entity type `CWPermission` from the standard library
   449 In addition to that the entity type `CWPermission` from the standard library
   450 allows to build very complex and dynamic security architectures. The schema of
   450 allow to build very complex and dynamic security architecture. The schema of
   451 this entity type is as follow :
   451 this entity type is as follow:
       
   452 
   452 
   453 .. sourcecode:: python
   453 .. sourcecode:: python
   454 
   454 
   455     class CWPermission(EntityType):
   455     class CWPermission(EntityType):
   456 	"""entity type that may be used to construct some advanced security configuration
   456         """entity type that may be used to construct some advanced security configuration
   457 	"""
   457         """
   458 	name = String(required=True, indexed=True, internationalizable=True, maxsize=100)
   458         name = String(required=True, indexed=True, internationalizable=True, maxsize=100)
   459  require_group = SubjectRelation('CWGroup', cardinality='+*',
   459  require_group = SubjectRelation('CWGroup', cardinality='+*',
   460 					description=_('groups to which the permission is granted'))
   460                                         description=_('groups to which the permission is granted'))
   461  require_state = SubjectRelation('State',
   461  require_state = SubjectRelation('State',
   462                                         description=_("entity's state in which the permission is applicable"))
   462                                         description=_("entity's state in which the permission is applicable"))
   463 	# can be used on any entity
   463         # can be used on any entity
   464  require_permission = ObjectRelation('**', cardinality='*1', composite='subject',
   464  require_permission = ObjectRelation('**', cardinality='*1', composite='subject',
   465 					    description=_("link a permission to the entity. This "
   465                                             description=_("link a permission to the entity. This "
   466 							  "permission should be used in the security "
   466                                                           "permission should be used in the security "
   467 							  "definition of the entity's type to be useful."))
   467                                                           "definition of the entity's type to be useful."))
   468 
   468 
   469 
   469 
   470 Example of configuration:
   470 Example of configuration:
   471 
   471 
   472 .. sourcecode:: python
   472 .. sourcecode:: python
   473 
   473 
   474 
       
   475     ...
       
   476 
       
   477     class Version(EntityType):
   474     class Version(EntityType):
   478 	"""a version is defining the content of a particular project's release"""
   475         """a version is defining the content of a particular project's release"""
   479 
   476 
   480 	__permissions__ = {'read':   ('managers', 'users', 'guests',),
   477         __permissions__ = {'read':   ('managers', 'users', 'guests',),
   481 		       'update': ('managers', 'logilab', 'owners',),
   478                            'update': ('managers', 'logilab', 'owners',),
   482 		       'delete': ('managers', ),
   479                            'delete': ('managers', ),
   483 		       'add':    ('managers', 'logilab',
   480                            'add':    ('managers', 'logilab',
   484 				  ERQLExpression('X version_of PROJ, U in_group G,'
   481                                        ERQLExpression('X version_of PROJ, U in_group G,'
   485 						 'PROJ require_permission P, P name "add_version",'
   482                                                  'PROJ require_permission P, P name "add_version",'
   486 						 'P require_group G'),)}
   483                                                  'P require_group G'),)}
   487 
   484 
   488 
   485 
   489     class version_of(RelationType):
   486     class version_of(RelationType):
   490 	"""link a version to its project. A version is necessarily linked to one and only one project.
   487         """link a version to its project. A version is necessarily linked to one and only one project.
   491 	"""
   488         """
   492 	__permissions__ = {'read':   ('managers', 'users', 'guests',),
   489         __permissions__ = {'read':   ('managers', 'users', 'guests',),
   493 		       'delete': ('managers', ),
   490                            'delete': ('managers', ),
   494 		       'add':    ('managers', 'logilab',
   491                            'add':    ('managers', 'logilab',
   495 				  RRQLExpression('O require_permission P, P name "add_version",'
   492                                   RRQLExpression('O require_permission P, P name "add_version",'
   496 						 'U in_group G, P require_group G'),)
   493                                                  'U in_group G, P require_group G'),)
   497 		       }
   494                        }
   498 	inlined = True
   495         inlined = True
       
   496 
   499 
   497 
   500 This configuration indicates that an entity `CWPermission` named
   498 This configuration indicates that an entity `CWPermission` named
   501 "add_version" can be associated to a project and provides rights to create
   499 "add_version" can be associated to a project and provides rights to create
   502 new versions on this project to specific groups. It is important to notice that :
   500 new versions on this project to specific groups. It is important to notice that :
   503 
   501