Files
opsx-vpn/backend/internal/api/tls.go
T

106 lines
3.5 KiB
Go

package api
import (
"encoding/json"
"fmt"
"net/http"
"github.com/gin-gonic/gin"
"vpn-platform/backend/internal/nginxconfig"
"vpn-platform/backend/internal/nginxsetup"
"vpn-platform/backend/internal/service"
"vpn-platform/backend/internal/store"
"vpn-platform/backend/internal/tlsservice"
)
func (s *Server) nginxSetupStatus(c *gin.Context) {
c.JSON(http.StatusOK, nginxsetup.Inspect())
}
func (s *Server) initializeNginx(c *gin.Context) {
status := nginxsetup.Inspect()
if !status.Supported || !status.Root {
c.JSON(http.StatusPreconditionFailed, gin.H{"error": "仅支持 root 运行的 Ubuntu / TencentOS Server 4"})
return
}
if !nginxsetup.Begin() {
c.JSON(http.StatusConflict, gin.H{"error": "初始化正在运行,请等待完成"})
return
}
defer nginxsetup.End()
c.Header("Content-Type", "application/x-ndjson; charset=utf-8")
c.Header("Cache-Control", "no-store")
c.Header("X-Accel-Buffering", "no")
c.Status(http.StatusOK)
write := func(kind, message string) {
payload, _ := json.Marshal(gin.H{"type": kind, "message": message})
fmt.Fprintf(c.Writer, "%s\n", payload)
c.Writer.Flush()
}
write("info", "开始初始化 Nginx / Certbot;此步骤不会启用 80/443 或签发证书。\n")
err := nginxsetup.Run(func(message string) { write("output", message) })
if err != nil {
store.Audit(c.GetString("username"), "nginx_setup", "failed", err.Error())
write("error", err.Error())
return
}
store.Audit(c.GetString("username"), "nginx_setup", "completed", "software and webroot ready")
write("done", "初始化完成;继续配置 HTTP-01 站点与证书。")
}
func (s *Server) tlsStatus(c *gin.Context) {
c.JSON(http.StatusOK, tlsservice.Status())
}
func (s *Server) nginxPreview(c *gin.Context) {
status := tlsservice.Status()
if status.ConfiguredDomain == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "请先在页面保存域名"})
return
}
httpSite, httpsSite, err := nginxconfig.Render(status.ConfiguredDomain, s.router.Routes())
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{
"http_site": httpSite, "https_site": httpsSite,
"warning": "仅预览:先安装 Nginx/Certbot,停用 Go 的 80/443 监听并签出证书;认证域名须单独配置。",
})
}
func (s *Server) setTLSMode(c *gin.Context) {
var req struct {
Mode string `json:"mode"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "请输入入口模式"})
return
}
if err := tlsservice.ConfigureMode(service.BaseDir(), req.Mode); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
store.Audit(c.GetString("username"), "tls_mode_configured", req.Mode, "需检查外部入口后重启")
status := tlsservice.Status()
c.JSON(http.StatusOK, gin.H{"status": status, "restart_required": status.RestartRequired})
}
func (s *Server) setTLSDomain(c *gin.Context) {
var req struct {
Domain string `json:"domain"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "请输入域名"})
return
}
if err := tlsservice.ConfigureDomain(service.BaseDir(), req.Domain); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
store.Audit(c.GetString("username"), "tls_domain_configured", req.Domain, "需重启后生效")
status := tlsservice.Status()
c.JSON(http.StatusOK, gin.H{"status": status, "restart_required": status.RestartRequired})
}