feat: support 1panel v2

This commit is contained in:
Fu Diwei 2025-05-16 18:57:39 +08:00
parent 06fd95782a
commit fd875feef3
18 changed files with 143 additions and 45 deletions

View File

@ -111,6 +111,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
case domain.DeploymentProviderType1PanelConsole: case domain.DeploymentProviderType1PanelConsole:
deployer, err := p1PanelConsole.NewDeployer(&p1PanelConsole.DeployerConfig{ deployer, err := p1PanelConsole.NewDeployer(&p1PanelConsole.DeployerConfig{
ApiUrl: access.ApiUrl, ApiUrl: access.ApiUrl,
ApiVersion: access.ApiVersion,
ApiKey: access.ApiKey, ApiKey: access.ApiKey,
AllowInsecureConnections: access.AllowInsecureConnections, AllowInsecureConnections: access.AllowInsecureConnections,
AutoRestart: maputil.GetBool(options.ProviderExtendedConfig, "autoRestart"), AutoRestart: maputil.GetBool(options.ProviderExtendedConfig, "autoRestart"),
@ -120,6 +121,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
case domain.DeploymentProviderType1PanelSite: case domain.DeploymentProviderType1PanelSite:
deployer, err := p1PanelSite.NewDeployer(&p1PanelSite.DeployerConfig{ deployer, err := p1PanelSite.NewDeployer(&p1PanelSite.DeployerConfig{
ApiUrl: access.ApiUrl, ApiUrl: access.ApiUrl,
ApiVersion: access.ApiVersion,
ApiKey: access.ApiKey, ApiKey: access.ApiKey,
AllowInsecureConnections: access.AllowInsecureConnections, AllowInsecureConnections: access.AllowInsecureConnections,
ResourceType: p1PanelSite.ResourceType(maputil.GetOrDefaultString(options.ProviderExtendedConfig, "resourceType", string(p1PanelSite.RESOURCE_TYPE_WEBSITE))), ResourceType: p1PanelSite.ResourceType(maputil.GetOrDefaultString(options.ProviderExtendedConfig, "resourceType", string(p1PanelSite.RESOURCE_TYPE_WEBSITE))),

View File

@ -17,6 +17,7 @@ type Access struct {
type AccessConfigFor1Panel struct { type AccessConfigFor1Panel struct {
ApiUrl string `json:"apiUrl"` ApiUrl string `json:"apiUrl"`
ApiVersion string `json:"apiVersion"`
ApiKey string `json:"apiKey"` ApiKey string `json:"apiKey"`
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
} }

View File

@ -9,12 +9,14 @@ import (
"net/url" "net/url"
"github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/deployer"
opsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/1panel" onepanelsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/1panel"
) )
type DeployerConfig struct { type DeployerConfig struct {
// 1Panel 地址。 // 1Panel 地址。
ApiUrl string `json:"apiUrl"` ApiUrl string `json:"apiUrl"`
// 1Panel 版本。
ApiVersion string `json:"apiVersion"`
// 1Panel 接口密钥。 // 1Panel 接口密钥。
ApiKey string `json:"apiKey"` ApiKey string `json:"apiKey"`
// 是否允许不安全的连接。 // 是否允许不安全的连接。
@ -26,7 +28,7 @@ type DeployerConfig struct {
type DeployerProvider struct { type DeployerProvider struct {
config *DeployerConfig config *DeployerConfig
logger *slog.Logger logger *slog.Logger
sdkClient *opsdk.Client sdkClient *onepanelsdk.Client
} }
var _ deployer.Deployer = (*DeployerProvider)(nil) var _ deployer.Deployer = (*DeployerProvider)(nil)
@ -36,7 +38,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
panic("config is nil") panic("config is nil")
} }
client, err := createSdkClient(config.ApiUrl, config.ApiKey, config.AllowInsecureConnections) client, err := createSdkClient(config.ApiUrl, config.ApiVersion, config.ApiKey, config.AllowInsecureConnections)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create sdk client: %w", err) return nil, fmt.Errorf("failed to create sdk client: %w", err)
} }
@ -59,7 +61,7 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
// 设置面板 SSL 证书 // 设置面板 SSL 证书
updateSystemSSLReq := &opsdk.UpdateSystemSSLRequest{ updateSystemSSLReq := &onepanelsdk.UpdateSystemSSLRequest{
Cert: certPEM, Cert: certPEM,
Key: privkeyPEM, Key: privkeyPEM,
SSL: "enable", SSL: "enable",
@ -79,16 +81,20 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE
return &deployer.DeployResult{}, nil return &deployer.DeployResult{}, nil
} }
func createSdkClient(apiUrl, apiKey string, skipTlsVerify bool) (*opsdk.Client, error) { func createSdkClient(apiUrl, apiVersion, apiKey string, skipTlsVerify bool) (*onepanelsdk.Client, error) {
if _, err := url.Parse(apiUrl); err != nil { if _, err := url.Parse(apiUrl); err != nil {
return nil, errors.New("invalid 1panel api url") return nil, errors.New("invalid 1panel api url")
} }
if apiVersion == "" {
return nil, errors.New("invalid 1panel api version")
}
if apiKey == "" { if apiKey == "" {
return nil, errors.New("invalid 1panel api key") return nil, errors.New("invalid 1panel api key")
} }
client := opsdk.NewClient(apiUrl, apiKey) client := onepanelsdk.NewClient(apiUrl, apiVersion, apiKey)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }

View File

@ -15,6 +15,7 @@ var (
fInputCertPath string fInputCertPath string
fInputKeyPath string fInputKeyPath string
fApiUrl string fApiUrl string
fApiVersion string
fApiKey string fApiKey string
) )
@ -24,6 +25,7 @@ func init() {
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "")
flag.StringVar(&fApiVersion, argsPrefix+"APIVERSION", "v1", "")
flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "") flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "")
} }
@ -34,6 +36,7 @@ Shell command to run this test:
--CERTIMATE_DEPLOYER_1PANELCONSOLE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_1PANELCONSOLE_INPUTCERTPATH="/path/to/your-input-cert.pem" \
--CERTIMATE_DEPLOYER_1PANELCONSOLE_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_1PANELCONSOLE_INPUTKEYPATH="/path/to/your-input-key.pem" \
--CERTIMATE_DEPLOYER_1PANELCONSOLE_APIURL="http://127.0.0.1:20410" \ --CERTIMATE_DEPLOYER_1PANELCONSOLE_APIURL="http://127.0.0.1:20410" \
--CERTIMATE_DEPLOYER_1PANELCONSOLE_APIVERSION="v1" \
--CERTIMATE_DEPLOYER_1PANELCONSOLE_APIKEY="your-api-key" --CERTIMATE_DEPLOYER_1PANELCONSOLE_APIKEY="your-api-key"
*/ */
func TestDeploy(t *testing.T) { func TestDeploy(t *testing.T) {
@ -45,11 +48,13 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
fmt.Sprintf("APIURL: %v", fApiUrl), fmt.Sprintf("APIURL: %v", fApiUrl),
fmt.Sprintf("APIVERSION: %v", fApiVersion),
fmt.Sprintf("APIKEY: %v", fApiKey), fmt.Sprintf("APIKEY: %v", fApiKey),
}, "\n")) }, "\n"))
deployer, err := provider.NewDeployer(&provider.DeployerConfig{ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
ApiUrl: fApiUrl, ApiUrl: fApiUrl,
ApiVersion: fApiVersion,
ApiKey: fApiKey, ApiKey: fApiKey,
AllowInsecureConnections: true, AllowInsecureConnections: true,
AutoRestart: true, AutoRestart: true,

View File

@ -12,12 +12,14 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/uploader" "github.com/usual2970/certimate/internal/pkg/core/uploader"
uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/1panel-ssl" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/1panel-ssl"
opsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/1panel" onepanelsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/1panel"
) )
type DeployerConfig struct { type DeployerConfig struct {
// 1Panel 地址。 // 1Panel 地址。
ApiUrl string `json:"apiUrl"` ApiUrl string `json:"apiUrl"`
// 1Panel 版本。
ApiVersion string `json:"apiVersion"`
// 1Panel 接口密钥。 // 1Panel 接口密钥。
ApiKey string `json:"apiKey"` ApiKey string `json:"apiKey"`
// 是否允许不安全的连接。 // 是否允许不安全的连接。
@ -35,7 +37,7 @@ type DeployerConfig struct {
type DeployerProvider struct { type DeployerProvider struct {
config *DeployerConfig config *DeployerConfig
logger *slog.Logger logger *slog.Logger
sdkClient *opsdk.Client sdkClient *onepanelsdk.Client
sslUploader uploader.Uploader sslUploader uploader.Uploader
} }
@ -46,13 +48,14 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
panic("config is nil") panic("config is nil")
} }
client, err := createSdkClient(config.ApiUrl, config.ApiKey, config.AllowInsecureConnections) client, err := createSdkClient(config.ApiUrl, config.ApiVersion, config.ApiKey, config.AllowInsecureConnections)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create sdk client: %w", err) return nil, fmt.Errorf("failed to create sdk client: %w", err)
} }
uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
ApiUrl: config.ApiUrl, ApiUrl: config.ApiUrl,
ApiVersion: config.ApiVersion,
ApiKey: config.ApiKey, ApiKey: config.ApiKey,
}) })
if err != nil { if err != nil {
@ -103,7 +106,7 @@ func (d *DeployerProvider) deployToWebsite(ctx context.Context, certPEM string,
} }
// 获取网站 HTTPS 配置 // 获取网站 HTTPS 配置
getHttpsConfReq := &opsdk.GetHttpsConfRequest{ getHttpsConfReq := &onepanelsdk.GetHttpsConfRequest{
WebsiteID: d.config.WebsiteId, WebsiteID: d.config.WebsiteId,
} }
getHttpsConfResp, err := d.sdkClient.GetHttpsConf(getHttpsConfReq) getHttpsConfResp, err := d.sdkClient.GetHttpsConf(getHttpsConfReq)
@ -122,7 +125,7 @@ func (d *DeployerProvider) deployToWebsite(ctx context.Context, certPEM string,
// 修改网站 HTTPS 配置 // 修改网站 HTTPS 配置
certId, _ := strconv.ParseInt(upres.CertId, 10, 64) certId, _ := strconv.ParseInt(upres.CertId, 10, 64)
updateHttpsConfReq := &opsdk.UpdateHttpsConfRequest{ updateHttpsConfReq := &onepanelsdk.UpdateHttpsConfRequest{
WebsiteID: d.config.WebsiteId, WebsiteID: d.config.WebsiteId,
Type: "existed", Type: "existed",
WebsiteSSLID: certId, WebsiteSSLID: certId,
@ -147,7 +150,7 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri
} }
// 获取证书详情 // 获取证书详情
getWebsiteSSLReq := &opsdk.GetWebsiteSSLRequest{ getWebsiteSSLReq := &onepanelsdk.GetWebsiteSSLRequest{
SSLID: d.config.CertificateId, SSLID: d.config.CertificateId,
} }
getWebsiteSSLResp, err := d.sdkClient.GetWebsiteSSL(getWebsiteSSLReq) getWebsiteSSLResp, err := d.sdkClient.GetWebsiteSSL(getWebsiteSSLReq)
@ -157,7 +160,7 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri
} }
// 更新证书 // 更新证书
uploadWebsiteSSLReq := &opsdk.UploadWebsiteSSLRequest{ uploadWebsiteSSLReq := &onepanelsdk.UploadWebsiteSSLRequest{
Type: "paste", Type: "paste",
SSLID: d.config.CertificateId, SSLID: d.config.CertificateId,
Description: getWebsiteSSLResp.Data.Description, Description: getWebsiteSSLResp.Data.Description,
@ -173,16 +176,20 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM stri
return nil return nil
} }
func createSdkClient(apiUrl, apiKey string, skipTlsVerify bool) (*opsdk.Client, error) { func createSdkClient(apiUrl, apiVersion, apiKey string, skipTlsVerify bool) (*onepanelsdk.Client, error) {
if _, err := url.Parse(apiUrl); err != nil { if _, err := url.Parse(apiUrl); err != nil {
return nil, errors.New("invalid 1panel api url") return nil, errors.New("invalid 1panel api url")
} }
if apiVersion == "" {
return nil, errors.New("invalid 1panel api version")
}
if apiKey == "" { if apiKey == "" {
return nil, errors.New("invalid 1panel api key") return nil, errors.New("invalid 1panel api key")
} }
client := opsdk.NewClient(apiUrl, apiKey) client := onepanelsdk.NewClient(apiUrl, apiVersion, apiKey)
if skipTlsVerify { if skipTlsVerify {
client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true})
} }

