schemas/base.py
changeset 0 b97547f5f1fa
child 6 29ab115b9fcb
equal deleted inserted replaced
-1:000000000000 0:b97547f5f1fa
       
     1 """core CubicWeb schema, but not necessary at bootstrap time
       
     2 
       
     3 :organization: Logilab
       
     4 :copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
       
     5 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
       
     6 """
       
     7 __docformat__ = "restructuredtext en"
       
     8 
       
     9 from cubicweb.schema import format_constraint
       
    10 
       
    11 
       
    12 class EUser(RestrictedEntityType):
       
    13     """define a CubicWeb user"""
       
    14     permissions = {
       
    15         'read':   ('managers', 'users', ERQLExpression('X identity U')),
       
    16         'add':    ('managers',),
       
    17         'delete': ('managers',),
       
    18         'update': ('managers', ERQLExpression('X identity U, NOT U in_group G, G name "guests"'),),
       
    19         }
       
    20 
       
    21     login     = String(required=True, unique=True, maxsize=64,
       
    22                        description=_('unique identifier used to connect to the application'))
       
    23     upassword = Password(required=True) # password is a reserved word for mysql
       
    24     firstname = String(maxsize=64)
       
    25     surname   = String(maxsize=64)
       
    26     last_login_time  = Datetime(description=_('last connection date'))
       
    27     # allowing an email to be the primary email of multiple entities is necessary for
       
    28     # test at least :-/    
       
    29     primary_email = SubjectRelation('EmailAddress', cardinality='??',
       
    30                                     description=_('email address to use for notification'))
       
    31     use_email     = SubjectRelation('EmailAddress', cardinality='*?', composite='subject')
       
    32 
       
    33     in_group = SubjectRelation('EGroup', cardinality='+*',
       
    34                                constraints=[RQLConstraint('NOT O name "owners"')],
       
    35                                description=_('groups grant permissions to the user'))
       
    36     in_state = SubjectRelation('State', cardinality='1*',
       
    37                                # XXX automatize this
       
    38                                constraints=[RQLConstraint('S is ET, O state_of ET')],
       
    39                                description=_('account state'))
       
    40     wf_info_for = ObjectRelation('TrInfo', cardinality='1*', composite='object')
       
    41 
       
    42 
       
    43 class EmailAddress(MetaEntityType):
       
    44     """an electronic mail address associated to a short alias"""
       
    45     permissions = {
       
    46         'read':   ('managers', 'users', 'guests',), # XXX if P use_email X, U has_read_permission P
       
    47         'add':    ('managers', 'users',),
       
    48         'delete': ('managers', 'owners', ERQLExpression('P use_email X, U has_update_permission P')),
       
    49         'update': ('managers', 'owners', ERQLExpression('P use_email X, U has_update_permission P')),
       
    50         }
       
    51     
       
    52     alias   = String(fulltextindexed=True, maxsize=56)
       
    53     address = String(required=True, fulltextindexed=True, 
       
    54                      indexed=True, unique=True, maxsize=128)
       
    55     canonical = Boolean(default=False,
       
    56                         description=_('when multiple addresses are equivalent \
       
    57 (such as python-projects@logilab.org and python-projects@lists.logilab.org), set this \
       
    58 to true on one of them which is the preferred form.'))
       
    59     identical_to = SubjectRelation('EmailAddress')
       
    60 
       
    61 class use_email(RelationType):
       
    62     """"""
       
    63     permissions = {
       
    64         'read':   ('managers', 'users', 'guests',),
       
    65         'add':    ('managers', RRQLExpression('U has_update_permission S'),),
       
    66         'delete': ('managers', RRQLExpression('U has_update_permission S'),),
       
    67         }
       
    68     fulltext_container = 'subject'
       
    69 
       
    70 class primary_email(RelationType):
       
    71     """the prefered email"""
       
    72     permissions = use_email.permissions
       
    73     
       
    74 class identical_to(RelationType):
       
    75     """identical_to"""
       
    76     symetric = True
       
    77     permissions = {
       
    78         'read':   ('managers', 'users', 'guests',),
       
    79         # XXX should have update permissions on both subject and object,
       
    80         #     though by doing this we will probably have no way to add
       
    81         #     this relation in the web ui. The easiest way to acheive this
       
    82         #     is probably to be able to have "U has_update_permission O" as
       
    83         #     RQLConstraint of the relation definition, though this is not yet
       
    84         #     possible
       
    85         'add':    ('managers', RRQLExpression('U has_update_permission S'),),
       
    86         'delete': ('managers', RRQLExpression('U has_update_permission S'),),
       
    87         }
       
    88 
       
    89 class in_group(MetaRelationType):
       
    90     """core relation indicating a user's groups"""
       
    91     meta = False
       
    92     
       
    93 class owned_by(MetaRelationType):
       
    94     """core relation indicating owners of an entity. This relation
       
    95     implicitly put the owner into the owners group for the entity
       
    96     """
       
    97     permissions = {
       
    98         'read':   ('managers', 'users', 'guests'),
       
    99         'add':    ('managers', RRQLExpression('S owned_by U'),), 
       
   100         'delete': ('managers', RRQLExpression('S owned_by U'),),
       
   101         }
       
   102     # 0..n cardinality for entities created by internal session (no attached user)
       
   103     # and to support later deletion of a user which has created some entities
       
   104     cardinality = '**'
       
   105     subject = '**'
       
   106     object = 'EUser'
       
   107     
       
   108 class created_by(MetaRelationType):
       
   109     """core relation indicating the original creator of an entity"""
       
   110     permissions = {
       
   111         'read':   ('managers', 'users', 'guests'),
       
   112         'add':    ('managers',),
       
   113         'delete': ('managers',),
       
   114         }
       
   115     # 0..1 cardinality for entities created by internal session (no attached user)
       
   116     # and to support later deletion of a user which has created some entities
       
   117     cardinality = '?*' 
       
   118     subject = '**'
       
   119     object = 'EUser'
       
   120 
       
   121     
       
   122 class creation_date(MetaAttributeRelationType):
       
   123     """creation time of an entity"""
       
   124     cardinality = '11'
       
   125     subject = '**'
       
   126     object = 'Datetime'
       
   127 
       
   128 class modification_date(MetaAttributeRelationType):
       
   129     """latest modification time of an entity"""
       
   130     cardinality = '11'
       
   131     subject = '**'
       
   132     object = 'Datetime'
       
   133 
       
   134 
       
   135 class State(MetaEntityType):
       
   136     """used to associate simple states to an entity type and/or to define
       
   137     workflows
       
   138     """
       
   139     name = String(required=True, indexed=True, internationalizable=True,
       
   140                   maxsize=256)
       
   141     description_format = String(meta=True, internationalizable=True, maxsize=50,
       
   142                                 default='text/rest', constraints=[format_constraint])
       
   143     description = String(fulltextindexed=True,
       
   144                          description=_('semantic description of this state'))
       
   145     
       
   146     state_of = SubjectRelation('EEType', cardinality='+*',
       
   147                     description=_('entity types which may use this state'),
       
   148                     constraints=[RQLConstraint('O final FALSE')])
       
   149     allowed_transition = SubjectRelation('Transition', cardinality='**',
       
   150                                          constraints=[RQLConstraint('S state_of ET, O transition_of ET')],
       
   151                                          description=_('allowed transitions from this state'))
       
   152     
       
   153     initial_state = ObjectRelation('EEType', cardinality='?*',
       
   154                                    # S initial_state O, O state_of S
       
   155                                    constraints=[RQLConstraint('O state_of S')],
       
   156                                    description=_('initial state for entities of this type'))
       
   157 
       
   158 
       
   159 class Transition(MetaEntityType):
       
   160     """use to define a transition from one or multiple states to a destination
       
   161     states in workflow's definitions.
       
   162     """
       
   163     name = String(required=True, indexed=True, internationalizable=True,
       
   164                   maxsize=256)
       
   165     description_format = String(meta=True, internationalizable=True, maxsize=50,
       
   166                                 default='text/rest', constraints=[format_constraint])
       
   167     description = String(fulltextindexed=True,
       
   168                          description=_('semantic description of this transition'))
       
   169     condition = SubjectRelation('RQLExpression', cardinality='*?', composite='subject',
       
   170                                 description=_('a RQL expression which should return some results, '
       
   171                                               'else the transition won\'t be available. '
       
   172                                               'This query may use X and U variables '
       
   173                                               'that will respectivly represents '
       
   174                                               'the current entity and the current user'))
       
   175     
       
   176     require_group = SubjectRelation('EGroup', cardinality='**',
       
   177                                     description=_('group in which a user should be to be '
       
   178                                                   'allowed to pass this transition'))
       
   179     transition_of = SubjectRelation('EEType', cardinality='+*',
       
   180                                     description=_('entity types which may use this transition'),
       
   181                                     constraints=[RQLConstraint('O final FALSE')])
       
   182     destination_state = SubjectRelation('State', cardinality='?*',
       
   183                                         constraints=[RQLConstraint('S transition_of ET, O state_of ET')],
       
   184                                         description=_('destination state for this transition'))
       
   185 
       
   186 
       
   187 class TrInfo(MetaEntityType):
       
   188     from_state = SubjectRelation('State', cardinality='?*')
       
   189     to_state = SubjectRelation('State', cardinality='1*')
       
   190     comment_format = String(meta=True, internationalizable=True, maxsize=50,
       
   191                             default='text/rest', constraints=[format_constraint])
       
   192     comment = String(fulltextindexed=True)
       
   193     # get actor and date time using owned_by and creation_date
       
   194 
       
   195 
       
   196 class from_state(MetaRelationType):
       
   197     inlined = True
       
   198 class to_state(MetaRelationType):
       
   199     inlined = True
       
   200 class wf_info_for(MetaRelationType):
       
   201     """link a transition information to its object"""
       
   202     permissions = {
       
   203         'read':   ('managers', 'users', 'guests',),# RRQLExpression('U has_read_permission O')),
       
   204         'add':    (), # handled automatically, no one should add one explicitly
       
   205         'delete': ('managers',), # RRQLExpression('U has_delete_permission O')
       
   206         }
       
   207     inlined = True
       
   208     composite = 'object'
       
   209     fulltext_container = composite
       
   210     
       
   211 class state_of(MetaRelationType):
       
   212     """link a state to one or more entity type"""
       
   213 class transition_of(MetaRelationType):
       
   214     """link a transition to one or more entity type"""
       
   215     
       
   216 class initial_state(MetaRelationType):
       
   217     """indicate which state should be used by default when an entity using
       
   218     states is created
       
   219     """
       
   220     inlined = True
       
   221 
       
   222 class destination_state(MetaRelationType):
       
   223     """destination state of a transition"""
       
   224     inlined = True
       
   225     
       
   226 class allowed_transition(MetaRelationType):
       
   227     """allowed transition from this state"""
       
   228 
       
   229 class in_state(UserRelationType):
       
   230     """indicate the current state of an entity"""
       
   231     meta = True
       
   232     # not inlined intentionnaly since when using ldap sources, user'state
       
   233     # has to be stored outside the EUser table
       
   234     
       
   235     # add/delete perms given to managers/users, after what most of the job
       
   236     # is done by workflow enforcment
       
   237     
       
   238 
       
   239 class EProperty(EntityType):
       
   240     """used for cubicweb configuration. Once a property has been created you
       
   241     can't change the key.
       
   242     """
       
   243     permissions = {
       
   244         'read':   ('managers', 'users', 'guests'),
       
   245         'add':    ('managers', 'users',),
       
   246         'update': ('managers', 'owners',),
       
   247         'delete': ('managers', 'owners',),
       
   248         }
       
   249     meta = True
       
   250     # key is a reserved word for mysql
       
   251     pkey = String(required=True, internationalizable=True, maxsize=256,
       
   252                   description=_('defines what\'s the property is applied for. '
       
   253                                 'You must select this first to be able to set '
       
   254                                 'value'))
       
   255     value = String(internationalizable=True, maxsize=256)
       
   256     
       
   257     for_user = SubjectRelation('EUser', cardinality='?*', composite='object',
       
   258                                description=_('user for which this property is '
       
   259                                              'applying. If this relation is not '
       
   260                                              'set, the property is considered as'
       
   261                                              ' a global property'))
       
   262 
       
   263 
       
   264 class for_user(MetaRelationType):
       
   265     """link a property to the user which want this property customization. Unless
       
   266     you're a site manager, this relation will be handled automatically.
       
   267     """
       
   268     permissions = {
       
   269         'read':   ('managers', 'users', 'guests'),
       
   270         'add':    ('managers',),
       
   271         'delete': ('managers',),
       
   272         }
       
   273     inlined = True
       
   274 
       
   275 
       
   276 class EPermission(MetaEntityType):
       
   277     """entity type that may be used to construct some advanced security configuration
       
   278     """
       
   279     name = String(required=True, indexed=True, internationalizable=True, maxsize=100,
       
   280                   description=_('name or identifier of the permission'))
       
   281     label = String(required=True, internationalizable=True, maxsize=100,
       
   282                    description=_('distinct label to distinguate between other permission entity of the same name'))
       
   283     require_group = SubjectRelation('EGroup', 
       
   284                                     description=_('groups to which the permission is granted'))
       
   285 
       
   286 # explicitly add X require_permission EPermission for each entity that should have
       
   287 # configurable security
       
   288 class require_permission(RelationType):
       
   289     """link a permission to the entity. This permission should be used in the
       
   290     security definition of the entity's type to be useful.
       
   291     """
       
   292     permissions = {
       
   293         'read':   ('managers', 'users', 'guests'),
       
   294         'add':    ('managers',),
       
   295         'delete': ('managers',),
       
   296         }
       
   297     
       
   298 class require_group(MetaRelationType):
       
   299     """used to grant a permission to a group"""
       
   300     permissions = {
       
   301         'read':   ('managers', 'users', 'guests'),
       
   302         'add':    ('managers',),
       
   303         'delete': ('managers',),
       
   304         }
       
   305 
       
   306     
       
   307 class see_also(RelationType):
       
   308     """generic relation to link one entity to another"""
       
   309     symetric = True
       
   310 
       
   311 class ECache(EntityType):
       
   312     name = String(required=True, unique=True, indexed=True, 
       
   313                   description=_('name of the cache'))
       
   314     timestamp = Datetime(default='NOW')