Files
pj0235-eai_agentplatform/eai_agentplatform/backend-go/internal/middleware/auth.go
T
eaiadminandClaude Code 0455f064ac feat: 新增语音转文字(ASR)功能
- 后端:新增 /api/audio/transcribe 接口,调用 Ollama whisper 进行语音识别
- 前端:新增 AudioTranscribePage.vue 页面,支持 MP3/WAV/M4A/OGG/FLAC 等格式
- 注册路由、工具卡片、智能助手欢迎语更新

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-14 00:53:36 +08:00

104 lines
3.5 KiB
Go

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
}