goa/doc/devmanual_fr/sect_definition_schema.txt
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Tue, 26 Jan 2010 16:48:06 +0100 (2010-01-26)
changeset 4375 6d34e3cf60a3
parent 1398 5fe84a5f7035
child 4467 0e73d299730a
permissions -rw-r--r--
cleanup base class

D�finition d'un type d'entit�
-----------------------------

Un type d'entit� est d�finit par une classe python h�ritant de `EntityType`. Le
nom de la classe correspond au nom du type. Ensuite le corps de la classe
contient la description des attributs et des relations pour ce type d'entit�,
par exemple ::

  class Personne(EntityType):
    """une personne avec les propri�t�s et relations n�cessaires � mon
    application"""

    nom = String(required=True, fulltextindexed=True)
    prenom = String(required=True, fulltextindexed=True)
    civilite = String(vocabulary=('M', 'Mme', 'Mlle'))
    date_naiss = Date()
    travaille_pour = SubjectRelation('Company', cardinality='?*')

* le nom de l'attribut python correspond au nom de l'attribut ou de la relation
  dans cubicweb.

* tout les types de bases sont disponibles nativement : `String`, `Int`, `Float`,
  `Boolean`, `Date`, `Datetime`, `Time`, `Byte`.

* Chaque type d'entit� a au moins les m�ta-relations suivantes :
  - `eid` (`Int`)
  - `creation_date` (`Datetime`)
  - `modification_date` (`Datetime`)
  - `owned_by` (`CWUser`)
  - `is` (`CWEType`)

* il est �galement possible de d�finir des relations dont le type d'entit� est
  l'objet en utilisant `ObjectRelation` plut�t que `SubjectRelation`

* le premier argument de `SubjectRelation` et `ObjectRelation` donne
  respectivement le type d'entit� objet /sujet de la relation. Cela
  peut �tre : 

  * une chaine de caract�res correspondant � un type d'entit�

  * un tuple de chaines de caract�res correspondant � plusieurs types d'entit�

  * les cha�nes de caract�res sp�ciales suivantes :

    - "**" : tout les types d'entit�
    - "*" : tout les types d'entit� non m�ta
    - "@" : tout les types d'entit� m�ta mais non "syst�me" (i.e. servant � la
      description du schema en base)

* il est possible d'utiliser l'attribut possible `meta` pour marquer un type
  d'entit� comme �tant "m�ta" (i.e. servant � d�crire / classifier d'autre
  entit�s) 

* propri�t�s optionnelles des attributs et relations : 

  - `description` : chaine de caract�res d�crivant un attribut ou une
    relation. Par d�faut cette chaine sera utilis�e dans le formulaire de saisie
    de l'entit�, elle est donc destin�e � aider l'utilisateur final et doit �tre
    marqu�e par la fonction `_` pour �tre correctement internationalis�e.

  - `constraints` : liste de contraintes devant �tre respect� par la relation
    (c.f. `Contraintes`_)

  - `cardinality` : chaine de 2 caract�res sp�cifiant la cardinalit� de la
    relation. Le premier caract�re donne la cardinalit� de la relation sur le
    sujet, le 2eme sur l'objet. Quand une relation poss�de plusieurs sujets ou
    objets possibles, la cardinalit� s'applique sur l'ensemble et non un � un (et
    doit donc � priori �tre coh�rente...). Les valeurs possibles sont inspir�es
    des expressions r�guli�res :

    * `1`: 1..1
    * `?`: 0..1
    * `+`: 1..n
    * `*`: 0..n

  - `meta` : bool�en indiquant que la relation est une m�ta relation (faux par
    d�faut)

* propri�t�s optionnelles des attributs : 

  - `required` : bool�en indiquant si l'attribut est obligatoire (faux par
    d�faut)

  - `unique` : bool�en indiquant si la valeur de l'attribut doit �tre unique
    parmi toutes les entit�s de ce type (faux par d�faut)

  - `indexed` : bool�en indiquant si un index doit �tre cr�� dans la base de
    donn�es sur cette attribut (faux par d�faut). C'est utile uniquement si vous
    savez que vous allez faire de nombreuses recherche sur la valeur de cet
    attribut. 

  - `default` : valeur par d�faut de l'attribut. A noter que dans le cas des
    types date, les chaines de caract�res correspondant aux mots-cl�s RQL
    `TODAY` et `NOW` sont utilisables.

  - `vocabulary` : sp�cifie statiquement les valeurs possibles d'un attribut

* propri�t�s optionnelles des attributs de type `String` : 

  - `fulltextindexed` : bool�en indiquant si l'attribut participe � l'index plein
    texte (faux par d�faut) (*valable �galement sur le type `Byte`*)

  - `internationalizable` : bool�en indiquant si la valeur de cet attribut est
    internationalisable (faux par d�faut) 

  - `maxsize` : entier donnant la taille maximum de la chaine (pas de limite par
    d�faut)  

