1 | import logging |
---|
2 | from ZODB.loglevels import TRACE |
---|
3 | |
---|
4 | from AccessControl import ClassSecurityInfo |
---|
5 | from AccessControl import getSecurityManager |
---|
6 | from Acquisition import aq_parent |
---|
7 | from Acquisition import aq_inner |
---|
8 | from Globals import InitializeClass |
---|
9 | |
---|
10 | from Products.CMFCore.utils import getToolByName |
---|
11 | from Products.CMFCore.WorkflowCore import ObjectMoved |
---|
12 | from Products.CMFCore.WorkflowCore import ObjectDeleted |
---|
13 | from Products.CMFCore.WorkflowCore import WorkflowException |
---|
14 | |
---|
15 | from Products.DCWorkflow.DCWorkflow import DCWorkflowDefinition |
---|
16 | from Products.DCWorkflow.Transitions import TRIGGER_USER_ACTION |
---|
17 | |
---|
18 | #from expression import CPSStateChangeInfo as StateChangeInfo |
---|
19 | #from expression import createExprContext |
---|
20 | |
---|
21 | #from zope.interface import implements |
---|
22 | #from Products.CPSWorkflow.interfaces import ICPSWorkflowDefinition |
---|
23 | |
---|
24 | from Products.CPSCore.ProxyBase import ProxyBase |
---|
25 | from Products.CPSCore.EventServiceTool import getEventService |
---|
26 | |
---|
27 | #from constants import TRANSITION_FLAGS_EXPORT |
---|
28 | |
---|
29 | # |
---|
30 | # Backwards compatibility with CPS3 <= 3.2.x |
---|
31 | # Importing transition flags from here before. |
---|
32 | # |
---|
33 | |
---|
34 | from Products.CPSWorkflow.transitions import * |
---|
35 | from Products.CPSWorkflow.states import * |
---|
36 | |
---|
37 | |
---|
38 | logger = logging.getLogger('CPSWorkflow.workflow') |
---|
39 | security = ClassSecurityInfo() |
---|
40 | |
---|
41 | security.declarePrivate('updateStackDefinitionsRoleMappingFor') |
---|
42 | def updateStackDefinitionsRoleMappingsFor(self, ob, **kw): |
---|
43 | """Update local roles for delegatees that are within workflow stacks |
---|
44 | """ |
---|
45 | current_wf_var_id = kw.get('current_wf_var_id', '') |
---|
46 | |
---|
47 | wftool = getToolByName(self, 'portal_workflow') |
---|
48 | stackdefs = wftool.getStackDefinitionsFor(ob) |
---|
49 | |
---|
50 | changed = 0 |
---|
51 | |
---|
52 | # |
---|
53 | # First save the former local roles maping They will be |
---|
54 | # overriden if defined on the state just after. For the other |
---|
55 | # ones, we need to keep the flrm's since the stackdef might be |
---|
56 | # defined on another state further within the process |
---|
57 | # definition or called by a stack flaged transition. |
---|
58 | # |
---|
59 | tdef = kw.get('tdef') |
---|
60 | history = wftool.getHistoryOf(self.id, ob) |
---|
61 | if history is not None: |
---|
62 | try: |
---|
63 | former_status = history[-2] |
---|
64 | except IndexError: |
---|
65 | # Virgin instance ;) |
---|
66 | pass |
---|
67 | else: |
---|
68 | sflrm = former_status.get('sflrm', {}) |
---|
69 | for k, v in sflrm.items(): |
---|
70 | wftool.updateFormerLocalRoleMappingForStack(ob, self.id, |
---|
71 | k, v) |
---|
72 | |
---|
73 | # |
---|
74 | # Let's ask the stack definition for the list of local roles |
---|
75 | # |
---|
76 | |
---|
77 | for stackdef in stackdefs.keys(): |
---|
78 | |
---|
79 | # Update only the variable on wich the transition just applied |
---|
80 | if not stackdef == current_wf_var_id: |
---|
81 | continue |
---|
82 | |
---|
83 | ds = wftool.getInfoFor(ob, stackdef, self.id) |
---|
84 | former_mapping = wftool.getFormerLocalRoleMappingForStack( |
---|
85 | ob, self.id, stackdef) |
---|
86 | mapping = stackdefs[stackdef]._getLocalRolesMapping(ds) |
---|
87 | |
---|
88 | # |
---|
89 | # First remove associated local roles to the ones who are not |
---|
90 | # supposed to have any (not a single one) |
---|
91 | # |
---|
92 | |
---|
93 | for id in former_mapping.keys(): |
---|
94 | old_local_roles = former_mapping[id] |
---|
95 | |
---|
96 | # Remove all previous local roles in this case |
---|
97 | if id not in mapping.keys(): |
---|
98 | roles_to_remove = old_local_roles |
---|
99 | |
---|
100 | # Remove only local roles that are only within the |
---|
101 | # previous mapping |
---|
102 | else: |
---|
103 | roles_to_remove = [] |
---|
104 | for old_role in old_local_roles: |
---|
105 | if old_role not in mapping[id]: |
---|
106 | roles_to_remove.append(old_role) |
---|
107 | |
---|
108 | |
---|
109 | # Check that no other stack distributes currently this role |
---|
110 | # to the current member |
---|
111 | roles_to_keep = () |
---|
112 | for old_local_role in roles_to_remove: |
---|
113 | stacks = wftool.getStacks(ob) |
---|
114 | for stack_id, stack in stacks.items(): |
---|
115 | if stack_id != current_wf_var_id: |
---|
116 | # The current transition is already |
---|
117 | # executed on ob thus we can take the |
---|
118 | # former mapping for this other given |
---|
119 | if (old_local_role in |
---|
120 | wftool.getFormerLocalRoleMappingForStack( |
---|
121 | ob, self.id, stack_id).get(id, ())): |
---|
122 | roles_to_keep += (old_local_role,) |
---|
123 | |
---|
124 | # Do the actual job to remove absolete roles |
---|
125 | for old_local_role in roles_to_remove: |
---|
126 | |
---|
127 | # Don't remove those already managed by another stack |
---|
128 | if old_local_role in roles_to_keep: |
---|
129 | continue |
---|
130 | |
---|
131 | if not id.startswith('group:'): |
---|
132 | current_roles = list( |
---|
133 | ob.get_local_roles_for_userid(userid=id)) |
---|
134 | new_roles = [role for role in current_roles |
---|
135 | if role != old_local_role] |
---|
136 | ob.manage_delLocalRoles(userids=[id]) |
---|
137 | if new_roles: |
---|
138 | ob.manage_setLocalRoles(id, new_roles) |
---|
139 | else: |
---|
140 | id = id[len('group:'):] |
---|
141 | current_roles = list( |
---|
142 | ob.get_local_roles_for_groupid(groupid=id)) |
---|
143 | new_roles = [role for role in current_roles |
---|
144 | if role != old_local_role] |
---|
145 | ob.manage_delLocalGroupRoles(groupids=[id]) |
---|
146 | if new_roles: |
---|
147 | ob.manage_setLocalGroupRoles(id, new_roles) |
---|
148 | |
---|
149 | # Update ? |
---|
150 | if roles_to_remove: |
---|
151 | changed = 1 |
---|
152 | |
---|
153 | # |
---|
154 | # Add local roles to member / groups within the mapping if |
---|
155 | # they don't have the roles already in their merged local roles |
---|
156 | # |
---|
157 | |
---|
158 | for id in mapping.keys(): |
---|
159 | changed = 1 |
---|
160 | local_roles = mapping[id] |
---|
161 | if not id.startswith('group:'): |
---|
162 | current_roles = ob.get_local_roles_for_userid(userid=id) |
---|
163 | new_roles = list(current_roles) |
---|
164 | for role in local_roles: |
---|
165 | if role not in new_roles: |
---|
166 | new_roles.append(role) |
---|
167 | ob.manage_setLocalRoles(id, new_roles) |
---|
168 | else: |
---|
169 | id = id[len('group:'):] |
---|
170 | current_roles = ob.get_local_roles_for_groupid(groupid=id) |
---|
171 | new_roles = list(current_roles) |
---|
172 | for role in local_roles: |
---|
173 | if role not in new_roles: |
---|
174 | new_roles.append(role) |
---|
175 | ob.manage_setLocalGroupRoles(id, new_roles) |
---|
176 | |
---|
177 | # Update the former local role mapping |
---|
178 | wftool.updateFormerLocalRoleMappingForStack(ob, self.id, stackdef, |
---|
179 | mapping) |
---|
180 | return changed |
---|
181 | |
---|
182 | from Products.CPSWorkflow.workflow import WorkflowDefinition |
---|
183 | WorkflowDefinition.updateStackDefinitionsRoleMappingsFor = updateStackDefinitionsRoleMappingsFor |
---|