schemas/workflow.py
changeset 2968 0e3460341023
parent 2950 643570a7770f
child 2977 6dd4f4a3ff2a
equal deleted inserted replaced
2902:dd9f2dd02f85 2968:0e3460341023
     8 __docformat__ = "restructuredtext en"
     8 __docformat__ = "restructuredtext en"
     9 _ = unicode
     9 _ = unicode
    10 
    10 
    11 from yams.buildobjs import (EntityType, RelationType, SubjectRelation,
    11 from yams.buildobjs import (EntityType, RelationType, SubjectRelation,
    12                             ObjectRelation, RichString, String)
    12                             ObjectRelation, RichString, String)
    13 from cubicweb.schema import RQLConstraint
    13 from cubicweb.schema import RQLConstraint, RQLUniqueConstraint
    14 from cubicweb.schemas import META_ETYPE_PERMS, META_RTYPE_PERMS, HOOKS_RTYPE_PERMS
    14 from cubicweb.schemas import (META_ETYPE_PERMS, META_RTYPE_PERMS,
       
    15                               HOOKS_RTYPE_PERMS)
       
    16 
       
    17 class Workflow(EntityType):
       
    18     permissions = META_ETYPE_PERMS
       
    19 
       
    20     name = String(required=True, indexed=True, internationalizable=True,
       
    21                   maxsize=256)
       
    22     description = RichString(fulltextindexed=True, default_format='text/rest',
       
    23                              description=_('semantic description of this workflow'))
       
    24 
       
    25     workflow_of = SubjectRelation('CWEType', cardinality='+*',
       
    26                                   description=_('entity types which may use this workflow'),
       
    27                                   constraints=[RQLConstraint('O final FALSE')])
       
    28 
       
    29     initial_state = SubjectRelation('State', cardinality='?*',
       
    30                                    # S initial_state O, O state_of S
       
    31                                    constraints=[RQLConstraint('O state_of S')],
       
    32                                    description=_('initial state for this workflow'))
       
    33 
       
    34 
       
    35 class default_workflow(RelationType):
       
    36     """default workflow for this entity types"""
       
    37     permissions = META_RTYPE_PERMS
       
    38 
       
    39     subject = 'CWEType'
       
    40     object = 'Workflow'
       
    41     cardinality = '?*'
       
    42     constraints = [RQLConstraint('S final FALSE, O workflow_of S')]
       
    43 
    15 
    44 
    16 class State(EntityType):
    45 class State(EntityType):
    17     """used to associate simple states to an entity type and/or to define
    46     """used to associate simple states to an entity type and/or to define
    18     workflows
    47     workflows
    19     """
    48     """
    22     name = String(required=True, indexed=True, internationalizable=True,
    51     name = String(required=True, indexed=True, internationalizable=True,
    23                   maxsize=256)
    52                   maxsize=256)
    24     description = RichString(fulltextindexed=True, default_format='text/rest',
    53     description = RichString(fulltextindexed=True, default_format='text/rest',
    25                              description=_('semantic description of this state'))
    54                              description=_('semantic description of this state'))
    26 
    55 
    27     state_of = SubjectRelation('CWEType', cardinality='+*',
    56     # XXX should be on BaseTransition w/ AND/OR selectors when we will
    28                     description=_('entity types which may use this state'),
    57     # implements #345274
    29                     constraints=[RQLConstraint('O final FALSE')])
    58     allowed_transition = SubjectRelation('BaseTransition', cardinality='**',
    30     allowed_transition = SubjectRelation('Transition', cardinality='**',
    59                                          constraints=[RQLConstraint('S state_of WF, O transition_of WF')],
    31                                          constraints=[RQLConstraint('S state_of ET, O transition_of ET')],
       
    32                                          description=_('allowed transitions from this state'))
    60                                          description=_('allowed transitions from this state'))
    33 
    61     state_of = SubjectRelation('Workflow', cardinality='+*',
    34     initial_state = ObjectRelation('CWEType', cardinality='?*',
    62                                description=_('workflow to which this state belongs'),
    35                                    # S initial_state O, O state_of S
    63                                constraints=[RQLUniqueConstraint('S name N, Y state_of O, Y name N')])
    36                                    constraints=[RQLConstraint('O state_of S')],
    64 
    37                                    description=_('initial state for entities of this type'))
    65 
    38 
    66 class BaseTransition(EntityType):
    39 
    67     """abstract base class for transitions"""
    40 class Transition(EntityType):
       
    41     """use to define a transition from one or multiple states to a destination
       
    42     states in workflow's definitions.
       
    43     """
       
    44     permissions = META_ETYPE_PERMS
    68     permissions = META_ETYPE_PERMS
    45 
    69 
    46     name = String(required=True, indexed=True, internationalizable=True,
    70     name = String(required=True, indexed=True, internationalizable=True,
    47                   maxsize=256)
    71                   maxsize=256)
    48     description = RichString(fulltextindexed=True,
    72     description = RichString(fulltextindexed=True,
    55                                               'the current entity and the current user'))
    79                                               'the current entity and the current user'))
    56 
    80 
    57     require_group = SubjectRelation('CWGroup', cardinality='**',
    81     require_group = SubjectRelation('CWGroup', cardinality='**',
    58                                     description=_('group in which a user should be to be '
    82                                     description=_('group in which a user should be to be '
    59                                                   'allowed to pass this transition'))
    83                                                   'allowed to pass this transition'))
    60     transition_of = SubjectRelation('CWEType', cardinality='+*',
    84     transition_of = SubjectRelation('Workflow', cardinality='+*',
    61                                     description=_('entity types which may use this transition'),
    85                                     description=_('workflow to which this transition belongs'),
    62                                     constraints=[RQLConstraint('O final FALSE')])
    86                                     constraints=[RQLUniqueConstraint('S name N, Y transition_of O, Y name N')])
       
    87 
       
    88 
       
    89 class Transition(BaseTransition):
       
    90     """use to define a transition from one or multiple states to a destination
       
    91     states in workflow's definitions.
       
    92     """
       
    93     __specializes_schema__ = True
       
    94 
    63     destination_state = SubjectRelation('State', cardinality='1*',
    95     destination_state = SubjectRelation('State', cardinality='1*',
    64                                         constraints=[RQLConstraint('S transition_of ET, O state_of ET')],
    96                                         constraints=[RQLConstraint('S transition_of WF, O state_of WF')],
    65                                         description=_('destination state for this transition'))
    97                                         description=_('destination state for this transition'))
    66 
    98 
    67 
    99 
       
   100 class WorkflowTransition(BaseTransition):
       
   101     """special transition allowing to go through a sub-workflow"""
       
   102     __specializes_schema__ = True
       
   103 
       
   104     subworkflow = SubjectRelation('Workflow', cardinality='1*',
       
   105                                   constraints=[RQLConstraint('S transition_of WF, WF workflow_of ET, O workflow_of ET')])
       
   106     subworkflow_exit = SubjectRelation('SubWorkflowExitPoint', cardinality='+1',
       
   107                                        composite='subject')
       
   108 
       
   109 
       
   110 class SubWorkflowExitPoint(EntityType):
       
   111     """define how we get out from a sub-workflow"""
       
   112     subworkflow_state = SubjectRelation('State', cardinality='1*',
       
   113                                         constraints=[RQLConstraint('T subworkflow_exit S, T subworkflow WF, O state_of WF')],
       
   114                                         description=_('subworkflow state'))
       
   115     destination_state = SubjectRelation('State', cardinality='1*',
       
   116                                         constraints=[RQLConstraint('T subworkflow_exit S, T transition_of WF, O state_of WF')],
       
   117                                         description=_('destination state'))
       
   118 
       
   119 
       
   120 # XXX should we allow managers to delete TrInfo?
       
   121 
    68 class TrInfo(EntityType):
   122 class TrInfo(EntityType):
    69     permissions = META_ETYPE_PERMS
   123     """workflow history item"""
    70 
   124     # 'add' security actually done by hooks
    71     from_state = SubjectRelation('State', cardinality='?*')
   125     permissions = {
       
   126         'read':   ('managers', 'users', 'guests',), # XXX U has_read_permission O ?
       
   127         'add':    ('managers', 'users', 'guests',),
       
   128         'delete': (),
       
   129         'update': ('managers', 'owners',),
       
   130     }
       
   131 
       
   132     from_state = SubjectRelation('State', cardinality='1*')
    72     to_state = SubjectRelation('State', cardinality='1*')
   133     to_state = SubjectRelation('State', cardinality='1*')
       
   134     # make by_transition optional because we want to allow managers to set
       
   135     # entity into an arbitrary state without having to respect wf transition
       
   136     by_transition = SubjectRelation('BaseTransition', cardinality='?*')
    73     comment = RichString(fulltextindexed=True)
   137     comment = RichString(fulltextindexed=True)
    74     # get actor and date time using owned_by and creation_date
   138     # get actor and date time using owned_by and creation_date
    75 
   139 
    76 
       
    77 class from_state(RelationType):
   140 class from_state(RelationType):
    78     permissions = HOOKS_RTYPE_PERMS
   141     permissions = HOOKS_RTYPE_PERMS.copy()
    79     inlined = True
   142     inlined = True
       
   143 
    80 class to_state(RelationType):
   144 class to_state(RelationType):
    81     permissions = HOOKS_RTYPE_PERMS
   145     permissions = {
    82     inlined = True
   146         'read':   ('managers', 'users', 'guests',),
    83 
   147         'add':    ('managers',),
    84 class wf_info_for(RelationType):
   148         'delete': (),
    85     """link a transition information to its object"""
   149     }
    86     permissions = {
   150     inlined = True
    87         'read':   ('managers', 'users', 'guests',),# RRQLExpression('U has_read_permission O')),
   151 
    88         'add':    (), # handled automatically, no one should add one explicitly
   152 class by_transition(RelationType):
    89         'delete': ('managers',), # RRQLExpression('U has_delete_permission O')
   153     # 'add' security actually done by hooks
    90         }
   154     permissions = {
    91     inlined = True
   155         'read':   ('managers', 'users', 'guests',),
    92     composite = 'object'
   156         'add':    ('managers', 'users', 'guests',),
    93     fulltext_container = composite
   157         'delete': (),
       
   158     }
       
   159     inlined = True
       
   160 
       
   161 class workflow_of(RelationType):
       
   162     """link a workflow to one or more entity type"""
       
   163     permissions = META_RTYPE_PERMS
    94 
   164 
    95 class state_of(RelationType):
   165 class state_of(RelationType):
    96     """link a state to one or more entity type"""
   166     """link a state to one or more workflow"""
    97     permissions = META_RTYPE_PERMS
   167     permissions = META_RTYPE_PERMS
       
   168 
    98 class transition_of(RelationType):
   169 class transition_of(RelationType):
    99     """link a transition to one or more entity type"""
   170     """link a transition to one or more workflow"""
   100     permissions = META_RTYPE_PERMS
   171     permissions = META_RTYPE_PERMS
       
   172 
       
   173 class subworkflow(RelationType):
       
   174     """link a transition to one or more workflow"""
       
   175     permissions = META_RTYPE_PERMS
       
   176     inlined = True
       
   177 
       
   178 class exit_point(RelationType):
       
   179     """link a transition to one or more workflow"""
       
   180     permissions = META_RTYPE_PERMS
       
   181 
       
   182 class subworkflow_state(RelationType):
       
   183     """link a transition to one or more workflow"""
       
   184     permissions = META_RTYPE_PERMS
       
   185     inlined = True
   101 
   186 
   102 class initial_state(RelationType):
   187 class initial_state(RelationType):
   103     """indicate which state should be used by default when an entity using
   188     """indicate which state should be used by default when an entity using
   104     states is created
   189     states is created
   105     """
   190     """
   113 
   198 
   114 class allowed_transition(RelationType):
   199 class allowed_transition(RelationType):
   115     """allowed transition from this state"""
   200     """allowed transition from this state"""
   116     permissions = META_RTYPE_PERMS
   201     permissions = META_RTYPE_PERMS
   117 
   202 
       
   203 
       
   204 # "abstract" relations, set by WorkflowableEntityType ##########################
       
   205 
       
   206 class custom_workflow(RelationType):
       
   207     """allow to set a specific workflow for an entity"""
       
   208     permissions = META_RTYPE_PERMS
       
   209 
       
   210     cardinality = '?*'
       
   211     constraints = [RQLConstraint('S is ET, O workflow_of ET')]
       
   212     object = 'Workflow'
       
   213 
       
   214 
       
   215 class wf_info_for(RelationType):
       
   216     """link a transition information to its object"""
       
   217     # 'add' security actually done by hooks
       
   218     permissions = {
       
   219         'read':   ('managers', 'users', 'guests',),
       
   220         'add':    ('managers', 'users', 'guests',),
       
   221         'delete': (),
       
   222     }
       
   223     inlined = True
       
   224 
       
   225     cardinality='1*'
       
   226     composite = 'object'
       
   227     fulltext_container = composite
       
   228     subject = 'TrInfo'
       
   229 
       
   230 
   118 class in_state(RelationType):
   231 class in_state(RelationType):
   119     """indicate the current state of an entity"""
   232     """indicate the current state of an entity"""
       
   233     permissions = HOOKS_RTYPE_PERMS
       
   234 
   120     # not inlined intentionnaly since when using ldap sources, user'state
   235     # not inlined intentionnaly since when using ldap sources, user'state
   121     # has to be stored outside the CWUser table
   236     # has to be stored outside the CWUser table
   122     inlined = False
   237     inlined = False
   123     # add/delete perms given to managers/users, after what most of the job
   238 
   124     # is done by workflow enforcment
   239     cardinality = '1*'
   125     permissions = {
   240     constraints = [RQLConstraint('S is ET, O state_of WF, WF workflow_of ET')]
   126         'read':   ('managers', 'users', 'guests',),
   241     object = 'State'
   127         'add':    ('managers', 'users',), # XXX has_update_perm
       
   128         'delete': ('managers', 'users',),
       
   129         }
       
   130