0001-wf-add-DispatchUserWorkflowStatusItem.patch
tests/test_backoffice_pages.py | ||
---|---|---|
26 | 26 |
DisplayMessageWorkflowStatusItem, |
27 | 27 |
JumpOnSubmitWorkflowStatusItem, WorkflowCriticalityLevel, |
28 | 28 |
WorkflowBackofficeFieldsFormDef) |
29 |
from wcs.wf.dispatch import DispatchWorkflowStatusItem |
|
29 |
from wcs.wf.dispatch import DispatchWorkflowStatusItem, DispatchUserWorkflowStatusItem
|
|
30 | 30 |
from wcs.wf.form import FormWorkflowStatusItem, WorkflowFormFieldsFormDef |
31 | 31 |
from wcs.wf.jump import JumpWorkflowStatusItem |
32 | 32 |
from wcs.wf.wscall import WebserviceCallStatusItem |
... | ... | |
3780 | 3780 |
assert resp.location == 'http://example.net/backoffice/submission/test/' |
3781 | 3781 |
resp = resp.follow() |
3782 | 3782 |
assert '<p class="comment-field ">XbarY</p>' in resp.body |
3783 | ||
3784 |
def test_backoffice_dispatch_user(pub): |
|
3785 |
user = create_user(pub) |
|
3786 |
create_environment(pub) |
|
3787 | ||
3788 |
target_role = Role(name='target') |
|
3789 |
target_role.allows_backoffice_access = True |
|
3790 |
target_role.store() |
|
3791 |
members = [] |
|
3792 |
for i in range(10): |
|
3793 |
member = pub.user_class(name='member%s' % i) |
|
3794 |
member.roles = [str(target_role.id)] |
|
3795 |
member.store() |
|
3796 |
account = PasswordAccount(id=member.name) |
|
3797 |
account.set_password(member.name) |
|
3798 |
account.user_id = member.id |
|
3799 |
account.store() |
|
3800 |
members.append(member) |
|
3801 | ||
3802 |
wf = Workflow(name='resubmit') |
|
3803 |
st1 = wf.add_status('Status1') |
|
3804 |
st2 = wf.add_status('Status2') |
|
3805 |
st3 = wf.add_status('Status3') |
|
3806 |
wf.roles['_responsible'] = 'Responsible' |
|
3807 | ||
3808 |
dispatch = DispatchUserWorkflowStatusItem() |
|
3809 |
dispatch.id = '_dispatch_user' |
|
3810 |
dispatch.by = user.roles[:] |
|
3811 |
dispatch.role_key = '_responsible' |
|
3812 |
dispatch.members_of_role = str(target_role.id) |
|
3813 | ||
3814 |
st1.items.append(dispatch) |
|
3815 |
dispatch.parent = st1 |
|
3816 | ||
3817 |
jump = JumpOnSubmitWorkflowStatusItem() |
|
3818 |
jump.id = '_jump' |
|
3819 |
jump.status = st2.id |
|
3820 |
st1.items.append(jump) |
|
3821 |
jump.parent = st1 |
|
3822 | ||
3823 |
jump1 = ChoiceWorkflowStatusItem() |
|
3824 |
jump1.id = '_jump_responible' |
|
3825 |
jump1.label = 'jump for responsible' |
|
3826 |
jump1.by = ['_responsible'] |
|
3827 |
jump1.status = st3.id |
|
3828 |
st2.items.append(jump1) |
|
3829 |
jump1.parent = st2 |
|
3830 | ||
3831 |
jump2 = ChoiceWorkflowStatusItem() |
|
3832 |
jump2.id = '_jump_submitter' |
|
3833 |
jump2.label = 'jump for submitter' |
|
3834 |
jump2.by = ['_submitter'] |
|
3835 |
jump2.status = st3.id |
|
3836 |
st2.items.append(jump2) |
|
3837 |
jump2.parent = st2 |
|
3838 | ||
3839 |
wf.store() |
|
3840 | ||
3841 |
formdef = FormDef.get_by_urlname('form-title') |
|
3842 |
formdef.fields[0].varname = 'foo' |
|
3843 |
formdef.workflow_id = wf.id |
|
3844 |
formdef.store() |
|
3845 | ||
3846 |
formdata = formdef.data_class()() |
|
3847 |
formdata.just_created() |
|
3848 |
formdata.data = {'1': 'XXX'} |
|
3849 |
formdata.store() |
|
3850 | ||
3851 |
member = members[1] |
|
3852 |
app = login(get_app(pub)) |
|
3853 |
resp = app.get(formdata.get_url(backoffice=True)) |
|
3854 |
resp = app.get(formdata.get_url(backoffice=True)) |
|
3855 |
resp.form['user'].value = str(member.id) |
|
3856 |
resp = resp.form.submit('button_dispatch_user') |
|
3857 |
resp = resp.follow() |
|
3858 |
app.get('/logout') |
|
3859 |
app = login(get_app(pub), username=member.name, password=member.name) |
|
3860 |
resp = app.get(formdata.get_url(backoffice=True)) |
|
3861 | ||
3862 |
assert 'jump for responsible' in resp |
|
3863 |
assert 'jump for submitter' not in resp |
|
3864 |
tests/test_workflows.py | ||
---|---|---|
27 | 27 |
AttachmentEvolutionPart, WorkflowBackofficeFieldsFormDef) |
28 | 28 |
from wcs.wf.anonymise import AnonymiseWorkflowStatusItem |
29 | 29 |
from wcs.wf.criticality import ModifyCriticalityWorkflowStatusItem, MODE_INC, MODE_DEC, MODE_SET |
30 |
from wcs.wf.dispatch import DispatchWorkflowStatusItem |
|
30 |
from wcs.wf.dispatch import DispatchWorkflowStatusItem, DispatchUserWorkflowStatusItem
|
|
31 | 31 |
from wcs.wf.form import FormWorkflowStatusItem, WorkflowFormFieldsFormDef |
32 | 32 |
from wcs.wf.jump import JumpWorkflowStatusItem, _apply_timeouts |
33 | 33 |
from wcs.wf.timeout_jump import TimeoutWorkflowStatusItem |
wcs/backoffice/management.py | ||
---|---|---|
212 | 212 |
# display list of open formdata for the user |
213 | 213 |
formdefs = [x for x in FormDef.select() if not x.skip_from_360_view] |
214 | 214 |
user_roles = set([logged_users_role().id] + (get_request().user.roles or [])) |
215 |
user_roles.add('_user-%s' % get_request().user.id) |
|
215 | 216 |
criterias = [Equal('is_at_endpoint', False), |
216 | 217 |
Equal('user_id', str(self.user.id)), |
217 | 218 |
Contains('formdef_id', [x.id for x in formdefs]), |
... | ... | |
461 | 462 | |
462 | 463 |
user = get_request().user |
463 | 464 |
user_roles = [logged_users_role().id] + (user.roles or []) |
465 |
user_roles.add('_user-%s' % user.id) |
|
464 | 466 | |
465 | 467 |
forms_without_pending_stuff = [] |
466 | 468 |
forms_with_pending_stuff = [] |
... | ... | |
733 | 735 |
def get_global_listing_criterias(self): |
734 | 736 |
parsed_values = {} |
735 | 737 |
user_roles = [logged_users_role().id] + (get_request().user.roles or []) |
738 |
user_roles.add('_user-%s' % user.id) |
|
736 | 739 |
criterias = get_global_criteria(get_request(), parsed_values) |
737 | 740 |
query_parameters = (get_request().form or {}).copy() |
738 | 741 |
query_parameters.pop('callback', None) # when using jsonp |
... | ... | |
2043 | 2046 |
if formdata.user_id and get_publisher().is_using_postgresql(): |
2044 | 2047 |
# display list of open formdata for the same user |
2045 | 2048 |
user_roles = [logged_users_role().id] + (get_request().user.roles or []) |
2049 |
user_roles.add('_user-%s' % user.id) |
|
2046 | 2050 |
criterias = [Equal('is_at_endpoint', False), |
2047 | 2051 |
Equal('user_id', str(formdata.user_id)), |
2048 | 2052 |
Intersects('concerned_roles_array', user_roles), |
wcs/formdef.py | ||
---|---|---|
1186 | 1186 |
for role_id in formdata.workflow_roles.values(): |
1187 | 1187 |
if role_id in (user.roles or []): |
1188 | 1188 |
return True |
1189 |
# if user was directly attributed a function |
|
1190 |
if ('_user-%s' % user.id) in formdata.workflow_roles.values(): |
|
1191 |
return True |
|
1189 | 1192 | |
1190 | 1193 |
# if no formdata was given, lookup if there are some existing formdata |
1191 | 1194 |
# where the user has access. |
... | ... | |
1194 | 1197 |
for role_id in user.roles or []: |
1195 | 1198 |
if data_class.get_ids_with_indexed_value('workflow_roles', role_id): |
1196 | 1199 |
return True |
1200 |
if data_class.get_ids_with_indexed_value('workflow_roles', '_user-%s' % user.id): |
|
1201 |
return True |
|
1197 | 1202 | |
1198 | 1203 |
return False |
1199 | 1204 | |
... | ... | |
1210 | 1215 |
user_roles = set(user.roles) |
1211 | 1216 |
else: |
1212 | 1217 |
user_roles = set([]) |
1218 |
user_roles.add('_user-%s' % user.id) |
|
1213 | 1219 |
user_roles.add(logged_users_role().id) |
1214 | 1220 | |
1215 | 1221 |
def ensure_role_are_strings(roles): |
... | ... | |
1243 | 1249 |
user_roles = set(user.roles) |
1244 | 1250 |
else: |
1245 | 1251 |
user_roles = set([]) |
1252 |
user_roles.add('_user-%s' % user.id) |
|
1246 | 1253 | |
1247 | 1254 |
if not self.workflow_roles: |
1248 | 1255 |
self.workflow_roles = {} |
wcs/forms/backoffice.py | ||
---|---|---|
126 | 126 |
item_ids = [x for x in item_ids if x not in drafts] |
127 | 127 |
elif selected_filter == 'waiting': |
128 | 128 |
user_roles = [logged_users_role().id] + (user.roles or []) |
129 |
user_roles.append('_user-%s' % user.id) |
|
129 | 130 |
item_ids = formdata_class.get_actionable_ids(user_roles) |
130 | 131 |
else: |
131 | 132 |
applied_filters = [] |
... | ... | |
156 | 157 |
# to consider treating roles. |
157 | 158 |
if not user.is_admin: |
158 | 159 |
user_roles = set(user.roles or []) |
160 |
user_roles.add('_user-%s' % user.id) |
|
159 | 161 |
concerned_ids = set() |
160 | 162 |
for role in user_roles: |
161 | 163 |
concerned_ids |= set(formdata_class.get_ids_with_indexed_value( |
wcs/forms/common.py | ||
---|---|---|
495 | 495 |
r += form.render() |
496 | 496 |
self.filled.mark_as_being_visited() |
497 | 497 |
related_user_forms = getattr(self.filled, 'related_user_forms', None) or [] |
498 |
user_roles = set(get_request().user.roles) |
|
498 |
user_roles = set(get_request().user.roles or []) |
|
499 |
user_roles.append('_user-%s' % get_request().user.id) |
|
499 | 500 |
for user_formdata in related_user_forms: |
500 | 501 |
if user_roles.intersection(user_formdata.actions_roles): |
501 | 502 |
user_formdata.mark_as_being_visited() |
wcs/wf/dispatch.py | ||
---|---|---|
17 | 17 |
import collections |
18 | 18 |
import xml.etree.ElementTree as ET |
19 | 19 | |
20 |
from quixote import get_publisher |
|
20 | 21 |
from qommon import _ |
21 | 22 |
from qommon.form import * |
22 | 23 |
from qommon import get_logger |
23 | 24 |
from wcs.roles import Role, get_user_roles |
25 |
from wcs.users import User |
|
24 | 26 |
from wcs.workflows import XmlSerialisable, WorkflowStatusItem, register_item_class |
25 | 27 | |
26 | 28 | |
... | ... | |
208 | 210 |
formdata.store() |
209 | 211 | |
210 | 212 |
register_item_class(DispatchWorkflowStatusItem) |
213 | ||
214 | ||
215 |
class DispatchUserWorkflowStatusItem(WorkflowStatusItem): |
|
216 |
description = N_('Dispatch user') |
|
217 |
key = 'dispatch-user' |
|
218 |
endpoint = False |
|
219 |
waitpoint = True |
|
220 |
ok_in_global_action = False |
|
221 | ||
222 |
by = [] |
|
223 |
label = None |
|
224 |
role_key = None |
|
225 |
members_of_role = None |
|
226 |
backoffice_info_text = None |
|
227 | ||
228 |
def get_parameters(self): |
|
229 |
return ('by', 'label', 'role_key', 'role_key', 'members_of_role', 'backoffice_info_text') |
|
230 | ||
231 |
def render_as_line(self): |
|
232 |
function = self.parent.parent.roles[self.role_key] |
|
233 |
if self.by: |
|
234 |
return _('Dispatch user to function %s by %s') % ( |
|
235 |
function, |
|
236 |
self.render_list_of_roles(self.by)) |
|
237 |
else: |
|
238 |
return _('Dispatch user to function %s (not completed)') % function |
|
239 | ||
240 |
def fill_form(self, form, formdata, user): |
|
241 |
function = self.parent.parent.roles[self.role_key] |
|
242 |
label = self.label |
|
243 |
if not label: |
|
244 |
label = _('Dispatch user to function %s') % function |
|
245 |
members = get_publisher().user_class.get_users_with_role(self.members_of_role) |
|
246 |
users = [(None, '---', None)] |
|
247 |
users += [(str(member.id), member.display_name, str(member.id)) for member in members] |
|
248 |
form.add(SingleSelectWidget, 'user', title=_('User'), |
|
249 |
required=True, options=users) |
|
250 |
form.add_submit('button%s' % self.id, label) |
|
251 |
form.get_widget('button%s' % self.id).backoffice_info_text = self.backoffice_info_text |
|
252 | ||
253 |
def submit_form(self, form, formdata, user, evo): |
|
254 |
if form.get_submit() != 'button%s' % self.id: |
|
255 |
return |
|
256 | ||
257 |
user_id = form.get_widget('user').parse() |
|
258 | ||
259 |
if not formdata.workflow_roles: |
|
260 |
formdata.workflow_roles = {} |
|
261 |
formdata.workflow_roles[self.role_key] = '_user-%s' % user_id |
|
262 |
formdata.store() |
|
263 | ||
264 |
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None): |
|
265 |
if 'by' in parameters: |
|
266 |
form.add(WidgetList, '%sby' % prefix, title=_('By'), element_type=SingleSelectWidget, |
|
267 |
value=self.by, |
|
268 |
add_element_label=_('Add Role'), |
|
269 |
element_kwargs={ |
|
270 |
'render_br': False, |
|
271 |
'options': [(None, '---', None)] + self.get_list_of_roles()}) |
|
272 |
if 'label' in parameters: |
|
273 |
form.add(StringWidget, '%slabel' % prefix, title=_('Button Label'), |
|
274 |
value=self.label or _('Resubmit')) |
|
275 |
if 'role_key' in parameters: |
|
276 |
if not self.parent.parent.roles: |
|
277 |
self.parent.parent.roles = {} |
|
278 |
form.add(SingleSelectWidget, '%srole_key' % prefix, |
|
279 |
title=_('Function to Set'), value=self.role_key, |
|
280 |
options=[(None, '----')] + self.parent.parent.roles.items()) |
|
281 |
if 'members_of_role' in parameters: |
|
282 |
form.add(SingleSelectWidget, '%smember_of_roles' % prefix, |
|
283 |
title=_('Members of role'), value=self.members_of_role, |
|
284 |
options=[(None, '----')] + self.get_list_of_roles()) |
|
285 |
if 'backoffice_info_text' in parameters: |
|
286 |
form.add(WysiwygTextWidget, '%sbackoffice_info_text' % prefix, |
|
287 |
title=_('Information Text for Backoffice'), |
|
288 |
value=self.backoffice_info_text) |
|
289 | ||
290 | ||
291 |
register_item_class(DispatchUserWorkflowStatusItem) |
wcs/workflows.py | ||
---|---|---|
403 | 403 |
if isinstance(trigger, WorkflowGlobalActionManualTrigger): |
404 | 404 |
roles = [get_role_translation(formdata, x) |
405 | 405 |
for x in (trigger.roles or [])] |
406 |
if set(roles).intersection(user.roles or []): |
|
406 |
if set(roles).intersection(user.roles or []) or ('_user-%s' % user.id) in roles:
|
|
407 | 407 |
actions.append(action) |
408 | 408 |
break |
409 | 409 |
return actions |
... | ... | |
1334 | 1334 |
role = get_role_translation(filled, role) |
1335 | 1335 |
if role in (user.roles or []): |
1336 | 1336 |
break |
1337 |
if role == '_user-%s' % user.id: |
|
1338 |
break |
|
1337 | 1339 |
else: |
1338 | 1340 |
continue |
1339 | 1341 |
next_url = item.submit_form(form, filled, user, evo) |
... | ... | |
1381 | 1383 |
if user: |
1382 | 1384 |
user_roles = set(user.roles or []) |
1383 | 1385 |
user_roles.add(logged_users_role().id) |
1386 |
user_roles.add('_user-%s' % user.id) |
|
1384 | 1387 |
else: |
1385 | 1388 |
user_roles = set([]) |
1386 | 1389 | |
... | ... | |
1536 | 1539 |
role = get_role_translation(formdata, role) |
1537 | 1540 |
if role in (user.roles or []): |
1538 | 1541 |
return True |
1542 |
if user and role == '_user-%s' % user.id: |
|
1543 |
return True |
|
1539 | 1544 | |
1540 | 1545 |
return False |
1541 | 1546 | |
... | ... | |
2310 | 2315 |
break |
2311 | 2316 |
elif user: |
2312 | 2317 |
role = get_role_translation(filled, role) |
2313 |
if role in (user.roles or []): |
|
2318 |
if role in (user.roles or []) or '_user-%s' % user == role:
|
|
2314 | 2319 |
break |
2315 | 2320 |
else: |
2316 | 2321 |
return '' |
2317 |
- |