Files
eaiadminandClaude Code 16d63de4e1 chore: 工作台产品化进行中的改动
把工作区里其余在制品一并入库,主要是工作台产品化的推进:

  后端:新增 capability_definition / project / my_app_center / office_skill
        接口与 action_definition / skill_definition / project / user_app_center
        模型,config 加路由健康上报。
  前端:新增 frontend/src/skills(Office 技能与 workbuddy 复刻)、
        项目管理、应用中心、能力目录页,以及配套 api / store / config;
        聊天侧新增 SpecialistChip / SpecialistPanel / SkillStrip / AppChatRail
        等组件。
  清理:移除旧 views/tools 下的单页工具(已并入工作台)、_frozen 冻结组件、
        cmd/inspect_oa_debug 调试入口,以及两份调试笔记。
  其它:文档与启动脚本同步。

(这批改动与上一提交的 SY23 工作并行进行,此前已在同一工作区内交织。)

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-17 21:32:35 +08:00

86 lines
1.9 KiB
Go

package middleware
import (
"strings"
"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)
c.Next()
}
}
// RequireAdmin 管理员角色守卫(须在 Auth 之后)
func RequireAdmin() gin.HandlerFunc {
return func(c *gin.Context) {
u := CurrentUser(c)
if u == nil || u.Role != "admin" {
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 ""
}