完善uniapp
This commit is contained in:
@@ -2,11 +2,13 @@ package middleware
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"server/models"
|
||||
"server/pkg/jwtutil"
|
||||
|
||||
"github.com/beego/beego/v2/server/web/context"
|
||||
)
|
||||
@@ -23,12 +25,96 @@ func BeginOperationLog(ctx *context.Context) {
|
||||
if shouldSkipLogging(method, url) {
|
||||
return
|
||||
}
|
||||
ctx.Input.SetData(oplogStartKey, time.Now())
|
||||
fmt.Printf("[oplog-begin] method=%s url=%s\n", method, url)
|
||||
|
||||
// 请求体由 main.go 的 CopyBody 保留在 Input.RequestBody
|
||||
// 解析用户信息(直接从 header 解析,不依赖 JWT 中间件设置的 context)
|
||||
var uid uint64
|
||||
var tid *uint64
|
||||
if auth := ctx.Request.Header.Get("Authorization"); auth != "" {
|
||||
parts := strings.SplitN(auth, " ", 2)
|
||||
if len(parts) == 2 && parts[0] == "Bearer" {
|
||||
if claims, err := jwtutil.ParseToken(parts[1]); err == nil {
|
||||
uid = uint64(claims.UserID)
|
||||
if claims.TenantId > 0 {
|
||||
tidVal := uint64(claims.TenantId)
|
||||
tid = &tidVal
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 采集请求信息
|
||||
reqBody := ""
|
||||
if rb := ctx.Input.RequestBody; len(rb) > 0 {
|
||||
s := string(rb)
|
||||
ctx.Input.SetData(oplogReqBodyKey, truncateString(maskSensitive(s), 5000))
|
||||
reqBody = truncateString(maskSensitive(string(rb)), 5000)
|
||||
} else if q := strings.TrimSpace(ctx.Request.URL.RawQuery); q != "" {
|
||||
reqBody = truncateString(maskSensitive(q), 5000)
|
||||
}
|
||||
|
||||
module := parseModule(url)
|
||||
action := parseAction(method, url)
|
||||
ip := truncateString(ctx.Input.IP(), 50)
|
||||
userAgent := truncateString(ctx.Request.Header.Get("User-Agent"), 500)
|
||||
|
||||
// 异步写入数据库
|
||||
go func() {
|
||||
time.Sleep(100 * time.Millisecond) // 等待响应完成
|
||||
logRow := &models.SystemOperationLog{
|
||||
Tid: tid,
|
||||
UserID: uid,
|
||||
Module: module,
|
||||
Action: action,
|
||||
Method: method,
|
||||
URL: truncateString(url, 255),
|
||||
IP: ip,
|
||||
UserAgent: userAgent,
|
||||
RequestData: strPtr(reqBody),
|
||||
Status: 1,
|
||||
ExecutionTime: 0,
|
||||
}
|
||||
_, err := models.Orm.Insert(logRow)
|
||||
if err != nil {
|
||||
fmt.Printf("[oplog] INSERT ERROR: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf("[oplog] INSERTED uid=%d module=%s action=%s\n", uid, module, action)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func strPtr(s string) *string {
|
||||
if s == "" {
|
||||
return nil
|
||||
}
|
||||
return &s
|
||||
}
|
||||
|
||||
// WriteDeleteLog 控制器删除后直接写操作日志(带标题)
|
||||
func WriteDeleteLog(userID uint64, tid int, module, title string) {
|
||||
moduleCN := oplogModuleLabel(module)
|
||||
desc := fmt.Sprintf("您删除了%s:【%s】", moduleCN, truncateString(title, 20))
|
||||
tidVal := uint64(tid)
|
||||
logRow := &models.SystemOperationLog{
|
||||
UserID: userID,
|
||||
Tid: &tidVal,
|
||||
Module: module,
|
||||
Action: "删除",
|
||||
Method: "DELETE",
|
||||
URL: fmt.Sprintf("/app/%s", module),
|
||||
Status: 1,
|
||||
RequestData: &desc,
|
||||
ExecutionTime: 0,
|
||||
}
|
||||
models.Orm.Insert(logRow)
|
||||
}
|
||||
|
||||
func oplogModuleLabel(m string) string {
|
||||
switch m {
|
||||
case "notebook":
|
||||
return "记事本"
|
||||
case "schedule":
|
||||
return "日程提醒"
|
||||
default:
|
||||
return m
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +122,9 @@ func BeginOperationLog(ctx *context.Context) {
|
||||
func FinishOperationLog(ctx *context.Context) {
|
||||
url := ctx.Input.URL()
|
||||
method := ctx.Input.Method()
|
||||
fmt.Printf("[oplog-finish] method=%s url=%s\n", method, url)
|
||||
if shouldSkipLogging(method, url) {
|
||||
fmt.Printf("[oplog-finish] SKIPPED\n")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -48,6 +136,22 @@ func FinishOperationLog(ctx *context.Context) {
|
||||
|
||||
uid := parseUint64FromCtx(ctx.Input.GetData("userId"))
|
||||
tidVal := parseUint64FromCtx(ctx.Input.GetData("tenantId"))
|
||||
|
||||
// 如果 context 中没有用户信息,尝试从 Authorization header 解析
|
||||
if uid == 0 {
|
||||
if auth := ctx.Request.Header.Get("Authorization"); auth != "" {
|
||||
parts := strings.SplitN(auth, " ", 2)
|
||||
if len(parts) == 2 && parts[0] == "Bearer" {
|
||||
if claims, err := jwtutil.ParseToken(parts[1]); err == nil {
|
||||
uid = uint64(claims.UserID)
|
||||
if claims.TenantId > 0 {
|
||||
tidVal = uint64(claims.TenantId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var tid *uint64
|
||||
if tidVal > 0 {
|
||||
tid = &tidVal
|
||||
@@ -100,7 +204,11 @@ func FinishOperationLog(ctx *context.Context) {
|
||||
ErrorMessage: errMsg,
|
||||
ExecutionTime: execSec,
|
||||
}
|
||||
_, _ = models.Orm.Insert(logRow)
|
||||
fmt.Printf("[oplog] method=%s url=%s uid=%d tid=%v module=%s action=%s\n", method, url, uid, tid, module, action)
|
||||
_, err := models.Orm.Insert(logRow)
|
||||
if err != nil {
|
||||
fmt.Printf("[oplog] INSERT ERROR: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func parseAction(method, url string) string {
|
||||
@@ -183,6 +291,14 @@ func shouldSkipLogging(method, url string) bool {
|
||||
if strings.HasPrefix(url, "/api/softwareupgrade/check") {
|
||||
return true
|
||||
}
|
||||
// App 端读接口跳过(只记录写操作:POST/PUT/DELETE)
|
||||
if strings.HasPrefix(url, "/app/") && method == "GET" {
|
||||
return true
|
||||
}
|
||||
// App 端 DELETE 由控制器自行记录(需要标题信息)
|
||||
if strings.HasPrefix(url, "/app/") && method == "DELETE" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user