feat: added button to generate random PFX/JKS password

This commit is contained in:
Snafu
2026-04-13 14:17:41 +08:00
committed by GitHub
parent c4d7227929
commit 4a2e741210
7 changed files with 176 additions and 45 deletions
@@ -1,6 +1,6 @@
import { getI18n, useTranslation } from "react-i18next";
import { IconBulb, IconChevronDown } from "@tabler/icons-react";
import { Button, Divider, Form, Input, Popover, Select, Space } from "antd";
import { IconBulb, IconChevronDown, IconDice6 } from "@tabler/icons-react";
import { Button, Divider, Form, Input, Popover, Select, Space, Tooltip } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
@@ -9,6 +9,7 @@ import PresetScriptTemplatesPopselect from "@/components/preset/PresetScriptTemp
import Show from "@/components/Show";
import Tips from "@/components/Tips";
import { CERTIFICATE_FORMATS } from "@/domain/certificate";
import { randomString } from "@/utils/random";
import { useFormNestedFieldsContext } from "./_context";
@@ -172,6 +173,21 @@ const BizDeployNodeConfigFieldsProviderLocal = () => {
}
};
const handleRandomPfxPasswordClick = () => {
const password = randomString();
formInst.setFieldValue([parentNamePath, "pfxPassword"], password);
};
const handleRandomJksKeypassClick = () => {
const password = randomString();
formInst.setFieldValue([parentNamePath, "jksKeypass"], password);
};
const handleRandomJksStorepassClick = () => {
const password = randomString();
formInst.setFieldValue([parentNamePath, "jksStorepass"], password);
};
const handlePresetPreScriptClick = (key: string) => {
switch (key) {
case "sh_backup_files":
@@ -281,13 +297,19 @@ const BizDeployNodeConfigFieldsProviderLocal = () => {
<Show when={fieldFormat === FORMAT_PFX}>
<Form.Item
name={[parentNamePath, "pfxPassword"]}
initialValue={initialValues.pfxPassword}
label={t("workflow_node.deploy.form.local_pfx_password.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.local_pfx_password.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.local_pfx_password.placeholder")} />
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "pfxPassword"]} initialValue={initialValues.pfxPassword} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.local_pfx_password.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomPfxPasswordClick}>
<IconDice6 size="1.25em" />
</Button>
</Tooltip>
</Space.Compact>
</Form.Item>
</Show>
@@ -303,23 +325,35 @@ const BizDeployNodeConfigFieldsProviderLocal = () => {
</Form.Item>
<Form.Item
name={[parentNamePath, "jksKeypass"]}
initialValue={initialValues.jksKeypass}
label={t("workflow_node.deploy.form.local_jks_keypass.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.local_jks_keypass.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.local_jks_keypass.placeholder")} />
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "jksKeypass"]} initialValue={initialValues.jksKeypass} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.local_jks_keypass.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomJksKeypassClick}>
<IconDice6 size="1.25em" />
</Button>
</Tooltip>
</Space.Compact>
</Form.Item>
<Form.Item
name={[parentNamePath, "jksStorepass"]}
initialValue={initialValues.jksStorepass}
label={t("workflow_node.deploy.form.local_jks_storepass.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.local_jks_storepass.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.local_jks_storepass.placeholder")} />
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "jksStorepass"]} initialValue={initialValues.jksStorepass} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.local_jks_storepass.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomJksStorepassClick}>
<IconDice6 size="1.25em" />
</Button>
</Tooltip>
</Space.Compact>
</Form.Item>
</Show>
@@ -1,10 +1,12 @@
import { getI18n, useTranslation } from "react-i18next";
import { Form, Input, Select } from "antd";
import { IconDice6 } from "@tabler/icons-react";
import { Button, Form, Input, Select, Space, Tooltip } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import Show from "@/components/Show";
import { CERTIFICATE_FORMATS } from "@/domain/certificate";
import { randomString } from "@/utils/random";
import { useFormNestedFieldsContext } from "./_context";
@@ -56,6 +58,21 @@ const BizDeployNodeConfigFieldsProviderS3 = () => {
}
};
const handleRandomPfxPasswordClick = () => {
const password = randomString();
formInst.setFieldValue([parentNamePath, "pfxPassword"], password);
};
const handleRandomJksKeypassClick = () => {
const password = randomString();
formInst.setFieldValue([parentNamePath, "jksKeypass"], password);
};
const handleRandomJksStorepassClick = () => {
const password = randomString();
formInst.setFieldValue([parentNamePath, "jksStorepass"], password);
};
return (
<>
<Form.Item
@@ -137,13 +154,19 @@ const BizDeployNodeConfigFieldsProviderS3 = () => {
<Show when={fieldFormat === FORMAT_PFX}>
<Form.Item
name={[parentNamePath, "pfxPassword"]}
initialValue={initialValues.pfxPassword}
label={t("workflow_node.deploy.form.s3_pfx_password.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.s3_pfx_password.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.s3_pfx_password.placeholder")} />
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "pfxPassword"]} initialValue={initialValues.pfxPassword} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.s3_pfx_password.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomPfxPasswordClick}>
<IconDice6 size="1.25em" />
</Button>
</Tooltip>
</Space.Compact>
</Form.Item>
</Show>
@@ -159,23 +182,35 @@ const BizDeployNodeConfigFieldsProviderS3 = () => {
</Form.Item>
<Form.Item
name={[parentNamePath, "jksKeypass"]}
initialValue={initialValues.jksKeypass}
label={t("workflow_node.deploy.form.s3_jks_keypass.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.s3_jks_keypass.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.s3_jks_keypass.placeholder")} />
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "jksKeypass"]} initialValue={initialValues.jksKeypass} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.s3_jks_keypass.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomJksKeypassClick}>
<IconDice6 size="1.25em" />
</Button>
</Tooltip>
</Space.Compact>
</Form.Item>
<Form.Item
name={[parentNamePath, "jksStorepass"]}
initialValue={initialValues.jksStorepass}
label={t("workflow_node.deploy.form.s3_jks_storepass.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.s3_jks_storepass.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.s3_jks_storepass.placeholder")} />
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "jksStorepass"]} initialValue={initialValues.jksStorepass} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.s3_jks_storepass.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomJksStorepassClick}>
<IconDice6 size="1.25em" />
</Button>
</Tooltip>
</Space.Compact>
</Form.Item>
</Show>
</>
@@ -1,6 +1,6 @@
import { getI18n, useTranslation } from "react-i18next";
import { IconBulb, IconChevronDown } from "@tabler/icons-react";
import { Button, Divider, Form, Input, Popover, Select, Space, Switch } from "antd";
import { IconBulb, IconChevronDown, IconDice6 } from "@tabler/icons-react";
import { Button, Divider, Form, Input, Popover, Select, Space, Switch, Tooltip } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
@@ -8,6 +8,7 @@ import CodeTextInput from "@/components/CodeTextInput";
import PresetScriptTemplatesPopselect from "@/components/preset/PresetScriptTemplatesPopselect";
import Show from "@/components/Show";
import { CERTIFICATE_FORMATS } from "@/domain/certificate";
import { randomString } from "@/utils/random";
import { useFormNestedFieldsContext } from "./_context";
import { initPresetScript as _initPresetScript } from "./BizDeployNodeConfigFieldsProviderLocal";
@@ -205,6 +206,21 @@ const BizDeployNodeConfigFieldsProviderSSH = () => {
}
};
const handleRandomPfxPasswordClick = () => {
const password = randomString();
formInst.setFieldValue([parentNamePath, "pfxPassword"], password);
};
const handleRandomJksKeypassClick = () => {
const password = randomString();
formInst.setFieldValue([parentNamePath, "jksKeypass"], password);
};
const handleRandomJksStorepassClick = () => {
const password = randomString();
formInst.setFieldValue([parentNamePath, "jksStorepass"], password);
};
const handlePresetPreScriptClick = (key: string) => {
switch (key) {
case "sh_backup_files":
@@ -331,13 +347,19 @@ const BizDeployNodeConfigFieldsProviderSSH = () => {
<Show when={fieldFormat === FORMAT_PFX}>
<Form.Item
name={[parentNamePath, "pfxPassword"]}
initialValue={initialValues.pfxPassword}
label={t("workflow_node.deploy.form.ssh_pfx_password.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.ssh_pfx_password.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.ssh_pfx_password.placeholder")} />
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "pfxPassword"]} initialValue={initialValues.pfxPassword} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.ssh_pfx_password.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomPfxPasswordClick}>
<IconDice6 size="1.25em" />
</Button>
</Tooltip>
</Space.Compact>
</Form.Item>
</Show>
@@ -353,23 +375,35 @@ const BizDeployNodeConfigFieldsProviderSSH = () => {
</Form.Item>
<Form.Item
name={[parentNamePath, "jksKeypass"]}
initialValue={initialValues.jksKeypass}
label={t("workflow_node.deploy.form.ssh_jks_keypass.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.ssh_jks_keypass.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.ssh_jks_keypass.placeholder")} />
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "jksKeypass"]} initialValue={initialValues.jksKeypass} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.ssh_jks_keypass.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomJksKeypassClick}>
<IconDice6 size="1.25em" />
</Button>
</Tooltip>
</Space.Compact>
</Form.Item>
<Form.Item
name={[parentNamePath, "jksStorepass"]}
initialValue={initialValues.jksStorepass}
label={t("workflow_node.deploy.form.ssh_jks_storepass.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.ssh_jks_storepass.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.ssh_jks_storepass.placeholder")} />
<Space.Compact className="w-full">
<Form.Item name={[parentNamePath, "jksStorepass"]} initialValue={initialValues.jksStorepass} rules={[formRule]} noStyle>
<Input placeholder={t("workflow_node.deploy.form.ssh_jks_storepass.placeholder")} />
</Form.Item>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomJksStorepassClick}>
<IconDice6 size="1.25em" />
</Button>
</Tooltip>
</Space.Compact>
</Form.Item>
</Show>
@@ -2,7 +2,7 @@
import { getI18n, useTranslation } from "react-i18next";
import { type FlowNodeEntity } from "@flowgram.ai/fixed-layout-editor";
import { IconDice6 } from "@tabler/icons-react";
import { type AnchorProps, Button, Form, type FormInstance, Input, Radio, Space } from "antd";
import { type AnchorProps, Button, Form, type FormInstance, Input, Radio, Space, Tooltip } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import dayjs from "dayjs";
import { z } from "zod";
@@ -95,9 +95,11 @@ const StartNodeConfigForm = ({ node, ...props }: StartNodeConfigFormProps) => {
<Form.Item name="triggerCron" noStyle rules={[formRule]}>
<Input placeholder={t("workflow_node.start.form.trigger_cron.placeholder")} />
</Form.Item>
<Button className="px-2" onClick={handleRandomCronClick}>
<IconDice6 size="1.25em" />
</Button>
<Tooltip title={t("common.text.random_roll")}>
<Button className="px-2" onClick={handleRandomCronClick}>
<IconDice6 size="1.25em" />
</Button>
</Tooltip>
</Space.Compact>
</Form.Item>
+1
View File
@@ -25,6 +25,7 @@
"common.text.operation_confirm": "Operation confirm",
"common.text.operation_succeeded": "Operation succeeded",
"common.text.operation_failed": "Operation failed",
"common.text.random_roll": "Random roll",
"common.text.request_error": "Request error",
"common.text.saved": "Saved successfully",
"common.text.saving": "Saving ...",
+1
View File
@@ -25,6 +25,7 @@
"common.text.operation_confirm": "操作确认",
"common.text.operation_succeeded": "操作成功",
"common.text.operation_failed": "操作失败",
"common.text.random_roll": "随机生成",
"common.text.request_error": "请求错误",
"common.text.saved": "已保存",
"common.text.saving": "保存中 ……",
+24
View File
@@ -0,0 +1,24 @@
export function randomString(): string;
export function randomString(length: number): string;
export function randomString(options: { length?: number; alphabet?: string }): string;
export function randomString(arg?: number | { length?: number; alphabet?: string }): string {
const DEFAULT_LENGTH = 32;
const DEFAULT_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
let length = DEFAULT_LENGTH;
let alphabet = DEFAULT_ALPHABET;
if (typeof arg === "number") {
length = arg;
} else if (arg && typeof arg === "object") {
if (arg.length != null) {
length = arg.length;
}
if (arg.alphabet != null) {
alphabet = arg.alphabet;
}
}
const randomBytes = crypto.getRandomValues(new Uint8Array(length));
return Array.from(randomBytes, (b) => alphabet[b % alphabet.length]).join("");
}