package util import ( "context" "fmt" "gitea.com/red-future/common/beans" "gitea.com/red-future/common/db/mongo" "gitea.com/red-future/common/redis" "gitea.com/red-future/common/utils" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "go.mongodb.org/mongo-driver/v2/bson" ) // GetTenantInfo 获取租户信息 // 优先从 token 获取,失败则从请求参数 customerServiceId 查询 customer_service_account 表 func GetTenantInfo(ctx context.Context) (user beans.User, err error) { // 1. 优先从 token 获取 user, err = utils.GetUserInfo(ctx) if err == nil { return } // 2. token 获取失败,尝试从请求参数或context获取 accountName var accountName string // 2.1 尝试从request获取(HTTP请求场景) req := g.RequestFromCtx(ctx) if req != nil { accountName = req.Get("accountName").String() if accountName == "" { accountName = req.Get("account_name").String() } } // 2.2 request不存在或未获取到,尝试从context.Value获取(WebSocket场景) if accountName == "" { if val := ctx.Value("accountName"); val != nil { if str, ok := val.(string); ok { accountName = str } } } if accountName == "" { return user, gerror.New("无法获取租户信息:无 token 且无 accountName 参数") } // 3. 先查Redis缓存(accountName -> tenantId映射) cacheKey := fmt.Sprintf("tenant:account:%s", accountName) cached, cacheErr := redis.RedisClient().Get(ctx, cacheKey) if cacheErr == nil && !g.IsEmpty(cached) { user.TenantId = cached.Interface() user.UserName = accountName return user, nil } // 4. 缓存未命中,查询 customer_service_account 表 filter := bson.M{"accountName": accountName, "isDeleted": false} var account struct { TenantId interface{} `bson:"tenantId"` } if findErr := mongo.GetDB().Collection("customer_service_account").FindOne(ctx, filter).Decode(&account); findErr != nil { return user, gerror.Newf("通过 accountName 查询租户失败: %v", findErr) } // 5. 写入缓存(3分钟过期,避免数据长时间不一致) redis.RedisClient().SetEX(ctx, cacheKey, account.TenantId, 180) user.TenantId = account.TenantId user.UserName = accountName return user, nil }