package middleware import ( "allapp/db" "allapp/db/repo" "allapp/utils/errorx" "allapp/utils/redisx" "allapp/utils/responsex" "strconv" "strings" "github.com/gofiber/fiber/v3" ) const CtxSpaceIDKey = "space_id" func SpaceGuard() fiber.Handler { return func(c fiber.Ctx) error { userID, err := GetUserID(c) if err != nil { return err } spaceIDStr := strings.TrimSpace(c.Get("SPACE_ID")) spaceID, err := strconv.ParseInt(spaceIDStr, 10, 64) if err != nil || spaceID <= 0 { return responsex.SpaceError(c, "请选择空间") } // 1 先查 Redis inSpace, err := redisx.SpaceIsMember(spaceID, userID) if err != nil { return err } if inSpace { c.Locals(CtxSpaceIDKey, spaceID) return c.Next() } // 2 Redis miss → 查数据库 role, err := db.Queries.GetUserSpaceRole(c.Context(), repo.GetUserSpaceRoleParams{ SpaceID: spaceID, UserID: userID, }) if err != nil { if errorx.IsNotFound(err) { return responsex.SpaceError(c, "未加入空间") } return err } // 3 写回 Redis(重建缓存) _ = redisx.SpaceAddOrUpdateMember(spaceID, userID, role) c.Locals(CtxSpaceIDKey, spaceID) // 4 放行 return c.Next() } } func GetSpaceID(c fiber.Ctx) (int64, error) { v := c.Locals(CtxSpaceIDKey) if v == nil { return 0, responsex.SpaceError(c, "空间无效") } spaceID, ok := v.(int64) if !ok { return 0, responsex.SpaceError(c, "空间无效") } return spaceID, nil }