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