This commit is contained in:
2026-07-21 15:53:31 +08:00
32 changed files with 1724 additions and 81 deletions

View File

@@ -0,0 +1,223 @@
package handlers
import (
"strconv"
"strings"
"hyapi-server/internal/application/user"
"hyapi-server/internal/application/user/dto/commands"
"hyapi-server/internal/application/user/dto/queries"
securityServices "hyapi-server/internal/domains/security/services"
"hyapi-server/internal/shared/interfaces"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
// AdminBlacklistHandler 管理端黑名单
type AdminBlacklistHandler struct {
userApp user.UserApplicationService
blacklist *securityServices.BlacklistService
response interfaces.ResponseBuilder
logger *zap.Logger
}
func NewAdminBlacklistHandler(
userApp user.UserApplicationService,
blacklist *securityServices.BlacklistService,
response interfaces.ResponseBuilder,
logger *zap.Logger,
) *AdminBlacklistHandler {
return &AdminBlacklistHandler{
userApp: userApp,
blacklist: blacklist,
response: response,
logger: logger,
}
}
func (h *AdminBlacklistHandler) operatorID(c *gin.Context) string {
if v, ok := c.Get("user_id"); ok {
if id, ok := v.(string); ok {
return id
}
}
return ""
}
func (h *AdminBlacklistHandler) pageParams(c *gin.Context) (int, int) {
page, pageSize := 1, 20
if v := c.Query("page"); v != "" {
if n, err := strconv.Atoi(v); err == nil && n > 0 {
page = n
}
}
if v := c.Query("page_size"); v != "" {
if n, err := strconv.Atoi(v); err == nil && n > 0 && n <= 100 {
pageSize = n
}
}
return page, pageSize
}
// ListUsers 用户黑名单列表
func (h *AdminBlacklistHandler) ListUsers(c *gin.Context) {
page, pageSize := h.pageParams(c)
flag := true
q := &queries.ListUsersQuery{
Page: page,
PageSize: pageSize,
Phone: c.Query("phone"),
IsBlacklisted: &flag,
}
resp, err := h.userApp.ListUsers(c.Request.Context(), q)
if err != nil {
h.logger.Error("查询用户黑名单失败", zap.Error(err))
h.response.BadRequest(c, "查询失败")
return
}
h.response.Success(c, resp, "ok")
}
// AddUser 按手机号或用户ID加入黑名单
func (h *AdminBlacklistHandler) AddUser(c *gin.Context) {
op := h.operatorID(c)
if op == "" {
h.response.Unauthorized(c, "未登录")
return
}
var body struct {
UserID string `json:"user_id"`
Phone string `json:"phone"`
Reason string `json:"reason" binding:"required"`
Source string `json:"source"`
}
if err := c.ShouldBindJSON(&body); err != nil {
h.response.BadRequest(c, "请填写纳入原因")
return
}
userID := strings.TrimSpace(body.UserID)
if userID == "" {
phone := strings.TrimSpace(body.Phone)
if phone == "" {
h.response.BadRequest(c, "请提供用户ID或手机号")
return
}
list, err := h.userApp.ListUsers(c.Request.Context(), &queries.ListUsersQuery{
Page: 1,
PageSize: 50,
Phone: phone,
})
if err != nil || list == nil || len(list.Items) == 0 {
h.response.BadRequest(c, "未找到该手机号用户")
return
}
for _, item := range list.Items {
if item.Phone == phone {
userID = item.ID
break
}
}
if userID == "" {
userID = list.Items[0].ID
}
}
cmd := &commands.BlacklistUserCommand{
UserID: userID,
OperatorUserID: op,
Reason: body.Reason,
Source: body.Source,
}
if err := h.userApp.BlacklistUser(c.Request.Context(), cmd); err != nil {
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, gin.H{"user_id": userID}, "已列入用户黑名单")
}
// RemoveUser 移出用户黑名单
func (h *AdminBlacklistHandler) RemoveUser(c *gin.Context) {
op := h.operatorID(c)
userID := c.Param("user_id")
if userID == "" {
h.response.BadRequest(c, "用户ID不能为空")
return
}
if err := h.userApp.UnblacklistUser(c.Request.Context(), &commands.UnblacklistUserCommand{
UserID: userID,
OperatorUserID: op,
}); err != nil {
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, nil, "已移出用户黑名单")
}
// ListIPs IP 黑名单
func (h *AdminBlacklistHandler) ListIPs(c *gin.Context) {
page, pageSize := h.pageParams(c)
list, total, err := h.blacklist.ListIP(c.Request.Context(), page, pageSize, c.Query("keyword"))
if err != nil {
h.response.BadRequest(c, "查询失败")
return
}
h.response.Success(c, gin.H{
"items": list,
"total": total,
"page": page,
"size": pageSize,
}, "ok")
}
// AddIP 添加 IP 黑名单
func (h *AdminBlacklistHandler) AddIP(c *gin.Context) {
op := h.operatorID(c)
var body struct {
IP string `json:"ip" binding:"required"`
Reason string `json:"reason" binding:"required"`
Source string `json:"source"`
}
if err := c.ShouldBindJSON(&body); err != nil {
h.response.BadRequest(c, "请填写IP和原因")
return
}
entry, err := h.blacklist.AddIP(c.Request.Context(), body.IP, body.Reason, body.Source, op)
if err != nil {
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, entry, "已加入IP黑名单")
}
// RemoveIP 移除 IP 黑名单
func (h *AdminBlacklistHandler) RemoveIP(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 64)
if err != nil {
h.response.BadRequest(c, "无效ID")
return
}
if err := h.blacklist.RemoveIP(c.Request.Context(), id); err != nil {
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, nil, "已移除IP黑名单")
}
// ListHits 拦截记录
func (h *AdminBlacklistHandler) ListHits(c *gin.Context) {
page, pageSize := h.pageParams(c)
list, total, err := h.blacklist.ListHits(c.Request.Context(), page, pageSize, c.Query("hit_type"), c.Query("keyword"))
if err != nil {
h.response.BadRequest(c, "查询失败")
return
}
h.response.Success(c, gin.H{
"items": list,
"total": total,
"page": page,
"size": pageSize,
}, "ok")
}

