Projet

Général

Profil

0001-wf-add-DispatchUserWorkflowStatusItem.patch

Benjamin Dauvergne, 08 septembre 2017 01:39

Télécharger (15,9 ko)

Voir les différences:

Subject: [PATCH] wf: add DispatchUserWorkflowStatusItem

 tests/test_backoffice_pages.py | 84 +++++++++++++++++++++++++++++++++++++++++-
 tests/test_workflows.py        |  2 +-
 wcs/backoffice/management.py   |  4 ++
 wcs/formdef.py                 |  7 ++++
 wcs/forms/backoffice.py        |  2 +
 wcs/forms/common.py            |  3 +-
 wcs/wf/dispatch.py             | 81 ++++++++++++++++++++++++++++++++++++++++
 wcs/workflows.py               |  9 ++++-
 8 files changed, 187 insertions(+), 5 deletions(-)
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
-