feat(auth): add auth session module with user entity and session management - #147
feat(auth): add auth session module with user entity and session management#147xyh202131 wants to merge 1 commit into
Conversation
…gement Split the auth session module from the main codebase: entities/user: - User, AuthTokens, UserApis type definitions - createUserApis backend adapter (snake_case -> camelCase mapping) - Supports ApiClient injection for testability features/auth-session: - AuthSessionProvider: three-state session (booting -> guest | authenticated) - useAuthSession() hook for consuming auth context - ProtectedRoute: route guard with safe returnTo validation - resolveAuthMode(): local dev by default, forces backend in production - createLocalUserApis(): browser-only dev adapter (no password verification) - session-storage: refresh token localStorage persistence with graceful degradation Tests: 14 test cases covering session lifecycle, token rotation, StrictMode dedup, stale request handling, JWT refresh scheduling, local dev adapter, and route protection.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
| email: string | ||
| purpose: 'login' | 'register' | 'reset_password' | ||
| }): Promise<void> | ||
| register(input: { |
There was a problem hiding this comment.
这里把认证模型定义成了 access/refresh token + code 登录/注册参数,但仓库现有后端 UserService 仍然是 session_token 语义,RegisterInput / LoginByPasswordInput 也不包含 code。按当前代码库状态,这个前端契约不会和后端对得上。
| bootstrapGenerationRef.current = bootstrapGeneration | ||
| const persistedRefreshToken = loadRefreshToken() | ||
| bootstrapPromiseRef.current = persistedRefreshToken | ||
| ? rotateTokens(persistedRefreshToken).then(async (tokens) => { |
There was a problem hiding this comment.
这里先成功刷新再调用 apis.me();如果 me() 只是短暂失败,后面的 rejection handler 会把刚刷新的 token 也清掉,导致一个本来可用的会话被当场登出。既然 refresh 返回值已经带了 user,至少不应该因为这一步失败就直接丢会话。
|
这份实现我们评审过,模块划分、注释与测试覆盖都达到了可以进 main 的水准,响应解析的显式校验、refresh 的并发去重、启动期 stale 结果保护都写得对。 考虑到你目前排期紧,这块工作我们接手,内容并入 #158,代码以这份实现为起点复用,PR 正文会注明来源与作者。评审中发现三处需要补齐的地方,已经写进 #158 的实现约束:对业务码 401 的响应式兜底(定时器在标签页挂起时不会准时触发)、跨标签页的 storage 同步(/auth/refresh 轮换 refresh token,两个标签页同时打开会互相失效)、以及 resolveAuthMode 与 AuthModeProvider 的装配职责归还 #103。 感谢这份工作,先关掉这个 PR,后续进展在 #158 跟进。 |
变更范围
拆分登录与认证会话模块到独立分支,包含两个子模块:
entities/user —— 用户实体契约
index.ts—User、AuthTokens、UserApis类型定义(sendCode / register / login / loginByCode / refresh / logout / me / changePassword 共 8 个方法)api.ts—createUserApis后端适配器,蛇形命名 → 驼峰命名映射,支持注入 ApiClientfeatures/auth-session —— 认证会话管理
index.tsx—AuthSessionProvider(三态:booting → guest | authenticated)、useAuthSession()hook、ProtectedRoute路由守卫(含安全 returnTo 校验)、resolveAuthMode()开发/生产适配、createLocalUserApis()本地开发适配器session-storage.ts— refresh token 的 localStorage 持久化与降级处理模块依赖
shared/api(已合入 main 的 feat(frontend): add shared API client infrastructure #117)测试覆盖(14 个测试用例)