屏蔽表已创建

This commit is contained in:
2026-06-04 12:08:25 +08:00
parent e6fa998854
commit acd03a614a
10 changed files with 1492 additions and 1 deletions
+211
View File
@@ -0,0 +1,211 @@
package main
import (
"errors"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type nodeBlockingRequest struct {
NodeID string `json:"node_id"`
NodeNum *int64 `json:"node_num"`
Reason string `json:"reason"`
Enabled bool `json:"enabled"`
}
type ipBlockingRequest struct {
IPValue string `json:"ip_value"`
Reason string `json:"reason"`
Enabled bool `json:"enabled"`
}
type forbiddenWordBlockingRequest struct {
Word string `json:"word"`
MatchType string `json:"match_type"`
CaseSensitive bool `json:"case_sensitive"`
Reason string `json:"reason"`
Enabled bool `json:"enabled"`
}
func registerAdminBlockingRoutes(r gin.IRouter, store *store) {
r.GET("/blocking/nodes", func(c *gin.Context) {
opts, ok := parseListOptions(c)
if !ok {
return
}
rows, err := store.ListNodeBlocking(opts)
if err != nil {
writeListResponse(c, rows, opts, err, nodeBlockingDTO)
return
}
total, err := store.CountNodeBlocking(opts)
writeListResponseWithTotal(c, rows, opts, total, err, nodeBlockingDTO)
})
r.POST("/blocking/nodes", func(c *gin.Context) {
var req nodeBlockingRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid node blocking request"})
return
}
row, err := store.CreateNodeBlocking(req.NodeID, req.NodeNum, req.Reason, req.Enabled)
writeBlockingMutationResponse(c, http.StatusCreated, row, err, nodeBlockingDTO)
})
r.PUT("/blocking/nodes/:id", func(c *gin.Context) {
id, ok := parseBlockingID(c)
if !ok {
return
}
var req nodeBlockingRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid node blocking request"})
return
}
row, err := store.UpdateNodeBlocking(id, req.NodeID, req.NodeNum, req.Reason, req.Enabled)
writeBlockingMutationResponse(c, http.StatusOK, row, err, nodeBlockingDTO)
})
r.DELETE("/blocking/nodes/:id", func(c *gin.Context) {
id, ok := parseBlockingID(c)
if !ok {
return
}
writeBlockingDeleteResponse(c, store.DeleteNodeBlocking(id))
})
r.GET("/blocking/ips", func(c *gin.Context) {
opts, ok := parseListOptions(c)
if !ok {
return
}
rows, err := store.ListIPBlocking(opts)
if err != nil {
writeListResponse(c, rows, opts, err, ipBlockingDTO)
return
}
total, err := store.CountIPBlocking(opts)
writeListResponseWithTotal(c, rows, opts, total, err, ipBlockingDTO)
})
r.POST("/blocking/ips", func(c *gin.Context) {
var req ipBlockingRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid ip blocking request"})
return
}
row, err := store.CreateIPBlocking(req.IPValue, req.Reason, req.Enabled)
writeBlockingMutationResponse(c, http.StatusCreated, row, err, ipBlockingDTO)
})
r.PUT("/blocking/ips/:id", func(c *gin.Context) {
id, ok := parseBlockingID(c)
if !ok {
return
}
var req ipBlockingRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid ip blocking request"})
return
}
row, err := store.UpdateIPBlocking(id, req.IPValue, req.Reason, req.Enabled)
writeBlockingMutationResponse(c, http.StatusOK, row, err, ipBlockingDTO)
})
r.DELETE("/blocking/ips/:id", func(c *gin.Context) {
id, ok := parseBlockingID(c)
if !ok {
return
}
writeBlockingDeleteResponse(c, store.DeleteIPBlocking(id))
})
r.GET("/blocking/words", func(c *gin.Context) {
opts, ok := parseListOptions(c)
if !ok {
return
}
rows, err := store.ListForbiddenWordBlocking(opts)
if err != nil {
writeListResponse(c, rows, opts, err, forbiddenWordBlockingDTO)
return
}
total, err := store.CountForbiddenWordBlocking(opts)
writeListResponseWithTotal(c, rows, opts, total, err, forbiddenWordBlockingDTO)
})
r.POST("/blocking/words", func(c *gin.Context) {
var req forbiddenWordBlockingRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid forbidden word blocking request"})
return
}
row, err := store.CreateForbiddenWordBlocking(req.Word, req.MatchType, req.CaseSensitive, req.Reason, req.Enabled)
writeBlockingMutationResponse(c, http.StatusCreated, row, err, forbiddenWordBlockingDTO)
})
r.PUT("/blocking/words/:id", func(c *gin.Context) {
id, ok := parseBlockingID(c)
if !ok {
return
}
var req forbiddenWordBlockingRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid forbidden word blocking request"})
return
}
row, err := store.UpdateForbiddenWordBlocking(id, req.Word, req.MatchType, req.CaseSensitive, req.Reason, req.Enabled)
writeBlockingMutationResponse(c, http.StatusOK, row, err, forbiddenWordBlockingDTO)
})
r.DELETE("/blocking/words/:id", func(c *gin.Context) {
id, ok := parseBlockingID(c)
if !ok {
return
}
writeBlockingDeleteResponse(c, store.DeleteForbiddenWordBlocking(id))
})
}
func parseBlockingID(c *gin.Context) (uint64, bool) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil || id == 0 {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid blocking rule id"})
return 0, false
}
return id, true
}
func writeBlockingMutationResponse[T any](c *gin.Context, status int, row *T, err error, convert func(T) gin.H) {
if errors.Is(err, errBlockingAlreadyExists) {
c.JSON(http.StatusConflict, gin.H{"error": "blocking rule already exists"})
return
}
if errors.Is(err, gorm.ErrRecordNotFound) {
c.JSON(http.StatusNotFound, gin.H{"error": "blocking rule not found"})
return
}
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(status, gin.H{"item": convert(*row)})
}
func writeBlockingDeleteResponse(c *gin.Context, err error) {
if errors.Is(err, gorm.ErrRecordNotFound) {
c.JSON(http.StatusNotFound, gin.H{"error": "blocking rule not found"})
return
}
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"status": "ok"})
}
func nodeBlockingDTO(row nodeBlockingRecord) gin.H {
return gin.H{"id": row.ID, "node_id": row.NodeID, "node_num": ptrInt64(row.NodeNum), "reason": row.Reason, "enabled": row.Enabled, "created_at": row.CreatedAt, "updated_at": row.UpdatedAt}
}
func ipBlockingDTO(row ipBlockingRecord) gin.H {
return gin.H{"id": row.ID, "ip_value": row.IPValue, "reason": row.Reason, "enabled": row.Enabled, "created_at": row.CreatedAt, "updated_at": row.UpdatedAt}
}
func forbiddenWordBlockingDTO(row forbiddenWordBlockingRecord) gin.H {
return gin.H{"id": row.ID, "word": row.Word, "match_type": row.MatchType, "case_sensitive": row.CaseSensitive, "reason": row.Reason, "enabled": row.Enabled, "created_at": row.CreatedAt, "updated_at": row.UpdatedAt}
}