From f4af53f1dde95c9a12e45a86e7a2ce4d868a33c6 Mon Sep 17 00:00:00 2001 From: jasquat Date: Fri, 21 Apr 2023 15:56:32 -0400 Subject: [PATCH] Revert "some updates so task_show no longer needs the processor. i think it mostly works w/ burnettk" This reverts commit f000f47794ca3377b2ed207e8b294faeb90a4af8. --- .../src/spiffworkflow_backend/models/task.py | 11 -- .../routes/tasks_controller.py | 145 +++++++---------- .../services/authorization_service.py | 10 +- .../services/process_instance_processor.py | 6 +- .../services/process_instance_service.py | 6 +- .../services/task_service.py | 55 ++----- .../call_activity_level_2b.bpmn | 68 ++------ .../call_activity_level_3.bpmn | 8 +- .../call_activity_nested/process_model.json | 11 -- .../data/call_activity_nested/schema.json | 1 + .../unit/test_process_model.py | 11 ++ .../unit/test_process_model_service.py | 4 + .../unit/test_task_service.py | 153 ------------------ .../src/components/InstructionsForEndUser.tsx | 5 +- .../src/routes/HomePageRoutes.tsx | 5 + .../src/routes/ProcessInterstitial.tsx | 7 +- .../src/routes/ProcessRoutes.tsx | 2 +- 17 files changed, 117 insertions(+), 391 deletions(-) delete mode 100644 spiffworkflow-backend/tests/data/call_activity_nested/process_model.json create mode 100644 spiffworkflow-backend/tests/data/call_activity_nested/schema.json delete mode 100644 spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_task_service.py diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/task.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/task.py index 3b67883cf..c9bf311b4 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/task.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/task.py @@ -69,17 +69,6 @@ class TaskModel(SpiffworkflowBaseDBModel): data: Optional[dict] = None - # these are here to be compatible with task api - form_schema: Optional[dict] = None - form_ui_schema: Optional[dict] = None - process_model_display_name: Optional[str] = None - process_model_identifier: Optional[str] = None - type: Optional[str] = None - can_complete: Optional[bool] = None - - def get_data(self) -> dict: - return {**self.python_env_data(), **self.json_data()} - def python_env_data(self) -> dict: return JsonDataModel.find_data_dict_by_hash(self.python_env_data_hash) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py index b1ed17c0f..4adc95364 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py @@ -1,7 +1,5 @@ """APIs for dealing with process groups, process models, and process instances.""" import json -from spiffworkflow_backend.services.authorization_service import UserDoesNotHaveAccessToTaskError -from spiffworkflow_backend.services.authorization_service import HumanTaskNotFoundError import os import uuid from sys import exc_info @@ -285,67 +283,39 @@ def task_show(process_instance_id: int, task_guid: str = "next") -> flask.wrappe form_schema_file_name = "" form_ui_schema_file_name = "" - processor = ProcessInstanceProcessor(process_instance) - spiff_task = _get_spiff_task_from_process_instance(task_guid, process_instance, processor=processor) + if task_guid == "next": + spiff_task = processor.next_task() + task_guid = spiff_task.id + else: + spiff_task = _get_spiff_task_from_process_instance(task_guid, process_instance, processor=processor) extensions = spiff_task.task_spec.extensions - task_model = _get_task_model_from_guid_or_raise(task_guid, process_instance_id) - # extensions = task_model.properties_json['extensions'] if 'extensions' in task_model.properties_json else {} - if "properties" in extensions: properties = extensions["properties"] if "formJsonSchemaFilename" in properties: form_schema_file_name = properties["formJsonSchemaFilename"] if "formUiSchemaFilename" in properties: form_ui_schema_file_name = properties["formUiSchemaFilename"] - - can_complete = False - try: - AuthorizationService.assert_user_can_complete_task( - process_instance.id, task_model.task_definition.bpmn_identifier, g.user - ) - can_complete = True - except HumanTaskNotFoundError: - can_complete = False - except UserDoesNotHaveAccessToTaskError: - can_complete = False - task = ProcessInstanceService.spiff_task_to_api_task(processor, spiff_task) task.data = spiff_task.data task.process_model_display_name = process_model.display_name task.process_model_identifier = process_model.id - # task.data - # task.form_schema - # task.form_ui_schema - # task.id - # task.process_model_display_name - # task.process_model_identifier - # task.state - # task.type - - task_model.data = task_model.get_data() - task_model.process_model_display_name = process_model.display_name - task_model.process_model_identifier = process_model.id - task_model.type = task_model.task_definition.typename - task_model.can_complete = can_complete - task_process_identifier = task_model.bpmn_process.bpmn_process_definition.bpmn_identifier - process_model_with_form = process_model refs = SpecFileService.get_references_for_process(process_model_with_form) all_processes = [i.identifier for i in refs] - if task_process_identifier not in all_processes: - top_bpmn_process = TaskService.bpmn_process_for_called_activity_or_top_level_process(task_model) + if task.process_identifier not in all_processes: + top_process_name = processor.find_process_model_process_name_by_task_name(task.process_identifier) bpmn_file_full_path = ProcessInstanceProcessor.bpmn_file_full_path_from_bpmn_process_identifier( - top_bpmn_process.bpmn_process_definition.bpmn_identifier + top_process_name ) relative_path = os.path.relpath(bpmn_file_full_path, start=FileSystemService.root_path()) process_model_relative_path = os.path.dirname(relative_path) process_model_with_form = ProcessModelService.get_process_model_from_relative_path(process_model_relative_path) - if task_model.task_definition.typename == "UserTask": + if task.type == "User Task": if not form_schema_file_name: raise ( ApiError( @@ -360,38 +330,37 @@ def task_show(process_instance_id: int, task_guid: str = "next") -> flask.wrappe form_dict = _prepare_form_data( form_schema_file_name, - task_model, + spiff_task, process_model_with_form, ) - if task_model.data: - _update_form_schema_with_task_data_as_needed(form_dict, task_model) + if task.data: + _update_form_schema_with_task_data_as_needed(form_dict, task, spiff_task) if form_dict: - task_model.form_schema = form_dict + task.form_schema = form_dict if form_ui_schema_file_name: ui_form_contents = _prepare_form_data( form_ui_schema_file_name, - task_model, + task, process_model_with_form, ) if ui_form_contents: - task_model.form_ui_schema = ui_form_contents + task.form_ui_schema = ui_form_contents - _munge_form_ui_schema_based_on_hidden_fields_in_task_data(task_model) - _render_instructions_for_end_user(task_model) - return make_response(jsonify(task_model), 200) + _munge_form_ui_schema_based_on_hidden_fields_in_task_data(task) + _render_instructions_for_end_user(spiff_task, task) + return make_response(jsonify(task), 200) -def _render_instructions_for_end_user(task_model: TaskModel) -> str: +def _render_instructions_for_end_user(spiff_task: SpiffTask, task: Task) -> str: """Assure any instructions for end user are processed for jinja syntax.""" - extensions = task_model.properties_json['extensions'] if 'extensions' in task_model.properties_json else {} - if extensions and "instructionsForEndUser" in extensions: - if extensions["instructionsForEndUser"]: + if task.properties and "instructionsForEndUser" in task.properties: + if task.properties["instructionsForEndUser"]: try: - instructions = _render_jinja_template(extensions["instructionsForEndUser"], task_model) - extensions["instructionsForEndUser"] = instructions + instructions = _render_jinja_template(task.properties["instructionsForEndUser"], spiff_task) + task.properties["instructionsForEndUser"] = instructions return instructions except WorkflowTaskException as wfe: wfe.add_note("Failed to render instructions for end user.") @@ -428,12 +397,10 @@ def _interstitial_stream(process_instance_id: int) -> Generator[str, Optional[st processor = ProcessInstanceProcessor(process_instance) reported_ids = [] # bit of an issue with end tasks showing as getting completed twice. spiff_task = processor.next_task() - task_model = TaskModel.query.filter_by(guid=str(spiff_task.id)).first() last_task = None while last_task != spiff_task: - # import pdb; pdb.set_trace() task = ProcessInstanceService.spiff_task_to_api_task(processor, processor.next_task()) - instructions = _render_instructions_for_end_user(task_model) + instructions = _render_instructions_for_end_user(spiff_task, task) if instructions and spiff_task.id not in reported_ids: reported_ids.append(spiff_task.id) yield f"data: {current_app.json.dumps(task)} \n\n" @@ -441,9 +408,6 @@ def _interstitial_stream(process_instance_id: int) -> Generator[str, Optional[st processor.do_engine_steps(execution_strategy_name="run_until_user_message") processor.do_engine_steps(execution_strategy_name="one_at_a_time") spiff_task = processor.next_task() - task_model = TaskModel.query.filter_by(guid=str(spiff_task.id)).first() - # print(f"spiff_task: {spiff_task}") - # print(f"last_task: {last_task}") # Note, this has to be done in case someone leaves the page, # which can otherwise cancel this function and leave completed tasks un-registered. processor.save() # Fixme - maybe find a way not to do this on every loop? @@ -482,7 +446,7 @@ def _task_submit_shared( processor = ProcessInstanceProcessor(process_instance) spiff_task = _get_spiff_task_from_process_instance(task_guid, process_instance, processor=processor) - AuthorizationService.assert_user_can_complete_task(process_instance.id, spiff_task.task_spec.name, principal.user) + AuthorizationService.assert_user_can_complete_spiff_task(process_instance.id, spiff_task, principal.user) if spiff_task.state != TaskState.READY: raise ( @@ -670,14 +634,14 @@ def _get_tasks( return make_response(jsonify(response_json), 200) -def _prepare_form_data(form_file: str, task_model: TaskModel, process_model: ProcessModelInfo) -> dict: +def _prepare_form_data(form_file: str, spiff_task: SpiffTask, process_model: ProcessModelInfo) -> dict: """Prepare_form_data.""" - if task_model.data is None: + if spiff_task.data is None: return {} file_contents = SpecFileService.get_data(process_model, form_file).decode("utf-8") try: - form_contents = _render_jinja_template(file_contents, task_model) + form_contents = _render_jinja_template(file_contents, spiff_task) try: # form_contents is a str hot_dict: dict = json.loads(form_contents) @@ -697,14 +661,14 @@ def _prepare_form_data(form_file: str, task_model: TaskModel, process_model: Pro raise api_error -def _render_jinja_template(unprocessed_template: str, task_model: TaskModel) -> str: +def _render_jinja_template(unprocessed_template: str, spiff_task: SpiffTask) -> str: """Render_jinja_template.""" jinja_environment = jinja2.Environment(autoescape=True, lstrip_blocks=True, trim_blocks=True) try: template = jinja_environment.from_string(unprocessed_template) - return template.render(**(task_model.data or {})) + return template.render(**spiff_task.data) except jinja2.exceptions.TemplateError as template_error: - wfe = WorkflowTaskException(str(template_error), task=task_model, exception=template_error) + wfe = WorkflowTaskException(str(template_error), task=spiff_task, exception=template_error) if isinstance(template_error, TemplateSyntaxError): wfe.line_number = template_error.lineno wfe.error_line = template_error.source.split("\n")[template_error.lineno - 1] @@ -712,7 +676,7 @@ def _render_jinja_template(unprocessed_template: str, task_model: TaskModel) -> raise wfe from template_error except Exception as error: _type, _value, tb = exc_info() - wfe = WorkflowTaskException(str(error), task=task_model, exception=error) + wfe = WorkflowTaskException(str(error), task=spiff_task, exception=error) while tb: if tb.tb_frame.f_code.co_filename == "