* propri�t�s optionnelles des relations : 

  - `composite` : cha�ne indiquant que le sujet (composite == 'subject') est
    compos� de ou des objets de la relation. Pour le cas oppos� (l'objet est
    compos� de ou des sujets de la relation, il suffit de mettre 'object' comme
    valeur. La composition implique que quand la relation est supprim� (et donc
    aussi quand le composite est supprim�), le ou les compos�s le sont
    �galement. 


Contraintes
```````````
Par d�faut les types de contraintes suivant sont disponibles :

* `SizeConstraint` : permet de sp�cifier une taille minimale et/ou maximale sur
  les chaines de caract�res (cas g�n�rique de `maxsize`)

* `BoundConstraint` : permet de sp�cifier une valeur minimale et/ou maximale sur
  les types num�riques

* `UniqueConstraint` : identique � "unique=True"

* `StaticVocabularyConstraint` : identique � "vocabulary=(...)"

* `RQLConstraint` : permet de sp�cifier une requ�te RQL devant �tre satisfaite
  par le sujet et/ou l'objet de la relation. Dans cette requ�te les variables `S`
  et `O` sont pr�f�finies respectivement comme l'entit� sujet et objet de la
  relation

* `RQLVocabularyConstraint` : similaire � la pr�c�dente, mais exprimant une
  contrainte "faible", i.e. servant uniquement � limiter les valeurs apparaissant
  dans la liste d�roulantes du formulaire d'�dition, mais n'emp�chant pas une
  autre entit� d'�tre s�l�ctionn�e


D�finition d'un type de relation
--------------------------------

Un type de relation est d�finit par une classe python h�ritant de `RelationType`. Le
nom de la classe correspond au nom du type. Ensuite le corps de la classe
contient la description des propri�t�s de ce type de relation, ainsi
qu'�ventuellement une chaine pour le sujet et une autre pour l'objet permettant
de cr�er des d�finitions de relations associ�es (auquel cas il est possibles de
donner sur la classe les propri�t�s de d�finition de relation explicit�es
ci-dessus), par exemple ::

  class verrouille_par(RelationType):
    """relation sur toutes les entit�s applicatives indiquant que celles-ci sont v�rouill�es
    inlined = True
    cardinality = '?*'
    subject = '*'
    object = 'CWUser'

En plus des permissions, les propri�t�s propres aux types de relation (et donc
partag�s par toutes les d�finitions de relation de ce type) sont :

* `inlined` : bool�en contr�lant l'optimisation physique consistant � stocker la
  relation dans la table de l'entit� sujet au lieu de cr�er une table sp�cifique
  � la relation. Cela se limite donc aux relations dont la cardinalit�
  sujet->relation->objet vaut 0..1 ('?') ou 1..1 ('1')

* `symetric` : bool�en indiquant que la relation est sym�trique, i.e. "X relation
   Y" implique "Y relation X"

Dans le cas de d�finitions de relations simultan�e, `sujet` et `object` peuvent
tout deux valoir la m�me chose que d�crite pour le 1er argument de
`SubjectRelation` et `ObjectRelation`.

A partir du moment o� une relation n'est ni mise en ligne, ni sym�trique, et
ne n�cessite pas de permissions particuli�res, sa d�finition (en utilisant
`SubjectRelation` ou `ObjectRelation`) est suffisante.


D�finition des permissions
--------------------------

La d�finition des permissions se fait � l'aide de l'attribut `permissions` des
types d'entit� ou de relation. Celui-ci est un dictionnaire dont les cl�s sont
les types d'acc�s (action), et les valeurs les groupes ou expressions autoris�es. 

Pour un type d'entit�, les actions possibles sont `read`, `add`, `update` et
`delete`.

Pour un type de relation, les actions possibles sont `read`, `add`, et `delete`.

Pour chaque type d'acc�s, un tuple indique le nom des groupes autoris�s et/ou
une ou plusieurs expressions RQL devant �tre v�rifi�es pour obtenir
l'acc�s. L'acc�s est donn� � partir du moment o� l'utilisateur fait parti d'un
des groupes requis ou d�s qu'une expression RQL est v�rifi�e.

Les groupes standards sont :

* `guests`

* `users`

* `managers`

* `owners` : groupe virtuel correspondant au propri�taire d'une entit�. Celui-ci
  ne peut �tre utilis� que pour les actions `update` et `delete` d'un type
  d'entit�. 

Il est �galement possible d'utiliser des groupes sp�cifiques devant �tre pour
cela cr��s dans le precreate de l'application (`migration/precreate.py`).

Utilisation d'expression RQL sur les droits en �criture
```````````````````````````````````````````````````````
Il est possible de d�finir des expressions RQL donnant des droits de
modification (`add`, `delete`, `update`) sur les types d'entit� et de relation.

Expression RQL pour les permissions sur un type d'entit� :

* il faut utiliser la classe `ERQLExpression`

* l'expression utilis�e correspond � la clause WHERE d'une requ�te RQL

* dans cette expression, les variables X et U sont des r�f�rences pr�d�finies
  respectivement sur l'entit� courante (sur laquelle l'action est v�rifi�e) et
  sur l'utilisateur ayant effectu� la requ�te

