issue_20 #24
@@ -3,7 +3,7 @@ package controller
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/middleware"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@@ -55,9 +55,9 @@ func SendErrorResponse(ctx *gin.Context, code ResponseCode, message string) {
|
||||
func setAuditDetails(c *gin.Context, actionType, description string, targetResource interface{}) {
|
||||
// 只有当 actionType 不为空时,才设置审计信息,这作为触发审计的标志
|
||||
if actionType != "" {
|
||||
c.Set(middleware.ContextAuditActionType, actionType)
|
||||
c.Set(middleware.ContextAuditDescription, description)
|
||||
c.Set(middleware.ContextAuditTargetResource, targetResource)
|
||||
c.Set(repository.ContextAuditActionType, actionType)
|
||||
c.Set(repository.ContextAuditDescription, description)
|
||||
c.Set(repository.ContextAuditTargetResource, targetResource)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Package middleware 存放 gin 中间件
|
||||
package middleware
|
||||
|
||||
import (
|
||||
@@ -8,15 +7,14 @@ import (
|
||||
"strconv"
|
||||
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/service/audit"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// --- 审计日志相关上下文键 ---
|
||||
const (
|
||||
ContextAuditActionType = "auditActionType"
|
||||
ContextAuditTargetResource = "auditTargetResource"
|
||||
ContextAuditDescription = "auditDescription"
|
||||
)
|
||||
type auditResponse struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// AuditLogMiddleware 创建一个Gin中间件,用于在请求结束后记录用户操作审计日志
|
||||
func AuditLogMiddleware(auditService audit.Service) gin.HandlerFunc {
|
||||
@@ -31,30 +29,36 @@ func AuditLogMiddleware(auditService audit.Service) gin.HandlerFunc {
|
||||
// --- 在这里,请求已经处理完毕 ---
|
||||
|
||||
// 从上下文中尝试获取由控制器设置的业务审计信息
|
||||
actionType, exists := c.Get(ContextAuditActionType)
|
||||
actionType, exists := c.Get(repository.ContextAuditActionType)
|
||||
if !exists {
|
||||
// 如果上下文中没有 actionType,说明此接口无需记录审计日志,直接返回
|
||||
return
|
||||
}
|
||||
|
||||
// 获取其他审计信息
|
||||
description, _ := c.Get(ContextAuditDescription)
|
||||
targetResource, _ := c.Get(ContextAuditTargetResource)
|
||||
description, _ := c.Get(repository.ContextAuditDescription)
|
||||
targetResource, _ := c.Get(repository.ContextAuditTargetResource)
|
||||
|
||||
// 判断操作状态
|
||||
status := "success"
|
||||
// 默认操作状态为成功
|
||||
status := repository.AuditStatusSuccess
|
||||
resultDetails := ""
|
||||
if c.Writer.Status() >= 400 {
|
||||
status = "failed"
|
||||
// 尝试从捕获的响应体中解析错误信息
|
||||
var errResp struct {
|
||||
Error string `json:"error"`
|
||||
|
||||
// 尝试从捕获的响应体中解析平台响应
|
||||
var platformResponse auditResponse
|
||||
if err := json.Unmarshal(blw.body.Bytes(), &platformResponse); err == nil {
|
||||
// 如果解析成功,根据平台状态码判断操作是否失败
|
||||
// 成功状态码范围是 2000-2999
|
||||
if platformResponse.Code < 2000 || platformResponse.Code >= 3000 {
|
||||
status = repository.AuditStatusFailed
|
||||
resultDetails = platformResponse.Message
|
||||
}
|
||||
if err := json.Unmarshal(blw.body.Bytes(), &errResp); err == nil {
|
||||
resultDetails = errResp.Error
|
||||
} else {
|
||||
resultDetails = "HTTP Status: " + strconv.Itoa(c.Writer.Status())
|
||||
} else {
|
||||
// 如果响应体不是预期的平台响应格式,或者解析失败,则记录原始HTTP状态码作为详情
|
||||
// 并且如果HTTP状态码不是2xx,则标记为失败
|
||||
if c.Writer.Status() < 200 || c.Writer.Status() >= 300 {
|
||||
status = repository.AuditStatusFailed
|
||||
}
|
||||
resultDetails = "HTTP Status: " + strconv.Itoa(c.Writer.Status()) + ", Body Parse Error: " + err.Error()
|
||||
}
|
||||
|
||||
// 调用审计服务记录日志(异步)
|
||||
|
||||
@@ -6,6 +6,19 @@ import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// --- 审计日志状态常量 ---
|
||||
const (
|
||||
AuditStatusSuccess = "success"
|
||||
AuditStatusFailed = "failed"
|
||||
)
|
||||
|
||||
// --- 审计日志相关上下文键 ---
|
||||
const (
|
||||
ContextAuditActionType = "auditActionType"
|
||||
ContextAuditTargetResource = "auditTargetResource"
|
||||
ContextAuditDescription = "auditDescription"
|
||||
)
|
||||
|
||||
// UserActionLogRepository 定义了与用户操作日志相关的数据库操作接口
|
||||
type UserActionLogRepository interface {
|
||||
Create(log *models.UserActionLog) error
|
||||
|
||||
Reference in New Issue
Block a user