workflows: add target roles in commenter workflow item (#38254)

This commit is contained in:
Nicolas Roche 2020-12-11 00:10:18 +01:00
parent a6bb719413
commit 09706c3b40
7 changed files with 241 additions and 5 deletions

View File

@ -1504,3 +1504,91 @@ def test_formdata_named_wscall_in_conditions(http_requests, pub):
assert '>3rd page<' not in resp.text
assert '>4th page<' in resp.text
assert len(http_requests.requests) == 1
def test_formdata_evolution_registercommenter_to(pub):
user = create_user(pub)
Role.wipe()
role1 = Role(name='role the user does not have')
role1.store()
role2 = Role(name='role the user does have')
role2.store()
user.roles = [role2.id]
user.store()
wf = Workflow(name='status')
st1 = wf.add_status('Status1', 'st1')
comment = RegisterCommenterWorkflowStatusItem()
comment.id = '_comment'
comment.comment = 'Hello World'
comment.to = None
st1.items.append(comment)
comment.parent = st1
wf.store()
FormDef.wipe()
formdef = FormDef()
formdef.name = 'test'
formdef.workflow_id = wf.id
formdef.fields = []
formdef.store()
formdef.data_class().wipe()
# register comment to all users
app = login(get_app(pub), username='foo', password='foo')
resp = app.get('/test/')
resp = resp.forms[0].submit('submit')
assert 'Check values then click submit.' in resp.text
resp = resp.forms[0].submit('submit')
assert resp.status_int == 302
resp = resp.follow()
assert 'The form has been recorded' in resp.text
formdata = formdef.data_class().select()[0]
assert formdata.evolution[0].parts[0].content == 'Hello World'
assert formdata.evolution[0].parts[0].to is None
resp = app.get('/test/%s/' % formdata.id)
resp.status_int = 200
assert resp.html.find('div', {'id': 'evolution-log'}).find('p').text == 'Hello World'
# register comment to other users
formdef.data_class().wipe()
comment.to = [role1.id]
wf.store()
resp = app.get('/test/')
resp = resp.forms[0].submit('submit')
assert 'Check values then click submit.' in resp.text
resp = resp.forms[0].submit('submit')
assert resp.status_int == 302
resp = resp.follow()
assert 'The form has been recorded' in resp.text
formdata = formdef.data_class().select()[0]
assert formdata.evolution[0].parts[0].content == 'Hello World'
assert formdata.evolution[0].parts[0].to == [role1.id]
resp = app.get('/test/%s/' % formdata.id)
resp.status_int = 200
assert not resp.html.find('div', {'id': 'evolution-log'}).find('p')
# register comment to this user
formdef.data_class().wipe()
comment.to = [role2.id]
wf.store()
resp = app.get('/test/')
resp = resp.forms[0].submit('submit')
assert 'Check values then click submit.' in resp.text
resp = resp.forms[0].submit('submit')
assert resp.status_int == 302
resp = resp.follow()
assert 'The form has been recorded' in resp.text
formdata = formdef.data_class().select()[0]
assert formdata.evolution[0].parts[0].content == 'Hello World'
assert formdata.evolution[0].parts[0].to == [role2.id]
resp = app.get('/test/%s/' % formdata.id)
resp.status_int = 200
assert resp.html.find('div', {'id': 'evolution-log'}).find('p').text == 'Hello World'

View File

@ -430,7 +430,7 @@ def test_get_json_export_dict_evolution(pub, local_user):
evo.who = '_submitter'
d.evolution = [evo]
d.store()
evo.add_part(JournalEvolutionPart(d, "ok"))
evo.add_part(JournalEvolutionPart(d, "ok", None))
evo.add_part(JournalWsCallErrorPart("summary", "label", "data"))
evo = Evolution()
evo.time = time.localtime()
@ -470,7 +470,7 @@ def test_get_json_export_dict_evolution(pub, local_user):
assert 'who' not in export['evolution'][0]
assert 'parts' in export['evolution'][0]
assert len(export['evolution'][0]['parts']) == 2
assert len(export['evolution'][0]['parts'][0]) == 1
assert len(export['evolution'][0]['parts'][0]) == 2
assert export['evolution'][0]['parts'][0]['type'] == 'workflow-comment'
assert len(export['evolution'][0]['parts'][1]) == 1
assert export['evolution'][0]['parts'][1]['type'] == 'wscall-error'

View File

@ -481,6 +481,39 @@ def test_global_actions(pub):
wf2 = assert_import_export_works(wf, True)
def test_register_comment_to(pub):
role = Role()
role.id = '5'
role.name = 'Test Role'
role.store()
wf = Workflow(name='global actions')
st1 = wf.add_status('Status1', 'st1')
add_to_journal1 = RegisterCommenterWorkflowStatusItem()
add_to_journal1.id = '_add_to_journal1'
add_to_journal1.comment = 'HELLO WORLD'
st1.items.append(add_to_journal1)
add_to_journal1.parent = st1
add_to_journal2 = RegisterCommenterWorkflowStatusItem()
add_to_journal2.id = '_add_to_journal2'
add_to_journal2.comment = 'OLA MUNDO'
add_to_journal2.to = [role.id]
st1.items.append(add_to_journal2)
add_to_journal2.parent = st1
assert wf.possible_status[0].items[0].to == None
assert wf.possible_status[0].items[1].to == [role.id]
xml_root = wf.export_to_xml()
assert 'to' not in [x.tag for x in xml_root.findall('possible_status/status/items/item[1]/')]
assert 'to' in [x.tag for x in xml_root.findall('possible_status/status/items/item[2]/')]
wf2 = assert_import_export_works(wf)
assert wf2.possible_status[0].items[0].to == []
assert wf2.possible_status[0].items[1].to == [role.id]
def test_backoffice_fields(pub):
wf = Workflow(name='bo fields')
wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)

