diff -r 52bf52e6fc77 -r 1091d8d63f51 doc/book/en/03-00-sect-definition-schema.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/03-00-sect-definition-schema.en.txt Thu Nov 20 20:14:23 2008 +0100 @@ -0,0 +1,344 @@ +.. -*- coding: utf-8 -*- + +Entity type definition +---------------------- + +An entity type is defined by a Python class which inherits `EntityType`. The +class name correponds to the type name. Then the content of the class contains +the description of attributes and relations for the defined entity type, +by example :: + + class Personne(EntityType): + """A person with the properties and the relations necessarry for my + application""" + + last_name = String(required=True, fulltextindexed=True) + first_name = String(required=True, fulltextindexed=True) + title = String(vocabulary=('M', 'Mme', 'Mlle')) + date_of_birth = Date() + works_for = SubjectRelation('Company', cardinality='?*') + +* the name of the Python attribute corresponds to the name of the attribute + or the relation in `LAX` application. + +* all built-in types are available: `String`, `Int`, `Float`, + `Boolean`, `Date`, `Datetime`, `Time`, `Byte`. + +* each entity has at least the following meta-relations: + + - `eid` (`Int`) + + - `creation_date` (`Datetime`) + + - `modification_date` (`Datetime`) + + - `created_by` (`EUser`) (which user created the entity) + + - `owned_by` (`EUser`) (who does the entity belongs to, by default the + creator but not necessarry and it could have multiple owners) + + - `is` (`EEType`) + + +* it is also possible to define relations of type object by using `ObjectRelation` + instead of `SubjectRelation` + +* the first argument of `SubjectRelation` and `ObjectRelation` gives respectively + the object/subject entity type of the relation. This could be: + + * a string corresponding to an entity type + + * a tuple of string correponding to multiple entities types + + * special string such as follows: + + - "**" : all types of entities + - "*" : all types of entities non meta + - "@" : all types of meta entities but not system entities (e.g. used for + the basis schema description) + +* it is possible to use the attribute `meta` to flag an entity type as a `meta` + (e.g. used to describe/categorize other entities) + +* optional properties for attributes and relations: + + - `description` : string describing an attribute or a relation. By default + this string will be used in the editing form of the entity, which means + that it is supposed to help the end-user and should be flagged by the + function `_` to be properly internationalized. + + - `constraints` : list of conditions/constraints that the relation needs to + satisfy (c.f. `Contraints`_) + + - `cardinality` : two characters string which specify the cardinality of the + relation. The first character defines the cardinality of the relation on + the subject, the second on the object of the relation. When a relation + has multiple possible subjects or objects, the cardinality applies to all + and not on a one to one basis (so it must be consistent...). The possible + values are inspired from regular expressions syntax: + + * `1`: 1..1 + * `?`: 0..1 + * `+`: 1..n + * `*`: 0..n + + - `meta` : boolean indicating that the relation is a meta-relation (false by + default) + +* optionnal properties for attributes: + + - `required` : boolean indicating if the attribute is required (false by default) + + - `unique` : boolean indicating if the value of the attribute has to be unique + or not within all entities of the same type (false by default) + + - `indexed` : boolean indicating if an index needs to be created for this + attribute in the database (false by default). This is usefull only if + you know that you will have to run numerous searches on the value of this + attribute. + + - `default` : default value of the attribute. In case of date types, the values + which could be used correpond to the RQL keywords `TODAY` and `NOW`. + + - `vocabulary` : specify static possible values of an attribute + +* optionnal properties of type `String`: + + - `fulltextindexed` : boolean indicating if the attribute is part of + the full text index (false by default) (*applicable on the type `Byte` + as well*) + + - `internationalizable` : boolean indicating if the value of the attribute + is internationalizable (false by default) + + - `maxsize` : integer providing the maximum size of the string (no limit by default) + +* optionnal properties for relations: + + - `composite` : string indicating that the subject (composite == 'subject') + is composed of the objects of the relations. For the opposite case (when + the object is composed of the subjects of the relation), we just need + to set 'object' as the value. The composition implies that when the relation + is deleted (so when the composite is deleted), the composed are also deleted. + [PAS CLAIR] + +Contraints +`````````` +By default, the available constraints types are: + +* `SizeConstraint` : allows to specify a minimum and/or maximum size on + string (generic case of `maxsize`) + +* `BoundConstraint` : allows to specify a minimum and/or maximum value on + numeric types + +* `UniqueConstraint` : identical to "unique=True" + +* `StaticVocabularyConstraint` : identical to "vocabulary=(...)" + +* `RQLConstraint` : allows to specify a RQL query that needs to be satisfied + by the subject and/or the object of the relation. In this query the variables + `S` and `O` are reserved for the entities subject and object of the + relation. + +* `RQLVocabularyConstraint` : similar to the previous type of constraint except + that it does not express a "strong" constraint, which means it is only used to + restrict the values listed in the drop-down menu of editing form, but it does + not prevent another entity to be selected + [PAS CLAIR] + + +Relation type definition +------------------------ + +A relation is defined by a Python class heriting `RelationType`. The name +of the class corresponds to the name of the type. The class then contains +a description of the properties of this type of relation, as well as a +string for the subject and a string for the object. This allows to create +new definition of associated relations, (so that the class can have the +definition properties from the relation)[PAS CLAIR] by example :: + + class locked_by(RelationType): + """relation on all entities indicating that they are locked""" + inlined = True + cardinality = '?*' + subject = '*' + object = 'EUser' + +In addition to the permissions, the own properties of the relation types +(shared also by all definition of relation of this type) are: + + +* `inlined` : boolean handling the physical optimization for archiving + the relation in the subject entity table, instead of creating a specific + table for the relation. This applies to the relation when the cardinality + of subject->relation->object is 0..1 ('?') or 1..1 ('1') + +* `symetric` : boolean indication that the relation is symetrical, which + means `X relation Y` implies `Y relation X` + +In the case of simultaneous relations definitions, `subject` and `object` +can both be equal to the value of the first argument of `SubjectRelation` +and `ObjectRelation`. + +When a relation is not inlined and not symetrical, and it does not require +specific permissions, its definition (by using `SubjectRelation` and +`ObjectRelation`) is all we need. + +Permissions definition +---------------------- + +Define permissions is set through to the attribute `permissions` of entities and +relations types. It defines a dictionnary where the keys are the access types +(action), and the values are the authorized groups or expressions. + +For an entity type, the possible actions are `read`, `add`, `update` and +`delete`. + +For a relation type, the possible actions are `read`, `add`, and `delete`. + +For each access type, a tuple indicates the name of the authorized groups and/or +one or multiple RQL expressions to satisfy to grant access. The access is +provided once the user is in the listed groups or one of the RQL condition is +satisfied. + +The standard groups are: + +* `guests` + +* `users` + +* `managers` + +* `owners` : virtual group corresponding to the entity's owner. + This can only be used for the actions `update` and `delete` of an entity + type. + +It is also possible to use specific groups if they are define in the precreate +of the application (``migration/precreate.py``). + +Use of RQL expression for writing rights +```````````````````````````````````````` +It is possible to define RQL expression to provide update permission +(`add`, `delete` and `update`) on relation and entity types. + +RQL expression for entity type permission: + +* you have to use the class `ERQLExpression` + +* the used expression corresponds to the WHERE statement of an RQL query + +* in this expression, the variables X and U are pre-defined references + respectively on the current entity (on which the action is verified) and + on the user who send the request + +* it is possible to use, in this expression, a special relation + "has__permission" where the subject is the user and the + object is a any variable, meaning that the user needs to have + permission to execute the action on the entities related + to this variable + +For RQL expressions on a relation type, the principles are the same except +for the following: + +* you have to use the class `RQLExpression` in the case of a non-final relation + [WHAT IS A NON FINALE RELATION] + +* in the expression, the variables S, O and U are pre-defined references + to respectively the subject and the object of the current relation (on + which the action is being verified) and the user who executed the query + +* we can also defined rights on attributes of an entity (non-final relation), + knowing that: + + - to defines RQL expression, we have to use the class `ERQLExpression` + in which X represents the entity the attribute belongs to + + - the permissions `add` and `delete` are equivalent. Only `add`/`read` + are actually taken in consideration. + + + +In addition to thatm the entity type `EPermission` from the standard library +allow to build very complex and dynamic security architecture. The schema of +this entity type is as follow: :: + + class EPermission(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('EGroup', 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.")) + + +Example of configuration :: + + ... + + 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 + +This configuration assumes/indicates [???] that an entity `EPermission` named +"add_version" can be associated to a project and provides rights to create +new versions on this project to specific groups. It is important to notice that: + +* in such case, we have to protect both the entity type "Version" and the relation + associating a version to a project ("version_of") + +* because of the genricity of the entity type `EPermission`, we have to execute + a unification with the groups and/or the states if necessary in the expression + ("U in_group G, P require_group G" in the above example) + + +Use of RQL expression for reading rights +```````````````````````````````````````` + +The principles are the same but with the following restrictions: + +* we can not [??] `RRQLExpression` on relation types for reading + +* special relations "has__permission" can not be used + + +Note on the use of RQL expression for `add` permission +`````````````````````````````````````````````````````` +Potentially, the use of an RQL expression to add an entity or a relation +can cause problems for the user interface, because if the expression uses +the entity or the relation to create, then we are not able to verify the +permissions before we actually add the entity (please note that this is +not a problem for the RQL server at all, because the permissions checks are +done after the creation). In such case, the permission checks methods +(check_perm, has_perm) can indicate that the user is not allowed to create +this entity but can obtain the permission. +To compensate this problem, it is usually necessary, for such case, +to use an action that reflects the schema permissions but which enables +to check properly the permissions so that it would show up if necessary. +[PAS CLAIR]