added new api endpoint to get task-info so users with access to process instances can see the tasks but not the data

This commit is contained in:
jasquat 2022-12-16 11:39:07 -05:00
parent e3fe09490b
commit 662a1ec5d6
8 changed files with 122 additions and 25 deletions

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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)

View File

@ -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)

View File

@ -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}`,

View File

@ -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(
<Button
data-qa="create-script-unit-test-button"

View File

@ -40,7 +40,7 @@ export default function TaskShow() {
const { targetUris } = useUriListForPermissions();
const permissionRequestData: PermissionsToCheck = {
[targetUris.processInstanceTaskListPath]: ['GET'],
[targetUris.processInstanceTaskListDataPath]: ['GET'],
};
const { ability, permissionsLoaded } = usePermissionFetcher(
permissionRequestData
@ -50,7 +50,7 @@ export default function TaskShow() {
if (permissionsLoaded) {
const processResult = (result: any) => {
setTask(result);
if (ability.can('GET', targetUris.processInstanceTaskListPath)) {
if (ability.can('GET', targetUris.processInstanceTaskListDataPath)) {
HttpService.makeCallToBackend({
path: `/task-data/${modifyProcessIdentifierForPathParam(
result.process_model_identifier