goa/doc/devmanual_fr/sect_definition_schema.txt
changeset 0 b97547f5f1fa
child 1398 5fe84a5f7035
equal deleted inserted replaced
-1:000000000000 0:b97547f5f1fa
       
     1 
       
     2 Définition d'un type d'entité
       
     3 -----------------------------
       
     4 
       
     5 Un type d'entité est définit par une classe python héritant de `EntityType`. Le
       
     6 nom de la classe correspond au nom du type. Ensuite le corps de la classe
       
     7 contient la description des attributs et des relations pour ce type d'entité,
       
     8 par exemple ::
       
     9 
       
    10   class Personne(EntityType):
       
    11     """une personne avec les propriétés et relations nécessaires à mon
       
    12     application"""
       
    13 
       
    14     nom = String(required=True, fulltextindexed=True)
       
    15     prenom = String(required=True, fulltextindexed=True)
       
    16     civilite = String(vocabulary=('M', 'Mme', 'Mlle'))
       
    17     date_naiss = Date()
       
    18     travaille_pour = SubjectRelation('Company', cardinality='?*')
       
    19 
       
    20 * le nom de l'attribut python correspond au nom de l'attribut ou de la relation
       
    21   dans cubicweb.
       
    22 
       
    23 * tout les types de bases sont disponibles nativement : `String`, `Int`, `Float`,
       
    24   `Boolean`, `Date`, `Datetime`, `Time`, `Byte`.
       
    25 
       
    26 * Chaque type d'entité a au moins les méta-relations suivantes :
       
    27   - `eid` (`Int`)
       
    28   - `creation_date` (`Datetime`)
       
    29   - `modification_date` (`Datetime`)
       
    30   - `owned_by` (`EUser`)
       
    31   - `is` (`EEType`)
       
    32 
       
    33 * il est également possible de définir des relations dont le type d'entité est
       
    34   l'objet en utilisant `ObjectRelation` plutôt que `SubjectRelation`
       
    35 
       
    36 * le premier argument de `SubjectRelation` et `ObjectRelation` donne
       
    37   respectivement le type d'entité objet /sujet de la relation. Cela
       
    38   peut être : 
       
    39 
       
    40   * une chaine de caractères correspondant à un type d'entité
       
    41 
       
    42   * un tuple de chaines de caractères correspondant à plusieurs types d'entité
       
    43 
       
    44   * les chaînes de caractères spéciales suivantes :
       
    45 
       
    46     - "**" : tout les types d'entité
       
    47     - "*" : tout les types d'entité non méta
       
    48     - "@" : tout les types d'entité méta mais non "système" (i.e. servant à la
       
    49       description du schema en base)
       
    50 
       
    51 * il est possible d'utiliser l'attribut possible `meta` pour marquer un type
       
    52   d'entité comme étant "méta" (i.e. servant à décrire / classifier d'autre
       
    53   entités) 
       
    54 
       
    55 * propriétés optionnelles des attributs et relations : 
       
    56 
       
    57   - `description` : chaine de caractères décrivant un attribut ou une
       
    58     relation. Par défaut cette chaine sera utilisée dans le formulaire de saisie
       
    59     de l'entité, elle est donc destinée à aider l'utilisateur final et doit être
       
    60     marquée par la fonction `_` pour être correctement internationalisée.
       
    61 
       
    62   - `constraints` : liste de contraintes devant être respecté par la relation
       
    63     (c.f. `Contraintes`_)
       
    64 
       
    65   - `cardinality` : chaine de 2 caractères spécifiant la cardinalité de la
       
    66     relation. Le premier caractère donne la cardinalité de la relation sur le
       
    67     sujet, le 2eme sur l'objet. Quand une relation possède plusieurs sujets ou
       
    68     objets possibles, la cardinalité s'applique sur l'ensemble et non un à un (et
       
    69     doit donc à priori être cohérente...). Les valeurs possibles sont inspirées
       
    70     des expressions régulières :
       
    71 
       
    72     * `1`: 1..1
       
    73     * `?`: 0..1
       
    74     * `+`: 1..n
       
    75     * `*`: 0..n
       
    76 
       
    77   - `meta` : booléen indiquant que la relation est une méta relation (faux par
       
    78     défaut)
       
    79 
       
    80 * propriétés optionnelles des attributs : 
       
    81 
       
    82   - `required` : booléen indiquant si l'attribut est obligatoire (faux par
       
    83     défaut)
       
    84 
       
    85   - `unique` : booléen indiquant si la valeur de l'attribut doit être unique
       
    86     parmi toutes les entités de ce type (faux par défaut)
       
    87 
       
    88   - `indexed` : booléen indiquant si un index doit être créé dans la base de
       
    89     données sur cette attribut (faux par défaut). C'est utile uniquement si vous
       
    90     savez que vous allez faire de nombreuses recherche sur la valeur de cet
       
    91     attribut. 
       
    92 
       
    93   - `default` : valeur par défaut de l'attribut. A noter que dans le cas des
       
    94     types date, les chaines de caractères correspondant aux mots-clés RQL
       
    95     `TODAY` et `NOW` sont utilisables.
       
    96 
       
    97   - `vocabulary` : spécifie statiquement les valeurs possibles d'un attribut
       
    98 
       
    99 * propriétés optionnelles des attributs de type `String` : 
       
   100 
       
   101   - `fulltextindexed` : booléen indiquant si l'attribut participe à l'index plein
       
   102     texte (faux par défaut) (*valable également sur le type `Byte`*)
       
   103 
       
   104   - `internationalizable` : booléen indiquant si la valeur de cet attribut est
       
   105     internationalisable (faux par défaut) 
       
   106 
       
   107   - `maxsize` : entier donnant la taille maximum de la chaine (pas de limite par
       
   108     défaut)  
       
   109 
       
   110 * propriétés optionnelles des relations : 
       
   111 
       
   112   - `composite` : chaîne indiquant que le sujet (composite == 'subject') est
       
   113     composé de ou des objets de la relation. Pour le cas opposé (l'objet est
       
   114     composé de ou des sujets de la relation, il suffit de mettre 'object' comme
       
   115     valeur. La composition implique que quand la relation est supprimé (et donc
       
   116     aussi quand le composite est supprimé), le ou les composés le sont
       
   117     également. 
       
   118 
       
   119 
       
   120 Contraintes
       
   121 ```````````
       
   122 Par défaut les types de contraintes suivant sont disponibles :
       
   123 
       
   124 * `SizeConstraint` : permet de spécifier une taille minimale et/ou maximale sur
       
   125   les chaines de caractères (cas générique de `maxsize`)
       
   126 
       
   127 * `BoundConstraint` : permet de spécifier une valeur minimale et/ou maximale sur
       
   128   les types numériques
       
   129 
       
   130 * `UniqueConstraint` : identique à "unique=True"
       
   131 
       
   132 * `StaticVocabularyConstraint` : identique à "vocabulary=(...)"
       
   133 
       
   134 * `RQLConstraint` : permet de spécifier une requête RQL devant être satisfaite
       
   135   par le sujet et/ou l'objet de la relation. Dans cette requête les variables `S`
       
   136   et `O` sont préféfinies respectivement comme l'entité sujet et objet de la
       
   137   relation
       
   138 
       
   139 * `RQLVocabularyConstraint` : similaire à la précédente, mais exprimant une
       
   140   contrainte "faible", i.e. servant uniquement à limiter les valeurs apparaissant
       
   141   dans la liste déroulantes du formulaire d'édition, mais n'empêchant pas une
       
   142   autre entité d'être séléctionnée
       
   143 
       
   144 
       
   145 Définition d'un type de relation
       
   146 --------------------------------
       
   147 
       
   148 Un type de relation est définit par une classe python héritant de `RelationType`. Le
       
   149 nom de la classe correspond au nom du type. Ensuite le corps de la classe
       
   150 contient la description des propriétés de ce type de relation, ainsi
       
   151 qu'éventuellement une chaine pour le sujet et une autre pour l'objet permettant
       
   152 de créer des définitions de relations associées (auquel cas il est possibles de
       
   153 donner sur la classe les propriétés de définition de relation explicitées
       
   154 ci-dessus), par exemple ::
       
   155 
       
   156   class verrouille_par(RelationType):
       
   157     """relation sur toutes les entités applicatives indiquant que celles-ci sont vérouillées
       
   158     inlined = True
       
   159     cardinality = '?*'
       
   160     subject = '*'
       
   161     object = 'EUser'
       
   162 
       
   163 En plus des permissions, les propriétés propres aux types de relation (et donc
       
   164 partagés par toutes les définitions de relation de ce type) sont :
       
   165 
       
   166 * `inlined` : booléen contrôlant l'optimisation physique consistant à stocker la
       
   167   relation dans la table de l'entité sujet au lieu de créer une table spécifique
       
   168   à la relation. Cela se limite donc aux relations dont la cardinalité
       
   169   sujet->relation->objet vaut 0..1 ('?') ou 1..1 ('1')
       
   170 
       
   171 * `symetric` : booléen indiquant que la relation est symétrique, i.e. "X relation
       
   172    Y" implique "Y relation X"
       
   173 
       
   174 Dans le cas de définitions de relations simultanée, `sujet` et `object` peuvent
       
   175 tout deux valoir la même chose que décrite pour le 1er argument de
       
   176 `SubjectRelation` et `ObjectRelation`.
       
   177 
       
   178 A partir du moment où une relation n'est ni mise en ligne, ni symétrique, et
       
   179 ne nécessite pas de permissions particulières, sa définition (en utilisant
       
   180 `SubjectRelation` ou `ObjectRelation`) est suffisante.
       
   181 
       
   182 
       
   183 Définition des permissions
       
   184 --------------------------
       
   185 
       
   186 La définition des permissions se fait à l'aide de l'attribut `permissions` des
       
   187 types d'entité ou de relation. Celui-ci est un dictionnaire dont les clés sont
       
   188 les types d'accès (action), et les valeurs les groupes ou expressions autorisées. 
       
   189 
       
   190 Pour un type d'entité, les actions possibles sont `read`, `add`, `update` et
       
   191 `delete`.
       
   192 
       
   193 Pour un type de relation, les actions possibles sont `read`, `add`, et `delete`.
       
   194 
       
   195 Pour chaque type d'accès, un tuple indique le nom des groupes autorisés et/ou
       
   196 une ou plusieurs expressions RQL devant être vérifiées pour obtenir
       
   197 l'accès. L'accès est donné à partir du moment où l'utilisateur fait parti d'un
       
   198 des groupes requis ou dès qu'une expression RQL est vérifiée.
       
   199 
       
   200 Les groupes standards sont :
       
   201 
       
   202 * `guests`
       
   203 
       
   204 * `users`
       
   205 
       
   206 * `managers`
       
   207 
       
   208 * `owners` : groupe virtuel correspondant au propriétaire d'une entité. Celui-ci
       
   209   ne peut être utilisé que pour les actions `update` et `delete` d'un type
       
   210   d'entité. 
       
   211 
       
   212 Il est également possible d'utiliser des groupes spécifiques devant être pour
       
   213 cela créés dans le precreate de l'application (`migration/precreate.py`).
       
   214 
       
   215 Utilisation d'expression RQL sur les droits en écriture
       
   216 ```````````````````````````````````````````````````````
       
   217 Il est possible de définir des expressions RQL donnant des droits de
       
   218 modification (`add`, `delete`, `update`) sur les types d'entité et de relation.
       
   219 
       
   220 Expression RQL pour les permissions sur un type d'entité :
       
   221 
       
   222 * il faut utiliser la classe `ERQLExpression`
       
   223 
       
   224 * l'expression utilisée correspond à la clause WHERE d'une requête RQL
       
   225 
       
   226 * dans cette expression, les variables X et U sont des références prédéfinies
       
   227   respectivement sur l'entité courante (sur laquelle l'action est vérifiée) et
       
   228   sur l'utilisateur ayant effectué la requête
       
   229 
       
   230 * il est possible d'utiliser dans cette expression les relations spéciales
       
   231   "has_<ACTION>_permission" dont le sujet est l'utilisateur et l'objet une
       
   232   variable quelquonque, signifiant ainsi que l'utilisateur doit avoir la
       
   233   permission d'effectuer l'action <ACTION> sur la ou les entités liées cette
       
   234   variable
       
   235 
       
   236 Pour les expressions RQL sur un type de relation, les principes sont les mêmes
       
   237 avec les différences suivantes :
       
   238 
       
   239 * il faut utiliser la classe `RRQLExpression` dans le cas d'une relation non
       
   240   finale
       
   241 
       
   242 * dans cette expression, les variables S, O et U sont des références
       
   243   prédéfinies respectivement sur le sujet et l'objet de la relation
       
   244   courante (sur laquelle l'action est vérifiée) et sur l'utilisateur
       
   245   ayant effectué la requête
       
   246 
       
   247 * On peut aussi définir des droits sur les attributs d'une entité (relation non
       
   248   finale), sachant les points suivants :
       
   249 
       
   250   - pour définir des expressions rql, il faut utiliser la classe `ERQLExpression`
       
   251     dans laquelle X représentera l'entité auquel appartient l'attribut
       
   252 
       
   253   - les permissions 'add' et 'delete' sont équivalentes. En pratique seul
       
   254     'add'/'read' son pris en considération
       
   255 
       
   256 
       
   257 En plus de cela, le type d'entité `EPermission` de la librairie standard permet
       
   258 de construire des modèles de sécurités très complexes et dynamiques. Le schéma
       
   259 de ce type d'entité est le suivant : ::
       
   260 
       
   261 
       
   262     class EPermission(MetaEntityType):
       
   263 	"""entity type that may be used to construct some advanced security configuration
       
   264 	"""
       
   265 	name = String(required=True, indexed=True, internationalizable=True, maxsize=100)
       
   266 	require_group = SubjectRelation('EGroup', cardinality='+*',
       
   267 					description=_('groups to which the permission is granted'))
       
   268 	require_state = SubjectRelation('State',
       
   269 				    description=_("entity'state in which the permission is applyable"))
       
   270 	# can be used on any entity
       
   271 	require_permission = ObjectRelation('**', cardinality='*1', composite='subject',
       
   272 					    description=_("link a permission to the entity. This "
       
   273 							  "permission should be used in the security "
       
   274 							  "definition of the entity's type to be useful."))
       
   275 
       
   276 
       
   277 Exemple de configuration extrait de *jpl* ::
       
   278 
       
   279     ...
       
   280 
       
   281     class Version(EntityType):
       
   282 	"""a version is defining the content of a particular project's release"""
       
   283 
       
   284 	permissions = {'read':   ('managers', 'users', 'guests',),
       
   285 		       'update': ('managers', 'logilab', 'owners',),
       
   286 		       'delete': ('managers', ),
       
   287 		       'add':    ('managers', 'logilab',
       
   288 				  ERQLExpression('X version_of PROJ, U in_group G,'
       
   289 						 'PROJ require_permission P, P name "add_version",'
       
   290 						 'P require_group G'),)}
       
   291 
       
   292     ...
       
   293 
       
   294     class version_of(RelationType):
       
   295 	"""link a version to its project. A version is necessarily linked to one and only one project.
       
   296 	"""
       
   297 	permissions = {'read':   ('managers', 'users', 'guests',),
       
   298 		       'delete': ('managers', ),
       
   299 		       'add':    ('managers', 'logilab',
       
   300 				  RRQLExpression('O require_permission P, P name "add_version",'
       
   301 						 'U in_group G, P require_group G'),)
       
   302 		       }
       
   303 	inlined = True
       
   304 
       
   305 Cette configuration suppose indique qu'une entité `EPermission` de nom
       
   306 "add_version" peut-être associée à un projet et donner le droit de créer des
       
   307 versions sur ce projet à des groupes spécifiques. Il est important de noter les
       
   308 points suivants :
       
   309 
       
   310 * dans ce cas il faut protéger à la fois le type d'entité "Version" et la
       
   311   relation liant une version à un projet ("version_of")
       
   312 
       
   313 * du fait de la généricité du type d'entité `EPermission`, il faut effectuer
       
   314   l'unification avec les groupes et / ou les états le cas échéant dans
       
   315   l'expression ("U in_group G, P require_group G" dans l'exemple ci-dessus)
       
   316 
       
   317 
       
   318 Utilisation d'expression RQL sur les droits en lecture
       
   319 ``````````````````````````````````````````````````````
       
   320 Les principes sont les mêmes mais avec les restrictions suivantes :
       
   321 
       
   322 * on ne peut de `RRQLExpression` sur les types de relation en lecture
       
   323 
       
   324 * les relations spéciales "has_<ACTION>_permission" ne sont pas utilisables
       
   325 
       
   326 
       
   327 Note sur l'utilisation d'expression RQL sur la permission 'add'
       
   328 ```````````````````````````````````````````````````````````````
       
   329 L'utilisation d'expression RQL sur l'ajout d'entité ou de relation pose
       
   330 potentiellement un problème pour l'interface utilisateur car si l'expression
       
   331 utilise l'entité ou la relation à créer, on est pas capable de vérifier les
       
   332 droits avant d'avoir effectué l'ajout (noter que cela n'est pas un problème coté
       
   333 serveur rql car la vérification des droits est effectuée après l'ajout
       
   334 effectif). Dans ce cas les méthodes de vérification des droits (check_perm,
       
   335 has_perm) peuvent inidquer qu'un utilisateur n'a pas le droit d'ajout alors
       
   336 qu'il pourrait effectivement l'obtenir. Pour palier à ce soucis il est en général
       
   337 nécessaire dans tel cas d'utiliser une action reflétant les droits du schéma
       
   338 mais permettant de faire la vérification correctement afin qu'elle apparaisse
       
   339 bien le cas échéant.