View File

@ -15,6 +15,7 @@ var (
fInputCertPath string fInputCertPath string
fInputKeyPath string fInputKeyPath string
fApiUrl string fApiUrl string
fApiVersion string
fApiKey string fApiKey string
fWebsiteId int64 fWebsiteId int64
) )
@ -25,6 +26,7 @@ func init() {
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "")
flag.StringVar(&fApiVersion, argsPrefix+"APIVERSION", "v1", "")
flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "") flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "")
flag.Int64Var(&fWebsiteId, argsPrefix+"WEBSITEID", 0, "") flag.Int64Var(&fWebsiteId, argsPrefix+"WEBSITEID", 0, "")
} }
@ -36,6 +38,7 @@ Shell command to run this test:
--CERTIMATE_DEPLOYER_1PANELSITE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_1PANELSITE_INPUTCERTPATH="/path/to/your-input-cert.pem" \
--CERTIMATE_DEPLOYER_1PANELSITE_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_1PANELSITE_INPUTKEYPATH="/path/to/your-input-key.pem" \
--CERTIMATE_DEPLOYER_1PANELSITE_APIURL="http://127.0.0.1:20410" \ --CERTIMATE_DEPLOYER_1PANELSITE_APIURL="http://127.0.0.1:20410" \
--CERTIMATE_DEPLOYER_1PANELSITE_APIVERSION="v1" \
--CERTIMATE_DEPLOYER_1PANELSITE_APIKEY="your-api-key" \ --CERTIMATE_DEPLOYER_1PANELSITE_APIKEY="your-api-key" \
--CERTIMATE_DEPLOYER_1PANELSITE_WEBSITEID="your-website-id" --CERTIMATE_DEPLOYER_1PANELSITE_WEBSITEID="your-website-id"
*/ */
@ -48,12 +51,14 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
fmt.Sprintf("APIURL: %v", fApiUrl), fmt.Sprintf("APIURL: %v", fApiUrl),
fmt.Sprintf("APIVERSION: %v", fApiVersion),
fmt.Sprintf("APIKEY: %v", fApiKey), fmt.Sprintf("APIKEY: %v", fApiKey),
fmt.Sprintf("WEBSITEID: %v", fWebsiteId), fmt.Sprintf("WEBSITEID: %v", fWebsiteId),
}, "\n")) }, "\n"))
deployer, err := provider.NewDeployer(&provider.DeployerConfig{ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
ApiUrl: fApiUrl, ApiUrl: fApiUrl,
ApiVersion: fApiVersion,
ApiKey: fApiKey, ApiKey: fApiKey,
AllowInsecureConnections: true, AllowInsecureConnections: true,
ResourceType: provider.RESOURCE_TYPE_WEBSITE, ResourceType: provider.RESOURCE_TYPE_WEBSITE,

View File

@ -10,12 +10,14 @@ import (
"time" "time"
"github.com/usual2970/certimate/internal/pkg/core/uploader" "github.com/usual2970/certimate/internal/pkg/core/uploader"
opsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/1panel" onepanelsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/1panel"
) )
type UploaderConfig struct { type UploaderConfig struct {
// 1Panel 地址。 // 1Panel 地址。
ApiUrl string `json:"apiUrl"` ApiUrl string `json:"apiUrl"`
// 1Panel 版本。
ApiVersion string `json:"apiVersion"`
// 1Panel 接口密钥。 // 1Panel 接口密钥。
ApiKey string `json:"apiKey"` ApiKey string `json:"apiKey"`
} }
@ -23,7 +25,7 @@ type UploaderConfig struct {
type UploaderProvider struct { type UploaderProvider struct {
config *UploaderConfig config *UploaderConfig
logger *slog.Logger logger *slog.Logger
sdkClient *opsdk.Client sdkClient *onepanelsdk.Client
} }
var _ uploader.Uploader = (*UploaderProvider)(nil) var _ uploader.Uploader = (*UploaderProvider)(nil)
@ -33,7 +35,7 @@ func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
panic("config is nil") panic("config is nil")
} }
client, err := createSdkClient(config.ApiUrl, config.ApiKey) client, err := createSdkClient(config.ApiUrl, config.ApiVersion, config.ApiKey)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create sdk client: %w", err) return nil, fmt.Errorf("failed to create sdk client: %w", err)
} }
@ -67,7 +69,7 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPE
certName := fmt.Sprintf("certimate-%d", time.Now().UnixMilli()) certName := fmt.Sprintf("certimate-%d", time.Now().UnixMilli())
// 上传证书 // 上传证书
uploadWebsiteSSLReq := &opsdk.UploadWebsiteSSLRequest{ uploadWebsiteSSLReq := &onepanelsdk.UploadWebsiteSSLRequest{
Type: "paste", Type: "paste",
Description: certName, Description: certName,
Certificate: certPEM, Certificate: certPEM,
@ -99,7 +101,7 @@ func (u *UploaderProvider) getCertIfExists(ctx context.Context, certPEM string,
default: default:
} }
searchWebsiteSSLReq := &opsdk.SearchWebsiteSSLRequest{ searchWebsiteSSLReq := &onepanelsdk.SearchWebsiteSSLRequest{
Page: searchWebsiteSSLPageNumber, Page: searchWebsiteSSLPageNumber,
PageSize: searchWebsiteSSLPageSize, PageSize: searchWebsiteSSLPageSize,
} }
@ -130,15 +132,19 @@ func (u *UploaderProvider) getCertIfExists(ctx context.Context, certPEM string,
return nil, nil return nil, nil
} }
func createSdkClient(apiUrl, apiKey string) (*opsdk.Client, error) { func createSdkClient(apiUrl, apiVersion, apiKey string) (*onepanelsdk.Client, error) {
if _, err := url.Parse(apiUrl); err != nil { if _, err := url.Parse(apiUrl); err != nil {
return nil, errors.New("invalid 1panel api url") return nil, errors.New("invalid 1panel api url")
} }
if apiVersion == "" {
return nil, errors.New("invalid 1panel api version")
}
if apiKey == "" { if apiKey == "" {
return nil, errors.New("invalid 1panel api key") return nil, errors.New("invalid 1panel api key")
} }
client := opsdk.NewClient(apiUrl, apiKey) client := onepanelsdk.NewClient(apiUrl, apiVersion, apiKey)
return client, nil return client, nil
} }

