chore: 初始提交 Fonu 1.0.2
- 公网反代:Nginx 状态卡片(版本 / 运行状态 / 配置校验 / 端口监听) - 部署设置第一、二梯队(HTTPS 开关、安全头、限流、连接数、仅中国大陆 IP) - 隧道检测兼容 frps v0.68 / v0.71(V2 与旧版端点) - 恢复被清空的 internal/frp/store.go、internal/api/ddns_handler.go、web/src/views/DdnsView.vue
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/fonu/fonu/internal/ddns"
|
||||
)
|
||||
|
||||
type DDNSHandler struct {
|
||||
svc *ddns.Service
|
||||
}
|
||||
|
||||
func NewDDNSHandler(svc *ddns.Service) *DDNSHandler {
|
||||
return &DDNSHandler{svc: svc}
|
||||
}
|
||||
|
||||
type ddnsRequest struct {
|
||||
Provider string `json:"provider"`
|
||||
RootDomain string `json:"root_domain"`
|
||||
RecordName string `json:"record_name"`
|
||||
RecordNames []string `json:"record_names"`
|
||||
Domains []string `json:"domains"`
|
||||
IPv4Enabled *bool `json:"ipv4_enabled"`
|
||||
IPv6Enabled *bool `json:"ipv6_enabled"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
CustomIPv4 string `json:"custom_ipv4"`
|
||||
CustomIPv6 string `json:"custom_ipv6"`
|
||||
APIToken string `json:"api_token"`
|
||||
APITokenID string `json:"api_token_id"`
|
||||
APISecret string `json:"api_secret"`
|
||||
}
|
||||
|
||||
func (h *DDNSHandler) toInput(req ddnsRequest) ddns.SaveInput {
|
||||
return ddns.SaveInput{
|
||||
Provider: req.Provider,
|
||||
RootDomain: req.RootDomain,
|
||||
RecordName: req.RecordName,
|
||||
RecordNames: req.RecordNames,
|
||||
Domains: req.Domains,
|
||||
IPv4Enabled: boolDefault(req.IPv4Enabled, true),
|
||||
IPv6Enabled: boolDefault(req.IPv6Enabled, false),
|
||||
Enabled: boolDefault(req.Enabled, true),
|
||||
CustomIPv4: req.CustomIPv4,
|
||||
CustomIPv6: req.CustomIPv6,
|
||||
APIToken: req.APIToken,
|
||||
APITokenID: req.APITokenID,
|
||||
APISecret: req.APISecret,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *DDNSHandler) List(w http.ResponseWriter, r *http.Request) {
|
||||
var configs []ddns.Config
|
||||
var err error
|
||||
if r.URL.Query().Get("lite") == "1" {
|
||||
configs, err = h.svc.ListLite(r.Context())
|
||||
} else {
|
||||
configs, err = h.svc.List(r.Context())
|
||||
}
|
||||
if err != nil {
|
||||
writeError(r, w, http.StatusInternalServerError, "读取 DDNS 配置失败")
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, configs)
|
||||
}
|
||||
|
||||
func (h *DDNSHandler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
var req ddnsRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
writeError(r, w, http.StatusBadRequest, "请求格式无效")
|
||||
return
|
||||
}
|
||||
cfg, err := h.svc.Create(r.Context(), h.toInput(req))
|
||||
if err != nil {
|
||||
writeError(r, w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, cfg)
|
||||
}
|
||||
|
||||
func (h *DDNSHandler) Update(w http.ResponseWriter, r *http.Request) {
|
||||
id, err := strconv.ParseInt(r.PathValue("id"), 10, 64)
|
||||
if err != nil {
|
||||
writeError(r, w, http.StatusBadRequest, "无效的配置 ID")
|
||||
return
|
||||
}
|
||||
var req ddnsRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
writeError(r, w, http.StatusBadRequest, "请求格式无效")
|
||||
return
|
||||
}
|
||||
cfg, err := h.svc.Update(r.Context(), id, h.toInput(req))
|
||||
if err != nil {
|
||||
writeError(r, w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, cfg)
|
||||
}
|
||||
|
||||
func (h *DDNSHandler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
id, err := strconv.ParseInt(r.PathValue("id"), 10, 64)
|
||||
if err != nil {
|
||||
writeError(r, w, http.StatusBadRequest, "无效的配置 ID")
|
||||
return
|
||||
}
|
||||
if err := h.svc.Delete(r.Context(), id); err != nil {
|
||||
writeError(r, w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func (h *DDNSHandler) Test(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
ConfigID int64 `json:"config_id"`
|
||||
Provider string `json:"provider"`
|
||||
APIToken string `json:"api_token"`
|
||||
APITokenID string `json:"api_token_id"`
|
||||
APISecret string `json:"api_secret"`
|
||||
}
|
||||
_ = json.NewDecoder(r.Body).Decode(&req)
|
||||
if err := h.svc.Test(r.Context(), ddns.TestInput{
|
||||
ConfigID: req.ConfigID,
|
||||
Provider: req.Provider,
|
||||
APIToken: req.APIToken,
|
||||
APITokenID: req.APITokenID,
|
||||
APISecret: req.APISecret,
|
||||
}); err != nil {
|
||||
writeError(r, w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]string{"message": "连接成功"})
|
||||
}
|
||||
|
||||
func (h *DDNSHandler) UpdateOne(w http.ResponseWriter, r *http.Request) {
|
||||
id, err := strconv.ParseInt(r.PathValue("id"), 10, 64)
|
||||
if err != nil {
|
||||
writeError(r, w, http.StatusBadRequest, "无效的配置 ID")
|
||||
return
|
||||
}
|
||||
cfg, err := h.svc.UpdateNow(r.Context(), id)
|
||||
if err != nil {
|
||||
writeError(r, w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, cfg)
|
||||
}
|
||||
|
||||
func (h *DDNSHandler) UpdateAll(w http.ResponseWriter, r *http.Request) {
|
||||
configs, err := h.svc.UpdateAll(r.Context())
|
||||
if err != nil {
|
||||
writeError(r, w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, configs)
|
||||
}
|
||||
Reference in New Issue
Block a user