Foundation:用户/空间/鉴权
前面几天多次看到 foundation 模块最先被初始化、几乎每个业务请求都要经过它检查权限。今天专门拆开这个"地基模块",看用户、空间、鉴权三件事是怎么串起来的。
为什么业务模块都先过 Foundation
api.Init 里 foundationHandler 是第一个被初始化的 handler,后面 llm/prompt/data/evaluation/observability 全部要拿它的接口(AuthService/UserService/FileService)作参数传入。backend/modules/foundation/application/ 下正好四个文件对应四种职责:user.go(用户信息)、auth.go(权限校验)、space.go(工作空间)、file.go(文件服务)。user.go
登录、注册、查用户信息——回答"当前操作的人是谁"。
auth.go
权限校验(MCheckPermission)——回答"这个人能不能做这件事"。
space.go
工作空间(Workspace)——回答"这件事发生在哪个团队隔离单位下"。
file.go
文件上传/签名 URL——多个模块共用的"存文件"能力。
user.go:用户是谁
Day 04 讲的 SessionMW 里调用的 us.GetUserInfo(...),实现就在 backend/modules/foundation/application/user.go——这条链路把"Cookie 里的一个 Session ID"最终变成"一个带用户名/邮箱的完整 User 对象",供全平台使用。
SessionMW 先验证 Session 合法,再用其中的 UserID 去 user.go 查完整的用户信息——这是"认证(Authentication,你是谁)"的完整过程。auth.go:能不能做这件事
backend/modules/foundation/application/auth.go 的 MCheckPermission 是"授权(Authorization,你能干什么)"的核心:
func (a *AuthApplicationImpl) MCheckPermission(ctx context.Context, request *auth.MCheckPermissionRequest) (r *auth.MCheckPermissionResponse, err error) {
userID, err := strconv.ParseInt(session.UserIDInCtxOrEmpty(ctx), 10, 64) // 从 ctx 取当前用户
if userID == 0 || err != nil {
return nil, errorx.NewByCode(errno.CommonInvalidParamCode, ...)
}
spaceID := request.GetSpaceID()
isUserSpace, err := a.userRepo.CheckUserSpaceExist(ctx, userID, spaceID) // 查"这个用户在这个空间里吗"
// ...
}
prompt 模块 CreatePrompt 里的这行代码:app.authRPCProvider.CheckSpacePermission(ctx, request.GetWorkspaceID(), consts.ActionWorkspaceCreateLoopPrompt)——这就是"用户是不是当前 ctx 里那个人 + 在 request.GetWorkspaceID() 这个空间下 + 有没有 ActionWorkspaceCreateLoopPrompt(创建 Prompt)这个动作的权限"。任何业务模块要做敏感操作,都要拼出这三个要素问一遍 Foundation。if userID == 0 || err != nil { return nil, errorx.NewByCode(...) }——Coze Loop 里没有"匿名可访问"的降级模式,Day 04 的 SessionMW 已经在最外层挡掉了未登录请求,所以走到这里 ctx 里一定应该有用户,一旦没有就是异常情况要立刻报错,而不是静默放行。space.go:在哪个空间里
backend/modules/foundation/application/space.go 提供空间的创建、查询、列出用户所在的所有空间等能力。几乎所有业务请求体(回顾 Day 07 IDL 里的 CreatePromptRequest)都带一个 workspace_id 字段——这是"资源归属哪个空间"的强制约束,不能省略。
前端 auth-pages 简介
后端的登录/注册/权限体系,前端对应的落地是 frontend/packages/loop-pages/auth-pages/——按 ARCHITECTURE.md 的前端分层,它属于 Level-5 loop-pages(页面模块层),负责渲染登录页、注册页,并在登录成功后把 Session Cookie 落下,后续所有请求会自动带上它,被 Day 04 的 SessionMW 校验。
/api/foundation/v1/users/login_by_password(Day 04 SessionMW 里特判放行的两个路径之一)完成登录,成功后浏览器带着 Session Cookie 访问其余接口。这是一条从"前端页面"到"后端 Foundation 模块"再到"每个业务请求的中间件校验"的完整闭环,前 8 天讲的所有知识点在这里汇合。今日小结 + 动手
🧠 今天你应该能回答
- Foundation 管哪四件事?(user 用户 / auth 鉴权 / space 空间 / file 文件)
- 认证和授权的区别?(认证=你是谁 Session→User;授权=你能干什么 MCheckPermission)
- 权限判断的三要素是什么?(用户 + 空间 + 动作)
- Workspace 空间的作用?(多租户资源隔离单位,几乎所有资源都挂在某个空间下)
✋ 动手 5 分钟
# 1. 看 foundation application 四件套
ls backend/modules/foundation/application/*.go | grep -v _test | grep -v wire
# 2. 看权限校验的核心函数
grep -n "func.*MCheckPermission\|func.*CheckSpacePermission" -r backend/modules/foundation/
# 3. 看 prompt 模块怎么调用 foundation 的鉴权(Day 06 讲过的"本地客户端"模式)
grep -n "authRPCProvider\|CheckSpacePermission" backend/modules/prompt/application/manage.go | head
# 4. 看前端登录页在哪
find frontend/packages/loop-pages/auth-pages -maxdepth 2 -type d