doc/book/en/B0012-schema-definition.en.txt
changeset 1808 aa09e20dd8c0
parent 1693 49075f57cf2c
parent 1807 6d541c610165
child 1810 e95e876be17c
equal deleted inserted replaced
1693:49075f57cf2c 1808:aa09e20dd8c0
     1 .. -*- coding: utf-8 -*-
       
     2 
       
     3 Entity type definition
       
     4 ----------------------
       
     5 
       
     6 An entity type is defined by a Python class which inherits from `EntityType`.
       
     7 The class definition contains the description of attributes and relations
       
     8 for the defined entity type.
       
     9 The class name corresponds to the entity type name. It is exepected to be
       
    10 defined in the module ``mycube.schema``.
       
    11 
       
    12 
       
    13 For example ::
       
    14 
       
    15   class Person(EntityType):
       
    16     """A person with the properties and the relations necessary for my
       
    17     application"""
       
    18 
       
    19     last_name = String(required=True, fulltextindexed=True)
       
    20     first_name = String(required=True, fulltextindexed=True)
       
    21     title = String(vocabulary=('Mr', 'Mrs', 'Miss'))
       
    22     date_of_birth = Date()
       
    23     works_for = SubjectRelation('Company', cardinality='?*')
       
    24 
       
    25 
       
    26 The entity described above defines three attributes of type String,
       
    27 last_name, first_name and title, an attribute of type Date for the date of
       
    28 birth and a relation that connects a `Person` to another entity of type
       
    29 `Company` through the semantic `works_for` (:ref:`relations`).
       
    30 
       
    31 The name of the Python attribute corresponds to the name of the attribute
       
    32 or the relation in `CubicWeb` application.
       
    33 
       
    34 Built-in types for attributes
       
    35 `````````````````````````````
       
    36 
       
    37 All `CubicWeb` built-in types are available : `String`, `Int`, `Float`,
       
    38 `Decimal`, `Boolean`, `Date`, `Datetime`, `Time`, `Interval`, `Byte` 
       
    39 and `Password`.
       
    40 They are implicitely imported (as well as the special the function "_"
       
    41 for translation :ref:`internationalisation`).
       
    42 
       
    43 An attribute is defined in the schema as follows::
       
    44     
       
    45     attr_name = attr_type(properties*)
       
    46 
       
    47 where `attr_type` is one of the type listed above and `properties` is
       
    48 a list of properties the attribute will comply to (see :ref:`properties`
       
    49 for more details). 
       
    50 
       
    51 
       
    52 Meta-data
       
    53 `````````
       
    54 
       
    55 Each entity type has at least the following meta-relations :
       
    56 
       
    57   - `eid` (`Int`): provides the unique numeric identifier of an entity
       
    58   
       
    59   - `creation_date` (`Datetime`): date on which the entity has been created
       
    60   
       
    61   - `modification_date` (`Datetime`: date on which the entity has been last modified
       
    62   
       
    63   - `created_by` (`EUser`): which user created the entity
       
    64   
       
    65   - `owned_by` (`EUser`): to whom the entity belongs; by default the 
       
    66      creator but not necessary, and it could have multiple owners
       
    67      
       
    68   - `is` (`EEType`): of which type the entity is
       
    69 
       
    70 .. _relations:
       
    71 
       
    72 Relation definition
       
    73 ```````````````````
       
    74 
       
    75 There are two types of relation you can use to define an entity type: 
       
    76 `ObjectRelation` or `SubjectRelation`.
       
    77 The first argument of `SubjectRelation` or `ObjectRelation` gives respectively
       
    78 the object/subject entity type of the relation. This could be :  
       
    79 
       
    80   * a string corresponding to an entity type
       
    81 
       
    82   * a tuple of string corresponding to multiple entity types
       
    83 
       
    84   * special string such as follows :
       
    85 
       
    86     - "**" : all types of entities
       
    87     - "*" : all types of non-meta entities 
       
    88     - "@" : all types of meta entities but not system entities (e.g. used for
       
    89       the basic schema description)
       
    90 
       
    91 .. it is possible to use the attribute `meta` to flag an entity type as a `meta`
       
    92   (e.g. used to describe/categorize other entities)
       
    93 
       
    94 .. _properties:
       
    95 
       
    96 Optionnal properties
       
    97 ````````````````````
       
    98 
       
    99 Follows the list of properties that are available for defining
       
   100 attribute and relation of a new entity type.
       
   101 
       
   102 * Optional properties for attributes and relations : 
       
   103 
       
   104   - `description` : a string describing an attribute or a relation. By default
       
   105     this string will be used in the editing form of the entity, which means
       
   106     that it is supposed to help the end-user and should be flagged by the
       
   107     function `_` to be properly internationalized.
       
   108 
       
   109   - `constraints` : a list of conditions/constraints that the relation has to
       
   110     satisfy (c.f. `Contraints`_)
       
   111 
       
   112   - `cardinality` : a two character string which specify the cardinality of the
       
   113     relation. The first character defines the cardinality of the relation on
       
   114     the subject, and the second on the object. When a relation can have 
       
   115     multiple subjects or objects, the cardinality applies to all,
       
   116     not on a one-to-one basis (so it must be consistent...). The possible
       
   117     values are inspired from regular expression syntax :
       
   118 
       
   119     * `1`: 1..1
       
   120     * `?`: 0..1
       
   121     * `+`: 1..n
       
   122     * `*`: 0..n
       
   123 
       
   124   - `meta` : boolean indicating that the relation is a meta-relation (false by
       
   125     default)
       
   126 
       
   127 * Optional properties for attributes : 
       
   128 
       
   129   - `required` : boolean indicating if the attribute is required (false by default)
       
   130 
       
   131   - `unique` : boolean indicating if the value of the attribute has to be unique
       
   132     or not within all entities of the same type (false by default)
       
   133 
       
   134   - `indexed` : boolean indicating if an index needs to be created for this 
       
   135     attribute in the database (false by default). This is useful only if
       
   136     you know that you will have to run numerous searches on the value of this
       
   137     attribute.
       
   138 
       
   139   - `default` : default value of the attribute. In case of date types, the values
       
   140     which could be used correspond to the RQL keywords `TODAY` and `NOW`.
       
   141   
       
   142   - `vocabulary` : specify static possible values of an attribute
       
   143 
       
   144 * Optional properties of type `String` : 
       
   145 
       
   146   - `fulltextindexed` : boolean indicating if the attribute is part of
       
   147     the full text index (false by default) (*applicable on the type `Byte`
       
   148     as well*)
       
   149 
       
   150   - `internationalizable` : boolean indicating if the value of the attribute
       
   151     is internationalizable (false by default)
       
   152 
       
   153   - `maxsize` : integer providing the maximum size of the string (no limit by default)
       
   154 
       
   155 * Optional properties for relations : 
       
   156 
       
   157   - `composite` : string indicating that the subject (composite == 'subject')
       
   158     is composed of the objects of the relations. For the opposite case (when
       
   159     the object is composed of the subjects of the relation), we just set 
       
   160     'object' as value. The composition implies that when the relation
       
   161     is deleted (so when the composite is deleted), the composed are also deleted.
       
   162 
       
   163 Constraints
       
   164 ```````````
       
   165 By default, the available constraint types are :
       
   166 
       
   167 * `SizeConstraint` : allows to specify a minimum and/or maximum size on
       
   168   string (generic case of `maxsize`)
       
   169 
       
   170 * `BoundConstraint` : allows to specify a minimum and/or maximum value on 
       
   171   numeric types
       
   172 
       
   173 * `UniqueConstraint` : identical to "unique=True"
       
   174 
       
   175 * `StaticVocabularyConstraint` : identical to "vocabulary=(...)"
       
   176 
       
   177 * `RQLConstraint` : allows to specify a RQL query that has to be satisfied
       
   178   by the subject and/or the object of the relation. In this query the variables
       
   179   `S` and `O` are reserved for the entities subject and object of the 
       
   180   relation.
       
   181 
       
   182 * `RQLVocabularyConstraint` : similar to the previous type of constraint except
       
   183   that it does not express a "strong" constraint, which means it is only used to
       
   184   restrict the values listed in the drop-down menu of editing form, but it does
       
   185   not prevent another entity to be selected.
       
   186 
       
   187 
       
   188 Definition of relations
       
   189 -----------------------
       
   190 
       
   191 XXX add note about defining relation type / definition
       
   192 
       
   193 A relation is defined by a Python class heriting `RelationType`. The name
       
   194 of the class corresponds to the name of the type. The class then contains
       
   195 a description of the properties of this type of relation, and could as well 
       
   196 contain a string for the subject and a string for the object. This allows to create
       
   197 new definition of associated relations, (so that the class can have the 
       
   198 definition properties from the relation) for example ::
       
   199 
       
   200   class locked_by(RelationType):
       
   201     """relation on all entities indicating that they are locked"""
       
   202     inlined = True
       
   203     cardinality = '?*'
       
   204     subject = '*'
       
   205     object = 'EUser'
       
   206 
       
   207 In addition to the permissions, the properties of the relation types
       
   208 (shared also by all definition of relation of this type) are :
       
   209 
       
   210 
       
   211 * `inlined` : boolean handling the physical optimization for archiving
       
   212   the relation in the subject entity table, instead of creating a specific
       
   213   table for the relation. This applies to the relation when the cardinality
       
   214   of subject->relation->object is 0..1 (`?`) or 1..1 (`1`)
       
   215 
       
   216 * `symmetric` : boolean indicating that the relation is symmetrical, which
       
   217   means `X relation Y` implies `Y relation X`
       
   218 
       
   219 In the case of simultaneous relations definitions, `subject` and `object`
       
   220 can both be equal to the value of the first argument of `SubjectRelation`
       
   221 and `ObjectRelation`.
       
   222 
       
   223 When a relation is not inlined and not symmetrical, and it does not require
       
   224 specific permissions, its definition (by using `SubjectRelation` and
       
   225 `ObjectRelation`) is all we need.
       
   226 
       
   227 .. _security:
       
   228 
       
   229 The security model
       
   230 ------------------
       
   231 
       
   232 The security model of `cubicWeb` is based on `Access Control List`. 
       
   233 The main principles are:
       
   234 
       
   235 * users and groups of users
       
   236 * a user belongs to at least one group of user
       
   237 * permissions (read, update, create, delete)
       
   238 * permissions are assigned to groups (and not to users)
       
   239 
       
   240 For `CubicWeb` in particular:
       
   241 
       
   242 * we associate rights at the enttities/relations schema level
       
   243 * for each entity, we distinguish four kind of permissions: read,
       
   244   add, update and delete
       
   245 * for each relation, we distinguish three king of permissions: read,
       
   246   add and delete (we can not modify a relation)
       
   247 * the basic groups are: Administrators, Users and Guests
       
   248 * by default, users belongs to the group Users
       
   249 * there is a virtual group called `Owners users` to which we
       
   250   can associate only deletion and update permissions
       
   251 * we can not add users to the `Owners users` group, they are
       
   252   implicetely added to it according to the context of the objects
       
   253   they own
       
   254 * the permissions of this group are only be checked on update/deletion
       
   255   actions if all the other groups the user belongs does not provide
       
   256   those permissions
       
   257 
       
   258   
       
   259 Permissions definition
       
   260 ``````````````````````
       
   261 
       
   262 Setting permissions is done with the attribute `permissions` of entities and
       
   263 relation types. It defines a dictionary where the keys are the access types
       
   264 (action), and the values are the authorized groups or expressions.
       
   265 
       
   266 For an entity type, the possible actions are `read`, `add`, `update` and
       
   267 `delete`.
       
   268 
       
   269 For a relation type, the possible actions are `read`, `add`, and `delete`.
       
   270 
       
   271 For each access type, a tuple indicates the name of the authorized groups and/or
       
   272 one or multiple RQL expressions to satisfy to grant access. The access is
       
   273 provided once the user is in the listed groups or one of the RQL condition is
       
   274 satisfied.
       
   275 
       
   276 The standard groups are :
       
   277 
       
   278 * `guests`
       
   279 
       
   280 * `users`
       
   281 
       
   282 * `managers`
       
   283 
       
   284 * `owners` : virtual group corresponding to the entity's owner.
       
   285   This can only be used for the actions `update` and `delete` of an entity
       
   286   type.
       
   287 
       
   288 It is also possible to use specific groups if they are defined in the precreate 
       
   289 of the cube (``migration/precreate.py``).
       
   290 
       
   291 
       
   292 Use of RQL expression for writing rights
       
   293 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       
   294 It is possible to define RQL expression to provide update permission 
       
   295 (`add`, `delete` and `update`) on relation and entity types.
       
   296 
       
   297 RQL expression for entity type permission :
       
   298 
       
   299 * you have to use the class `ERQLExpression`
       
   300 
       
   301 * the used expression corresponds to the WHERE statement of an RQL query
       
   302 
       
   303 * in this expression, the variables X and U are pre-defined references
       
   304   respectively on the current entity (on which the action is verified) and
       
   305   on the user who send the request
       
   306 
       
   307 * it is possible to use, in this expression, a special relation 
       
   308   "has_<ACTION>_permission" where the subject is the user and the 
       
   309   object is a any variable, meaning that the user needs to have
       
   310   permission to execute the action <ACTION> on the entities related
       
   311   to this variable 
       
   312 
       
   313 For RQL expressions on a relation type, the principles are the same except 
       
   314 for the following :
       
   315 
       
   316 * you have to use the class `RQLExpression` in the case of a non-final relation
       
   317 
       
   318 * in the expression, the variables S, O and U are pre-defined references
       
   319   to respectively the subject and the object of the current relation (on
       
   320   which the action is being verified) and the user who executed the query
       
   321 
       
   322 * we can also defined rights on attributes of an entity (non-final relation),
       
   323   knowing that : 
       
   324 
       
   325   - to defines RQL expression, we have to use the class `ERQLExpression`
       
   326     in which X represents the entity the attribute belongs to
       
   327 
       
   328   - the permissions `add` and `delete` are equivalent. Only `add`/`read`
       
   329     are actually taken in consideration.
       
   330 
       
   331 In addition to that the entity type `EPermission` from the standard library
       
   332 allow to build very complex and dynamic security architecture. The schema of
       
   333 this entity type is as follow : ::
       
   334 
       
   335     class EPermission(MetaEntityType):
       
   336 	"""entity type that may be used to construct some advanced security configuration
       
   337 	"""
       
   338 	name = String(required=True, indexed=True, internationalizable=True, maxsize=100)
       
   339 	require_group = SubjectRelation('EGroup', cardinality='+*',
       
   340 					description=_('groups to which the permission is granted'))
       
   341 	require_state = SubjectRelation('State',
       
   342 				    description=_("entity'state in which the permission is applyable"))
       
   343 	# can be used on any entity
       
   344 	require_permission = ObjectRelation('**', cardinality='*1', composite='subject',
       
   345 					    description=_("link a permission to the entity. This "
       
   346 							  "permission should be used in the security "
       
   347 							  "definition of the entity's type to be useful."))
       
   348 
       
   349 
       
   350 Example of configuration ::
       
   351 
       
   352 
       
   353     ...
       
   354 
       
   355     class Version(EntityType):
       
   356 	"""a version is defining the content of a particular project's release"""
       
   357 
       
   358 	permissions = {'read':   ('managers', 'users', 'guests',),
       
   359 		       'update': ('managers', 'logilab', 'owners',),
       
   360 		       'delete': ('managers', ),
       
   361 		       'add':    ('managers', 'logilab',
       
   362 				  ERQLExpression('X version_of PROJ, U in_group G,'
       
   363 						 'PROJ require_permission P, P name "add_version",'
       
   364 						 'P require_group G'),)}
       
   365 
       
   366     ...
       
   367 
       
   368     class version_of(RelationType):
       
   369 	"""link a version to its project. A version is necessarily linked to one and only one project.
       
   370 	"""
       
   371 	permissions = {'read':   ('managers', 'users', 'guests',),
       
   372 		       'delete': ('managers', ),
       
   373 		       'add':    ('managers', 'logilab',
       
   374 				  RRQLExpression('O require_permission P, P name "add_version",'
       
   375 						 'U in_group G, P require_group G'),)
       
   376 		       }
       
   377 	inlined = True
       
   378 
       
   379 This configuration indicates that an entity `EPermission` named
       
   380 "add_version" can be associated to a project and provides rights to create
       
   381 new versions on this project to specific groups. It is important to notice that :
       
   382 
       
   383 * in such case, we have to protect both the entity type "Version" and the relation
       
   384   associating a version to a project ("version_of")
       
   385 
       
   386 * because of the genricity of the entity type `EPermission`, we have to execute
       
   387   a unification with the groups and/or the states if necessary in the expression
       
   388   ("U in_group G, P require_group G" in the above example)
       
   389 
       
   390 Use of RQL expression for reading rights
       
   391 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       
   392 
       
   393 The principles are the same but with the following restrictions :
       
   394 
       
   395 * we can not use `RRQLExpression` on relation types for reading
       
   396 
       
   397 * special relations "has_<ACTION>_permission" can not be used
       
   398 
       
   399 
       
   400 Note on the use of RQL expression for `add` permission
       
   401 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       
   402 Potentially, the use of an RQL expression to add an entity or a relation
       
   403 can cause problems for the user interface, because if the expression uses
       
   404 the entity or the relation to create, then we are not able to verify the 
       
   405 permissions before we actually add the entity (please note that this is
       
   406 not a problem for the RQL server at all, because the permissions checks are
       
   407 done after the creation). In such case, the permission check methods 
       
   408 (check_perm, has_perm) can indicate that the user is not allowed to create 
       
   409 this entity but can obtain the permission. 
       
   410 To compensate this problem, it is usually necessary, for such case,
       
   411 to use an action that reflects the schema permissions but which enables
       
   412 to check properly the permissions so that it would show up if necessary.
       
   413 
       
   414 
       
   415 Updating your application with your new schema
       
   416 ``````````````````````````````````````````````
       
   417 
       
   418 If you modified your schema, the update is not automatic; indeed, this is 
       
   419 in general not a good idea.
       
   420 Instead, you call a shell on your application, which is a 
       
   421 an interactive python shell, with an appropriate
       
   422 cubicweb environment ::
       
   423 
       
   424    cubicweb-ctl shell myinstance
       
   425 
       
   426 and type ::
       
   427 
       
   428    add_entity_type('Person')
       
   429 
       
   430 And restart your application!