diff -r 058bb3dc685f -r 0b59724cb3f2 cubicweb/schemas/base.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cubicweb/schemas/base.py Sat Jan 16 13:48:51 2016 +0100 @@ -0,0 +1,383 @@ +# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved. +# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr +# +# This file is part of CubicWeb. +# +# CubicWeb is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 2.1 of the License, or (at your option) +# any later version. +# +# CubicWeb is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License along +# with CubicWeb. If not, see . +"""core CubicWeb schema, but not necessary at bootstrap time""" + +__docformat__ = "restructuredtext en" +from cubicweb import _ + +from yams.buildobjs import (EntityType, RelationType, RelationDefinition, + SubjectRelation, + String, TZDatetime, Datetime, Password, Interval, + Boolean, UniqueConstraint) +from cubicweb.schema import ( + RQLConstraint, WorkflowableEntityType, ERQLExpression, RRQLExpression, + PUB_SYSTEM_ENTITY_PERMS, PUB_SYSTEM_REL_PERMS, PUB_SYSTEM_ATTR_PERMS, + RO_ATTR_PERMS) + +class CWUser(WorkflowableEntityType): + """define a CubicWeb user""" + __permissions__ = { + 'read': ('managers', 'users', ERQLExpression('X identity U')), + 'add': ('managers',), + 'delete': ('managers',), + 'update': ('managers', ERQLExpression('X identity U, NOT U in_group G, G name "guests"'),), + } + + login = String(required=True, unique=True, maxsize=64, + description=_('unique identifier used to connect to the application')) + upassword = Password(required=True) # password is a reserved word for mysql + firstname = String(maxsize=64) + surname = String(maxsize=64) + last_login_time = TZDatetime(description=_('last connection date')) + in_group = SubjectRelation('CWGroup', cardinality='+*', + constraints=[RQLConstraint('NOT O name "owners"')], + description=_('groups grant permissions to the user')) + + +class EmailAddress(EntityType): + """an electronic mail address associated to a short alias""" + __permissions__ = { + # application that wishes public email, or use it for something else + # than users (eg Company, Person), should explicitly change permissions + 'read': ('managers', ERQLExpression('U use_email X')), + 'add': ('managers', 'users',), + 'delete': ('managers', 'owners', ERQLExpression('P use_email X, U has_update_permission P')), + 'update': ('managers', 'owners', ERQLExpression('P use_email X, U has_update_permission P')), + } + + alias = String(fulltextindexed=True, maxsize=56) + address = String(required=True, fulltextindexed=True, + indexed=True, unique=True, maxsize=128) + prefered_form = SubjectRelation('EmailAddress', cardinality='?*', + description=_('when multiple addresses are equivalent \ +(such as python-projects@logilab.org and python-projects@lists.logilab.org), set this \ +to indicate which is the preferred form.')) + +class use_email(RelationType): + fulltext_container = 'subject' + + +class use_email_relation(RelationDefinition): + """user's email account""" + name = "use_email" + __permissions__ = { + 'read': ('managers', 'users', 'guests',), + 'add': ('managers', RRQLExpression('U has_update_permission S'),), + 'delete': ('managers', RRQLExpression('U has_update_permission S'),), + } + subject = "CWUser" + object = "EmailAddress" + cardinality = '*?' + composite = 'subject' + + +class primary_email(RelationDefinition): + """the prefered email""" + __permissions__ = { + 'read': ('managers', 'users', 'guests',), + 'add': ('managers', RRQLExpression('U has_update_permission S'),), + 'delete': ('managers', RRQLExpression('U has_update_permission S'),), + } + subject = "CWUser" + object = "EmailAddress" + cardinality = '??' + constraints= [RQLConstraint('S use_email O')] + + +class prefered_form(RelationType): + __permissions__ = { + 'read': ('managers', 'users', 'guests',), + # XXX should have update __permissions__ on both subject and object, + # though by doing this we will probably have no way to add + # this relation in the web ui. The easiest way to acheive this + # is probably to be able to have "U has_update_permission O" as + # RQLConstraint of the relation definition, though this is not yet + # possible + 'add': ('managers', RRQLExpression('U has_update_permission S'),), + 'delete': ('managers', RRQLExpression('U has_update_permission S'),), + } + +class in_group(RelationType): + """core relation indicating a user's groups""" + __permissions__ = PUB_SYSTEM_REL_PERMS + +class owned_by(RelationType): + """core relation indicating owners of an entity. This relation + implicitly put the owner into the owners group for the entity + """ + __permissions__ = { + 'read': ('managers', 'users', 'guests'), + 'add': ('managers', RRQLExpression('S owned_by U'),), + 'delete': ('managers', RRQLExpression('S owned_by U'),), + } + # 0..n cardinality for entities created by internal session (no attached user) + # and to support later deletion of a user which has created some entities + cardinality = '**' + subject = '*' + object = 'CWUser' + +class created_by(RelationType): + """core relation indicating the original creator of an entity""" + __permissions__ = { + 'read': ('managers', 'users', 'guests'), + 'add': ('managers',), + 'delete': ('managers',), + } + # 0..1 cardinality for entities created by internal session (no attached user) + # and to support later deletion of a user which has created some entities + cardinality = '?*' + subject = '*' + object = 'CWUser' + + +class creation_date(RelationType): + """creation time of an entity""" + __permissions__ = PUB_SYSTEM_ATTR_PERMS + cardinality = '11' + subject = '*' + object = 'TZDatetime' + + +class modification_date(RelationType): + """latest modification time of an entity""" + __permissions__ = PUB_SYSTEM_ATTR_PERMS + cardinality = '11' + subject = '*' + object = 'TZDatetime' + + +class cwuri(RelationType): + """internal entity uri""" + __permissions__ = RO_ATTR_PERMS + cardinality = '11' + subject = '*' + object = 'String' + + +# XXX find a better relation name +class for_user(RelationType): + """link a property to the user which want this property customization. Unless + you're a site manager, this relation will be handled automatically. + """ + __permissions__ = { + 'read': ('managers', 'users', 'guests'), + 'add': ('managers',), + 'delete': ('managers',), + } + inlined = True + subject = 'CWProperty' + object = 'CWUser' + composite = 'object' + cardinality = '?*' + + +class ExternalUri(EntityType): + """a URI representing an object in external data store""" + uri = String(required=True, unique=True, maxsize=256, + description=_('the URI of the object')) + + +class same_as(RelationType): + """generic relation to specify that an external entity represent the same + object as a local one: + http://www.w3.org/TR/owl-ref/#sameAs-def + """ + #NOTE: You'll have to explicitly declare which entity types can have a + #same_as relation + __permissions__ = { + 'read': ('managers', 'users', 'guests',), + 'add': ('managers', 'users'), + 'delete': ('managers', 'owners'), + } + cardinality = '**' + symmetric = True + # NOTE: the 'object = ExternalUri' declaration will still be mandatory + # in the cube's schema. + object = 'ExternalUri' + + +class CWCache(EntityType): + """a simple cache entity characterized by a name and + a validity date. + + The target application is responsible for updating timestamp + when necessary to invalidate the cache (typically in hooks). + + Also, checkout the AppObject.get_cache() method. + """ + # XXX only handle by hooks, shouldn't be readable/editable at all through + # the ui and so no permissions should be granted, no? + __permissions__ = { + 'read': ('managers', 'users', 'guests'), + 'add': ('managers',), + 'update': ('managers', 'users',), # XXX + 'delete': ('managers',), + } + + name = String(required=True, unique=True, maxsize=128, + description=_('name of the cache')) + timestamp = TZDatetime(default='NOW') + + +class CWSource(EntityType): + __permissions__ = { + 'read': ('managers', 'users', 'guests'), + 'add': ('managers',), + 'update': ('managers',), + 'delete': ('managers',), + } + name = String(required=True, unique=True, maxsize=128, + description=_('name of the source')) + type = String(required=True, maxsize=20, description=_('type of the source')) + config = String(description=_('source\'s configuration. One key=value per ' + 'line, authorized keys depending on the ' + 'source\'s type'), + __permissions__={ + 'read': ('managers',), + 'add': ('managers',), + 'update': ('managers',), + }) + # put this here and not in a subclass even if it's only for some sources + # since having subclasses on generic relation (cw_source) double the number + # of rdef in the schema, and make ms planning harder since queries solutions + # may changes when sources are specified + url = String(description=_('URLs from which content will be imported. You can put one url per line')) + parser = String(description=_('parser to use to extract entities from content retrieved at given URLs.')) + latest_retrieval = TZDatetime(description=_('latest synchronization time')) + in_synchronization = TZDatetime(description=_('start timestamp of the currently in synchronization, or NULL when no synchronization in progress.')) + + +ENTITY_MANAGERS_PERMISSIONS = { + 'read': ('managers',), + 'add': ('managers',), + 'update': ('managers',), + 'delete': ('managers',), + } +RELATION_MANAGERS_PERMISSIONS = { + 'read': ('managers',), + 'add': ('managers',), + 'delete': ('managers',), + } + + +class CWSourceHostConfig(EntityType): + __permissions__ = ENTITY_MANAGERS_PERMISSIONS + __unique_together__ = [('match_host', 'cw_host_config_of')] + match_host = String(required=True, maxsize=128, + description=_('regexp matching host(s) to which this config applies')) + config = String(required=True, + description=_('Source\'s configuration for a particular host. ' + 'One key=value per line, authorized keys ' + 'depending on the source\'s type, overriding ' + 'values defined on the source.'), + __permissions__={ + 'read': ('managers',), + 'add': ('managers',), + 'update': ('managers',), + }) + + +class cw_host_config_of(RelationDefinition): + __permissions__ = RELATION_MANAGERS_PERMISSIONS + subject = 'CWSourceHostConfig' + object = 'CWSource' + cardinality = '1*' + composite = 'object' + inlined = True + +class cw_source(RelationDefinition): + __permissions__ = { + 'read': ('managers', 'users', 'guests'), + 'add': ('managers',), + 'delete': ('managers',), + } + subject = '*' + object = 'CWSource' + cardinality = '1*' + composite = 'object' + + +class CWDataImport(EntityType): + __permissions__ = ENTITY_MANAGERS_PERMISSIONS + start_timestamp = TZDatetime() + end_timestamp = TZDatetime() + log = String() + status = String(required=True, internationalizable=True, indexed=True, + default='in progress', + vocabulary=[_('in progress'), _('success'), _('failed')]) + +class cw_import_of(RelationDefinition): + __permissions__ = RELATION_MANAGERS_PERMISSIONS + subject = 'CWDataImport' + object = 'CWSource' + cardinality = '1*' + composite = 'object' + + +class CWSourceSchemaConfig(EntityType): + __permissions__ = ENTITY_MANAGERS_PERMISSIONS + cw_for_source = SubjectRelation( + 'CWSource', inlined=True, cardinality='1*', composite='object', + __permissions__=RELATION_MANAGERS_PERMISSIONS) + options = String(description=_('allowed options depends on the source type')) + + +class rtype_cw_schema(RelationDefinition): + __permissions__ = RELATION_MANAGERS_PERMISSIONS + name = 'cw_schema' + subject = 'CWSourceSchemaConfig' + object = ('CWEType', 'CWRType') + inlined = True + cardinality = '1*' + composite = 'object' + constraints = [RQLConstraint('NOT O final TRUE')] + +class rdef_cw_schema(RelationDefinition): + __permissions__ = RELATION_MANAGERS_PERMISSIONS + name = 'cw_schema' + subject = 'CWSourceSchemaConfig' + object = 'CWRelation' + inlined = True + cardinality = '1*' + composite = 'object' + +# "abtract" relation types, no definition in cubicweb itself ################### + +class identical_to(RelationType): + """identical to""" + symmetric = True + __permissions__ = { + 'read': ('managers', 'users', 'guests',), + # XXX should have update __permissions__ on both subject and object, + # though by doing this we will probably have no way to add + # this relation in the web ui. The easiest way to acheive this + # is probably to be able to have "U has_update_permission O" as + # RQLConstraint of the relation definition, though this is not yet + # possible + 'add': ('managers', RRQLExpression('U has_update_permission S'),), + 'delete': ('managers', RRQLExpression('U has_update_permission S'),), + } + +class see_also(RelationType): + """generic relation to link one entity to another""" + symmetric = True + __permissions__ = { + 'read': ('managers', 'users', 'guests',), + 'add': ('managers', RRQLExpression('U has_update_permission S'),), + 'delete': ('managers', RRQLExpression('U has_update_permission S'),), + }