mirror of
https://github.com/certimate-go/certimate.git
synced 2026-09-24 23:10:13 +08:00
feat(provider): new acme dns-01 provider: hostinger
This commit is contained in:
@@ -6,7 +6,7 @@ import (
|
||||
"github.com/go-acme/lego/v4/challenge"
|
||||
|
||||
"github.com/certimate-go/certimate/internal/domain"
|
||||
hetzner "github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/hetzner"
|
||||
"github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/hetzner"
|
||||
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package applicators
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-acme/lego/v4/challenge"
|
||||
|
||||
"github.com/certimate-go/certimate/internal/domain"
|
||||
"github.com/certimate-go/certimate/pkg/core/ssl-applicator/acme-dns01/providers/hostinger"
|
||||
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if err := ACMEDns01Registries.Register(domain.ACMEDns01ProviderTypeHostinger, func(options *ProviderFactoryOptions) (challenge.Provider, error) {
|
||||
credentials := domain.AccessConfigForHostinger{}
|
||||
if err := xmaps.Populate(options.ProviderAccessConfig, &credentials); err != nil {
|
||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||
}
|
||||
|
||||
provider, err := hostinger.NewChallengeProvider(&hostinger.ChallengeProviderConfig{
|
||||
ApiToken: credentials.ApiToken,
|
||||
DnsPropagationTimeout: options.DnsPropagationTimeout,
|
||||
DnsTTL: options.DnsTTL,
|
||||
})
|
||||
return provider, err
|
||||
}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
@@ -242,6 +242,10 @@ type AccessConfigForHetzner struct {
|
||||
ApiToken string `json:"apiToken"`
|
||||
}
|
||||
|
||||
type AccessConfigForHostinger struct {
|
||||
ApiToken string `json:"apiToken"`
|
||||
}
|
||||
|
||||
type AccessConfigForHuaweiCloud struct {
|
||||
AccessKeyId string `json:"accessKeyId"`
|
||||
SecretAccessKey string `json:"secretAccessKey"`
|
||||
|
||||
@@ -53,7 +53,7 @@ const (
|
||||
AccessProviderTypeGlobalSignAtlas = AccessProviderType("globalsignatlas")
|
||||
AccessProviderTypeGoogleTrustServices = AccessProviderType("googletrustservices")
|
||||
AccessProviderTypeHetzner = AccessProviderType("hetzner")
|
||||
AccessProviderTypeHostinger = AccessProviderType("hostinger") // Hostinger(预留)
|
||||
AccessProviderTypeHostinger = AccessProviderType("hostinger")
|
||||
AccessProviderTypeHuaweiCloud = AccessProviderType("huaweicloud")
|
||||
AccessProviderTypeJDCloud = AccessProviderType("jdcloud")
|
||||
AccessProviderTypeKong = AccessProviderType("kong")
|
||||
@@ -162,6 +162,7 @@ const (
|
||||
ACMEDns01ProviderTypeGname = ACMEDns01ProviderType(AccessProviderTypeGname)
|
||||
ACMEDns01ProviderTypeGoDaddy = ACMEDns01ProviderType(AccessProviderTypeGoDaddy)
|
||||
ACMEDns01ProviderTypeHetzner = ACMEDns01ProviderType(AccessProviderTypeHetzner)
|
||||
ACMEDns01ProviderTypeHostinger = ACMEDns01ProviderType(AccessProviderTypeHostinger)
|
||||
ACMEDns01ProviderTypeHuaweiCloud = ACMEDns01ProviderType(AccessProviderTypeHuaweiCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeHuaweiCloudDNS]
|
||||
ACMEDns01ProviderTypeHuaweiCloudDNS = ACMEDns01ProviderType(AccessProviderTypeHuaweiCloud + "-dns")
|
||||
ACMEDns01ProviderTypeJDCloud = ACMEDns01ProviderType(AccessProviderTypeJDCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeJDCloudDNS]
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package hostinger
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/go-acme/lego/v4/providers/dns/hostinger"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
)
|
||||
|
||||
type ChallengeProviderConfig struct {
|
||||
ApiToken string `json:"apiToken"`
|
||||
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
|
||||
DnsTTL int32 `json:"dnsTTL,omitempty"`
|
||||
}
|
||||
|
||||
func NewChallengeProvider(config *ChallengeProviderConfig) (core.ACMEChallenger, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("the configuration of the acme challenge provider is nil")
|
||||
}
|
||||
|
||||
providerConfig := hostinger.NewDefaultConfig()
|
||||
providerConfig.APIToken = config.ApiToken
|
||||
if config.DnsPropagationTimeout != 0 {
|
||||
providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second
|
||||
}
|
||||
if config.DnsTTL != 0 {
|
||||
providerConfig.TTL = int(config.DnsTTL)
|
||||
}
|
||||
|
||||
provider, err := hostinger.NewDNSProviderConfig(providerConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return provider, nil
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg clip-rule="evenodd" fill-rule="evenodd" height="200" stroke-linejoin="round" stroke-miterlimit="2" viewBox="7.002 8.287 148.203 175.426" width="200" xmlns="http://www.w3.org/2000/svg"><path d="m7.002 8.287 39.319 21.172v39.32h57.467l36.295 21.172h-133.081zm148.203 75.615v-54.443l-42.344-21.172v51.418zm0 99.811-39.319-21.172v-39.32h-57.467l-36.295-21.172h133.081zm-148.203-75.615v54.443l42.343 21.172v-51.418z" fill="#6747c7"/></svg>
|
||||
|
After Width: | Height: | Size: 440 B |
@@ -52,6 +52,7 @@ import AccessConfigFieldsProviderGoDaddy from "./forms/AccessConfigFieldsProvide
|
||||
import AccessConfigFieldsProviderGoEdge from "./forms/AccessConfigFieldsProviderGoEdge";
|
||||
import AccessConfigFieldsProviderGoogleTrustServices from "./forms/AccessConfigFieldsProviderGoogleTrustServices";
|
||||
import AccessConfigFieldsProviderHetzner from "./forms/AccessConfigFieldsProviderHetzner";
|
||||
import AccessConfigFieldsProviderHostinger from "./forms/AccessConfigFieldsProviderHostinger";
|
||||
import AccessConfigFieldsProviderHuaweiCloud from "./forms/AccessConfigFieldsProviderHuaweiCloud";
|
||||
import AccessConfigFieldsProviderJDCloud from "./forms/AccessConfigFieldsProviderJDCloud";
|
||||
import AccessConfigFieldsProviderKong from "./forms/AccessConfigFieldsProviderKong";
|
||||
@@ -259,6 +260,9 @@ const AccessForm = ({ className, style, disabled, initialValues, mode, usage, on
|
||||
case ACCESS_PROVIDERS.HETZNER: {
|
||||
return <AccessConfigFieldsProviderHetzner />;
|
||||
}
|
||||
case ACCESS_PROVIDERS.HOSTINGER: {
|
||||
return <AccessConfigFieldsProviderHostinger />;
|
||||
}
|
||||
case ACCESS_PROVIDERS.HUAWEICLOUD: {
|
||||
return <AccessConfigFieldsProviderHuaweiCloud />;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import { getI18n, useTranslation } from "react-i18next";
|
||||
import { Form, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { useFormNestedFieldsContext } from "./_context";
|
||||
|
||||
const AccessConfigFormFieldsProviderHostinger = () => {
|
||||
const { i18n, t } = useTranslation();
|
||||
|
||||
const { parentNamePath } = useFormNestedFieldsContext();
|
||||
const formSchema = z.object({
|
||||
[parentNamePath]: getSchema({ i18n }),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const initialValues = getInitialValues();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name={[parentNamePath, "apiToken"]}
|
||||
initialValue={initialValues.apiToken}
|
||||
label={t("access.form.hostinger_api_token.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.hostinger_api_token.tooltip") }}></span>}
|
||||
>
|
||||
<Input.Password autoComplete="new-password" placeholder={t("access.form.hostinger_api_token.placeholder")} />
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
|
||||
return {
|
||||
apiToken: "",
|
||||
};
|
||||
};
|
||||
|
||||
const getSchema = ({ i18n = getI18n() }: { i18n: ReturnType<typeof getI18n> }) => {
|
||||
const { t } = i18n;
|
||||
|
||||
return z.object({
|
||||
apiToken: z.string().nonempty(t("access.form.hostinger_api_token.placeholder")),
|
||||
});
|
||||
};
|
||||
|
||||
const _default = Object.assign(AccessConfigFormFieldsProviderHostinger, {
|
||||
getInitialValues,
|
||||
getSchema,
|
||||
});
|
||||
|
||||
export default _default;
|
||||
@@ -56,6 +56,7 @@ export const ACCESS_PROVIDERS = Object.freeze({
|
||||
GOEDGE: "goedge",
|
||||
GOOGLETRUSTSERVICES: "googletrustservices",
|
||||
HETZNER: "hetzner",
|
||||
HOSTINGER: "hostinger",
|
||||
HUAWEICLOUD: "huaweicloud",
|
||||
JDCLOUD: "jdcloud",
|
||||
KONG: "kong",
|
||||
@@ -177,6 +178,7 @@ export const accessProvidersMap: Map<AccessProvider["type"] | string, AccessProv
|
||||
[ACCESS_PROVIDERS.GNAME, "provider.gname", "/imgs/providers/gname.png", [ACCESS_USAGES.DNS]],
|
||||
[ACCESS_PROVIDERS.GODADDY, "provider.godaddy", "/imgs/providers/godaddy.svg", [ACCESS_USAGES.DNS]],
|
||||
[ACCESS_PROVIDERS.HETZNER, "provider.hetzner", "/imgs/providers/hetzner.svg", [ACCESS_USAGES.DNS]],
|
||||
[ACCESS_PROVIDERS.HOSTINGER, "provider.hostinger", "/imgs/providers/hostinger.svg", [ACCESS_USAGES.DNS]],
|
||||
[ACCESS_PROVIDERS.NAMECHEAP, "provider.namecheap", "/imgs/providers/namecheap.svg", [ACCESS_USAGES.DNS]],
|
||||
[ACCESS_PROVIDERS.NAMEDOTCOM, "provider.namedotcom", "/imgs/providers/namedotcom.svg", [ACCESS_USAGES.DNS]],
|
||||
[ACCESS_PROVIDERS.NAMESILO, "provider.namesilo", "/imgs/providers/namesilo.svg", [ACCESS_USAGES.DNS]],
|
||||
@@ -312,6 +314,7 @@ export const ACME_DNS01_PROVIDERS = Object.freeze({
|
||||
GNAME: `${ACCESS_PROVIDERS.GNAME}`,
|
||||
GODADDY: `${ACCESS_PROVIDERS.GODADDY}`,
|
||||
HETZNER: `${ACCESS_PROVIDERS.HETZNER}`,
|
||||
HOSTINGER: `${ACCESS_PROVIDERS.HOSTINGER}`,
|
||||
HUAWEICLOUD: `${ACCESS_PROVIDERS.HUAWEICLOUD}`, // 兼容旧值,等同于 `HUAWEICLOUD_DNS`
|
||||
HUAWEICLOUD_DNS: `${ACCESS_PROVIDERS.HUAWEICLOUD}-dns`,
|
||||
JDCLOUD: `${ACCESS_PROVIDERS.JDCLOUD}`, // 兼容旧值,等同于 `JDCLOUD_DNS`
|
||||
@@ -374,6 +377,7 @@ export const acmeDns01ProvidersMap: Map<ACMEDns01Provider["type"] | string, ACME
|
||||
[ACME_DNS01_PROVIDERS.GNAME, "provider.gname"],
|
||||
[ACME_DNS01_PROVIDERS.GODADDY, "provider.godaddy"],
|
||||
[ACME_DNS01_PROVIDERS.HETZNER, "provider.hetzner"],
|
||||
[ACME_DNS01_PROVIDERS.HOSTINGER, "provider.hostinger"],
|
||||
[ACME_DNS01_PROVIDERS.NAMECHEAP, "provider.namecheap"],
|
||||
[ACME_DNS01_PROVIDERS.NAMEDOTCOM, "provider.namedotcom"],
|
||||
[ACME_DNS01_PROVIDERS.NAMESILO, "provider.namesilo"],
|
||||
|
||||
@@ -293,6 +293,9 @@
|
||||
"access.form.hetzner_api_token.label": "Hetzner API token",
|
||||
"access.form.hetzner_api_token.placeholder": "Please enter Hetzner API token",
|
||||
"access.form.hetzner_api_token.tooltip": "For more information, see <a href=\"https://docs.hetzner.com/cloud/api/getting-started/generating-api-token\" target=\"_blank\">https://docs.hetzner.com/cloud/api/getting-started/generating-api-token</a>",
|
||||
"access.form.hostinger_api_token.label": "Hostinger API token",
|
||||
"access.form.hostinger_api_token.placeholder": "Please enter Hostinger API token",
|
||||
"access.form.hostinger_api_token.tooltip": "For more information, see <a href=\"https://developers.hostinger.com/#description/authentication\" target=\"_blank\">https://developers.hostinger.com/#description/authentication</a>",
|
||||
"access.form.huaweicloud_access_key_id.label": "Huawei Cloud AccessKeyId",
|
||||
"access.form.huaweicloud_access_key_id.placeholder": "Please enter Huawei Cloud AccessKeyId",
|
||||
"access.form.huaweicloud_access_key_id.tooltip": "For more information, see <a href=\"https://support.huaweicloud.com/intl/en-us/usermanual-ca/ca_01_0003.html\" target=\"_blank\">https://support.huaweicloud.com/intl/en-us/usermanual-ca/ca_01_0003.html</a>",
|
||||
|
||||
@@ -92,6 +92,7 @@
|
||||
"provider.goedge": "GoEdge",
|
||||
"provider.googletrustservices": "Google Trust Services",
|
||||
"provider.hetzner": "Hetzner",
|
||||
"provider.hostinger": "Hostinger",
|
||||
"provider.huaweicloud": "Huawei Cloud",
|
||||
"provider.huaweicloud.cdn": "Huawei Cloud - CDN (Content Delivery Network)",
|
||||
"provider.huaweicloud.dns": "Huawei Cloud - DNS",
|
||||
|
||||
@@ -292,6 +292,9 @@
|
||||
"access.form.hetzner_api_token.label": "Hetzner API Token",
|
||||
"access.form.hetzner_api_token.placeholder": "请输入 Hetzner API Token",
|
||||
"access.form.hetzner_api_token.tooltip": "这是什么?请参阅 <a href=\"https://docs.hetzner.com/cloud/api/getting-started/generating-api-token\" target=\"_blank\">https://docs.hetzner.com/cloud/api/getting-started/generating-api-token</a>",
|
||||
"access.form.hostinger_api_token.label": "Hostinger API Token",
|
||||
"access.form.hostinger_api_token.placeholder": "请输入 Hostinger API Token",
|
||||
"access.form.hostinger_api_token.tooltip": "这是什么?请参阅 <a href=\"https://developers.hostinger.com/#description/authentication\" target=\"_blank\">https://developers.hostinger.com/#description/authentication</a>",
|
||||
"access.form.huaweicloud_access_key_id.label": "华为云 AccessKeyId",
|
||||
"access.form.huaweicloud_access_key_id.placeholder": "请输入华为云 AccessKeyId",
|
||||
"access.form.huaweicloud_access_key_id.tooltip": "这是什么?请参阅 <a href=\"https://support.huaweicloud.com/usermanual-ca/ca_01_0003.html\" target=\"_blank\">https://support.huaweicloud.com/usermanual-ca/ca_01_0003.html</a>",
|
||||
|
||||
@@ -92,6 +92,7 @@
|
||||
"provider.goedge": "GoEdge",
|
||||
"provider.googletrustservices": "Google Trust Services",
|
||||
"provider.hetzner": "Hetzner",
|
||||
"provider.hostinger": "Hostinger",
|
||||
"provider.huaweicloud": "华为云",
|
||||
"provider.huaweicloud.cdn": "华为云 - 内容分发网络 CDN",
|
||||
"provider.huaweicloud.dns": "华为云 - 云解析 DNS",
|
||||
|
||||
Reference in New Issue
Block a user