package permlib import ( "context" "net/http" ) // PermDecl 权限声明,用于静态注册(permgen 插件生成) type PermDecl struct { Code string Name string } // RoutePermDecl 路由-权限映射,用于静态注册 type RoutePermDecl struct { Method string Path string PermCode string DataCode string // 配对的 data 权限 code } // FieldNode 树形字段权限节点,支持任意深度嵌套 type FieldNode struct { Fields map[string]string // jsonName → permCode(当前层需过滤的字段) Nested map[string]*FieldNode // jsonName → 子节点(有嵌套结构的字段) } // FieldPermMap 字段权限映射,用于静态注册(替代反射) type FieldPermMap struct { Request *FieldNode Response *FieldNode } type Engine struct { cfg Config client *grpcClient cache *permCache staticPerms []PermDecl routePerms map[string]RoutePermDecl // "METHOD /path" → RoutePermDecl fieldPerms map[string]FieldPermMap // "METHOD /path" → FieldPermMap } type LoginResult struct { AccessToken string RefreshToken string Expires int64 UserId int64 Username string Nickname string MemberType string Perms []string } type RefreshTokenResult struct { AccessToken string RefreshToken string Expires int64 Perms []string } type UserPermsResult struct { Perms []string MemberType string } func New(cfg Config) (*Engine, error) { cfg.defaults() if err := cfg.validate(); err != nil { return nil, err } client, err := newGRPCClient(cfg.PermServerAddr) if err != nil { return nil, err } return &Engine{ cfg: cfg, client: client, cache: newPermCache(cfg.CacheTTL), routePerms: make(map[string]RoutePermDecl), fieldPerms: make(map[string]FieldPermMap), }, nil } // RegisterPerms 静态注册权限声明(由 permgen 插件生成的代码调用) func (e *Engine) RegisterPerms(perms []PermDecl) { e.staticPerms = append(e.staticPerms, perms...) } // RegisterRoutePerms 静态注册路由-权限映射(由 permgen 插件生成的代码调用) func (e *Engine) RegisterRoutePerms(decls []RoutePermDecl) { for _, d := range decls { key := d.Method + " " + d.Path e.routePerms[key] = d } } // RegisterFieldPerms 静态注册字段权限映射(由 permgen 插件生成的代码调用,替代反射) func (e *Engine) RegisterFieldPerms(m map[string]FieldPermMap) { for k, v := range m { e.fieldPerms[k] = v } } func (e *Engine) Start(ctx context.Context) error { perms := e.collectPerms() if len(perms) > 0 { if err := e.syncPerms(ctx, perms); err != nil { return err } } return nil } // Login 调用权限系统 gRPC Login 接口 func (e *Engine) Login(ctx context.Context, username, password string) (*LoginResult, error) { resp, err := e.client.login(ctx, e.cfg.ProductCode, username, password) if err != nil { return nil, err } return &LoginResult{ AccessToken: resp.AccessToken, RefreshToken: resp.RefreshToken, Expires: resp.Expires, UserId: resp.UserId, Username: resp.Username, Nickname: resp.Nickname, MemberType: resp.MemberType, Perms: resp.Perms, }, nil } // RefreshToken 调用权限系统 gRPC RefreshToken 接口 func (e *Engine) RefreshToken(ctx context.Context, refreshToken string) (*RefreshTokenResult, error) { resp, err := e.client.refreshToken(ctx, refreshToken, e.cfg.ProductCode) if err != nil { return nil, err } return &RefreshTokenResult{ AccessToken: resp.AccessToken, RefreshToken: resp.RefreshToken, Expires: resp.Expires, Perms: resp.Perms, }, nil } // GetUserPerms 查询指定用户在当前产品下的权限列表,使用 appKey/appSecret 做服务间认证 // 适用于定时任务、服务间调用等不走 token 验证的场景 func (e *Engine) GetUserPerms(ctx context.Context, userId int64) (*UserPermsResult, error) { resp, err := e.client.getUserPerms(ctx, e.cfg.AppKey, e.cfg.AppSecret, userId, e.cfg.ProductCode) if err != nil { return nil, err } return &UserPermsResult{ Perms: resp.Perms, MemberType: resp.MemberType, }, nil } // Logout 调用权限系统 gRPC Logout 接口,使 accessToken 对应用户的所有令牌立即失效 func (e *Engine) Logout(ctx context.Context, accessToken string) error { return e.client.logout(ctx, accessToken) } // AuthMiddleware 返回鉴权 handler,供产品端中间件直接调用 func (e *Engine) AuthMiddleware(next http.HandlerFunc) http.HandlerFunc { return e.authMiddleware(next) }