| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- package admin
- import (
- "errors"
- "strconv"
- "github.com/Wei-Shaw/sub2api/internal/handler/dto"
- "github.com/Wei-Shaw/sub2api/internal/pkg/response"
- "github.com/Wei-Shaw/sub2api/internal/service"
- "github.com/gin-gonic/gin"
- )
- // SecurityPolicyHandler 管理安全策略自定义词与会话解封。
- // 分组开关本身走分组管理接口(PUT /admin/groups/:id)。
- type SecurityPolicyHandler struct {
- service *service.SecurityPolicyService
- }
- func NewSecurityPolicyHandler(svc *service.SecurityPolicyService) *SecurityPolicyHandler {
- return &SecurityPolicyHandler{service: svc}
- }
- func (h *SecurityPolicyHandler) requireService(c *gin.Context) bool {
- if h == nil || h.service == nil {
- response.ErrorFrom(c, errors.New("security policy service unavailable"))
- return false
- }
- return true
- }
- // ListBuiltin 返回内置 seed 词包(只读,供管理端审计/调优参考)。
- func (h *SecurityPolicyHandler) ListBuiltin(c *gin.Context) {
- if !h.requireService(c) {
- return
- }
- seeds := h.service.GetBuiltinKeywords()
- out := make([]dto.SecurityPolicyKeywordSeed, 0, len(seeds))
- for _, seed := range seeds {
- out = append(out, dto.SecurityPolicyKeywordSeedFromService(seed))
- }
- response.Success(c, gin.H{"keywords": out, "count": len(out)})
- }
- // ListKeywords 查询自定义词:?group_id=(缺省全部,0 仅全局)&include_disabled=true。
- func (h *SecurityPolicyHandler) ListKeywords(c *gin.Context) {
- if !h.requireService(c) {
- return
- }
- var groupID *int64
- if raw := c.Query("group_id"); raw != "" {
- id, err := strconv.ParseInt(raw, 10, 64)
- if err != nil || id < 0 {
- response.BadRequest(c, "Invalid group_id")
- return
- }
- groupID = &id
- }
- includeDisabled := c.Query("include_disabled") == "true"
- words, err := h.service.ListKeywords(c.Request.Context(), groupID, includeDisabled)
- if err != nil {
- response.ErrorFrom(c, err)
- return
- }
- response.Success(c, gin.H{"keywords": dto.SecurityPolicyKeywordsFromService(words)})
- }
- type securityPolicyKeywordCreateRequest struct {
- GroupID *int64 `json:"group_id"`
- Keyword string `json:"keyword"`
- Category string `json:"category"`
- }
- // CreateKeyword 新建自定义词(group_id 缺省/0 为全局词)。
- func (h *SecurityPolicyHandler) CreateKeyword(c *gin.Context) {
- if !h.requireService(c) {
- return
- }
- var req securityPolicyKeywordCreateRequest
- if err := c.ShouldBindJSON(&req); err != nil {
- response.BadRequest(c, "Invalid request: "+err.Error())
- return
- }
- if req.GroupID != nil && *req.GroupID <= 0 {
- req.GroupID = nil
- }
- word, err := h.service.CreateKeyword(c.Request.Context(), service.SecurityPolicyKeywordInput{
- GroupID: req.GroupID,
- Keyword: req.Keyword,
- Category: req.Category,
- })
- if err != nil {
- response.ErrorFrom(c, err)
- return
- }
- response.Success(c, dto.SecurityPolicyKeywordFromService(word))
- }
- type securityPolicyKeywordUpdateRequest struct {
- Keyword *string `json:"keyword"`
- Category *string `json:"category"`
- Enabled *bool `json:"enabled"`
- }
- // UpdateKeyword 更新自定义词(词/分类/启用)。
- func (h *SecurityPolicyHandler) UpdateKeyword(c *gin.Context) {
- if !h.requireService(c) {
- return
- }
- id, err := strconv.ParseInt(c.Param("id"), 10, 64)
- if err != nil || id <= 0 {
- response.BadRequest(c, "Invalid keyword ID")
- return
- }
- var req securityPolicyKeywordUpdateRequest
- if err := c.ShouldBindJSON(&req); err != nil {
- response.BadRequest(c, "Invalid request: "+err.Error())
- return
- }
- word, err := h.service.UpdateKeyword(c.Request.Context(), id, service.SecurityPolicyKeywordUpdate{
- Keyword: req.Keyword,
- Category: req.Category,
- Enabled: req.Enabled,
- })
- if err != nil {
- response.ErrorFrom(c, err)
- return
- }
- response.Success(c, dto.SecurityPolicyKeywordFromService(word))
- }
- // DeleteKeyword 软删除自定义词。
- func (h *SecurityPolicyHandler) DeleteKeyword(c *gin.Context) {
- if !h.requireService(c) {
- return
- }
- id, err := strconv.ParseInt(c.Param("id"), 10, 64)
- if err != nil || id <= 0 {
- response.BadRequest(c, "Invalid keyword ID")
- return
- }
- if err := h.service.DeleteKeyword(c.Request.Context(), id); err != nil {
- response.ErrorFrom(c, err)
- return
- }
- response.Success(c, gin.H{"message": "Keyword deleted successfully"})
- }
- type securityPolicyUnblockRequest struct {
- GroupID int64 `json:"group_id"`
- APIKeyID int64 `json:"api_key_id"`
- }
- // UnblockSession 清除指定分组+Key 的全部会话封禁(需新建会话的反向操作)。
- func (h *SecurityPolicyHandler) UnblockSession(c *gin.Context) {
- if !h.requireService(c) {
- return
- }
- var req securityPolicyUnblockRequest
- if err := c.ShouldBindJSON(&req); err != nil {
- response.BadRequest(c, "Invalid request: "+err.Error())
- return
- }
- if req.GroupID <= 0 || req.APIKeyID <= 0 {
- response.BadRequest(c, "group_id and api_key_id must be positive")
- return
- }
- unblocked, err := h.service.UnblockSessionScope(c.Request.Context(), req.GroupID, req.APIKeyID)
- if err != nil {
- response.ErrorFrom(c, err)
- return
- }
- response.Success(c, gin.H{"unblocked": unblocked})
- }
|