feat: 添加日志管理和敏感词过滤功能
- 新增日志管理模块:操作日志、登录日志、数据变更日志 - 新增敏感词过滤器 (sanitizer) - 新增日志异步写入管理器 - 新增日志定时清理服务 - 优化帖子相关服务和上传服务
This commit is contained in:
215
internal/handler/admin_log_handler.go
Normal file
215
internal/handler/admin_log_handler.go
Normal file
@@ -0,0 +1,215 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"carrot_bbs/internal/pkg/response"
|
||||
"carrot_bbs/internal/repository"
|
||||
"carrot_bbs/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// AdminLogHandler 管理后台日志处理器
|
||||
type AdminLogHandler struct {
|
||||
operationLogService service.OperationLogService
|
||||
loginLogService service.LoginLogService
|
||||
dataChangeLogService service.DataChangeLogService
|
||||
}
|
||||
|
||||
// NewAdminLogHandler 创建管理后台日志处理器
|
||||
func NewAdminLogHandler(
|
||||
operationLogService service.OperationLogService,
|
||||
loginLogService service.LoginLogService,
|
||||
dataChangeLogService service.DataChangeLogService,
|
||||
) *AdminLogHandler {
|
||||
return &AdminLogHandler{
|
||||
operationLogService: operationLogService,
|
||||
loginLogService: loginLogService,
|
||||
dataChangeLogService: dataChangeLogService,
|
||||
}
|
||||
}
|
||||
|
||||
// GetOperationLogs 获取操作日志列表
|
||||
// GET /api/v1/admin/logs/operations
|
||||
func (h *AdminLogHandler) GetOperationLogs(c *gin.Context) {
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
||||
|
||||
filters := repository.LogFilter{
|
||||
UserID: c.Query("user_id"),
|
||||
Operation: c.Query("operation"),
|
||||
TargetType: c.Query("target_type"),
|
||||
TargetID: c.Query("target_id"),
|
||||
Status: c.Query("status"),
|
||||
IP: c.Query("ip"),
|
||||
StartTime: c.Query("start_time"),
|
||||
EndTime: c.Query("end_time"),
|
||||
}
|
||||
|
||||
logs, total, err := h.operationLogService.GetOperationLogs(c.Request.Context(), filters, page, pageSize)
|
||||
if err != nil {
|
||||
response.HandleError(c, err, "failed to get operation logs")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{
|
||||
"logs": logs,
|
||||
"pagination": gin.H{
|
||||
"page": page,
|
||||
"page_size": pageSize,
|
||||
"total": total,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// GetLoginLogs 获取登录日志列表
|
||||
// GET /api/v1/admin/logs/logins
|
||||
func (h *AdminLogHandler) GetLoginLogs(c *gin.Context) {
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
||||
|
||||
filters := repository.LoginFilter{
|
||||
UserID: c.Query("user_id"),
|
||||
Event: c.Query("event"),
|
||||
Result: c.Query("result"),
|
||||
FailReason: c.Query("fail_reason"),
|
||||
LoginType: c.Query("login_type"),
|
||||
IP: c.Query("ip"),
|
||||
}
|
||||
|
||||
if startTime := c.Query("start_time"); startTime != "" {
|
||||
if t, err := time.Parse(time.RFC3339, startTime); err == nil {
|
||||
filters.StartTime = t
|
||||
}
|
||||
}
|
||||
|
||||
if endTime := c.Query("end_time"); endTime != "" {
|
||||
if t, err := time.Parse(time.RFC3339, endTime); err == nil {
|
||||
filters.EndTime = t
|
||||
}
|
||||
}
|
||||
|
||||
logs, total, err := h.loginLogService.GetLoginLogs(c.Request.Context(), filters, page, pageSize)
|
||||
if err != nil {
|
||||
response.HandleError(c, err, "failed to get login logs")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{
|
||||
"logs": logs,
|
||||
"pagination": gin.H{
|
||||
"page": page,
|
||||
"page_size": pageSize,
|
||||
"total": total,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// GetDataChangeLogs 获取数据变更日志列表
|
||||
// GET /api/v1/admin/logs/data-changes
|
||||
func (h *AdminLogHandler) GetDataChangeLogs(c *gin.Context) {
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
||||
|
||||
filters := repository.DataChangeFilter{
|
||||
UserID: c.Query("user_id"),
|
||||
OperatorID: c.Query("operator_id"),
|
||||
ChangeType: c.Query("change_type"),
|
||||
TargetType: c.Query("target_type"),
|
||||
OperatorType: c.Query("operator_type"),
|
||||
IP: c.Query("ip"),
|
||||
StartTime: c.Query("start_time"),
|
||||
EndTime: c.Query("end_time"),
|
||||
}
|
||||
|
||||
logs, total, err := h.dataChangeLogService.GetDataChangeLogs(c.Request.Context(), filters, page, pageSize)
|
||||
if err != nil {
|
||||
response.HandleError(c, err, "failed to get data change logs")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{
|
||||
"logs": logs,
|
||||
"pagination": gin.H{
|
||||
"page": page,
|
||||
"page_size": pageSize,
|
||||
"total": total,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// GetLogStatistics 获取日志统计
|
||||
// GET /api/v1/admin/logs/statistics
|
||||
func (h *AdminLogHandler) GetLogStatistics(c *gin.Context) {
|
||||
startTime := c.DefaultQuery("start_time", "")
|
||||
endTime := c.DefaultQuery("end_time", "")
|
||||
|
||||
operationStats, err := h.operationLogService.GetStatistics(c.Request.Context(), startTime, endTime)
|
||||
if err != nil {
|
||||
response.HandleError(c, err, "failed to get operation log statistics")
|
||||
return
|
||||
}
|
||||
|
||||
loginStats, err := h.loginLogService.GetStatistics(c.Request.Context(), startTime, endTime)
|
||||
if err != nil {
|
||||
response.HandleError(c, err, "failed to get login log statistics")
|
||||
return
|
||||
}
|
||||
|
||||
dataChangeStats, err := h.dataChangeLogService.GetStatistics(c.Request.Context(), startTime, endTime)
|
||||
if err != nil {
|
||||
response.HandleError(c, err, "failed to get data change log statistics")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{
|
||||
"operation_logs": operationStats,
|
||||
"login_logs": loginStats,
|
||||
"data_change_logs": dataChangeStats,
|
||||
})
|
||||
}
|
||||
|
||||
// ExportLogs 导出日志
|
||||
// GET /api/v1/admin/logs/export
|
||||
func (h *AdminLogHandler) ExportLogs(c *gin.Context) {
|
||||
logType := c.Query("type")
|
||||
startTime := c.Query("start_time")
|
||||
endTime := c.Query("end_time")
|
||||
|
||||
switch logType {
|
||||
case "operation":
|
||||
logs, _, err := h.operationLogService.GetOperationLogsByTimeRange(c.Request.Context(), startTime, endTime, 1, 10000)
|
||||
if err != nil {
|
||||
response.HandleError(c, err, "failed to export operation logs")
|
||||
return
|
||||
}
|
||||
response.Success(c, gin.H{
|
||||
"type": "operation",
|
||||
"logs": logs,
|
||||
})
|
||||
case "login":
|
||||
logs, _, err := h.loginLogService.GetLoginLogs(c.Request.Context(), repository.LoginFilter{}, 1, 10000)
|
||||
if err != nil {
|
||||
response.HandleError(c, err, "failed to export login logs")
|
||||
return
|
||||
}
|
||||
response.Success(c, gin.H{
|
||||
"type": "login",
|
||||
"log": logs,
|
||||
})
|
||||
case "data_change":
|
||||
logs, _, err := h.dataChangeLogService.GetDataChangeLogs(c.Request.Context(), repository.DataChangeFilter{}, 1, 10000)
|
||||
if err != nil {
|
||||
response.HandleError(c, err, "failed to export data change logs")
|
||||
return
|
||||
}
|
||||
response.Success(c, gin.H{
|
||||
"type": "data_change",
|
||||
"log": logs,
|
||||
})
|
||||
default:
|
||||
response.Error(c, 400, "invalid log type")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user