* il est possible d'utiliser dans cette expression les relations sp�ciales
  "has_<ACTION>_permission" dont le sujet est l'utilisateur et l'objet une
  variable quelquonque, signifiant ainsi que l'utilisateur doit avoir la
  permission d'effectuer l'action <ACTION> sur la ou les entit�s li�es cette
  variable

Pour les expressions RQL sur un type de relation, les principes sont les m�mes
avec les diff�rences suivantes :

* il faut utiliser la classe `RRQLExpression` dans le cas d'une relation non
  finale

* dans cette expression, les variables S, O et U sont des r�f�rences
  pr�d�finies respectivement sur le sujet et l'objet de la relation
  courante (sur laquelle l'action est v�rifi�e) et sur l'utilisateur
  ayant effectu� la requ�te

* On peut aussi d�finir des droits sur les attributs d'une entit� (relation non
  finale), sachant les points suivants :

  - pour d�finir des expressions rql, il faut utiliser la classe `ERQLExpression`
    dans laquelle X repr�sentera l'entit� auquel appartient l'attribut

  - les permissions 'add' et 'delete' sont �quivalentes. En pratique seul
    'add'/'read' son pris en consid�ration


En plus de cela, le type d'entit� `CWPermission` de la librairie standard permet
de construire des mod�les de s�curit�s tr�s complexes et dynamiques. Le sch�ma
de ce type d'entit� est le suivant : ::


    class CWPermission(MetaEntityType):
	"""entity type that may be used to construct some advanced security configuration
	"""
	name = String(required=True, indexed=True, internationalizable=True, maxsize=100)
	require_group = SubjectRelation('CWGroup', cardinality='+*',
					description=_('groups to which the permission is granted'))
	require_state = SubjectRelation('State',
				    description=_("entity'state in which the permission is applyable"))
	# can be used on any entity
	require_permission = ObjectRelation('**', cardinality='*1', composite='subject',
					    description=_("link a permission to the entity. This "
							  "permission should be used in the security "
							  "definition of the entity's type to be useful."))


Exemple de configuration extrait de *jpl* ::

    ...

    class Version(EntityType):
	"""a version is defining the content of a particular project's release"""

	permissions = {'read':   ('managers', 'users', 'guests',),
		       'update': ('managers', 'logilab', 'owners',),
		       'delete': ('managers', ),
		       'add':    ('managers', 'logilab',
				  ERQLExpression('X version_of PROJ, U in_group G,'
						 'PROJ require_permission P, P name "add_version",'
						 'P require_group G'),)}

    ...

    class version_of(RelationType):
	"""link a version to its project. A version is necessarily linked to one and only one project.
	"""
	permissions = {'read':   ('managers', 'users', 'guests',),
		       'delete': ('managers', ),
		       'add':    ('managers', 'logilab',
				  RRQLExpression('O require_permission P, P name "add_version",'
						 'U in_group G, P require_group G'),)
		       }
	inlined = True

Cette configuration suppose indique qu'une entit� `CWPermission` de nom
"add_version" peut-�tre associ�e � un projet et donner le droit de cr�er des
versions sur ce projet � des groupes sp�cifiques. Il est important de noter les
points suivants :

* dans ce cas il faut prot�ger � la fois le type d'entit� "Version" et la
  relation liant une version � un projet ("version_of")

* du fait de la g�n�ricit� du type d'entit� `CWPermission`, il faut effectuer
  l'unification avec les groupes et / ou les �tats le cas �ch�ant dans
  l'expression ("U in_group G, P require_group G" dans l'exemple ci-dessus)


Utilisation d'expression RQL sur les droits en lecture
``````````````````````````````````````````````````````
Les principes sont les m�mes mais avec les restrictions suivantes :

* on ne peut de `RRQLExpression` sur les types de relation en lecture

* les relations sp�ciales "has_<ACTION>_permission" ne sont pas utilisables


Note sur l'utilisation d'expression RQL sur la permission 'add'
```````````````````````````````````````````````````````````````
L'utilisation d'expression RQL sur l'ajout d'entit� ou de relation pose
potentiellement un probl�me pour l'interface utilisateur car si l'expression
utilise l'entit� ou la relation � cr�er, on est pas capable de v�rifier les
droits avant d'avoir effectu� l'ajout (noter que cela n'est pas un probl�me cot�
serveur rql car la v�rification des droits est effectu�e apr�s l'ajout
effectif). Dans ce cas les m�thodes de v�rification des droits (check_perm,
has_perm) peuvent inidquer qu'un utilisateur n'a pas le droit d'ajout alors
qu'il pourrait effectivement l'obtenir. Pour palier � ce soucis il est en g�n�ral
n�cessaire dans tel cas d'utiliser une action refl�tant les droits du sch�ma
mais permettant de faire la v�rification correctement afin qu'elle apparaisse
bien le cas �ch�ant.