View File

@ -1153,6 +1153,100 @@ def test_register_comment_with_attachment_file(pub):
assert comment_view == '<p>%s</p>' % comment_text
def test_register_comment_to(pub):
workflow = Workflow(name='register comment to')
st1 = workflow.add_status('Status1', 'st1')
role = Role(name='foorole')
role.store()
role2 = Role(name='no-one-role')
role2.store()
user = pub.user_class(name='baruser')
user.roles = []
user.store()
FormDef.wipe()
formdef = FormDef()
formdef.url_name = 'foobar'
formdef._workflow = workflow
formdata = formdef.data_class()()
formdata.just_created()
assert formdata.status == 'wf-st1'
formdata.store()
register_commenter = RegisterCommenterWorkflowStatusItem()
register_commenter.parent = st1
st1.items.append(register_commenter)
def display_parts():
formdata.evolution[-1]._display_parts = None # invalidate cache
return [str(x) for x in formdata.evolution[-1].display_parts()]
register_commenter.comment = 'all'
register_commenter.to = None
register_commenter.perform(formdata)
assert len(formdata.evolution[-1].parts) == 1
assert display_parts() == ['<p>all</p>']
register_commenter.comment = 'to-role'
register_commenter.to = [role.id]
register_commenter.perform(formdata)
assert len(formdata.evolution[-1].parts) == 2
assert len(display_parts()) == 1
pub._request._user = user
assert display_parts() == ['<p>all</p>']
user.roles = [role.id]
assert display_parts() == ['<p>all</p>', '<p>to-role</p>']
user.roles = []
register_commenter.comment = 'to-submitter'
register_commenter.to = ['_submitter']
register_commenter.perform(formdata)
assert len(formdata.evolution[-1].parts) == 3
assert display_parts() == ['<p>all</p>']
formdata.user_id = user.id
assert display_parts() == ['<p>all</p>', '<p>to-submitter</p>']
register_commenter.comment = 'to-role-or-submitter'
register_commenter.to = [role.id, '_submitter']
register_commenter.perform(formdata)
assert len(formdata.evolution[-1].parts) == 4
assert display_parts() == ['<p>all</p>', '<p>to-submitter</p>', '<p>to-role-or-submitter</p>']
formdata.user_id = None
assert display_parts() == ['<p>all</p>']
user.roles = [role.id]
assert display_parts() == ['<p>all</p>', '<p>to-role</p>', '<p>to-role-or-submitter</p>']
formdata.user_id = user.id
assert display_parts() == [
'<p>all</p>',
'<p>to-role</p>',
'<p>to-submitter</p>',
'<p>to-role-or-submitter</p>',
]
register_commenter.comment = 'd1'
register_commenter.to = [role2.id]
register_commenter.perform(formdata)
assert len(formdata.evolution[-1].parts) == 5
assert display_parts() == [
'<p>all</p>',
'<p>to-role</p>',
'<p>to-submitter</p>',
'<p>to-role-or-submitter</p>',
]
register_commenter2 = RegisterCommenterWorkflowStatusItem()
register_commenter2.parent = st1
st1.items.append(register_commenter2)
register_commenter2.comment = 'd2'
register_commenter2.to = [role.id, '_submitter']
user.roles = [role.id, role2.id]
register_commenter2.perform(formdata)
assert len(formdata.evolution[-1].parts) == 6
assert '<p>d1</p>' in [str(x) for x in display_parts()]
assert '<p>d2</p>' in [str(x) for x in display_parts()]
def test_email(pub, emails):
pub.substitutions.feed(MockSubstitutionVariables())

