package consts import ( "context" "time" "github.com/gogf/gf/v2/frame/g" ) // ============================== 请求上下文键与读写工具 ============================== // contextKey 上下文键私有类型 // 使用私有类型避免跨包键名冲突 type contextKey string // 请求上下文键 // 由 JWT、租户中间件写入,供全链路读取 const ( KeyUserID contextKey = "userID" // 当前登录用户ID KeyTenantID contextKey = "tenantID" // 当前租户ID(0=平台级) KeyUsername contextKey = "username" // 当前登录用户名 KeyRealname contextKey = "realname" // 当前登录用户姓名 KeyRoles contextKey = "roles" // 角色编码集合 []string KeyPerms contextKey = "perms" // 权限节点集合 []string,如 sys:user:page KeyTokenJTI contextKey = "tokenJTI" // 当前令牌 jti KeyTokenExp contextKey = "tokenExpire" // 令牌过期时间 time.Time,用于登出黑名单TTL KeyDataScope contextKey = "dataScope" // 角色数据范围(多角色取最宽松),见 DataScopeXxx 常量 KeyDeptID contextKey = "deptID" // 当前登录用户部门ID(0=未分配) // 请求元信息,由 Response 中间件写入,供登录日志、操作日志读取 KeyClientIP contextKey = "clientIP" // 客户端IP KeyUserAgent contextKey = "userAgent" // User-Agent KeyReqMethod contextKey = "reqMethod" // HTTP方法 KeyReqURL contextKey = "reqURL" // 请求URL ) // WithUserID 写入当前登录用户ID func WithUserID(ctx context.Context, id int) context.Context { return context.WithValue(ctx, KeyUserID, id) } // GetUserID 读取当前登录用户ID // 未登录时返回 0 func GetUserID(ctx context.Context) int { v, _ := ctx.Value(KeyUserID).(int) return v } // WithTenantID 写入当前租户ID // 0 表示平台级 func WithTenantID(ctx context.Context, id int) context.Context { return context.WithValue(ctx, KeyTenantID, id) } // CtxTenantID 读取上下文原始租户ID // // 未登录时返回 0(平台级)。仅供租户隔离设施使用(超管判断、查询过滤、中间件校验), // 业务模块取归属租户请使用 GetTenantID。 func CtxTenantID(ctx context.Context) int { v, _ := ctx.Value(KeyTenantID).(int) return v } // DefaultTenantID 默认归属租户ID // // 超管新增租户级数据时使用。读取配置 tenant.defaultId,未配置或非法值(≤0)回退 1。 func DefaultTenantID(ctx context.Context) int { v := g.Cfg().MustGet(ctx, "tenant.defaultId").Int() if v <= 0 { return 1 } return v } // GetTenantID 读取当前上下文的归属租户ID // // 租户用户返回自身租户ID,超管返回默认租户ID。 // 业务模块新增、导入、唯一校验等取归属租户统一使用本方法。 func GetTenantID(ctx context.Context) int { if t := CtxTenantID(ctx); t > 0 { return t } return DefaultTenantID(ctx) } // IsPlatform 是否平台级租户 // 上下文租户ID为0时表示平台级(超管) func IsPlatform(ctx context.Context) bool { return CtxTenantID(ctx) == 0 } // WithUsername 写入当前登录用户名 func WithUsername(ctx context.Context, username string) context.Context { return context.WithValue(ctx, KeyUsername, username) } // GetUsername 读取当前登录用户名 func GetUsername(ctx context.Context) string { v, _ := ctx.Value(KeyUsername).(string) return v } // WithRealname 写入当前登录用户姓名 func WithRealname(ctx context.Context, realname string) context.Context { return context.WithValue(ctx, KeyRealname, realname) } // GetRealname 读取当前登录用户姓名 // 审计字段 create_user 优先使用本方法 func GetRealname(ctx context.Context) string { v, _ := ctx.Value(KeyRealname).(string) return v } // WithRoles 写入当前用户角色编码 func WithRoles(ctx context.Context, roles []string) context.Context { return context.WithValue(ctx, KeyRoles, roles) } // GetRoles 读取当前用户角色编码 func GetRoles(ctx context.Context) []string { v, _ := ctx.Value(KeyRoles).([]string) return v } // WithPerms 写入当前用户权限节点 func WithPerms(ctx context.Context, perms []string) context.Context { return context.WithValue(ctx, KeyPerms, perms) } // GetPerms 读取当前用户权限节点 func GetPerms(ctx context.Context) []string { v, _ := ctx.Value(KeyPerms).([]string) return v } // HasPerm 校验权限节点 // 权限节点为空视为无需校验;超级管理员拥有全部权限 func HasPerm(ctx context.Context, permission string) bool { if permission == "" { return true } for _, r := range GetRoles(ctx) { if r == RoleCodeSuperAdmin { return true } } for _, p := range GetPerms(ctx) { if p == permission { return true } } return false } // 数据范围档位(角色 data_scope 列值;数值越小可见面越宽) const ( DataScopeAll = 1 // 全部(租户隔离之内) DataScopeDeptAndBelow = 2 // 本部门及以下 DataScopeDept = 3 // 本部门 DataScopeSelf = 4 // 仅本人 ) // WithDataScope 写入当前用户数据范围 func WithDataScope(ctx context.Context, scope int) context.Context { return context.WithValue(ctx, KeyDataScope, scope) } // GetDataScope 读取当前用户数据范围 // 未注入时返回 DataScopeAll(视为全量可见) func GetDataScope(ctx context.Context) int { v, _ := ctx.Value(KeyDataScope).(int) if v <= 0 { return DataScopeAll } return v } // WithDeptID 写入当前登录用户部门ID func WithDeptID(ctx context.Context, id int) context.Context { return context.WithValue(ctx, KeyDeptID, id) } // GetDeptID 读取当前登录用户部门ID // 未分配或未登录时返回 0 func GetDeptID(ctx context.Context) int { v, _ := ctx.Value(KeyDeptID).(int) return v } // WithTokenJTI 写入当前令牌 jti // 登出时依据该值将令牌加入黑名单 func WithTokenJTI(ctx context.Context, jti string) context.Context { return context.WithValue(ctx, KeyTokenJTI, jti) } // GetTokenJTI 读取当前令牌 jti func GetTokenJTI(ctx context.Context) string { v, _ := ctx.Value(KeyTokenJTI).(string) return v } // WithTokenExpire 写入当前令牌过期时间 // 黑名单 TTL 取令牌剩余有效期 func WithTokenExpire(ctx context.Context, t time.Time) context.Context { return context.WithValue(ctx, KeyTokenExp, t) } // GetTokenExpire 读取当前令牌过期时间 func GetTokenExpire(ctx context.Context) time.Time { v, _ := ctx.Value(KeyTokenExp).(time.Time) return v } // WithRequestMeta 写入请求元信息 // 由 Response 中间件调用 func WithRequestMeta(ctx context.Context, ip, userAgent, method, url string) context.Context { ctx = context.WithValue(ctx, KeyClientIP, ip) ctx = context.WithValue(ctx, KeyUserAgent, userAgent) ctx = context.WithValue(ctx, KeyReqMethod, method) ctx = context.WithValue(ctx, KeyReqURL, url) return ctx } // GetClientIP 读取客户端IP func GetClientIP(ctx context.Context) string { v, _ := ctx.Value(KeyClientIP).(string) return v } // GetUserAgent 读取 User-Agent func GetUserAgent(ctx context.Context) string { v, _ := ctx.Value(KeyUserAgent).(string) return v } // GetReqMethod 读取HTTP方法 func GetReqMethod(ctx context.Context) string { v, _ := ctx.Value(KeyReqMethod).(string) return v } // GetReqURL 读取请求URL func GetReqURL(ctx context.Context) string { v, _ := ctx.Value(KeyReqURL).(string) return v }