mirror of https://github.com/usual2970/certimate
feat: certificate key algorithm
parent
71f43c5bd4
commit
1ce2a52d70
|
@ -60,11 +60,12 @@ type Certificate struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApplyOption struct {
|
type ApplyOption struct {
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Domain string `json:"domain"`
|
Domain string `json:"domain"`
|
||||||
Access string `json:"access"`
|
Access string `json:"access"`
|
||||||
Nameservers string `json:"nameservers"`
|
KeyAlgorithm string `json:"keyAlgorithm"`
|
||||||
Timeout int64 `json:"timeout"`
|
Nameservers string `json:"nameservers"`
|
||||||
|
Timeout int64 `json:"timeout"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApplyUser struct {
|
type ApplyUser struct {
|
||||||
|
@ -91,11 +92,10 @@ type Applicant interface {
|
||||||
|
|
||||||
func Get(record *models.Record) (Applicant, error) {
|
func Get(record *models.Record) (Applicant, error) {
|
||||||
if record.GetString("applyConfig") == "" {
|
if record.GetString("applyConfig") == "" {
|
||||||
return nil, errors.New("apply config is empty")
|
return nil, errors.New("applyConfig is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
applyConfig := &domain.ApplyConfig{}
|
applyConfig := &domain.ApplyConfig{}
|
||||||
|
|
||||||
record.UnmarshalJSONField("applyConfig", applyConfig)
|
record.UnmarshalJSONField("applyConfig", applyConfig)
|
||||||
|
|
||||||
access, err := app.GetApp().Dao().FindRecordById("access", applyConfig.Access)
|
access, err := app.GetApp().Dao().FindRecordById("access", applyConfig.Access)
|
||||||
|
@ -103,17 +103,23 @@ func Get(record *models.Record) (Applicant, error) {
|
||||||
return nil, fmt.Errorf("access record not found: %w", err)
|
return nil, fmt.Errorf("access record not found: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
email := applyConfig.Email
|
if applyConfig.Email == "" {
|
||||||
if email == "" {
|
applyConfig.Email = defaultEmail
|
||||||
email = defaultEmail
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if applyConfig.Timeout == 0 {
|
||||||
|
applyConfig.Timeout = defaultTimeout
|
||||||
|
}
|
||||||
|
|
||||||
option := &ApplyOption{
|
option := &ApplyOption{
|
||||||
Email: email,
|
Email: applyConfig.Email,
|
||||||
Domain: record.GetString("domain"),
|
Domain: record.GetString("domain"),
|
||||||
Access: access.GetString("config"),
|
Access: access.GetString("config"),
|
||||||
Nameservers: applyConfig.Nameservers,
|
KeyAlgorithm: applyConfig.KeyAlgorithm,
|
||||||
Timeout: applyConfig.Timeout,
|
Nameservers: applyConfig.Nameservers,
|
||||||
|
Timeout: applyConfig.Timeout,
|
||||||
}
|
}
|
||||||
|
|
||||||
switch access.GetString("configType") {
|
switch access.GetString("configType") {
|
||||||
case configTypeAliyun:
|
case configTypeAliyun:
|
||||||
return NewAliyun(option), nil
|
return NewAliyun(option), nil
|
||||||
|
@ -171,7 +177,7 @@ func apply(option *ApplyOption, provider challenge.Provider) (*Certificate, erro
|
||||||
|
|
||||||
// This CA URL is configured for a local dev instance of Boulder running in Docker in a VM.
|
// This CA URL is configured for a local dev instance of Boulder running in Docker in a VM.
|
||||||
config.CADirURL = sslProviderUrls[sslProvider.Provider]
|
config.CADirURL = sslProviderUrls[sslProvider.Provider]
|
||||||
config.Certificate.KeyType = certcrypto.RSA2048
|
config.Certificate.KeyType = parseKeyAlgorithm(option.KeyAlgorithm)
|
||||||
|
|
||||||
// A client facilitates communication with the CA server.
|
// A client facilitates communication with the CA server.
|
||||||
client, err := lego.NewClient(config)
|
client, err := lego.NewClient(config)
|
||||||
|
@ -180,7 +186,7 @@ func apply(option *ApplyOption, provider challenge.Provider) (*Certificate, erro
|
||||||
}
|
}
|
||||||
|
|
||||||
challengeOptions := make([]dns01.ChallengeOption, 0)
|
challengeOptions := make([]dns01.ChallengeOption, 0)
|
||||||
nameservers := ParseNameservers(option.Nameservers)
|
nameservers := parseNameservers(option.Nameservers)
|
||||||
if len(nameservers) > 0 {
|
if len(nameservers) > 0 {
|
||||||
challengeOptions = append(challengeOptions, dns01.AddRecursiveNameservers(nameservers))
|
challengeOptions = append(challengeOptions, dns01.AddRecursiveNameservers(nameservers))
|
||||||
}
|
}
|
||||||
|
@ -195,7 +201,6 @@ func apply(option *ApplyOption, provider challenge.Provider) (*Certificate, erro
|
||||||
myUser.Registration = reg
|
myUser.Registration = reg
|
||||||
|
|
||||||
domains := strings.Split(option.Domain, ";")
|
domains := strings.Split(option.Domain, ";")
|
||||||
|
|
||||||
request := certificate.ObtainRequest{
|
request := certificate.ObtainRequest{
|
||||||
Domains: domains,
|
Domains: domains,
|
||||||
Bundle: true,
|
Bundle: true,
|
||||||
|
@ -231,7 +236,6 @@ func getReg(client *lego.Client, sslProvider *SSLProviderConfig) (*registration.
|
||||||
|
|
||||||
default:
|
default:
|
||||||
err = errors.New("unknown ssl provider")
|
err = errors.New("unknown ssl provider")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -241,15 +245,13 @@ func getReg(client *lego.Client, sslProvider *SSLProviderConfig) (*registration.
|
||||||
return reg, nil
|
return reg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseNameservers(ns string) []string {
|
func parseNameservers(ns string) []string {
|
||||||
nameservers := make([]string, 0)
|
nameservers := make([]string, 0)
|
||||||
|
|
||||||
lines := strings.Split(ns, ";")
|
lines := strings.Split(ns, ";")
|
||||||
|
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
|
|
||||||
line = strings.TrimSpace(line)
|
line = strings.TrimSpace(line)
|
||||||
|
|
||||||
if line == "" {
|
if line == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -259,3 +261,22 @@ func ParseNameservers(ns string) []string {
|
||||||
|
|
||||||
return nameservers
|
return nameservers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseKeyAlgorithm(algo string) certcrypto.KeyType {
|
||||||
|
switch algo {
|
||||||
|
case "RSA2048":
|
||||||
|
return certcrypto.RSA2048
|
||||||
|
case "RSA3072":
|
||||||
|
return certcrypto.RSA3072
|
||||||
|
case "RSA4096":
|
||||||
|
return certcrypto.RSA4096
|
||||||
|
case "RSA8192":
|
||||||
|
return certcrypto.RSA8192
|
||||||
|
case "EC256":
|
||||||
|
return certcrypto.EC256
|
||||||
|
case "EC384":
|
||||||
|
return certcrypto.EC384
|
||||||
|
default:
|
||||||
|
return certcrypto.RSA2048
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
package domain
|
package domain
|
||||||
|
|
||||||
type ApplyConfig struct {
|
type ApplyConfig struct {
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Access string `json:"access"`
|
Access string `json:"access"`
|
||||||
Timeout int64 `json:"timeout"`
|
KeyAlgorithm string `json:"keyAlgorithm"`
|
||||||
Nameservers string `json:"nameservers"`
|
Nameservers string `json:"nameservers"`
|
||||||
|
Timeout int64 `json:"timeout"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeployConfig struct {
|
type DeployConfig struct {
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -5,8 +5,8 @@
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Certimate - Your Trusted SSL Automation Partner</title>
|
<title>Certimate - Your Trusted SSL Automation Partner</title>
|
||||||
<script type="module" crossorigin src="/assets/index-DIhd7QG6.js"></script>
|
<script type="module" crossorigin src="/assets/index-C20g8xcX.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-CV_7sKTK.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-YqBWA4KK.css">
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-background">
|
<body class="bg-background">
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"@hookform/resolvers": "^3.9.0",
|
"@hookform/resolvers": "^3.9.0",
|
||||||
"@radix-ui/react-accordion": "^1.2.0",
|
"@radix-ui/react-accordion": "^1.2.0",
|
||||||
"@radix-ui/react-alert-dialog": "^1.1.1",
|
"@radix-ui/react-alert-dialog": "^1.1.1",
|
||||||
|
"@radix-ui/react-collapsible": "^1.1.1",
|
||||||
"@radix-ui/react-dialog": "^1.1.1",
|
"@radix-ui/react-dialog": "^1.1.1",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.1",
|
"@radix-ui/react-dropdown-menu": "^2.1.1",
|
||||||
"@radix-ui/react-label": "^2.1.0",
|
"@radix-ui/react-label": "^2.1.0",
|
||||||
|
@ -1184,6 +1185,35 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/react-collapsible": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@radix-ui/react-collapsible/-/react-collapsible-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-zQY7Epa8sTL0mq4ajSJpjgn2YmCgyrG7RsQgLp3C0LQVkG7+Tf6Pv1CeNWZLyqMjhdPkBa5Lx7wYBeSu7uCSTA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/primitive": "1.1.0",
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.0",
|
||||||
|
"@radix-ui/react-context": "1.1.0",
|
||||||
|
"@radix-ui/react-id": "1.1.0",
|
||||||
|
"@radix-ui/react-presence": "1.1.0",
|
||||||
|
"@radix-ui/react-primitive": "2.0.0",
|
||||||
|
"@radix-ui/react-use-controllable-state": "1.1.0",
|
||||||
|
"@radix-ui/react-use-layout-effect": "1.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-alert-dialog": {
|
"node_modules/@radix-ui/react-alert-dialog": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmmirror.com/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.1.tgz",
|
"resolved": "https://registry.npmmirror.com/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.1.tgz",
|
||||||
|
@ -1234,15 +1264,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-collapsible": {
|
"node_modules/@radix-ui/react-collapsible": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmmirror.com/@radix-ui/react-collapsible/-/react-collapsible-1.1.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@radix-ui/react-collapsible/-/react-collapsible-1.1.1.tgz",
|
||||||
"integrity": "sha512-zQY7Epa8sTL0mq4ajSJpjgn2YmCgyrG7RsQgLp3C0LQVkG7+Tf6Pv1CeNWZLyqMjhdPkBa5Lx7wYBeSu7uCSTA==",
|
"integrity": "sha512-1///SnrfQHJEofLokyczERxQbWfCGQlQ2XsCZMucVs6it+lq9iw4vXy+uDn1edlb58cOZOWSldnfPAYcT4O/Yg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/primitive": "1.1.0",
|
"@radix-ui/primitive": "1.1.0",
|
||||||
"@radix-ui/react-compose-refs": "1.1.0",
|
"@radix-ui/react-compose-refs": "1.1.0",
|
||||||
"@radix-ui/react-context": "1.1.0",
|
"@radix-ui/react-context": "1.1.1",
|
||||||
"@radix-ui/react-id": "1.1.0",
|
"@radix-ui/react-id": "1.1.0",
|
||||||
"@radix-ui/react-presence": "1.1.0",
|
"@radix-ui/react-presence": "1.1.1",
|
||||||
"@radix-ui/react-primitive": "2.0.0",
|
"@radix-ui/react-primitive": "2.0.0",
|
||||||
"@radix-ui/react-use-controllable-state": "1.1.0",
|
"@radix-ui/react-use-controllable-state": "1.1.0",
|
||||||
"@radix-ui/react-use-layout-effect": "1.1.0"
|
"@radix-ui/react-use-layout-effect": "1.1.0"
|
||||||
|
@ -1262,6 +1292,43 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-context": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@radix-ui/react-context/-/react-context-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-presence": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@radix-ui/react-presence/-/react-presence-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.0",
|
||||||
|
"@radix-ui/react-use-layout-effect": "1.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-collection": {
|
"node_modules/@radix-ui/react-collection": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@radix-ui/react-collection/-/react-collection-1.1.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@radix-ui/react-collection/-/react-collection-1.1.0.tgz",
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
"@hookform/resolvers": "^3.9.0",
|
"@hookform/resolvers": "^3.9.0",
|
||||||
"@radix-ui/react-accordion": "^1.2.0",
|
"@radix-ui/react-accordion": "^1.2.0",
|
||||||
"@radix-ui/react-alert-dialog": "^1.1.1",
|
"@radix-ui/react-alert-dialog": "^1.1.1",
|
||||||
|
"@radix-ui/react-collapsible": "^1.1.1",
|
||||||
"@radix-ui/react-dialog": "^1.1.1",
|
"@radix-ui/react-dialog": "^1.1.1",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.1",
|
"@radix-ui/react-dropdown-menu": "^2.1.1",
|
||||||
"@radix-ui/react-label": "^2.1.0",
|
"@radix-ui/react-label": "^2.1.0",
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import * as React from "react";
|
||||||
|
import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
const Collapsible = CollapsiblePrimitive.Root;
|
||||||
|
|
||||||
|
const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger;
|
||||||
|
|
||||||
|
const CollapsibleContent = React.forwardRef<
|
||||||
|
React.ElementRef<typeof CollapsiblePrimitive.CollapsibleContent>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof CollapsiblePrimitive.CollapsibleContent>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<CollapsiblePrimitive.CollapsibleContent
|
||||||
|
ref={ref}
|
||||||
|
className={cn("overflow-y-hidden transition-all data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
CollapsibleContent.displayName = CollapsiblePrimitive.CollapsibleContent.displayName;
|
||||||
|
|
||||||
|
export { Collapsible, CollapsibleTrigger, CollapsibleContent };
|
|
@ -50,8 +50,9 @@ export type DeployConfig = {
|
||||||
export type ApplyConfig = {
|
export type ApplyConfig = {
|
||||||
access: string;
|
access: string;
|
||||||
email: string;
|
email: string;
|
||||||
timeout?: number;
|
keyAlgorithm?: string;
|
||||||
nameservers?: string;
|
nameservers?: string;
|
||||||
|
timeout?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Statistic = {
|
export type Statistic = {
|
||||||
|
|
|
@ -30,15 +30,17 @@
|
||||||
"domain.application.form.domain.changed.message": "Domain updated successfully",
|
"domain.application.form.domain.changed.message": "Domain updated successfully",
|
||||||
"domain.application.form.email.label": "Email",
|
"domain.application.form.email.label": "Email",
|
||||||
"domain.application.form.email.tips": "(A email is required to apply for a certificate)",
|
"domain.application.form.email.tips": "(A email is required to apply for a certificate)",
|
||||||
|
"domain.application.form.email.placeholder": "Please select email",
|
||||||
"domain.application.form.email.add": "Add Email",
|
"domain.application.form.email.add": "Add Email",
|
||||||
"domain.application.form.email.list": "Email List",
|
"domain.application.form.email.list": "Email List",
|
||||||
"domain.application.form.email.errmsg.empty": "Please select email",
|
|
||||||
"domain.application.form.access.label": "DNS Provider Authorization Configuration",
|
"domain.application.form.access.label": "DNS Provider Authorization Configuration",
|
||||||
"domain.application.form.access.placeholder": "Please select DNS provider authorization configuration",
|
"domain.application.form.access.placeholder": "Please select DNS provider authorization configuration",
|
||||||
"domain.application.form.access.errmsg.empty": "Please select DNS provider authorization configuration",
|
|
||||||
"domain.application.form.access.list": "Provider Authorization Configurations",
|
"domain.application.form.access.list": "Provider Authorization Configurations",
|
||||||
"domain.application.form.timeout.label": "Timeout",
|
"domain.application.form.advanced_settings.label": "Advanced Settings",
|
||||||
"domain.application.form.timeoue.placeholder": "Timeout (seconds)",
|
"domain.application.form.key_algorithm.label": "Certificate Key Algorithm",
|
||||||
|
"domain.application.form.key_algorithm.placeholder": "Please select certificate key algorithm",
|
||||||
|
"domain.application.form.timeout.label": "DNS Propagation Timeout (seconds)",
|
||||||
|
"domain.application.form.timeoue.placeholder": "Please enter maximum waiting time for DNS propagation",
|
||||||
"domain.application.unsaved.message": "Please save applyment configuration first",
|
"domain.application.unsaved.message": "Please save applyment configuration first",
|
||||||
|
|
||||||
"domain.deployment.tab": "Deploy Settings",
|
"domain.deployment.tab": "Deploy Settings",
|
||||||
|
|
|
@ -30,15 +30,17 @@
|
||||||
"domain.application.form.domain.changed.message": "域名编辑成功",
|
"domain.application.form.domain.changed.message": "域名编辑成功",
|
||||||
"domain.application.form.email.label": "邮箱",
|
"domain.application.form.email.label": "邮箱",
|
||||||
"domain.application.form.email.tips": "(申请证书需要提供邮箱)",
|
"domain.application.form.email.tips": "(申请证书需要提供邮箱)",
|
||||||
|
"domain.application.form.email.placeholder": "请选择邮箱",
|
||||||
"domain.application.form.email.add": "添加邮箱",
|
"domain.application.form.email.add": "添加邮箱",
|
||||||
"domain.application.form.email.list": "邮箱列表",
|
"domain.application.form.email.list": "邮箱列表",
|
||||||
"domain.application.form.email.errmsg.empty": "请选择邮箱",
|
|
||||||
"domain.application.form.access.label": "DNS 服务商授权配置",
|
"domain.application.form.access.label": "DNS 服务商授权配置",
|
||||||
"domain.application.form.access.placeholder": "请选择 DNS 服务商授权配置",
|
"domain.application.form.access.placeholder": "请选择 DNS 服务商授权配置",
|
||||||
"domain.application.form.access.errmsg.empty": "请选择 DNS 服务商授权配置",
|
|
||||||
"domain.application.form.access.list": "已有的 DNS 服务商授权配置",
|
"domain.application.form.access.list": "已有的 DNS 服务商授权配置",
|
||||||
"domain.application.form.timeout.label": "超时时间",
|
"domain.application.form.advanced_settings.label": "高级设置",
|
||||||
"domain.application.form.timeoue.placeholder": "超时时间(单位:秒)",
|
"domain.application.form.key_algorithm.label": "数字证书算法",
|
||||||
|
"domain.application.form.key_algorithm.placeholder": "请选择数字证书算法",
|
||||||
|
"domain.application.form.timeout.label": "DNS 传播检查超时时间(单位:秒)",
|
||||||
|
"domain.application.form.timeoue.placeholder": "请输入 DNS 传播检查超时时间",
|
||||||
"domain.application.unsaved.message": "请先保存申请配置",
|
"domain.application.unsaved.message": "请先保存申请配置",
|
||||||
|
|
||||||
"domain.deployment.tab": "部署配置",
|
"domain.deployment.tab": "部署配置",
|
||||||
|
|
|
@ -4,11 +4,12 @@ import { useForm } from "react-hook-form";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import z from "zod";
|
import z from "zod";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { Plus } from "lucide-react";
|
import { ChevronsUpDown, Plus } from "lucide-react";
|
||||||
import { ClientResponseError } from "pocketbase";
|
import { ClientResponseError } from "pocketbase";
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "@/components/ui/breadcrumb";
|
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "@/components/ui/breadcrumb";
|
||||||
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
|
||||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
|
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@/components/ui/select";
|
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||||
|
@ -58,8 +59,9 @@ const Edit = () => {
|
||||||
}),
|
}),
|
||||||
email: z.string().email("common.errmsg.email_invalid").optional(),
|
email: z.string().email("common.errmsg.email_invalid").optional(),
|
||||||
access: z.string().regex(/^[a-zA-Z0-9]+$/, {
|
access: z.string().regex(/^[a-zA-Z0-9]+$/, {
|
||||||
message: "domain.application.form.access.errmsg.empty",
|
message: "domain.application.form.access.placeholder",
|
||||||
}),
|
}),
|
||||||
|
keyAlgorithm: z.string().optional(),
|
||||||
nameservers: z.string().optional(),
|
nameservers: z.string().optional(),
|
||||||
timeout: z.number().optional(),
|
timeout: z.number().optional(),
|
||||||
});
|
});
|
||||||
|
@ -71,6 +73,7 @@ const Edit = () => {
|
||||||
domain: "",
|
domain: "",
|
||||||
email: "",
|
email: "",
|
||||||
access: "",
|
access: "",
|
||||||
|
keyAlgorithm: "RSA2048",
|
||||||
nameservers: "",
|
nameservers: "",
|
||||||
timeout: 60,
|
timeout: 60,
|
||||||
},
|
},
|
||||||
|
@ -83,6 +86,7 @@ const Edit = () => {
|
||||||
domain: domain.domain,
|
domain: domain.domain,
|
||||||
email: domain.applyConfig?.email,
|
email: domain.applyConfig?.email,
|
||||||
access: domain.applyConfig?.access,
|
access: domain.applyConfig?.access,
|
||||||
|
keyAlgorithm: domain.applyConfig?.keyAlgorithm,
|
||||||
nameservers: domain.applyConfig?.nameservers,
|
nameservers: domain.applyConfig?.nameservers,
|
||||||
timeout: domain.applyConfig?.timeout,
|
timeout: domain.applyConfig?.timeout,
|
||||||
});
|
});
|
||||||
|
@ -101,6 +105,7 @@ const Edit = () => {
|
||||||
applyConfig: {
|
applyConfig: {
|
||||||
email: data.email ?? "",
|
email: data.email ?? "",
|
||||||
access: data.access,
|
access: data.access,
|
||||||
|
keyAlgorithm: data.keyAlgorithm,
|
||||||
nameservers: data.nameservers,
|
nameservers: data.nameservers,
|
||||||
timeout: data.timeout,
|
timeout: data.timeout,
|
||||||
},
|
},
|
||||||
|
@ -235,6 +240,7 @@ const Edit = () => {
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* 邮箱 */}
|
{/* 邮箱 */}
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
|
@ -261,7 +267,7 @@ const Edit = () => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
<SelectValue placeholder={t("domain.application.form.email.errmsg.empty")} />
|
<SelectValue placeholder={t("domain.application.form.email.placeholder")} />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectGroup>
|
<SelectGroup>
|
||||||
|
@ -280,7 +286,8 @@ const Edit = () => {
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
{/* 授权 */}
|
|
||||||
|
{/* DNS 服务商授权 */}
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="access"
|
name="access"
|
||||||
|
@ -332,48 +339,95 @@ const Edit = () => {
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* 超时时间 */}
|
<div>
|
||||||
<FormField
|
<hr />
|
||||||
control={form.control}
|
<Collapsible>
|
||||||
name="timeout"
|
<CollapsibleTrigger className="w-full my-4">
|
||||||
render={({ field }) => (
|
<div className="flex items-center justify-between space-x-4">
|
||||||
<FormItem>
|
<span className="flex-1 text-sm text-gray-600 text-left">{t("domain.application.form.advanced_settings.label")}</span>
|
||||||
<FormLabel>{t("domain.application.form.timeout.label")}</FormLabel>
|
<ChevronsUpDown className="h-4 w-4" />
|
||||||
<FormControl>
|
</div>
|
||||||
<Input
|
</CollapsibleTrigger>
|
||||||
type="number"
|
<CollapsibleContent>
|
||||||
placeholder={t("ddomain.application.form.timeout.placeholder")}
|
<div className="flex flex-col space-y-8">
|
||||||
{...field}
|
{/* 证书算法 */}
|
||||||
value={field.value}
|
<FormField
|
||||||
onChange={(e) => {
|
control={form.control}
|
||||||
form.setValue("timeout", parseInt(e.target.value));
|
name="keyAlgorithm"
|
||||||
}}
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("domain.application.form.key_algorithm.label")}</FormLabel>
|
||||||
|
<Select
|
||||||
|
{...field}
|
||||||
|
value={field.value}
|
||||||
|
onValueChange={(value) => {
|
||||||
|
form.setValue("keyAlgorithm", value);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder={t("domain.application.form.key_algorithm.placeholder")} />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectItem value="RSA2048">RSA2048</SelectItem>
|
||||||
|
<SelectItem value="RSA3072">RSA3072</SelectItem>
|
||||||
|
<SelectItem value="RSA4096">RSA4096</SelectItem>
|
||||||
|
<SelectItem value="RSA8192">RSA8192</SelectItem>
|
||||||
|
<SelectItem value="EC256">EC256</SelectItem>
|
||||||
|
<SelectItem value="EC384">EC384</SelectItem>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
|
||||||
|
|
||||||
<FormMessage />
|
{/* DNS */}
|
||||||
</FormItem>
|
<FormField
|
||||||
)}
|
control={form.control}
|
||||||
/>
|
name="nameservers"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<StringList
|
||||||
|
value={field.value ?? ""}
|
||||||
|
onValueChange={(val: string) => {
|
||||||
|
form.setValue("nameservers", val);
|
||||||
|
}}
|
||||||
|
valueType="dns"
|
||||||
|
></StringList>
|
||||||
|
|
||||||
{/* nameservers */}
|
<FormMessage />
|
||||||
<FormField
|
</FormItem>
|
||||||
control={form.control}
|
)}
|
||||||
name="nameservers"
|
/>
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<StringList
|
|
||||||
value={field.value ?? ""}
|
|
||||||
onValueChange={(val: string) => {
|
|
||||||
form.setValue("nameservers", val);
|
|
||||||
}}
|
|
||||||
valueType="dns"
|
|
||||||
></StringList>
|
|
||||||
|
|
||||||
<FormMessage />
|
{/* DNS 超时时间 */}
|
||||||
</FormItem>
|
<FormField
|
||||||
)}
|
control={form.control}
|
||||||
/>
|
name="timeout"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("domain.application.form.timeout.label")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
type="number"
|
||||||
|
placeholder={t("domain.application.form.timeout.placeholder")}
|
||||||
|
{...field}
|
||||||
|
value={field.value}
|
||||||
|
onChange={(e) => {
|
||||||
|
form.setValue("timeout", parseInt(e.target.value));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</CollapsibleContent>
|
||||||
|
</Collapsible>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">{domain?.id ? t("common.save") : t("common.next")}</Button>
|
<Button type="submit">{domain?.id ? t("common.save") : t("common.next")}</Button>
|
||||||
|
|
|
@ -70,10 +70,20 @@ module.exports = {
|
||||||
height: "0",
|
height: "0",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"collapsible-down": {
|
||||||
|
from: { height: 0 },
|
||||||
|
to: { height: "var(--radix-collapsible-content-height)" },
|
||||||
|
},
|
||||||
|
"collapsible-up": {
|
||||||
|
from: { height: "var(--radix-collapsible-content-height)" },
|
||||||
|
to: { height: 0 },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
animation: {
|
animation: {
|
||||||
"accordion-down": "accordion-down 0.2s ease-out",
|
"accordion-down": "accordion-down 0.2s ease-out",
|
||||||
"accordion-up": "accordion-up 0.2s ease-out",
|
"accordion-up": "accordion-up 0.2s ease-out",
|
||||||
|
"collapsible-down": "collapsible-down 0.2s ease-out",
|
||||||
|
"collapsible-up": "collapsible-up 0.2s ease-out",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue