206 lines
5.6 KiB
Go
206 lines
5.6 KiB
Go
package handler
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
"time"
|
|
|
|
"git.zkcoi.com/zkcoi/meshray/internal/model"
|
|
"git.zkcoi.com/zkcoi/meshray/internal/service"
|
|
sqlite "git.zkcoi.com/zkcoi/meshray/internal/store/sqlite"
|
|
"github.com/gin-gonic/gin"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// PendingJoinHandler 待审核 Handler
|
|
type PendingJoinHandler struct {
|
|
service *service.PendingJoinService
|
|
store *sqlite.Store // ← 新增
|
|
logger *zap.Logger
|
|
}
|
|
|
|
// NewPendingJoinHandler 创建待审核 Handler
|
|
func NewPendingJoinHandler(service *service.PendingJoinService, store *sqlite.Store, logger *zap.Logger) *PendingJoinHandler {
|
|
return &PendingJoinHandler{
|
|
service: service,
|
|
store: store, // ← 新增
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
// ListPendingJoins 获取待审核列表
|
|
func (h *PendingJoinHandler) ListPendingJoins(c *gin.Context) {
|
|
// 获取查询参数
|
|
networkIDStr := c.DefaultQuery("network_id", "0")
|
|
status := c.DefaultQuery("status", "pending")
|
|
pageStr := c.DefaultQuery("page", "1")
|
|
sizeStr := c.DefaultQuery("size", "20")
|
|
|
|
// 转换参数
|
|
networkID, _ := strconv.ParseUint(networkIDStr, 10, 32)
|
|
page, _ := strconv.Atoi(pageStr)
|
|
size, _ := strconv.Atoi(sizeStr)
|
|
|
|
if page < 1 {
|
|
page = 1
|
|
}
|
|
if size < 1 || size > 100 {
|
|
size = 20
|
|
}
|
|
|
|
// 调用 Service
|
|
list, total, err := h.service.ListPendingJoins(uint(networkID), status, page, size)
|
|
if err != nil {
|
|
h.logger.Error("获取待审核列表失败", zap.Error(err))
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取失败"})
|
|
return
|
|
}
|
|
|
|
// 转换为响应格式
|
|
type ResponseItem struct {
|
|
ID uint `json:"id"`
|
|
SeedID string `json:"seed_id"`
|
|
DeviceName string `json:"device_name"`
|
|
RequestIP string `json:"request_ip"`
|
|
Status string `json:"status"`
|
|
ExpireAt string `json:"expire_at"`
|
|
ApprovedAt string `json:"approved_at"`
|
|
RejectedAt string `json:"rejected_at"`
|
|
Reason string `json:"reason"`
|
|
CreatedAt string `json:"created_at"`
|
|
UpdatedAt string `json:"updated_at"`
|
|
NetworkID uint `json:"network_id"`
|
|
NetworkName string `json:"network_name"`
|
|
ApplicantIP string `json:"applicant_ip"`
|
|
ApplyTime string `json:"apply_time"`
|
|
Message string `json:"message"`
|
|
}
|
|
|
|
var responseList []ResponseItem
|
|
for _, item := range list {
|
|
// 通过 SeedID 关联查询 MeshSeed 获取 NetworkID
|
|
var meshSeed model.MeshSeed
|
|
networkName := "未知网络"
|
|
networkID := uint(0)
|
|
if err := h.store.DB().Where("seed_id = ?", item.SeedID).First(&meshSeed).Error; err == nil {
|
|
// 查询网络信息
|
|
var network model.Network
|
|
if err := h.store.DB().Where("id = ?", meshSeed.NetworkID).First(&network).Error; err == nil {
|
|
networkName = network.Name
|
|
networkID = uint(network.ID)
|
|
}
|
|
}
|
|
|
|
responseList = append(responseList, ResponseItem{
|
|
ID: item.ID,
|
|
SeedID: item.SeedID,
|
|
DeviceName: item.DeviceName,
|
|
RequestIP: item.RequestIP,
|
|
Status: item.Status,
|
|
ExpireAt: item.ExpireAt.Format("2006-01-02 15:04:05"),
|
|
ApprovedAt: formatTime(item.ApprovedAt),
|
|
RejectedAt: formatTime(item.RejectedAt),
|
|
Reason: item.Reason,
|
|
CreatedAt: item.CreatedAt.Format("2006-01-02 15:04:05"),
|
|
UpdatedAt: item.UpdatedAt.Format("2006-01-02 15:04:05"),
|
|
NetworkID: networkID,
|
|
NetworkName: networkName,
|
|
ApplicantIP: item.RequestIP,
|
|
ApplyTime: item.CreatedAt.Format("2006-01-02 15:04:05"),
|
|
Message: "",
|
|
})
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"data": gin.H{
|
|
"list": responseList,
|
|
"total": total,
|
|
},
|
|
})
|
|
}
|
|
|
|
// ApproveJoin 审核通过
|
|
func (h *PendingJoinHandler) ApproveJoin(c *gin.Context) {
|
|
idStr := c.Param("id")
|
|
id, _ := strconv.ParseUint(idStr, 10, 32)
|
|
|
|
result, err := h.service.ApproveJoin(uint(id))
|
|
if err != nil {
|
|
h.logger.Error("审核通过失败", zap.Error(err))
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
// 返回完整配置给前端
|
|
h.logger.Info("审核通过成功",
|
|
zap.Uint64("id", uint64(id)),
|
|
zap.String("device_name", result.Device.Name),
|
|
zap.String("device_ip", result.Device.VirtualIP))
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"message": "审核通过",
|
|
"data": gin.H{
|
|
"device": result.Device,
|
|
"private_key": result.PrivateKey,
|
|
"network": result.Network,
|
|
"wireguard_config": result.ConfigText,
|
|
},
|
|
})
|
|
}
|
|
|
|
// RejectJoin 审核拒绝
|
|
func (h *PendingJoinHandler) RejectJoin(c *gin.Context) {
|
|
idStr := c.Param("id")
|
|
id, _ := strconv.ParseUint(idStr, 10, 32)
|
|
|
|
var req struct {
|
|
Reason string `json:"reason"`
|
|
}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误"})
|
|
return
|
|
}
|
|
|
|
if err := h.service.RejectJoin(uint(id), req.Reason); err != nil {
|
|
h.logger.Error("审核拒绝失败", zap.Error(err))
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "已拒绝"})
|
|
}
|
|
|
|
// CountPending 统计待审核数量
|
|
func (h *PendingJoinHandler) CountPending(c *gin.Context) {
|
|
count, err := h.service.CountPending()
|
|
if err != nil {
|
|
h.logger.Error("统计待审核数量失败", zap.Error(err))
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "统计失败"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"data": gin.H{
|
|
"count": count,
|
|
},
|
|
})
|
|
}
|
|
|
|
// DeleteExpired 清理过期记录
|
|
func (h *PendingJoinHandler) DeleteExpired(c *gin.Context) {
|
|
if err := h.service.DeleteExpired(); err != nil {
|
|
h.logger.Error("清理过期记录失败", zap.Error(err))
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "清理失败"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "清理完成"})
|
|
}
|
|
|
|
func formatTime(t *time.Time) string {
|
|
if t == nil {
|
|
return ""
|
|
}
|
|
return t.Format("2006-01-02 15:04:05")
|
|
}
|