From 1eed6e24443ef16e98319b842a82d230d6993470 Mon Sep 17 00:00:00 2001 From: jasquat <2487833+jasquat@users.noreply.github.com> Date: Thu, 16 Nov 2023 10:05:08 -0500 Subject: [PATCH] feature/full-breadcrumb-on-task-show (#675) * show the full breadcrumb on task show page w/ burnettk * check read permission of process model before displaying in breadcrumb on task show page * in the breadcrumb if the api returns 401 then just ignore the breadcrumb * pyl --------- Co-authored-by: jasquat --- .../config/permissions/local_development.yml | 4 +- .../routes/process_models_controller.py | 3 +- .../src/components/ProcessBreadcrumb.tsx | 139 ++++++++++-------- .../src/hooks/PermissionService.tsx | 23 ++- spiffworkflow-frontend/src/interfaces.ts | 1 + .../src/routes/TaskShow.tsx | 11 +- 6 files changed, 110 insertions(+), 71 deletions(-) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/local_development.yml b/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/local_development.yml index cc53d8c7..759ab010 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/local_development.yml +++ b/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/local_development.yml @@ -17,6 +17,8 @@ groups: users: [jason@sartography.com, kevin@sartography.com] group2: users: [dan@sartography.com] + group3: + users: [jon@sartography.com] permissions: admin: @@ -25,7 +27,7 @@ permissions: uri: /* basic: - groups: [group2] + groups: [group2, group3] actions: [all] uri: BASIC diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_models_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_models_controller.py index de9aeddd..9fc7fe55 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_models_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_models_controller.py @@ -158,7 +158,8 @@ def process_model_show(modified_process_model_identifier: str, include_file_refe process_model.bpmn_version_control_identifier = current_git_revision - available_actions = {} + # if the user got here then they can read the process model + available_actions = {"read": {"path": f"/process-models/{modified_process_model_identifier}", "method": "GET"}} if GitService.check_for_publish_configs(raise_on_missing=False): available_actions = { "publish": {"path": f"/process-model-publish/{modified_process_model_identifier}", "method": "POST"} diff --git a/spiffworkflow-frontend/src/components/ProcessBreadcrumb.tsx b/spiffworkflow-frontend/src/components/ProcessBreadcrumb.tsx index e979f4b6..8a6db736 100644 --- a/spiffworkflow-frontend/src/components/ProcessBreadcrumb.tsx +++ b/spiffworkflow-frontend/src/components/ProcessBreadcrumb.tsx @@ -4,6 +4,8 @@ import { useEffect, useState } from 'react'; import { modifyProcessIdentifierForPathParam } from '../helpers'; import { HotCrumbItem, + HotCrumbItemArray, + HotCrumbItemObject, ProcessGroup, ProcessGroupLite, ProcessModel, @@ -29,6 +31,7 @@ export default function ProcessBreadcrumb({ hotCrumbs }: OwnProps) { entityToExplode as string )}`, successCallback: setProcessEntity, + onUnauthorized: () => {}, }); } else if (entityType === 'process-group-id') { HttpService.makeCallToBackend({ @@ -36,6 +39,7 @@ export default function ProcessBreadcrumb({ hotCrumbs }: OwnProps) { entityToExplode as string )}`, successCallback: setProcessEntity, + onUnauthorized: () => {}, }); } else { setProcessEntity(entityToExplode as any); @@ -47,74 +51,91 @@ export default function ProcessBreadcrumb({ hotCrumbs }: OwnProps) { } }, [setProcessEntity, hotCrumbs]); + const checkPermissions = (crumb: HotCrumbItemObject) => { + if (!crumb.checkPermission) { + return true; + } + return ( + processEntity && + 'actions' in processEntity && + processEntity.actions && + 'read' in processEntity.actions + ); + }; + // eslint-disable-next-line sonarjs/cognitive-complexity const hotCrumbElement = () => { if (hotCrumbs) { - const leadingCrumbLinks = hotCrumbs.map((crumb: any) => { - if ( - 'entityToExplode' in crumb && - processEntity && - processEntity.parent_groups - ) { - const breadcrumbs = processEntity.parent_groups.map( - (parentGroup: ProcessGroupLite) => { - const fullUrl = `/process-groups/${modifyProcessIdentifierForPathParam( - parentGroup.id + const leadingCrumbLinks = hotCrumbs.map( + (crumb: HotCrumbItemArray | HotCrumbItemObject) => { + if ( + 'entityToExplode' in crumb && + processEntity && + processEntity.parent_groups && + checkPermissions(crumb) + ) { + const breadcrumbs = processEntity.parent_groups.map( + (parentGroup: ProcessGroupLite) => { + const fullUrl = `/process-groups/${modifyProcessIdentifierForPathParam( + parentGroup.id + )}`; + return ( + + {parentGroup.display_name} + + ); + } + ); + + if (crumb.linkLastItem) { + let apiBase = '/process-groups'; + let dataQaTag = ''; + if (crumb.entityType.startsWith('process-model')) { + apiBase = '/process-models'; + dataQaTag = 'process-model-breadcrumb-link'; + } + const fullUrl = `${apiBase}/${modifyProcessIdentifierForPathParam( + processEntity.id )}`; - return ( - - {parentGroup.display_name} + breadcrumbs.push( + + {processEntity.display_name} + + ); + } else { + breadcrumbs.push( + + {processEntity.display_name} ); } - ); - - if (crumb.linkLastItem) { - let apiBase = '/process-groups'; - let dataQaTag = ''; - if (crumb.entityType.startsWith('process-model')) { - apiBase = '/process-models'; - dataQaTag = 'process-model-breadcrumb-link'; - } - const fullUrl = `${apiBase}/${modifyProcessIdentifierForPathParam( - processEntity.id - )}`; - breadcrumbs.push( - - {processEntity.display_name} - - ); - } else { - breadcrumbs.push( - - {processEntity.display_name} - - ); + return breadcrumbs; } - return breadcrumbs; + if (Array.isArray(crumb)) { + const valueLabel = crumb[0]; + const url = crumb[1]; + if (!url && valueLabel) { + return ( + + {valueLabel} + + ); + } + if (url && valueLabel) { + return ( + + {valueLabel} + + ); + } + } + return null; } - const valueLabel = crumb[0]; - const url = crumb[1]; - if (!url && valueLabel) { - return ( - - {valueLabel} - - ); - } - if (url && valueLabel) { - return ( - - {valueLabel} - - ); - } - return null; - }); + ); return {leadingCrumbLinks}; } return null; diff --git a/spiffworkflow-frontend/src/hooks/PermissionService.tsx b/spiffworkflow-frontend/src/hooks/PermissionService.tsx index fad496a7..017ea4cb 100644 --- a/spiffworkflow-frontend/src/hooks/PermissionService.tsx +++ b/spiffworkflow-frontend/src/hooks/PermissionService.tsx @@ -6,6 +6,20 @@ import { AbilityContext } from '../contexts/Can'; import { PermissionCheckResponseBody, PermissionsToCheck } from '../interfaces'; import HttpService from '../services/HttpService'; +export const checkPermissions = ( + permissionsToCheck: PermissionsToCheck, + successCallback: Function +) => { + if (Object.keys(permissionsToCheck).length !== 0) { + HttpService.makeCallToBackend({ + path: `/permissions-check`, + httpMethod: 'POST', + successCallback, + postBody: { requests_to_check: permissionsToCheck }, + }); + } +}; + export const usePermissionFetcher = ( permissionsToCheck: PermissionsToCheck ) => { @@ -37,14 +51,7 @@ export const usePermissionFetcher = ( ability.update(rules); setPermissionsLoaded(true); }; - if (Object.keys(permissionsToCheck).length !== 0) { - HttpService.makeCallToBackend({ - path: `/permissions-check`, - httpMethod: 'POST', - successCallback: processPermissionResult, - postBody: { requests_to_check: permissionsToCheck }, - }); - } + checkPermissions(permissionsToCheck, processPermissionResult); }); return { ability, permissionsLoaded }; diff --git a/spiffworkflow-frontend/src/interfaces.ts b/spiffworkflow-frontend/src/interfaces.ts index 97a14baa..da3e2142 100644 --- a/spiffworkflow-frontend/src/interfaces.ts +++ b/spiffworkflow-frontend/src/interfaces.ts @@ -299,6 +299,7 @@ export interface HotCrumbItemObject { entityToExplode: ProcessModel | ProcessGroup | string; entityType: string; linkLastItem?: boolean; + checkPermission?: boolean; } export type HotCrumbItemArray = [displayValue: string, url?: string]; diff --git a/spiffworkflow-frontend/src/routes/TaskShow.tsx b/spiffworkflow-frontend/src/routes/TaskShow.tsx index 2263ceb2..227aa817 100644 --- a/spiffworkflow-frontend/src/routes/TaskShow.tsx +++ b/spiffworkflow-frontend/src/routes/TaskShow.tsx @@ -411,11 +411,18 @@ export default function TaskShow() { pageElements.push(