View File

@@ -445,6 +445,12 @@ func (h *UserHandler) ListUsers(c *gin.Context) {
}
}
if isBlacklisted := c.Query("is_blacklisted"); isBlacklisted != "" {
if blacklisted, err := strconv.ParseBool(isBlacklisted); err == nil {
query.IsBlacklisted = &blacklisted
}
}
// 调用应用服务
resp, err := h.appService.ListUsers(c.Request.Context(), query)
if err != nil {
@@ -520,6 +526,71 @@ func (h *UserHandler) GetUserStats(c *gin.Context) {
h.response.Success(c, resp, "获取用户统计信息成功")
}
// BlacklistUser 管理员将用户列入黑名单
func (h *UserHandler) BlacklistUser(c *gin.Context) {
operatorID := h.getCurrentUserID(c)
if operatorID == "" {
h.response.Unauthorized(c, "用户未登录")
return
}
targetUserID := c.Param("user_id")
if targetUserID == "" {
h.response.BadRequest(c, "用户ID不能为空")
return
}
var body struct {
Reason string `json:"reason" binding:"required"`
Source string `json:"source"`
}
if err := c.ShouldBindJSON(&body); err != nil {
h.response.BadRequest(c, "请填写纳入原因")
return
}
cmd := &commands.BlacklistUserCommand{
UserID: targetUserID,
OperatorUserID: operatorID,
Reason: body.Reason,
Source: body.Source,
}
if err := h.appService.BlacklistUser(c.Request.Context(), cmd); err != nil {
h.logger.Error("列入黑名单失败", zap.Error(err), zap.String("user_id", targetUserID))
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, nil, "已列入黑名单")
}
// UnblacklistUser 管理员将用户移出黑名单
func (h *UserHandler) UnblacklistUser(c *gin.Context) {
operatorID := h.getCurrentUserID(c)
if operatorID == "" {
h.response.Unauthorized(c, "用户未登录")
return
}
targetUserID := c.Param("user_id")
if targetUserID == "" {
h.response.BadRequest(c, "用户ID不能为空")
return
}
cmd := &commands.UnblacklistUserCommand{
UserID: targetUserID,
OperatorUserID: operatorID,
}
if err := h.appService.UnblacklistUser(c.Request.Context(), cmd); err != nil {
h.logger.Error("移出黑名单失败", zap.Error(err), zap.String("user_id", targetUserID))
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, nil, "已移出黑名单")
}
// getCurrentUserID 获取当前用户ID
func (h *UserHandler) getCurrentUserID(c *gin.Context) string {
if userID, exists := c.Get("user_id"); exists {