package middleware import ( "bytes" "encoding/json" "net/http" "strings" "time" "github.com/gin-gonic/gin" "eai_agentplatform/backend/internal/auth" "eai_agentplatform/backend/internal/config" "eai_agentplatform/backend/internal/model" "eai_agentplatform/backend/internal/store" "eai_agentplatform/backend/internal/web" ) // Auth 解析 JWT → 校验用户 → 注入 current_user func Auth(cfg *config.Config) gin.HandlerFunc { return func(c *gin.Context) { tokenStr := extractBearer(c) if tokenStr == "" { web.Fail(c, web.NewAuthError("缺少 Authorization Bearer 令牌")) c.Abort() return } claims, err := auth.ParseToken(tokenStr, cfg.JWTSecret) if err != nil { web.Fail(c, web.NewAuthError("令牌无效或已过期")) c.Abort() return } username, _ := claims["sub"].(string) if username == "" { web.Fail(c, web.NewAuthError("令牌中缺少用户标识")) c.Abort() return } var user model.User if err := store.DB.Where("username = ?", username).First(&user).Error; err != nil { web.Fail(c, web.NewAuthError("用户不存在")) c.Abort() return } if user.Status != "active" { web.Fail(c, web.NewAuthError("账号已禁用")) c.Abort() return } c.Set("current_user", &user) // #region debug-point C:auth-success go func(path, method, username, role string, userID uint) { _, _ = http.Post("http://127.0.0.1:7777/event", "application/json", bytes.NewBuffer(mustJSON(map[string]any{"sessionId": "admin-auth-misjudge", "runId": "pre-fix", "hypothesisId": "C", "location": "internal/middleware/auth.go:Auth", "msg": "[DEBUG] auth accepted request", "data": map[string]any{"path": path, "method": method, "username": username, "role": role, "user_id": userID, "token_present": true}, "ts": time.Now().UnixMilli()}))) }(c.Request.URL.Path, c.Request.Method, user.Username, user.Role, user.ID) // #endregion c.Next() } } // RequireAdmin 管理员角色守卫(须在 Auth 之后) func RequireAdmin() gin.HandlerFunc { return func(c *gin.Context) { u := CurrentUser(c) if u == nil || u.Role != "admin" { // #region debug-point D:require-admin-reject go func(path, method string, u *model.User) { payload := map[string]any{"sessionId": "admin-auth-misjudge", "runId": "pre-fix", "hypothesisId": "D", "location": "internal/middleware/auth.go:RequireAdmin", "msg": "[DEBUG] require admin rejected request", "data": map[string]any{"path": path, "method": method, "user_nil": u == nil}, "ts": time.Now().UnixMilli()}; if u != nil { payload["data"] = map[string]any{"path": path, "method": method, "user_nil": false, "username": u.Username, "role": u.Role, "user_id": u.ID} }; _, _ = http.Post("http://127.0.0.1:7777/event", "application/json", bytes.NewBuffer(mustJSON(payload))) }(c.Request.URL.Path, c.Request.Method, u) // #endregion web.Fail(c, web.NewForbiddenError("需要管理员权限")) c.Abort() return } c.Next() } } // CurrentUser 从 context 取当前用户(可能为 nil) func CurrentUser(c *gin.Context) *model.User { if v, ok := c.Get("current_user"); ok { if u, ok := v.(*model.User); ok { return u } } return nil } func extractBearer(c *gin.Context) string { h := c.GetHeader("Authorization") if strings.HasPrefix(h, "Bearer ") { return strings.TrimSpace(h[len("Bearer "):]) } return "" } func mustJSON(v any) []byte { b, err := json.Marshal(v) if err != nil { return []byte(`{"sessionId":"admin-auth-misjudge","runId":"pre-fix","hypothesisId":"D","location":"internal/middleware/auth.go:mustJSON","msg":"[DEBUG] marshal failed","ts":0}`) } return b }