[F] views: fix 2 unicode errors
1. You can now use valid unicode strings in ValidationError exception.
Previously, if 'err' contains unicode, UnicodeDecodeError was raised by format_errors()
>>> templstr = '<li>%s</li>\n'
>>> e = ValidationError(None, {None: u'oué, une exception en unicode!'})
>>> templstr % e
'<li>None (None): ou\xc3\xa9, une exception en unicode!</li>\n'
>>> templstr = u'<li>%s</li>\n'
>>> templstr % e
u'<li>None (None): ou\xe9, une exception en unicode!</li>\n'
2. The message of an Exception can contains unicode. But it now properly managed by “informal” string representation.
We can easily fix the problem by using the Exception.message attribute that still contains the original message.
>>> a = AssertionError(u'séfdsdf')
>>> a.message
u's\xe9fdsdf'
>>> str(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 1: ordinal not in range(128)
>>> a = ValueError(u'fsdfsdéfsdfs')
>>> str(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 6: ordinal not in range(128)
>>> a
ValueError(u'fsdfsd\xe9fsdfs',)
>>> unicode(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 6: ordinal not in range(128)
>>> a.message
u'fsdfsd\xe9fsdfs'
Dfinition d'un type d'entit
-----------------------------
Un type d'entit est dfinit par une classe python hritant 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 proprits et relations ncessaires 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 mta-relations suivantes :
- `eid` (`Int`)
- `creation_date` (`Datetime`)
- `modification_date` (`Datetime`)
- `owned_by` (`CWUser`)
- `is` (`CWEType`)
* il est galement possible de dfinir des relations dont le type d'entit est
l'objet en utilisant `ObjectRelation` plutt 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 caractres correspondant un type d'entit
* un tuple de chaines de caractres correspondant plusieurs types d'entit
* les chanes de caractres spciales suivantes :
- "**" : tout les types d'entit
- "*" : tout les types d'entit non mta
- "@" : tout les types d'entit mta mais non "systme" (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 "mta" (i.e. servant dcrire / classifier d'autre
entits)
* proprits optionnelles des attributs et relations :
- `description` : chaine de caractres dcrivant un attribut ou une
relation. Par dfaut cette chaine sera utilise dans le formulaire de saisie
de l'entit, elle est donc destine aider l'utilisateur final et doit tre
marque par la fonction `_` pour tre correctement internationalise.
- `constraints` : liste de contraintes devant tre respect par la relation
(c.f. `Contraintes`_)
- `cardinality` : chaine de 2 caractres spcifiant la cardinalit de la
relation. Le premier caractre donne la cardinalit de la relation sur le
sujet, le 2eme sur l'objet. Quand une relation possde plusieurs sujets ou
objets possibles, la cardinalit s'applique sur l'ensemble et non un un (et
doit donc priori tre cohrente...). Les valeurs possibles sont inspires
des expressions rgulires :
* `1`: 1..1
* `?`: 0..1
* `+`: 1..n
* `*`: 0..n
- `meta` : boolen indiquant que la relation est une mta relation (faux par
dfaut)
* proprits optionnelles des attributs :
- `required` : boolen indiquant si l'attribut est obligatoire (faux par
dfaut)
- `unique` : boolen indiquant si la valeur de l'attribut doit tre unique
parmi toutes les entits de ce type (faux par dfaut)
- `indexed` : boolen indiquant si un index doit tre cr dans la base de
donnes sur cette attribut (faux par dfaut). C'est utile uniquement si vous
savez que vous allez faire de nombreuses recherche sur la valeur de cet
attribut.
- `default` : valeur par dfaut de l'attribut. A noter que dans le cas des
types date, les chaines de caractres correspondant aux mots-cls RQL
`TODAY` et `NOW` sont utilisables.
- `vocabulary` : spcifie statiquement les valeurs possibles d'un attribut
* proprits optionnelles des attributs de type `String` :
- `fulltextindexed` : boolen indiquant si l'attribut participe l'index plein
texte (faux par dfaut) (*valable galement sur le type `Byte`*)
- `internationalizable` : boolen indiquant si la valeur de cet attribut est
internationalisable (faux par dfaut)
- `maxsize` : entier donnant la taille maximum de la chaine (pas de limite par
dfaut)
* proprits optionnelles des relations :
- `composite` : chane 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 composs le sont
galement.
Contraintes
```````````
Par dfaut les types de contraintes suivant sont disponibles :
* `SizeConstraint` : permet de spcifier une taille minimale et/ou maximale sur
les chaines de caractres (cas gnrique de `maxsize`)
* `BoundConstraint` : permet de spcifier une valeur minimale et/ou maximale sur
les types numriques
* `UniqueConstraint` : identique "unique=True"
* `StaticVocabularyConstraint` : identique "vocabulary=(...)"
* `RQLConstraint` : permet de spcifier une requte RQL devant tre satisfaite
par le sujet et/ou l'objet de la relation. Dans cette requte les variables `S`
et `O` sont prffinies respectivement comme l'entit sujet et objet de la
relation
* `RQLVocabularyConstraint` : similaire la prcdente, mais exprimant une
contrainte "faible", i.e. servant uniquement limiter les valeurs apparaissant
dans la liste droulantes du formulaire d'dition, mais n'empchant pas une
autre entit d'tre slctionne
Dfinition d'un type de relation
--------------------------------
Un type de relation est dfinit par une classe python hritant de `RelationType`. Le
nom de la classe correspond au nom du type. Ensuite le corps de la classe
contient la description des proprits de ce type de relation, ainsi
qu'ventuellement une chaine pour le sujet et une autre pour l'objet permettant
de crer des dfinitions de relations associes (auquel cas il est possibles de
donner sur la classe les proprits de dfinition de relation explicites
ci-dessus), par exemple ::
class verrouille_par(RelationType):
"""relation sur toutes les entits applicatives indiquant que celles-ci sont vrouilles
inlined = True
cardinality = '?*'
subject = '*'
object = 'CWUser'
En plus des permissions, les proprits propres aux types de relation (et donc
partags par toutes les dfinitions de relation de ce type) sont :
* `inlined` : boolen contrlant l'optimisation physique consistant stocker la
relation dans la table de l'entit sujet au lieu de crer une table spcifique
la relation. Cela se limite donc aux relations dont la cardinalit
sujet->relation->objet vaut 0..1 ('?') ou 1..1 ('1')
* `symmetric` : boolen indiquant que la relation est symtrique, i.e. "X relation
Y" implique "Y relation X"
Dans le cas de dfinitions de relations simultane, `sujet` et `object` peuvent
tout deux valoir la mme chose que dcrite pour le 1er argument de
`SubjectRelation` et `ObjectRelation`.
A partir du moment o une relation n'est ni mise en ligne, ni symtrique, et
ne ncessite pas de permissions particulires, sa dfinition (en utilisant
`SubjectRelation` ou `ObjectRelation`) est suffisante.
Dfinition des permissions
--------------------------
La dfinition des permissions se fait l'aide de l'attribut `permissions` des
types d'entit ou de relation. Celui-ci est un dictionnaire dont les cls sont
les types d'accs (action), et les valeurs les groupes ou expressions autorises.
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'accs, un tuple indique le nom des groupes autoriss et/ou
une ou plusieurs expressions RQL devant tre vrifies pour obtenir
l'accs. L'accs est donn partir du moment o l'utilisateur fait parti d'un
des groupes requis ou ds qu'une expression RQL est vrifie.
Les groupes standards sont :
* `guests`
* `users`
* `managers`
* `owners` : groupe virtuel correspondant au propritaire 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 spcifiques devant tre pour
cela crs dans le precreate de l'application (`migration/precreate.py`).
Utilisation d'expression RQL sur les droits en criture
```````````````````````````````````````````````````````
Il est possible de dfinir 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 utilise correspond la clause WHERE d'une requte RQL
* dans cette expression, les variables X et U sont des rfrences prdfinies
respectivement sur l'entit courante (sur laquelle l'action est vrifie) et
sur l'utilisateur ayant effectu la requte
* il est possible d'utiliser dans cette expression les relations spciales
"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 entits lies cette
variable
Pour les expressions RQL sur un type de relation, les principes sont les mmes
avec les diffrences 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 rfrences
prdfinies respectivement sur le sujet et l'objet de la relation
courante (sur laquelle l'action est vrifie) et sur l'utilisateur
ayant effectu la requte
* On peut aussi dfinir des droits sur les attributs d'une entit (relation non
finale), sachant les points suivants :
- pour dfinir des expressions rql, il faut utiliser la classe `ERQLExpression`
dans laquelle X reprsentera l'entit auquel appartient l'attribut
- les permissions 'add' et 'delete' sont quivalentes. En pratique seul
'add'/'read' son pris en considration
En plus de cela, le type d'entit `CWPermission` de la librairie standard permet
de construire des modles de scurits trs complexes et dynamiques. Le schma
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 associe un projet et donner le droit de crer des
versions sur ce projet des groupes spcifiques. Il est important de noter les
points suivants :
* dans ce cas il faut protger la fois le type d'entit "Version" et la
relation liant une version un projet ("version_of")
* du fait de la gnricit du type d'entit `CWPermission`, il faut effectuer
l'unification avec les groupes et / ou les tats le cas chant 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 mmes mais avec les restrictions suivantes :
* on ne peut de `RRQLExpression` sur les types de relation en lecture
* les relations spciales "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 problme pour l'interface utilisateur car si l'expression
utilise l'entit ou la relation crer, on est pas capable de vrifier les
droits avant d'avoir effectu l'ajout (noter que cela n'est pas un problme cot
serveur rql car la vrification des droits est effectue aprs l'ajout
effectif). Dans ce cas les mthodes de vrification 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 gnral
ncessaire dans tel cas d'utiliser une action refltant les droits du schma
mais permettant de faire la vrification correctement afin qu'elle apparaisse
bien le cas chant.