From 64a344570484c2671dff3c2042f5093a4e4d8b9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Thu, 14 Jan 2016 13:57:04 +0100 Subject: [PATCH] workflows: let anonymous signed calls trigger jumps (#9659) --- tests/test_api.py | 40 ++++++++++++++++++++++++++++++++++++++++ tests/test_form_pages.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ wcs/wf/jump.py | 9 +++++---- 3 files changed, 89 insertions(+), 4 deletions(-) diff --git a/tests/test_api.py b/tests/test_api.py index 5f261bc..0954ae9 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -18,6 +18,7 @@ from wcs.formdef import FormDef from wcs.categories import Category from wcs.data_sources import NamedDataSource from wcs.workflows import Workflow +from wcs.wf.jump import JumpWorkflowStatusItem from wcs import fields from wcs.api import sign_url @@ -780,3 +781,42 @@ def test_users(pub, local_user): assert len(resp.json['data']) == 1 resp = get_app(pub).get(sign_uri('/api/users/?q=foobar')) assert len(resp.json['data']) == 0 + +def test_workflow_trigger(pub, local_user): + workflow = Workflow(name='test') + st1 = workflow.add_status('Status1', 'st1') + jump = JumpWorkflowStatusItem() + jump.trigger = 'XXX' + jump.status = 'st2' + st1.items.append(jump) + jump.parent = st1 + st2 = workflow.add_status('Status2', 'st2') + workflow.store() + + FormDef.wipe() + formdef = FormDef() + formdef.name = 'test' + formdef.fields = [] + formdef.workflow_id = workflow.id + formdef.store() + + formdef.data_class().wipe() + formdata = formdef.data_class()() + formdata.just_created() + formdata.store() + assert formdef.data_class().get(formdata.id).status == 'wf-st1' + + resp = get_app(pub).post(sign_uri(formdata.get_url() + 'jump/trigger/XXX'), + status=200) + assert formdef.data_class().get(formdata.id).status == 'wf-st2' + + Role.wipe() + role = Role(name='xxx') + role.store() + + jump.by = [role.id] + workflow.store() + + formdata.store() # (will get back to wf-st1) + resp = get_app(pub).post(sign_uri(formdata.get_url() + 'jump/trigger/XXX'), + status=403) diff --git a/tests/test_form_pages.py b/tests/test_form_pages.py index 3ecb1ec..1771183 100644 --- a/tests/test_form_pages.py +++ b/tests/test_form_pages.py @@ -2164,3 +2164,47 @@ def test_form_string_field_autocomplete(pub): resp = get_app(pub).get('/test/') assert ').autocomplete({' in resp.body assert 'http://example.net' in resp.body + +def test_form_workflow_trigger(pub): + user = create_user(pub) + + formdef = create_formdef() + formdef.fields = [] + formdef.store() + + workflow = Workflow(name='test') + st1 = workflow.add_status('Status1', 'st1') + jump = JumpWorkflowStatusItem() + jump.trigger = 'XXX' + jump.status = 'st2' + st1.items.append(jump) + jump.parent = st1 + st2 = workflow.add_status('Status2', 'st2') + workflow.store() + + formdef.workflow_id = workflow.id + formdef.store() + + formdef.data_class().wipe() + formdata = formdef.data_class()() + formdata.just_created() + formdata.store() + assert formdef.data_class().get(formdata.id).status == 'wf-st1' + + app = get_app(pub) + resp = login(app, username='foo', password='foo').get('/') + resp = app.post(formdata.get_url() + 'jump/trigger/XXX', status=403) + + Role.wipe() + role = Role(name='xxx') + role.store() + + jump.by = [role.id] + workflow.store() + resp = app.post(formdata.get_url() + 'jump/trigger/XXX', status=403) + + user.roles = [role.id] + user.store() + resp = app.post(formdata.get_url() + 'jump/trigger/XXX', status=302) + + assert formdef.data_class().get(formdata.id).status == 'wf-st2' diff --git a/wcs/wf/jump.py b/wcs/wf/jump.py index f650c1c..a737668 100644 --- a/wcs/wf/jump.py +++ b/wcs/wf/jump.py @@ -27,7 +27,7 @@ from qommon.publisher import get_publisher_class from qommon.cron import CronJob from wcs.workflows import Workflow, WorkflowStatusJumpItem, register_item_class -from wcs.api import get_user_from_api_query_string +from wcs.api import get_user_from_api_query_string, is_url_signed def jump_and_perform(formdata, status, workflow_data=None): if workflow_data: @@ -62,16 +62,17 @@ class TriggerDirectory(Directory): if not get_request().get_method() == 'POST': raise errors.AccessForbiddenError() + signed_request = is_url_signed() user = get_user_from_api_query_string() or get_request().user - if not user: - raise errors.AccessForbiddenError() for item in self.wfstatus.items: if not isinstance(item, JumpWorkflowStatusItem): continue if not hasattr(item, 'trigger'): continue if component == item.trigger: - if not item.check_auth(self.formdata, user): + if signed_request and not item.by: + pass + elif not item.check_auth(self.formdata, user): raise errors.AccessForbiddenError() get_request().trigger_name = component workflow_data = None -- 2.7.0.rc3