workflows: report all missing things in one time (#57753)
gitea-wip/wcs/pipeline/head Build started...
Details
gitea-wip/wcs/pipeline/head Build started...
Details
This commit is contained in:
parent
3c1ca2d57b
commit
252955bf2f
|
@ -302,7 +302,7 @@ def test_settings_export_import(pub):
|
|||
resp = app.get('/backoffice/settings/import')
|
||||
resp.form['file'] = Upload('export.wcs', zip_content.getvalue())
|
||||
resp = resp.form.submit('submit')
|
||||
assert 'Unknown referenced role (qux)' in resp
|
||||
assert 'Unknown referenced objects [Unknown roles: qux]' in resp
|
||||
|
||||
|
||||
def test_settings_themes(pub):
|
||||
|
|
|
@ -644,7 +644,7 @@ def test_workflows_export_import_create_role(pub):
|
|||
resp = resp.click('Import')
|
||||
resp.form['file'] = Upload('xxx.wcs', wf_export)
|
||||
resp = resp.form.submit('submit')
|
||||
assert 'Invalid File (Unknown referenced role (PLOP))' in resp.text
|
||||
assert 'Invalid File (Unknown referenced objects [Unknown roles: PLOP])' in resp.text
|
||||
|
||||
|
||||
def test_workflows_duplicate(pub):
|
||||
|
|
|
@ -282,7 +282,7 @@ def test_form_snapshot_restore_with_import_error(pub):
|
|||
snapshot = pub.snapshot_class.select_object_history(formdef)[0]
|
||||
resp = app.get('/backoffice/forms/%s/history/%s/restore' % (formdef.id, snapshot.id))
|
||||
resp = resp.form.submit('submit')
|
||||
assert 'Can not restore snapshot (Unknown datasources [unknown])' in resp
|
||||
assert 'Can not restore snapshot (Unknown referenced objects [Unknown datasources: unknown])' in resp
|
||||
|
||||
|
||||
def test_block_snapshot_browse(pub):
|
||||
|
@ -461,7 +461,7 @@ def test_form_snapshot_browse_with_import_error(pub):
|
|||
resp = app.get('/backoffice/forms/%s/history/%s/view/' % (formdef.id, snapshot.id), status=302)
|
||||
assert resp.location == 'http://example.net/backoffice/forms/%s/history/' % formdef.id
|
||||
resp = resp.follow()
|
||||
assert 'Can not display snapshot (Unknown field type [foobar])' in resp
|
||||
assert 'Can not display snapshot (Unknown referenced objects [Unknown field types: foobar])' in resp
|
||||
|
||||
|
||||
def test_workflow_snapshot_browse(pub):
|
||||
|
@ -563,7 +563,7 @@ def test_workflow_snapshot_restore_with_import_error(pub):
|
|||
snapshot = pub.snapshot_class.select_object_history(wf)[0]
|
||||
resp = app.get('/backoffice/workflows/%s/history/%s/restore' % (wf.id, snapshot.id))
|
||||
resp = resp.form.submit('submit')
|
||||
assert 'Can not restore snapshot (Unknown datasources [unknown])' in resp
|
||||
assert 'Can not restore snapshot (Unknown referenced objects [Unknown datasources: unknown])' in resp
|
||||
|
||||
|
||||
def test_workflow_snapshot_restore_with_missing_role(pub):
|
||||
|
|
|
@ -136,8 +136,10 @@ def test_action_dispatch(pub):
|
|||
pub.cfg['sp'] = {'idp-manage-roles': True}
|
||||
# now roles are managed: cannot create them
|
||||
dispatch.role_id = 'unknown'
|
||||
with pytest.raises(WorkflowImportError, match=r'.*Unknown referenced role.*'):
|
||||
with pytest.raises(WorkflowImportError) as excinfo:
|
||||
wf2 = assert_import_export_works(wf)
|
||||
assert excinfo.value.msg == 'Unknown referenced objects'
|
||||
assert excinfo.value.details == 'Unknown roles: unknown'
|
||||
# but allow computed roles
|
||||
dispatch.role_id = '=form_var_bar'
|
||||
wf2 = assert_import_export_works(wf)
|
||||
|
@ -895,8 +897,10 @@ def test_worklow_with_mail_template(pub):
|
|||
# import with non existing mail template
|
||||
MailTemplate.wipe()
|
||||
export = ET.tostring(wf.export_to_xml(include_id=True))
|
||||
with pytest.raises(WorkflowImportError, match='Unknown referenced mail template'):
|
||||
with pytest.raises(WorkflowImportError) as excinfo:
|
||||
Workflow.import_from_xml_tree(ET.fromstring(export), include_id=True)
|
||||
assert excinfo.value.msg == 'Unknown referenced objects'
|
||||
assert excinfo.value.details == 'Unknown mail templates: test-mail-template'
|
||||
|
||||
|
||||
def test_workflow_with_unknown_data_source(pub):
|
||||
|
@ -1039,3 +1043,73 @@ def test_workflow_with_category(pub):
|
|||
export = ET.tostring(wf.export_to_xml(include_id=True))
|
||||
wf3 = Workflow.import_from_xml_tree(ET.fromstring(export), include_id=True)
|
||||
assert wf3.category_id is None
|
||||
|
||||
|
||||
def test_import_workflow_multiple_errors(pub):
|
||||
BlockDef.wipe()
|
||||
pub.cfg['sp'] = {'idp-manage-roles': True}
|
||||
|
||||
wf = Workflow(name='status')
|
||||
st1 = wf.add_status('Status1', 'st1')
|
||||
display_form = FormWorkflowStatusItem()
|
||||
display_form.id = '_x'
|
||||
display_form.formdef = WorkflowFormFieldsFormDef(item=display_form)
|
||||
display_form.formdef.fields = [
|
||||
BlockField(id='1', type='block:foobar1'),
|
||||
BlockField(id='2', type='block:foobaz1'),
|
||||
StringField(id='3', type='string', data_source={'type': 'foobar1'}),
|
||||
StringField(id='4', type='string', data_source={'type': 'carddef:unknown1'}),
|
||||
]
|
||||
st1.items.append(display_form)
|
||||
display_form.parent = st1
|
||||
|
||||
dispatch1 = DispatchWorkflowStatusItem()
|
||||
dispatch1.id = '_x1'
|
||||
dispatch1.role_id = 'unknown-role1'
|
||||
dispatch1.role_key = 'plop'
|
||||
st1.items.append(dispatch1)
|
||||
dispatch1.parent = st1
|
||||
dispatch2 = DispatchWorkflowStatusItem()
|
||||
dispatch2.id = '_x2'
|
||||
dispatch2.role_id = 'unknown-role2'
|
||||
dispatch2.role_key = 'plop'
|
||||
st1.items.append(dispatch2)
|
||||
dispatch2.parent = st1
|
||||
|
||||
item1 = SendmailWorkflowStatusItem()
|
||||
item1.to = ['_receiver']
|
||||
item1.mail_template = 'unknown-mt-1'
|
||||
st1.items.append(item1)
|
||||
item1.parent = st1
|
||||
item2 = SendmailWorkflowStatusItem()
|
||||
item2.to = ['_receiver']
|
||||
item2.mail_template = 'unknown-mt-2'
|
||||
st1.items.append(item2)
|
||||
item2.parent = st1
|
||||
|
||||
wf.variables_formdef = WorkflowVariablesFieldsFormDef(workflow=wf)
|
||||
wf.variables_formdef.fields = [
|
||||
BlockField(id='1', type='block:foobar2'),
|
||||
BlockField(id='2', type='block:foobaz2'),
|
||||
StringField(id='3', type='string', data_source={'type': 'foobar2'}),
|
||||
StringField(id='4', type='string', data_source={'type': 'carddef:unknown2'}),
|
||||
]
|
||||
|
||||
wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
|
||||
wf.backoffice_fields_formdef.fields = [
|
||||
BlockField(id='1', type='block:foobar3'),
|
||||
BlockField(id='2', type='block:foobaz3'),
|
||||
StringField(id='3', type='string', data_source={'type': 'foobar3'}),
|
||||
StringField(id='4', type='string', data_source={'type': 'carddef:unknown3'}),
|
||||
]
|
||||
|
||||
export = ET.tostring(export_to_indented_xml(wf))
|
||||
with pytest.raises(WorkflowImportError) as excinfo:
|
||||
Workflow.import_from_xml(io.BytesIO(export))
|
||||
assert excinfo.value.msg == 'Unknown referenced objects'
|
||||
assert excinfo.value.details == (
|
||||
'Unknown datasources: carddef:unknown1, carddef:unknown2, carddef:unknown3, foobar1, foobar2, foobar3; '
|
||||
'Unknown field types: block:foobar1, block:foobar2, block:foobar3, block:foobaz1, block:foobaz2, block:foobaz3; '
|
||||
'Unknown mail templates: unknown-mt-1, unknown-mt-2; '
|
||||
'Unknown roles: unknown-role1, unknown-role2'
|
||||
)
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import base64
|
||||
import collections
|
||||
import contextlib
|
||||
import copy
|
||||
import datetime
|
||||
|
@ -60,6 +61,22 @@ class FormdefImportError(Exception):
|
|||
self.details = details
|
||||
|
||||
|
||||
class FormdefImportUnknownReferencedError(FormdefImportError):
|
||||
def __init__(self, msg, msg_args=None, details=None):
|
||||
self.msg = msg
|
||||
self.msg_args = msg_args or ()
|
||||
self._details = details
|
||||
|
||||
@property
|
||||
def details(self):
|
||||
if not self._details:
|
||||
return None
|
||||
details = []
|
||||
for kind in self._details:
|
||||
details.append('%s: %s' % (kind, ', '.join(sorted(self._details[kind]))))
|
||||
return '; '.join(details)
|
||||
|
||||
|
||||
class FormdefImportRecoverableError(FormdefImportError):
|
||||
pass
|
||||
|
||||
|
@ -1357,12 +1374,12 @@ class FormDef(StorableObject):
|
|||
unknown_datasources.add(data_source_id)
|
||||
|
||||
if unknown_field_types or unknown_datasources:
|
||||
details = []
|
||||
details = collections.defaultdict(set)
|
||||
if unknown_field_types:
|
||||
details.append('%s: %s' % (_('Unknown field types'), ', '.join(sorted(unknown_field_types))))
|
||||
details[_('Unknown field types')].update(unknown_field_types)
|
||||
if unknown_datasources:
|
||||
details.append('%s: %s' % (_('Unknown datasources'), ', '.join(sorted(unknown_datasources))))
|
||||
raise FormdefImportError(_('Unknown referenced objects'), details='; '.join(details))
|
||||
details[_('Unknown datasources')].update(unknown_datasources)
|
||||
raise FormdefImportUnknownReferencedError(_('Unknown referenced objects'), details=details)
|
||||
|
||||
return formdef
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ from .categories import WorkflowCategory
|
|||
from .conditions import Condition
|
||||
from .fields import FileField
|
||||
from .formdata import Evolution
|
||||
from .formdef import FormDef, FormdefImportError
|
||||
from .formdef import FormDef, FormdefImportError, FormdefImportUnknownReferencedError
|
||||
from .mail_templates import MailTemplate
|
||||
from .qommon import _, emails, errors, ezt, force_str, get_cfg, misc
|
||||
from .qommon.form import (
|
||||
|
@ -121,6 +121,22 @@ class WorkflowImportError(Exception):
|
|||
self.details = details
|
||||
|
||||
|
||||
class WorkflowImportUnknownReferencedError(WorkflowImportError):
|
||||
def __init__(self, msg, msg_args=None, details=None):
|
||||
self.msg = msg
|
||||
self.msg_args = msg_args or ()
|
||||
self._details = details
|
||||
|
||||
@property
|
||||
def details(self):
|
||||
if not self._details:
|
||||
return None
|
||||
details = []
|
||||
for kind in sorted(self._details.keys()):
|
||||
details.append('%s: %s' % (kind, ', '.join(sorted(self._details[kind]))))
|
||||
return '; '.join(details)
|
||||
|
||||
|
||||
class AbortActionException(Exception):
|
||||
def __init__(self, url=None):
|
||||
self.url = url
|
||||
|
@ -802,6 +818,7 @@ class Workflow(StorableObject):
|
|||
for role_node in tree.findall('roles/role'):
|
||||
workflow.roles[role_node.attrib['id']] = xml_node_text(role_node)
|
||||
|
||||
unknown_referenced_objects_details = collections.defaultdict(set)
|
||||
workflow.possible_status = []
|
||||
for status in tree.find('possible_status'):
|
||||
status_o = WorkflowStatus()
|
||||
|
@ -814,9 +831,13 @@ class Workflow(StorableObject):
|
|||
snapshot=snapshot,
|
||||
check_datasources=check_datasources,
|
||||
)
|
||||
except WorkflowImportUnknownReferencedError as e:
|
||||
for k, v in e._details.items():
|
||||
unknown_referenced_objects_details[k].update(v)
|
||||
except FormdefImportError as e:
|
||||
raise WorkflowImportError(e.msg, details=e.details)
|
||||
workflow.possible_status.append(status_o)
|
||||
else:
|
||||
workflow.possible_status.append(status_o)
|
||||
|
||||
workflow.global_actions = []
|
||||
global_actions = tree.find('global_actions')
|
||||
|
@ -842,10 +863,14 @@ class Workflow(StorableObject):
|
|||
imported_formdef = FormDef.import_from_xml_tree(
|
||||
formdef, include_id=True, snapshot=snapshot, check_datasources=check_datasources
|
||||
)
|
||||
except FormdefImportUnknownReferencedError as e:
|
||||
for k, v in e._details.items():
|
||||
unknown_referenced_objects_details[k].update(v)
|
||||
except FormdefImportError as e:
|
||||
raise WorkflowImportError(e.msg, details=e.details)
|
||||
workflow.variables_formdef = WorkflowVariablesFieldsFormDef(workflow=workflow)
|
||||
workflow.variables_formdef.fields = imported_formdef.fields
|
||||
else:
|
||||
workflow.variables_formdef = WorkflowVariablesFieldsFormDef(workflow=workflow)
|
||||
workflow.variables_formdef.fields = imported_formdef.fields
|
||||
|
||||
variables = tree.find('backoffice-fields')
|
||||
if variables is not None:
|
||||
|
@ -854,10 +879,19 @@ class Workflow(StorableObject):
|
|||
imported_formdef = FormDef.import_from_xml_tree(
|
||||
formdef, include_id=True, snapshot=snapshot, check_datasources=check_datasources
|
||||
)
|
||||
except FormdefImportUnknownReferencedError as e:
|
||||
for k, v in e._details.items():
|
||||
unknown_referenced_objects_details[k].update(v)
|
||||
except FormdefImportError as e:
|
||||
raise WorkflowImportError(e.msg, details=e.details)
|
||||
workflow.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(workflow=workflow)
|
||||
workflow.backoffice_fields_formdef.fields = imported_formdef.fields
|
||||
else:
|
||||
workflow.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(workflow=workflow)
|
||||
workflow.backoffice_fields_formdef.fields = imported_formdef.fields
|
||||
|
||||
if unknown_referenced_objects_details:
|
||||
raise WorkflowImportUnknownReferencedError(
|
||||
_('Unknown referenced objects'), details=unknown_referenced_objects_details
|
||||
)
|
||||
|
||||
return workflow
|
||||
|
||||
|
@ -1197,7 +1231,9 @@ class XmlSerialisable:
|
|||
if get_publisher() and get_cfg('sp', {}).get('idp-manage-roles') is True:
|
||||
if snapshot:
|
||||
return value
|
||||
raise WorkflowImportError(_('Unknown referenced role (%s)'), (value,))
|
||||
raise WorkflowImportUnknownReferencedError(
|
||||
_('Unknown referenced role (%s)'), details={_('Unknown roles'): {value}}
|
||||
)
|
||||
|
||||
# and if there's no match, create a new role
|
||||
role = get_publisher().role_class()
|
||||
|
@ -2003,13 +2039,29 @@ class WorkflowStatus:
|
|||
self.visibility.append(visibility_role.text)
|
||||
|
||||
self.items = []
|
||||
unknown_referenced_objects_details = collections.defaultdict(set)
|
||||
for item in elem.find('items'):
|
||||
item_type = item.attrib['type']
|
||||
self.append_item(item_type)
|
||||
item_o = self.items[-1]
|
||||
item_o.parent = self
|
||||
item_o.init_with_xml(
|
||||
item, charset, include_id=include_id, snapshot=snapshot, check_datasources=check_datasources
|
||||
try:
|
||||
item_o.init_with_xml(
|
||||
item,
|
||||
charset,
|
||||
include_id=include_id,
|
||||
snapshot=snapshot,
|
||||
check_datasources=check_datasources,
|
||||
)
|
||||
except (WorkflowImportUnknownReferencedError, FormdefImportUnknownReferencedError) as e:
|
||||
for k, v in e._details.items():
|
||||
unknown_referenced_objects_details[k].update(v)
|
||||
except FormdefImportError as e:
|
||||
raise WorkflowImportError(e.msg, details=e.details)
|
||||
|
||||
if unknown_referenced_objects_details:
|
||||
raise WorkflowImportUnknownReferencedError(
|
||||
_('Unknown referenced objects'), details=unknown_referenced_objects_details
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
|
@ -2442,7 +2494,9 @@ class WorkflowStatusItem(XmlSerialisable):
|
|||
value = xml_node_text(elem)
|
||||
mail_template = MailTemplate.get_by_slug(value)
|
||||
if not mail_template:
|
||||
raise WorkflowImportError(_('Unknown referenced mail template (%s)'), (value,))
|
||||
raise WorkflowImportUnknownReferencedError(
|
||||
_('Unknown referenced mail template (%s)'), details={_('Unknown mail templates'): {value}}
|
||||
)
|
||||
self.mail_template = value
|
||||
return
|
||||
|
||||
|
|
Loading…
Reference in New Issue