diff --git a/flask-bpmn/src/flask_bpmn/api/api_error.py b/flask-bpmn/src/flask_bpmn/api/api_error.py index eb390abe1..c782c2d38 100644 --- a/flask-bpmn/src/flask_bpmn/api/api_error.py +++ b/flask-bpmn/src/flask_bpmn/api/api_error.py @@ -170,15 +170,17 @@ def set_user_sentry_context() -> None: def handle_exception(exception: Exception) -> flask.wrappers.Response: """Handles unexpected exceptions.""" set_user_sentry_context() - id = capture_exception(exception) - organization_slug = current_app.config.get("SENTRY_ORGANIZATION_SLUG") - project_slug = current_app.config.get("SENTRY_PROJECT_SLUG") sentry_link = None - if organization_slug and project_slug: - sentry_link = ( - f"https://sentry.io/{organization_slug}/{project_slug}/events/{id}" - ) + if not isinstance(exception, ApiError) or exception.error_code != "invalid_token": + id = capture_exception(exception) + + organization_slug = current_app.config.get("SENTRY_ORGANIZATION_SLUG") + project_slug = current_app.config.get("SENTRY_PROJECT_SLUG") + if organization_slug and project_slug: + sentry_link = ( + f"https://sentry.io/{organization_slug}/{project_slug}/events/{id}" + ) # !!!NOTE!!!: do this after sentry stuff since calling logger.exception # seems to break the sentry sdk context where we no longer get back diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/api.yml b/spiffworkflow-backend/src/spiffworkflow_backend/api.yml index c559ba98a..a97a3b11f 100755 --- a/spiffworkflow-backend/src/spiffworkflow_backend/api.yml +++ b/spiffworkflow-backend/src/spiffworkflow_backend/api.yml @@ -673,6 +673,53 @@ paths: schema: $ref: "#/components/schemas/Workflow" + /process-instances/{modified_process_model_identifier}/{process_instance_id}/task-info: + parameters: + - name: modified_process_model_identifier + in: path + required: true + description: The unique id of an existing process model + schema: + type: string + - name: process_instance_id + in: path + required: true + description: The unique id of an existing process instance. + schema: + type: integer + - name: process_identifier + in: query + required: false + description: The identifier of the process to use for the diagram. Useful for displaying the diagram for a call activity. + schema: + type: string + - name: all_tasks + in: query + required: false + description: If true, this wil return all tasks associated with the process instance and not just user tasks. + schema: + type: boolean + - name: spiff_step + in: query + required: false + description: If set will return the tasks as they were during a specific step of execution. + schema: + type: integer + get: + tags: + - Process Instances + operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_task_list_without_task_data + summary: returns the list of all user tasks associated with process instance without the task data + responses: + "200": + description: list of tasks + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/Task" + /process-instances/{modified_process_model_identifier}/{process_instance_id}: parameters: - name: modified_process_model_identifier @@ -1132,8 +1179,8 @@ paths: get: tags: - Process Instances - operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_task_list - summary: returns the list of all user tasks associated with process instance + operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_task_list_with_task_data + summary: returns the list of all user tasks associated with process instance with the task data responses: "200": description: list of tasks diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/development.yml b/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/development.yml index 99790fed7..14061da78 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/development.yml +++ b/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/development.yml @@ -123,12 +123,12 @@ permissions: users: [] allowed_permissions: [read] uri: /v1.0/processes - - task-data-read: - groups: [demo] - users: [] - allowed_permissions: [read] - uri: /v1.0/task-data/* + # + # task-data-read: + # groups: [demo] + # users: [] + # allowed_permissions: [read] + # uri: /v1.0/task-data/* manage-procurement-admin: diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_logging.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_logging.py index b0b908877..532a6c09c 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_logging.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_logging.py @@ -8,7 +8,7 @@ from flask_bpmn.models.db import SpiffworkflowBaseDBModel @dataclass class SpiffLoggingModel(SpiffworkflowBaseDBModel): - """LoggingModel.""" + """SpiffLoggingModel.""" __tablename__ = "spiff_logging" id: int = db.Column(db.Integer, primary_key=True) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py index ba2f65c29..616d07ca6 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py @@ -1440,11 +1440,44 @@ def get_tasks( return make_response(jsonify(response_json), 200) -def process_instance_task_list( +def process_instance_task_list_without_task_data( modified_process_model_identifier: str, process_instance_id: int, all_tasks: bool = False, spiff_step: int = 0, +) -> flask.wrappers.Response: + """Process_instance_task_list_without_task_data.""" + return process_instance_task_list( + modified_process_model_identifier, + process_instance_id, + all_tasks, + spiff_step, + get_task_data=False, + ) + + +def process_instance_task_list_with_task_data( + modified_process_model_identifier: str, + process_instance_id: int, + all_tasks: bool = False, + spiff_step: int = 0, +) -> flask.wrappers.Response: + """Process_instance_task_list_with_task_data.""" + return process_instance_task_list( + modified_process_model_identifier, + process_instance_id, + all_tasks, + spiff_step, + get_task_data=True, + ) + + +def process_instance_task_list( + _modified_process_model_identifier: str, + process_instance_id: int, + all_tasks: bool = False, + spiff_step: int = 0, + get_task_data: bool = False, ) -> flask.wrappers.Response: """Process_instance_task_list.""" process_instance = find_process_instance_by_id_or_raise(process_instance_id) @@ -1475,7 +1508,8 @@ def process_instance_task_list( tasks = [] for spiff_task in spiff_tasks: task = ProcessInstanceService.spiff_task_to_api_task(spiff_task) - task.data = spiff_task.data + if get_task_data: + task.data = spiff_task.data tasks.append(task) return make_response(jsonify(tasks), 200) diff --git a/spiffworkflow-frontend/src/hooks/UriListForPermissions.tsx b/spiffworkflow-frontend/src/hooks/UriListForPermissions.tsx index f84465c82..4ba04352b 100644 --- a/spiffworkflow-frontend/src/hooks/UriListForPermissions.tsx +++ b/spiffworkflow-frontend/src/hooks/UriListForPermissions.tsx @@ -14,7 +14,8 @@ export const useUriListForPermissions = () => { processInstanceListPath: '/v1.0/process-instances', processInstanceLogListPath: `/v1.0/logs/${params.process_model_id}/${params.process_instance_id}`, processInstanceReportListPath: '/v1.0/process-instances/reports', - processInstanceTaskListPath: `/v1.0/task-data/${params.process_model_id}/${params.process_instance_id}`, + processInstanceTaskListPath: `/v1.0/process-instances/${params.process_model_id}/${params.process_instance_id}/task-info`, + processInstanceTaskListDataPath: `/v1.0/task-data/${params.process_model_id}/${params.process_instance_id}`, processModelCreatePath: `/v1.0/process-models/${params.process_group_id}`, processModelFileCreatePath: `/v1.0/process-models/${params.process_model_id}/files`, processModelFileShowPath: `/v1.0/process-models/${params.process_model_id}/files/${params.file_name}`, diff --git a/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx b/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx index 7a9b97943..1adb585bf 100644 --- a/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx +++ b/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx @@ -70,8 +70,10 @@ export default function ProcessInstanceShow() { const permissionRequestData: PermissionsToCheck = { [targetUris.messageInstanceListPath]: ['GET'], [targetUris.processInstanceTaskListPath]: ['GET'], + [targetUris.processInstanceTaskListDataPath]: ['GET', 'PUT'], [targetUris.processInstanceActionPath]: ['DELETE'], [targetUris.processInstanceLogListPath]: ['GET'], + [targetUris.processModelShowPath]: ['PUT'], [`${targetUris.processInstanceActionPath}/suspend`]: ['PUT'], [`${targetUris.processInstanceActionPath}/terminate`]: ['PUT'], [`${targetUris.processInstanceActionPath}/resume`]: ['PUT'], @@ -104,9 +106,15 @@ export default function ProcessInstanceShow() { if (typeof params.spiff_step !== 'undefined') { taskParams = `${taskParams}&spiff_step=${params.spiff_step}`; } - if (ability.can('GET', targetUris.processInstanceTaskListPath)) { + let taskPath = ''; + if (ability.can('GET', targetUris.processInstanceTaskListDataPath)) { + taskPath = `${targetUris.processInstanceTaskListDataPath}${taskParams}`; + } else if (ability.can('GET', targetUris.processInstanceTaskListPath)) { + taskPath = `${targetUris.processInstanceTaskListPath}${taskParams}`; + } + if (taskPath) { HttpService.makeCallToBackend({ - path: `${targetUris.processInstanceTaskListPath}${taskParams}`, + path: taskPath, successCallback: setTasks, failureCallback: processTaskFailure, }); @@ -442,7 +450,9 @@ export default function ProcessInstanceShow() { const canEditTaskData = (task: any) => { return ( - task.state === 'READY' && showingLastSpiffStep(processInstance as any) + ability.can('PUT', targetUris.processInstanceTaskListDataPath) && + task.state === 'READY' && + showingLastSpiffStep(processInstance as any) ); }; @@ -491,7 +501,10 @@ export default function ProcessInstanceShow() { const taskDataButtons = (task: any) => { const buttons = []; - if (task.type === 'Script Task') { + if ( + task.type === 'Script Task' && + ability.can('PUT', targetUris.processModelShowPath) + ) { buttons.push(