feat: 新增语音转文字(ASR)功能
- 后端:新增 /api/audio/transcribe 接口,调用 Ollama whisper 进行语音识别 - 前端:新增 AudioTranscribePage.vue 页面,支持 MP3/WAV/M4A/OGG/FLAC 等格式 - 注册路由、工具卡片、智能助手欢迎语更新 Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user