From 02bcab8802e0f5baf1eac39e81afe656dd698e7d Mon Sep 17 00:00:00 2001 From: Archer <545436317@qq.com> Date: Thu, 10 Oct 2024 19:31:51 +0800 Subject: [PATCH] fix: workflow delete error (#2879) * fix: workflow delete key error * fix: chat auth error --- .../api/core/chat/getPaginationRecords.ts | 1 + projects/app/src/pages/api/core/chat/init.ts | 2 +- .../src/pages/api/core/chat/outLink/init.ts | 2 +- .../app/src/pages/api/core/chat/team/init.ts | 2 +- .../Flow/hooks/useWorkflow.tsx | 109 ++++++++---------- .../WorkflowComponents/Flow/index.tsx | 2 +- .../service/support/permission/auth/chat.ts | 17 ++- 7 files changed, 62 insertions(+), 73 deletions(-) diff --git a/projects/app/src/pages/api/core/chat/getPaginationRecords.ts b/projects/app/src/pages/api/core/chat/getPaginationRecords.ts index 618ff74c536..82d1ed1c708 100644 --- a/projects/app/src/pages/api/core/chat/getPaginationRecords.ts +++ b/projects/app/src/pages/api/core/chat/getPaginationRecords.ts @@ -44,6 +44,7 @@ async function handler( per: ReadPermissionVal }) ]); + if (!app) { return Promise.reject(AppErrEnum.unExist); } diff --git a/projects/app/src/pages/api/core/chat/init.ts b/projects/app/src/pages/api/core/chat/init.ts index d0b1a581e39..19efff18867 100644 --- a/projects/app/src/pages/api/core/chat/init.ts +++ b/projects/app/src/pages/api/core/chat/init.ts @@ -37,7 +37,7 @@ async function handler( // auth chat permission if (chat && !app.permission.hasManagePer && String(tmbId) !== String(chat?.tmbId)) { - throw new Error(ChatErrEnum.unAuthChat); + return Promise.reject(ChatErrEnum.unAuthChat); } // get app and history diff --git a/projects/app/src/pages/api/core/chat/outLink/init.ts b/projects/app/src/pages/api/core/chat/outLink/init.ts index fa78d67c70f..20487b0e1d6 100644 --- a/projects/app/src/pages/api/core/chat/outLink/init.ts +++ b/projects/app/src/pages/api/core/chat/outLink/init.ts @@ -32,7 +32,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { // auth chat permission if (chat && chat.outLinkUid !== uid) { - throw new Error(ChatErrEnum.unAuthChat); + return Promise.reject(ChatErrEnum.unAuthChat); } const { nodes, chatConfig } = await getAppLatestVersion(app._id, app); diff --git a/projects/app/src/pages/api/core/chat/team/init.ts b/projects/app/src/pages/api/core/chat/team/init.ts index 32bdd1976b9..3bda119a302 100644 --- a/projects/app/src/pages/api/core/chat/team/init.ts +++ b/projects/app/src/pages/api/core/chat/team/init.ts @@ -37,7 +37,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { // auth chat permission if (chat && chat.outLinkUid !== uid) { - throw new Error(ChatErrEnum.unAuthChat); + return Promise.reject(ChatErrEnum.unAuthChat); } // get app and history diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useWorkflow.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useWorkflow.tsx index 94ffbbabcc4..65db3e1163d 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useWorkflow.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useWorkflow.tsx @@ -25,12 +25,14 @@ import { useContextSelector } from 'use-context-selector'; import { WorkflowContext } from '../../context'; import { THelperLine } from '@fastgpt/global/core/workflow/type'; import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants'; -import { useKeyPress, useMemoizedFn } from 'ahooks'; +import { useMemoizedFn } from 'ahooks'; import { Input_Template_Node_Height, Input_Template_Node_Width } from '@fastgpt/global/core/workflow/template/input'; import { FlowNodeItemType } from '@fastgpt/global/core/workflow/type/node'; +import { getHandleId } from '@fastgpt/global/core/workflow/utils'; +import { IfElseResultEnum } from '@fastgpt/global/core/workflow/template/system/ifElse/constant'; /* Compute helper lines for snapping nodes to each other @@ -282,8 +284,7 @@ export const useWorkflow = () => { onChangeNode, onEdgesChange, setHoverEdgeId, - setMenu, - mouseInCanvas + setMenu } = useContextSelector(WorkflowContext, (v) => v); const { getIntersectingNodes } = useReactFlow(); @@ -413,7 +414,33 @@ export const useWorkflow = () => { }); /* node */ + const handleRemoveNode = useMemoizedFn((change: NodeRemoveChange, nodeId: string) => { + // If the node has child nodes, remove the child nodes + const childNodes = nodes.filter((n) => n.data.parentNodeId === nodeId); + if (childNodes.length > 0) { + const childNodeIds = childNodes.map((node) => node.id); + const childEdges = edges.filter( + (edge) => childNodeIds.includes(edge.source) || childNodeIds.includes(edge.target) + ); + + onNodesChange( + childNodes.map((node) => ({ + type: 'remove', + id: node.id + })) + ); + onEdgesChange( + childEdges.map((edge) => ({ + type: 'remove', + id: edge.id + })) + ); + } + + onNodesChange([change]); + return; + }); const handleSelectNode = useMemoizedFn((change: NodeSelectionChange) => { // If the node is not selected and the Ctrl key is pressed, select the node if (change.selected === false && isDowningCtrl) { @@ -477,10 +504,25 @@ export const useWorkflow = () => { } } ); - const handleNodesChange = useMemoizedFn((changes: NodeChange[]) => { for (const change of changes) { - if (change.type === 'select') { + if (change.type === 'remove') { + const node = nodes.find((n) => n.id === change.id); + if (!node) continue; + + const parentNodeDeleted = changes.find( + (c) => c.type === 'remove' && c.id === node?.data.parentNodeId + ); + // Forbidden delete && Parents are not deleted together + if (node.data.forbidDelete && !parentNodeDeleted) { + toast({ + status: 'warning', + title: t('common:core.workflow.Can not delete node') + }); + continue; + } + handleRemoveNode(change, node.id); + } else if (change.type === 'select') { handleSelectNode(change); } else if (change.type === 'position') { const node = nodes.find((n) => n.id === change.id); @@ -490,7 +532,8 @@ export const useWorkflow = () => { } } - onNodesChange(changes); + // Remove separately + onNodesChange(changes.filter((c) => c.type !== 'remove')); }); const handleEdgeChange = useCallback( @@ -591,60 +634,6 @@ export const useWorkflow = () => { setMenu(null); }, [setMenu]); - useKeyPress(['Delete', 'Backspace'], (e) => { - if (!mouseInCanvas) return; - - const selectedNodes = nodes.filter((node) => node.selected); - if (selectedNodes.length > 0) { - for (const node of selectedNodes) { - if (node.data.forbidDelete) { - toast({ - status: 'warning', - title: t('common:core.workflow.Can not delete node') - }); - continue; - } - - // Computed deleted node and its edges - const removedNodeId = node.id; - const removedNodeEdges = edges.filter( - (edge) => edge.source === removedNodeId || edge.target === removedNodeId - ); - - const childNodes = nodes.filter((n) => n.data.parentNodeId === removedNodeId); - const childNodeIds = childNodes.map((node) => node.id); - const childEdges = edges.filter( - (edge) => childNodeIds.includes(edge.source) || childNodeIds.includes(edge.target) - ); - - // Delete - onNodesChange( - [removedNodeId, ...childNodeIds].map((nodeId) => ({ - type: 'remove', - id: nodeId - })) - ); - onEdgesChange( - [...removedNodeEdges, ...childEdges].map((edge) => ({ - type: 'remove', - id: edge.id - })) - ); - } - } - - // Delete selected edges - const selectedEdges = edges.filter((edge) => edge.selected); - if (selectedEdges.length > 0) { - onEdgesChange( - selectedEdges.map((edge) => ({ - type: 'remove', - id: edge.id - })) - ); - } - }); - return { handleNodesChange, handleEdgeChange, diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/index.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/index.tsx index df435fca501..925edf51394 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/index.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/index.tsx @@ -160,7 +160,7 @@ const Workflow = () => { } : {})} onNodeDragStop={onNodeDragStop} - deleteKeyCode={[]} + // deleteKeyCode={[]} > diff --git a/projects/app/src/service/support/permission/auth/chat.ts b/projects/app/src/service/support/permission/auth/chat.ts index 7c1a03ba0d8..1699c5af499 100644 --- a/projects/app/src/service/support/permission/auth/chat.ts +++ b/projects/app/src/service/support/permission/auth/chat.ts @@ -3,7 +3,6 @@ import { MongoChat } from '@fastgpt/service/core/chat/chatSchema'; import { AuthModeType } from '@fastgpt/service/support/permission/type'; import { authOutLink, authOutLinkInit } from './outLink'; import { ChatErrEnum } from '@fastgpt/global/common/error/code/chat'; -import { authUserPer } from '@fastgpt/service/support/permission/user/auth'; import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant'; import { authTeamSpaceToken } from './team'; import { authCert } from '@fastgpt/service/support/permission/auth/common'; @@ -11,12 +10,12 @@ import { authOutLinkValid } from '@fastgpt/service/support/permission/publish/au import { AuthUserTypeEnum, OwnerPermissionVal, - ReadPermissionVal, - WritePermissionVal + ReadPermissionVal } from '@fastgpt/global/support/permission/constant'; import { MongoTeamMember } from '@fastgpt/service/support/user/team/teamMemberSchema'; import { OutLinkChatAuthProps } from '@fastgpt/global/support/permission/chat'; import { addLog } from '@fastgpt/service/common/system/log'; +import { authApp } from '@fastgpt/service/support/permission/app/auth'; /* outLink: Must be the owner token: team owner and chat owner have all permissions @@ -71,19 +70,19 @@ export async function authChatCrud({ if (!chat) return { id: outLinkUid }; // auth req - const { teamId, tmbId, permission } = await authUserPer({ - ...props, + const { teamId, tmbId, permission } = await authApp({ + req: props.req, + authToken: true, + authApiKey: true, + appId, per: ReadPermissionVal }); if (String(teamId) !== String(chat.teamId)) return Promise.reject(ChatErrEnum.unAuthChat); - if (permission.isOwner) return { uid: outLinkUid }; + if (permission.hasManagePer) return { uid: outLinkUid }; if (String(tmbId) === String(chat.tmbId)) return { uid: outLinkUid }; - // Admin can manage all chat - if (per === WritePermissionVal && permission.hasManagePer) return { uid: outLinkUid }; - return Promise.reject(ChatErrEnum.unAuthChat); })();