View File

@ -157,6 +157,8 @@ class Evolution(object):
for p in self.parts:
if not hasattr(p, 'view'):
continue
if hasattr(p, 'to') and not self.formdata.is_for_current_user(p.to):
continue
text = p.view()
if text:
l.append(text)

View File

@ -2022,6 +2022,8 @@ class SqlDataMixin(SqlMixin):
fts_strings.append(evo.comment)
for part in evo.parts or []:
if hasattr(part, 'view'):
if hasattr(part, 'to') and not self.is_for_current_user(part.to):
continue
html_part = part.view()
if html_part:
fts_strings.append(qommon.misc.html2text(html_part))

View File

@ -31,10 +31,12 @@ import sys
class JournalEvolutionPart: # pylint: disable=C1001
content = None
to = None
def __init__(self, formdata, message):
def __init__(self, formdata, message, to):
if not message:
return
self.to = to
if '{{' in message or '{%' in message:
# django template
content = template_on_formdata(formdata, message)
@ -68,6 +70,7 @@ class JournalEvolutionPart: # pylint: disable=C1001
def get_json_export_dict(self, anonymise=False):
d = {
'type': 'workflow-comment',
'to': self.to,
}
if not anonymise:
d['content'] = self.content
@ -80,6 +83,7 @@ class RegisterCommenterWorkflowStatusItem(WorkflowStatusItem):
category = 'interaction'
comment = None
to = None
attachments = None
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
@ -90,9 +94,22 @@ class RegisterCommenterWorkflowStatusItem(WorkflowStatusItem):
form.add(
TextWidget, '%scomment' % prefix, title=_('Message'), value=self.comment, cols=80, rows=10
)
if 'to' in parameters:
form.add(
WidgetList,
'%sto' % prefix,
title=_('To'),
element_type=SingleSelectWidget,
value=self.to or [],
add_element_label=self.get_add_role_label(),
element_kwargs={
'render_br': False,
'options': [(None, '---', None)] + self.get_list_of_roles(include_logged_in_users=False),
},
)
def get_parameters(self):
return ('comment', 'attachments', 'condition')
return ('comment', 'to', 'attachments', 'condition')
def attach_uploads_to_formdata(self, formdata, uploads):
if not formdata.evolution[-1].parts:
@ -120,7 +137,7 @@ class RegisterCommenterWorkflowStatusItem(WorkflowStatusItem):
# the comment can use attachments done above
try:
formdata.evolution[-1].add_part(JournalEvolutionPart(formdata, self.comment))
formdata.evolution[-1].add_part(JournalEvolutionPart(formdata, self.comment, self.to))
formdata.store()
except TemplateError as e:
url = formdata.get_url()