From a6cc34e3f6350fac63d54fc8cf10175835ab4b4a Mon Sep 17 00:00:00 2001 From: Kerem Yilmaz Date: Thu, 12 Sep 2024 02:01:26 -0700 Subject: [PATCH] Fix parameters being lost on save bug (#818) --- .../workflows/editor/WorkflowEditor.tsx | 25 +++++++- .../editor/nodes/SendEmailNode/types.ts | 4 ++ .../workflows/editor/workflowEditorUtils.ts | 63 ++++++++++++++++++- .../routes/workflows/types/workflowTypes.ts | 10 +-- .../workflows/types/workflowYamlTypes.ts | 30 ++++++++- 5 files changed, 123 insertions(+), 9 deletions(-) diff --git a/skyvern-frontend/src/routes/workflows/editor/WorkflowEditor.tsx b/skyvern-frontend/src/routes/workflows/editor/WorkflowEditor.tsx index 15f8a976..72b6f525 100644 --- a/skyvern-frontend/src/routes/workflows/editor/WorkflowEditor.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/WorkflowEditor.tsx @@ -1,6 +1,6 @@ import { useParams } from "react-router-dom"; import { useWorkflowQuery } from "../hooks/useWorkflowQuery"; -import { getElements } from "./workflowEditorUtils"; +import { convertEchoParameters, getElements } from "./workflowEditorUtils"; import { useMutation, useQueryClient } from "@tanstack/react-query"; import { BlockYAML, @@ -14,6 +14,11 @@ import { ReactFlowProvider } from "@xyflow/react"; import { FlowRenderer } from "./FlowRenderer"; import { toast } from "@/components/ui/use-toast"; import { AxiosError } from "axios"; +import { + AWSSecretParameter, + BitwardenSensitiveInformationParameter, + ContextParameter, +} from "../types/workflowTypes"; function WorkflowEditor() { const { workflowPermanentId } = useParams(); @@ -122,8 +127,24 @@ function WorkflowEditor() { } })} handleSave={(parameters, blocks, title) => { + const filteredParameters = + workflow.workflow_definition.parameters.filter((parameter) => { + return ( + parameter.parameter_type === "aws_secret" || + parameter.parameter_type === + "bitwarden_sensitive_information" || + parameter.parameter_type === "context" + ); + }) as Array< + | AWSSecretParameter + | BitwardenSensitiveInformationParameter + | ContextParameter + >; + + const echoParameters = convertEchoParameters(filteredParameters); + saveWorkflowMutation.mutate({ - parameters, + parameters: [...echoParameters, ...parameters], blocks, title, }); diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/SendEmailNode/types.ts b/skyvern-frontend/src/routes/workflows/editor/nodes/SendEmailNode/types.ts index bf2713ea..1a72b229 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/SendEmailNode/types.ts +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/SendEmailNode/types.ts @@ -8,6 +8,10 @@ export type SendEmailNodeData = { editable: boolean; label: string; sender: string; + smtpHostSecretParameterKey?: string; + smtpPortSecretParameterKey?: string; + smtpUsernameSecretParameterKey?: string; + smtpPasswordSecretParameterKey?: string; }; export type SendEmailNode = Node; diff --git a/skyvern-frontend/src/routes/workflows/editor/workflowEditorUtils.ts b/skyvern-frontend/src/routes/workflows/editor/workflowEditorUtils.ts index 2dcd6fa9..576520f4 100644 --- a/skyvern-frontend/src/routes/workflows/editor/workflowEditorUtils.ts +++ b/skyvern-frontend/src/routes/workflows/editor/workflowEditorUtils.ts @@ -2,7 +2,7 @@ import Dagre from "@dagrejs/dagre"; import { Edge } from "@xyflow/react"; import { nanoid } from "nanoid"; import type { WorkflowBlock } from "../types/workflowTypes"; -import { BlockYAML } from "../types/workflowYamlTypes"; +import { BlockYAML, ParameterYAML } from "../types/workflowYamlTypes"; import { REACT_FLOW_EDGE_Z_INDEX } from "./constants"; import { AppNode, nodeTypes } from "./nodes"; import { codeBlockNodeDefaultData } from "./nodes/CodeBlockNode/types"; @@ -145,6 +145,10 @@ function convertToNode( recipients: block.recipients.join(", "), subject: block.subject, sender: block.sender, + smtpHostSecretParameterKey: block.smtp_host?.key, + smtpPortSecretParameterKey: block.smtp_port?.key, + smtpUsernameSecretParameterKey: block.smtp_username?.key, + smtpPasswordSecretParameterKey: block.smtp_password?.key, }, }; } @@ -467,6 +471,12 @@ function getWorkflowBlock( recipients: node.data.recipients.split(","), subject: node.data.subject, sender: node.data.sender, + smtp_host_secret_parameter_key: node.data.smtpHostSecretParameterKey, + smtp_port_secret_parameter_key: node.data.smtpPortSecretParameterKey, + smtp_username_secret_parameter_key: + node.data.smtpUsernameSecretParameterKey, + smtp_password_secret_parameter_key: + node.data.smtpPasswordSecretParameterKey, }; } case "codeBlock": { @@ -556,6 +566,56 @@ function generateNodeLabel(existingLabels: Array) { throw new Error("Failed to generate a new node label"); } +import type { + AWSSecretParameter, + BitwardenSensitiveInformationParameter, + ContextParameter, +} from "../types/workflowTypes"; + +/** + * If a parameter is not displayed in the editor, we should echo its value back when saved. + */ +function convertEchoParameters( + parameters: Array< + | ContextParameter + | BitwardenSensitiveInformationParameter + | AWSSecretParameter + >, +): Array { + return parameters.map((parameter) => { + if (parameter.parameter_type === "aws_secret") { + return { + key: parameter.key, + parameter_type: "aws_secret", + aws_key: parameter.aws_key, + }; + } + if (parameter.parameter_type === "bitwarden_sensitive_information") { + return { + key: parameter.key, + parameter_type: "bitwarden_sensitive_information", + bitwarden_collection_id: parameter.bitwarden_collection_id, + bitwarden_identity_key: parameter.bitwarden_identity_key, + bitwarden_identity_fields: parameter.bitwarden_identity_fields, + bitwarden_client_id_aws_secret_key: + parameter.bitwarden_client_id_aws_secret_key, + bitwarden_client_secret_aws_secret_key: + parameter.bitwarden_client_secret_aws_secret_key, + bitwarden_master_password_aws_secret_key: + parameter.bitwarden_master_password_aws_secret_key, + }; + } + if (parameter.parameter_type === "context") { + return { + key: parameter.key, + parameter_type: "context", + source_parameter_key: parameter.source.key, + }; + } + throw new Error("Unknown parameter type"); + }); +} + export { createNode, generateNodeData, @@ -563,4 +623,5 @@ export { getWorkflowBlocks, layout, generateNodeLabel, + convertEchoParameters, }; diff --git a/skyvern-frontend/src/routes/workflows/types/workflowTypes.ts b/skyvern-frontend/src/routes/workflows/types/workflowTypes.ts index c98c20de..c59681e3 100644 --- a/skyvern-frontend/src/routes/workflows/types/workflowTypes.ts +++ b/skyvern-frontend/src/routes/workflows/types/workflowTypes.ts @@ -37,7 +37,7 @@ export type BitwardenSensitiveInformationParameter = WorkflowParameterBase & { bitwarden_master_password_aws_secret_key: string; bitwarden_collection_id: string; bitwarden_identity_key: string; - bitwarden_identity_fields: string; + bitwarden_identity_fields: Array; created_at: string; modified_at: string; deleted_at: string | null; @@ -171,10 +171,10 @@ export type UploadToS3Block = WorkflowBlockBase & { export type SendEmailBlock = WorkflowBlockBase & { block_type: "send_email"; - smtp_host: AWSSecretParameter; - smtp_port: AWSSecretParameter; - smtp_username: AWSSecretParameter; - smtp_password: AWSSecretParameter; + smtp_host?: AWSSecretParameter; + smtp_port?: AWSSecretParameter; + smtp_username?: AWSSecretParameter; + smtp_password?: AWSSecretParameter; sender: string; recipients: Array; subject: string; diff --git a/skyvern-frontend/src/routes/workflows/types/workflowYamlTypes.ts b/skyvern-frontend/src/routes/workflows/types/workflowYamlTypes.ts index 5675f4b8..57ce7f34 100644 --- a/skyvern-frontend/src/routes/workflows/types/workflowYamlTypes.ts +++ b/skyvern-frontend/src/routes/workflows/types/workflowYamlTypes.ts @@ -15,7 +15,11 @@ export type WorkflowDefinitionYAML = { export type ParameterYAML = | WorkflowParameterYAML - | BitwardenLoginCredentialParameterYAML; + | BitwardenLoginCredentialParameterYAML + | AWSSecretParameterYAML + | ContextParameterYAML + | OutputParameterYAML + | BitwardenSensitiveInformationParameterYAML; export type ParameterYAMLBase = { parameter_type: string; @@ -38,6 +42,30 @@ export type BitwardenLoginCredentialParameterYAML = ParameterYAMLBase & { bitwarden_master_password_aws_secret_key: "SKYVERN_BITWARDEN_MASTER_PASSWORD"; }; +export type AWSSecretParameterYAML = ParameterYAMLBase & { + parameter_type: "aws_secret"; + aws_key: string; +}; + +export type BitwardenSensitiveInformationParameterYAML = ParameterYAMLBase & { + parameter_type: "bitwarden_sensitive_information"; + bitwarden_collection_id: string; + bitwarden_identity_key: string; + bitwarden_identity_fields: Array; + bitwarden_client_id_aws_secret_key: string; + bitwarden_client_secret_aws_secret_key: string; + bitwarden_master_password_aws_secret_key: string; +}; + +export type ContextParameterYAML = ParameterYAMLBase & { + parameter_type: "context"; + source_parameter_key: string; +}; + +export type OutputParameterYAML = ParameterYAMLBase & { + parameter_type: "output"; +}; + const BlockTypes = { TASK: "task", FOR_LOOP: "for_loop",