View File

@ -16,6 +16,7 @@ var (
fInputCertPath string fInputCertPath string
fInputKeyPath string fInputKeyPath string
fApiUrl string fApiUrl string
fApiVersion string
fApiKey string fApiKey string
) )
@ -25,6 +26,7 @@ func init() {
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "")
flag.StringVar(&fApiVersion, argsPrefix+"APIVERSION", "v1", "")
flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "") flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "")
} }
@ -35,6 +37,7 @@ Shell command to run this test:
--CERTIMATE_UPLOADER_1PANELSSL_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_UPLOADER_1PANELSSL_INPUTCERTPATH="/path/to/your-input-cert.pem" \
--CERTIMATE_UPLOADER_1PANELSSL_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_UPLOADER_1PANELSSL_INPUTKEYPATH="/path/to/your-input-key.pem" \
--CERTIMATE_UPLOADER_1PANELSSL_APIURL="http://127.0.0.1:20410" \ --CERTIMATE_UPLOADER_1PANELSSL_APIURL="http://127.0.0.1:20410" \
--CERTIMATE_UPLOADER_1PANELSSL_APIVERSION="v1" \
--CERTIMATE_UPLOADER_1PANELSSL_APIKEY="your-api-key" --CERTIMATE_UPLOADER_1PANELSSL_APIKEY="your-api-key"
*/ */
func TestDeploy(t *testing.T) { func TestDeploy(t *testing.T) {
@ -46,11 +49,13 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
fmt.Sprintf("APIURL: %v", fApiUrl), fmt.Sprintf("APIURL: %v", fApiUrl),
fmt.Sprintf("APIVERSION: %v", fApiVersion),
fmt.Sprintf("APIKEY: %v", fApiKey), fmt.Sprintf("APIKEY: %v", fApiKey),
}, "\n")) }, "\n"))
uploader, err := provider.NewUploader(&provider.UploaderConfig{ uploader, err := provider.NewUploader(&provider.UploaderConfig{
ApiUrl: fApiUrl, ApiUrl: fApiUrl,
ApiVersion: fApiVersion,
ApiKey: fApiKey, ApiKey: fApiKey,
}) })
if err != nil { if err != nil {

View File

@ -15,16 +15,22 @@ import (
type Client struct { type Client struct {
apiHost string apiHost string
apiVersion string
apiKey string apiKey string
client *resty.Client client *resty.Client
} }
func NewClient(apiHost, apiKey string) *Client { func NewClient(apiHost, apiVersion, apiKey string) *Client {
client := resty.New() client := resty.New()
if apiVersion == "" {
apiVersion = "v1"
}
return &Client{ return &Client{
apiHost: strings.TrimRight(apiHost, "/"), apiHost: strings.TrimRight(apiHost, "/"),
apiVersion: apiVersion,
apiKey: apiKey, apiKey: apiKey,
client: client, client: client,
} }
@ -49,7 +55,7 @@ func (c *Client) generateToken(timestamp string) string {
func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) { func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) {
req := c.client.R() req := c.client.R()
req.Method = method req.Method = method
req.URL = c.apiHost + "/api/v1" + path req.URL = c.apiHost + "/api/" + c.apiVersion + path
if strings.EqualFold(method, http.MethodGet) { if strings.EqualFold(method, http.MethodGet) {
qs := make(map[string]string) qs := make(map[string]string)
if params != nil { if params != nil {

View File

@ -0,0 +1,44 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
// migrate data
{
accesses, err := app.FindAllRecords("access")
if err != nil {
return err
}
for _, access := range accesses {
changed := false
if access.GetString("provider") == "1panel" {
config := make(map[string]any)
if err := access.UnmarshalJSONField("config", &config); err != nil {
return err
}
config["apiVersion"] = "v1"
access.Set("config", config)
changed = true
}
if changed {
err = app.Save(access)
if err != nil {
return err
}
}
}
}
return nil
}, func(app core.App) error {
return nil
})
}

View File

@ -1,5 +1,5 @@
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Switch } from "antd"; import { Form, type FormInstance, Input, Select, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod"; import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod"; import { z } from "zod";
@ -18,6 +18,7 @@ export type AccessForm1PanelConfigProps = {
const initFormModel = (): AccessForm1PanelConfigFieldValues => { const initFormModel = (): AccessForm1PanelConfigFieldValues => {
return { return {
apiUrl: "http://<your-host-addr>:20410/", apiUrl: "http://<your-host-addr>:20410/",
apiVersion: "v1",
apiKey: "", apiKey: "",
}; };
}; };
@ -27,6 +28,7 @@ const AccessForm1PanelConfig = ({ form: formInst, formName, disabled, initialVal
const formSchema = z.object({ const formSchema = z.object({
apiUrl: z.string().url(t("common.errmsg.url_invalid")), apiUrl: z.string().url(t("common.errmsg.url_invalid")),
apiVersion: z.string().nonempty(t("access.form.1panel_api_version.placeholder")),
apiKey: z apiKey: z
.string() .string()
.min(1, t("access.form.1panel_api_key.placeholder")) .min(1, t("access.form.1panel_api_key.placeholder"))
@ -53,6 +55,10 @@ const AccessForm1PanelConfig = ({ form: formInst, formName, disabled, initialVal
<Input placeholder={t("access.form.1panel_api_url.placeholder")} /> <Input placeholder={t("access.form.1panel_api_url.placeholder")} />
</Form.Item> </Form.Item>
<Form.Item name="apiVersion" label={t("access.form.1panel_api_version.label")} rules={[formRule]}>
<Select options={["v1", "v2"].map((s) => ({ label: s, value: s }))} placeholder={t("access.form.1panel_api_version.placeholder")} />
</Form.Item>
<Form.Item <Form.Item
name="apiKey" name="apiKey"
label={t("access.form.1panel_api_key.label")} label={t("access.form.1panel_api_key.label")}

View File

@ -69,6 +69,7 @@ export interface AccessModel extends BaseModel {
// #region AccessConfig // #region AccessConfig
export type AccessConfigFor1Panel = { export type AccessConfigFor1Panel = {
apiUrl: string; apiUrl: string;
apiVersion: string;
apiKey: string; apiKey: string;
allowInsecureConnections?: boolean; allowInsecureConnections?: boolean;
}; };

View File

@ -36,6 +36,8 @@
"access.form.notification_channel.placeholder": "Please select a notification channel", "access.form.notification_channel.placeholder": "Please select a notification channel",
"access.form.1panel_api_url.label": "1Panel URL", "access.form.1panel_api_url.label": "1Panel URL",
"access.form.1panel_api_url.placeholder": "Please enter 1Panel URL", "access.form.1panel_api_url.placeholder": "Please enter 1Panel URL",
"access.form.1panel_api_version.label": "1Panel version",
"access.form.1panel_api_version.placeholder": "Please select 1Panel version",
"access.form.1panel_api_key.label": "1Panel API key", "access.form.1panel_api_key.label": "1Panel API key",
"access.form.1panel_api_key.placeholder": "Please enter 1Panel API key", "access.form.1panel_api_key.placeholder": "Please enter 1Panel API key",
"access.form.1panel_api_key.tooltip": "For more information, see <a href=\"https://docs.1panel.pro/dev_manual/api_manual/\" target=\"_blank\">https://docs.1panel.pro/dev_manual/api_manual/</a>", "access.form.1panel_api_key.tooltip": "For more information, see <a href=\"https://docs.1panel.pro/dev_manual/api_manual/\" target=\"_blank\">https://docs.1panel.pro/dev_manual/api_manual/</a>",
@ -262,8 +264,8 @@
"access.form.namesilo_api_key.label": "NameSilo API key", "access.form.namesilo_api_key.label": "NameSilo API key",
"access.form.namesilo_api_key.placeholder": "Please enter NameSilo API key", "access.form.namesilo_api_key.placeholder": "Please enter NameSilo API key",
"access.form.namesilo_api_key.tooltip": "For more information, see <a href=\"https://www.namesilo.com/support/v2/articles/account-options/api-manager\" target=\"_blank\">https://www.namesilo.com/support/v2/articles/account-options/api-manager</a>", "access.form.namesilo_api_key.tooltip": "For more information, see <a href=\"https://www.namesilo.com/support/v2/articles/account-options/api-manager\" target=\"_blank\">https://www.namesilo.com/support/v2/articles/account-options/api-manager</a>",
"access.form.netlify_api_token.label": "netlify API token", "access.form.netlify_api_token.label": "Netlify API token",
"access.form.netlify_api_token.placeholder": "Please enter netlify API token", "access.form.netlify_api_token.placeholder": "Please enter Netlify API token",
"access.form.netlify_api_token.tooltip": "For more information, see <a href=\"https://docs.netlify.com/api/get-started/#authentication\" target=\"_blank\">https://docs.netlify.com/api/get-started/#authentication</a>", "access.form.netlify_api_token.tooltip": "For more information, see <a href=\"https://docs.netlify.com/api/get-started/#authentication\" target=\"_blank\">https://docs.netlify.com/api/get-started/#authentication</a>",
"access.form.netcup_customer_number.label": "netcup customer number", "access.form.netcup_customer_number.label": "netcup customer number",
"access.form.netcup_customer_number.placeholder": "Please enter netcup customer number", "access.form.netcup_customer_number.placeholder": "Please enter netcup customer number",

View File

@ -91,8 +91,8 @@
"provider.namedotcom": "Name.com", "provider.namedotcom": "Name.com",
"provider.namesilo": "NameSilo", "provider.namesilo": "NameSilo",
"provider.netcup": "netcup", "provider.netcup": "netcup",
"provider.netlify": "netlify", "provider.netlify": "Netlify",
"provider.netlify.site": "netlify - Site", "provider.netlify.site": "Netlify - Site",
"provider.ns1": "NS1 (IBM NS1 Connect)", "provider.ns1": "NS1 (IBM NS1 Connect)",
"provider.porkbun": "Porkbun", "provider.porkbun": "Porkbun",
"provider.powerdns": "PowerDNS", "provider.powerdns": "PowerDNS",

View File

@ -489,8 +489,8 @@
"workflow_node.deploy.form.local_preset_scripts.option.ps_binding_iis.label": "PowerShell - Binding IIS", "workflow_node.deploy.form.local_preset_scripts.option.ps_binding_iis.label": "PowerShell - Binding IIS",
"workflow_node.deploy.form.local_preset_scripts.option.ps_binding_netsh.label": "PowerShell - Binding netsh", "workflow_node.deploy.form.local_preset_scripts.option.ps_binding_netsh.label": "PowerShell - Binding netsh",
"workflow_node.deploy.form.local_preset_scripts.option.ps_.label": "PowerShell - Binding RDP", "workflow_node.deploy.form.local_preset_scripts.option.ps_.label": "PowerShell - Binding RDP",
"workflow_node.deploy.form.netlify_site_id.label": "netlify site ID", "workflow_node.deploy.form.netlify_site_id.label": "Netlify site ID",
"workflow_node.deploy.form.netlify_site_id.placeholder": "Please enter netlify site ID", "workflow_node.deploy.form.netlify_site_id.placeholder": "Please enter Netlify site ID",
"workflow_node.deploy.form.netlify_site_id.tooltip": "For more information, see <a href=\"https://docs.netlify.com/api/get-started/#get-site\" target=\"_blank\">https://docs.netlify.com/api/get-started/#get-site</a>", "workflow_node.deploy.form.netlify_site_id.tooltip": "For more information, see <a href=\"https://docs.netlify.com/api/get-started/#get-site\" target=\"_blank\">https://docs.netlify.com/api/get-started/#get-site</a>",
"workflow_node.deploy.form.proxmoxve_node_name.label": "Proxmox VE cluster node name", "workflow_node.deploy.form.proxmoxve_node_name.label": "Proxmox VE cluster node name",
"workflow_node.deploy.form.proxmoxve_node_name.placeholder": "Please enter Proxmox VE cluster node name", "workflow_node.deploy.form.proxmoxve_node_name.placeholder": "Please enter Proxmox VE cluster node name",

View File

@ -36,6 +36,8 @@
"access.form.notification_channel.placeholder": "请选择通知渠道", "access.form.notification_channel.placeholder": "请选择通知渠道",
"access.form.1panel_api_url.label": "1Panel URL", "access.form.1panel_api_url.label": "1Panel URL",
"access.form.1panel_api_url.placeholder": "请输入 1Panel URL", "access.form.1panel_api_url.placeholder": "请输入 1Panel URL",
"access.form.1panel_api_version.label": "1Panel 版本",
"access.form.1panel_api_version.placeholder": "请选择 1Panel 版本",
"access.form.1panel_api_key.label": "1Panel 接口密钥", "access.form.1panel_api_key.label": "1Panel 接口密钥",
"access.form.1panel_api_key.placeholder": "请输入 1Panel 接口密钥", "access.form.1panel_api_key.placeholder": "请输入 1Panel 接口密钥",
"access.form.1panel_api_key.tooltip": "这是什么?请参阅 <a href=\"https://1panel.cn/docs/dev_manual/api_manual/\" target=\"_blank\">https://1panel.cn/docs/dev_manual/api_manual/</a>", "access.form.1panel_api_key.tooltip": "这是什么?请参阅 <a href=\"https://1panel.cn/docs/dev_manual/api_manual/\" target=\"_blank\">https://1panel.cn/docs/dev_manual/api_manual/</a>",
@ -256,8 +258,8 @@
"access.form.namesilo_api_key.label": "NameSilo API Key", "access.form.namesilo_api_key.label": "NameSilo API Key",
"access.form.namesilo_api_key.placeholder": "请输入 NameSilo API Key", "access.form.namesilo_api_key.placeholder": "请输入 NameSilo API Key",
"access.form.namesilo_api_key.tooltip": "这是什么?请参阅 <a href=\"https://www.namesilo.com/support/v2/articles/account-options/api-manager\" target=\"_blank\">https://www.namesilo.com/support/v2/articles/account-options/api-manager</a>", "access.form.namesilo_api_key.tooltip": "这是什么?请参阅 <a href=\"https://www.namesilo.com/support/v2/articles/account-options/api-manager\" target=\"_blank\">https://www.namesilo.com/support/v2/articles/account-options/api-manager</a>",
"access.form.netlify_api_token.label": "netlify API Token", "access.form.netlify_api_token.label": "Netlify API Token",
"access.form.netlify_api_token.placeholder": "请输入 netlify API Token", "access.form.netlify_api_token.placeholder": "请输入 Netlify API Token",
"access.form.netlify_api_token.tooltip": "这是什么?请参阅 <a href=\"https://docs.netlify.com/api/get-started/#authentication\" target=\"_blank\">https://docs.netlify.com/api/get-started/#authentication</a>", "access.form.netlify_api_token.tooltip": "这是什么?请参阅 <a href=\"https://docs.netlify.com/api/get-started/#authentication\" target=\"_blank\">https://docs.netlify.com/api/get-started/#authentication</a>",
"access.form.netcup_customer_number.label": "netcup 客户编号", "access.form.netcup_customer_number.label": "netcup 客户编号",
"access.form.netcup_customer_number.placeholder": "请输入 netcup 客户编号", "access.form.netcup_customer_number.placeholder": "请输入 netcup 客户编号",

View File

@ -91,8 +91,8 @@
"provider.namedotcom": "Name.com", "provider.namedotcom": "Name.com",
"provider.namesilo": "NameSilo", "provider.namesilo": "NameSilo",
"provider.netcup": "netcup", "provider.netcup": "netcup",
"provider.netlify": "netlify", "provider.netlify": "Netlify",
"provider.netlify.site": "netlify - Site", "provider.netlify.site": "Netlify - Site",
"provider.ns1": "NS1 (IBM NS1 Connect)", "provider.ns1": "NS1 (IBM NS1 Connect)",
"provider.porkbun": "Porkbun", "provider.porkbun": "Porkbun",
"provider.powerdns": "PowerDNS", "provider.powerdns": "PowerDNS",

View File

@ -488,7 +488,7 @@
"workflow_node.deploy.form.local_preset_scripts.option.ps_binding_iis.label": "PowerShell - 导入并绑定到 IIS", "workflow_node.deploy.form.local_preset_scripts.option.ps_binding_iis.label": "PowerShell - 导入并绑定到 IIS",
"workflow_node.deploy.form.local_preset_scripts.option.ps_binding_netsh.label": "PowerShell - 导入并绑定到 netsh", "workflow_node.deploy.form.local_preset_scripts.option.ps_binding_netsh.label": "PowerShell - 导入并绑定到 netsh",
"workflow_node.deploy.form.local_preset_scripts.option.ps_binding_rdp.label": "PowerShell - 导入并绑定到 RDP", "workflow_node.deploy.form.local_preset_scripts.option.ps_binding_rdp.label": "PowerShell - 导入并绑定到 RDP",
"workflow_node.deploy.form.netlify_site_id.label": "netlify 网站 ID", "workflow_node.deploy.form.netlify_site_id.label": "Netlify 网站 ID",
"workflow_node.deploy.form.netlify_site_id.placeholder": "请输入 netlify 网站 ID", "workflow_node.deploy.form.netlify_site_id.placeholder": "请输入 netlify 网站 ID",
"workflow_node.deploy.form.netlify_site_id.tooltip": "这是什么?请参阅 <a href=\"https://docs.netlify.com/api/get-started/#get-site\" target=\"_blank\">https://docs.netlify.com/api/get-started/#get-site</a>", "workflow_node.deploy.form.netlify_site_id.tooltip": "这是什么?请参阅 <a href=\"https://docs.netlify.com/api/get-started/#get-site\" target=\"_blank\">https://docs.netlify.com/api/get-started/#get-site</a>",
"workflow_node.deploy.form.proxmoxve_node_name.label": "Proxmox VE 集群节点名称", "workflow_node.deploy.form.proxmoxve_node_name.label": "Proxmox VE 集群节点名称",