补充管理端DNS在线测试接口

This commit is contained in:
xuans 2026-08-30 22:51:15 +08:00
parent 755af3e09d
commit c11eaad1f9
3 changed files with 100 additions and 0 deletions

View File

@ -0,0 +1,82 @@
package httpapi
import (
"encoding/json"
"net/http"
"net/http/httptest"
"strings"
"testing"
"git.pcux.cn/xuans/Scert/backend/internal/config"
"git.pcux.cn/xuans/Scert/backend/internal/setup"
)
func TestAdminDNSProvidersRequiresAuthentication(t *testing.T) {
cfg := config.Default(t.TempDir())
cfg.SetupReady = true
server := New(Dependencies{Config: cfg, SetupDNS: &fakeSetupDNSVerifier{}})
response := httptest.NewRecorder()
request := httptest.NewRequest(http.MethodGet, "/api/v1/dns/providers", nil)
server.Handler().ServeHTTP(response, request)
if response.Code != http.StatusUnauthorized {
t.Fatalf("未登录访问 DNS 服务商接口应返回 401,实际为 %d:%s", response.Code, response.Body.String())
}
}
func TestAdminDNSProvidersReturnsCatalog(t *testing.T) {
cfg := config.Default(t.TempDir())
cfg.SetupReady = true
server := New(Dependencies{Config: cfg, SetupDNS: &fakeSetupDNSVerifier{}})
response := httptest.NewRecorder()
request := httptest.NewRequest(http.MethodGet, "/api/v1/dns/providers", nil)
serveAdminHTTP(server, response, request)
if response.Code != http.StatusOK {
t.Fatalf("读取 DNS 服务商目录失败:%d %s", response.Code, response.Body.String())
}
if !strings.Contains(response.Body.String(), "Cloudflare") || !strings.Contains(response.Body.String(), "credential_fields") {
t.Fatalf("DNS 服务商目录内容不完整:%s", response.Body.String())
}
}
func TestAdminDNSTestReturnsVerificationResult(t *testing.T) {
cfg := config.Default(t.TempDir())
cfg.SetupReady = true
verifier := &fakeSetupDNSVerifier{}
server := New(Dependencies{Config: cfg, SetupDNS: verifier})
response := httptest.NewRecorder()
request := httptest.NewRequest(http.MethodPost, "/api/v1/dns/test", strings.NewReader(`{
"provider":"cloudflare",
"test_domain":"example.com",
"credentials":{"api_token":"test-token"}
}`))
request.Header.Set("Content-Type", "application/json")
serveAdminHTTP(server, response, request)
if response.Code != http.StatusOK {
t.Fatalf("DNS 在线测试失败:%d %s", response.Code, response.Body.String())
}
var payload struct {
Verified bool `json:"verified"`
CredentialRef string `json:"credential_ref"`
VerificationToken string `json:"verification_token"`
TestReport setup.DNSVerificationReport `json:"test_report"`
}
if err := json.Unmarshal(response.Body.Bytes(), &payload); err != nil {
t.Fatalf("解析 DNS 在线测试响应失败:%v", err)
}
if !payload.Verified || payload.CredentialRef == "" || payload.VerificationToken == "" || payload.TestReport.RecordName == "" {
t.Fatalf("DNS 在线测试响应内容不正确:%+v", payload)
}
}
func TestAdminDNSTestRejectsUnavailableService(t *testing.T) {
cfg := config.Default(t.TempDir())
cfg.SetupReady = true
server := New(Dependencies{Config: cfg})
response := httptest.NewRecorder()
request := httptest.NewRequest(http.MethodPost, "/api/v1/dns/test", strings.NewReader(`{"provider":"cloudflare","test_domain":"example.com","credentials":{"api_token":"test-token"}}`))
request.Header.Set("Content-Type", "application/json")
serveAdminHTTP(server, response, request)
if response.Code != http.StatusServiceUnavailable {
t.Fatalf("DNS 服务未初始化时应返回 503,实际为 %d:%s", response.Code, response.Body.String())
}
}

View File

@ -164,6 +164,8 @@ func (s *Server) registerRoutes() {
adminAPI.GET("/audit-logs", s.listAuditLogs)
adminAPI.GET("/settings", s.getSettings)
adminAPI.PUT("/settings", s.updateSettings)
adminAPI.GET("/dns/providers", s.listAdminDNSProviders)
adminAPI.POST("/dns/test", s.testAdminDNS)
adminAPI.POST("/renewal/run", s.runRenewalNow)
adminAPI.GET("/certificates", s.listCertificates)
adminAPI.GET("/certificates/:id", s.getCertificate)

View File

@ -125,6 +125,14 @@ func (s *Server) setupDNSProviders(c *gin.Context) {
if !s.allowSetupRequest(c) {
return
}
s.listDNSProviders(c)
}
func (s *Server) listAdminDNSProviders(c *gin.Context) {
s.listDNSProviders(c)
}
func (s *Server) listDNSProviders(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"items": dnsprovider.Descriptors()})
}
@ -132,6 +140,14 @@ func (s *Server) testSetupDNS(c *gin.Context) {
if !s.allowSetupRequest(c) {
return
}
s.testDNS(c)
}
func (s *Server) testAdminDNS(c *gin.Context) {
s.testDNS(c)
}
func (s *Server) testDNS(c *gin.Context) {
if s.setupDNS == nil {
s.writeError(c, http.StatusServiceUnavailable, "DNS 在线验证服务尚未初始化", nil)
return