Files
social-app/docs/plans/2026-02-26-auth-ux-enhancement-plan.md
T
qzl 76853452f6 chore: commit remaining workspace updates
include AGENTS guidance updates, plan doc replacements, and utility script changes left in working tree
2026-02-26 17:59:30 +08:00

403 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Auth UX Enhancement Implementation Plan
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** 以最小风险完成 Auth UX 优化(忘记密码、注册提示、邀请码、用户搜索修复),并确保与现有 Supabase SDK 能力完全一致。
**Architecture:** 对客户端暴露两步重置流程:`password-reset` 发码 + `password-reset/confirm` 确认改密。`confirm` 在后端内部串行执行 `verify_otp(type="recovery")``update_user(password=...)`,既符合 SDK 限制又保持交互简洁。用户查询从 `GET /users/{username}` 迁移到 `POST /users/search`,并同步前端数据层,避免断链。全流程按 TDD 执行并同步路由文档。
**Tech Stack:** FastAPI, Pydantic, SQLAlchemy, Supabase Auth, Flutter, Dio, Bloc/Cubit
---
## Phase 0: 基线与保护
### Task 1: 建立基线测试(RED 前准备)
**Files:**
- Modify: `backend/tests/integration/test_auth_routes.py`
- Modify: `backend/tests/integration/test_users_routes.py`
**Step 1: 新增失败测试占位(不改实现)**
新增并期望失败的测试:
- `test_password_reset_request_returns_204`
- `test_password_reset_confirm_returns_204`
- `test_search_users_returns_list`
**Step 2: 运行后端测试确认 RED**
Run: `uv run pytest backend/tests/integration/test_auth_routes.py backend/tests/integration/test_users_routes.py -v`
Expected: 新增用例失败(404/AttributeError/未实现)。
**Step 3: Commit**
```bash
git add backend/tests/integration/test_auth_routes.py backend/tests/integration/test_users_routes.py
git commit -m "test: add failing tests for auth ux enhancement"
```
---
## Phase 1: 后端密码重置(对外两步)
### Task 2: 完成密码重置请求接口(发码)
**Files:**
- Modify: `backend/src/v1/auth/schemas.py`
- Modify: `backend/src/v1/auth/service.py`
- Modify: `backend/src/v1/auth/gateway.py`
- Modify: `backend/src/v1/auth/router.py`
- Test: `backend/tests/integration/test_auth_routes.py`
**Step 1: 写失败测试(若 Task 1 未覆盖细节)**
确保 `POST /api/v1/auth/password-reset`
- 合法邮箱返回 `204`
- 非法参数返回 `422`
- 触发限流返回 `429`
**Step 2: 跑单测确认失败**
Run: `uv run pytest backend/tests/integration/test_auth_routes.py::test_password_reset_request_returns_204 -v`
Expected: FAIL。
**Step 3: 最小实现(GREEN**
- `schemas.py`: 复用已有 `PasswordResetRequest`,不要重复定义同名模型。
- `service.py`: 增加 `request_password_reset(...)`
- `gateway.py`: 调用 `self._client.auth.reset_password_email(email, options)`
- `router.py`: 新增 `POST /auth/password-reset`,返回 `204`,保留限流。
**Step 4: 跑测试确认通过**
Run: `uv run pytest backend/tests/integration/test_auth_routes.py::test_password_reset_request_returns_204 -v`
Expected: PASS。
**Step 5: Commit**
```bash
git add backend/src/v1/auth/schemas.py backend/src/v1/auth/service.py backend/src/v1/auth/gateway.py backend/src/v1/auth/router.py backend/tests/integration/test_auth_routes.py
git commit -m "feat(auth): add password reset request endpoint"
```
---
### Task 3: 完成密码重置确认接口(验码 + 改密)
**Files:**
- Modify: `backend/src/v1/auth/schemas.py`
- Modify: `backend/src/v1/auth/service.py`
- Modify: `backend/src/v1/auth/gateway.py`
- Modify: `backend/src/v1/auth/router.py`
- Test: `backend/tests/integration/test_auth_routes.py`
**Step 1: 写失败测试**
测试 `POST /api/v1/auth/password-reset/confirm`
- 正确 `email + token + new_password` 返回 `204`
- 错误验证码返回 `401`
- 弱密码/参数错误返回 `422`
**Step 2: 跑测试确认失败**
Run: `uv run pytest backend/tests/integration/test_auth_routes.py::test_password_reset_confirm_returns_204 -v`
Expected: FAIL。
**Step 3: 最小实现**
- `schemas.py`: 新增 `PasswordResetConfirmRequest(email, token, new_password)`
- `service.py`: 增加 `confirm_password_reset(...)`
- `gateway.py`: 在单个方法内先调用 `verify_otp({"type":"recovery", ...})`,再在该会话上下文调用 `update_user({"password": new_password})`
- `router.py`: 新增 `POST /auth/password-reset/confirm`,返回 `204`
**Step 4: 跑测试确认通过**
Run: `uv run pytest backend/tests/integration/test_auth_routes.py::test_password_reset_confirm_returns_204 -v`
Expected: PASS。
**Step 5: Commit**
```bash
git add backend/src/v1/auth/schemas.py backend/src/v1/auth/service.py backend/src/v1/auth/gateway.py backend/src/v1/auth/router.py backend/tests/integration/test_auth_routes.py
git commit -m "feat(auth): add password reset confirm endpoint"
```
---
## Phase 2: 后端用户搜索替代用户名路由
### Task 4: 新增 POST /users/search 并移除旧路由
**Files:**
- Modify: `backend/src/v1/users/schemas.py`
- Modify: `backend/src/v1/users/repository.py`
- Modify: `backend/src/v1/users/service.py`
- Modify: `backend/src/v1/users/router.py`
- Test: `backend/tests/integration/test_users_routes.py`
**Step 1: 写失败测试**
新增测试:
- `POST /api/v1/users/search` 成功返回列表
- `query` 为空返回 `422`
- 删除后 `GET /api/v1/users/{username}` 返回 `404`
**Step 2: 跑测试确认失败**
Run: `uv run pytest backend/tests/integration/test_users_routes.py -v`
Expected: FAIL。
**Step 3: 最小实现**
- `schemas.py`: 增加 `UserSearchRequest`, `UserSearchResult`
- `repository.py`: 新增 `search_users(query)`username `ilike` + email 精确匹配,`limit 20`
- `service.py`: 增加 `search_users(...)` 并映射公开字段。
- `router.py`: 增加 `POST /users/search`;删除 `GET /users/{username}`
**Step 4: 跑测试确认通过**
Run: `uv run pytest backend/tests/integration/test_users_routes.py -v`
Expected: PASS。
**Step 5: Commit**
```bash
git add backend/src/v1/users/schemas.py backend/src/v1/users/repository.py backend/src/v1/users/service.py backend/src/v1/users/router.py backend/tests/integration/test_users_routes.py
git commit -m "refactor(users): replace username endpoint with search"
```
---
## Phase 3: 前端认证 UX
### Task 5: 数据层支持密码重置两步接口
**Files:**
- Modify: `apps/lib/features/auth/data/models/login_request.dart`
- Modify: `apps/lib/features/auth/data/auth_api.dart`
- Modify: `apps/lib/features/auth/data/auth_repository.dart`
- Modify: `apps/lib/features/auth/data/auth_repository_impl.dart`
- Test: `apps/test/features/auth/data/auth_repository_impl_test.dart`(如不存在则创建)
**Step 1: 写失败测试**
覆盖:
- request -> confirm 的调用顺序
- confirm 请求包含 `email + token + new_password`
**Step 2: 跑测试确认失败**
Run: `flutter test apps/test/features/auth/data/auth_repository_impl_test.dart`
Expected: FAIL。
**Step 3: 最小实现**
- 增加 `requestPasswordReset` / `confirmPasswordReset`
- 模型保持 snake_case JSON 键与后端一致。
**Step 4: 跑测试确认通过**
Run: `flutter test apps/test/features/auth/data/auth_repository_impl_test.dart`
Expected: PASS。
**Step 5: Commit**
```bash
git add apps/lib/features/auth/data apps/test/features/auth/data/auth_repository_impl_test.dart
git commit -m "feat(auth): add password reset data layer"
```
---
### Task 6: 新增忘记密码页面与状态管理
**Files:**
- Create: `apps/lib/features/auth/ui/screens/forgot_password_screen.dart`
- Create: `apps/lib/features/auth/ui/screens/reset_password_screen.dart`
- Create: `apps/lib/features/auth/presentation/cubits/forgot_password_cubit.dart`
- Create: `apps/lib/features/auth/presentation/cubits/reset_password_cubit.dart`
- Modify: `apps/lib/features/auth/ui/screens/login_screen.dart`
- Modify: `apps/lib/core/router/app_router.dart`
- Test: `apps/test/features/auth/ui/forgot_password_screen_test.dart`(可新建)
**Step 1: 写失败测试**
至少覆盖:
- 登录页点击“忘记密码”可跳转
- 忘记密码页提交后进入验证码改密页
**Step 2: 跑测试确认失败**
Run: `flutter test apps/test/features/auth/ui/forgot_password_screen_test.dart`
Expected: FAIL。
**Step 3: 最小实现**
- 使用 `Toast` 呈现提交成功/失败反馈。
- reset 页面提交时调用单个 confirm 接口完成验码与改密。
- 成功后跳回登录并提示“密码已重置”。
**Step 4: 跑测试确认通过**
Run: `flutter test apps/test/features/auth/ui/forgot_password_screen_test.dart`
Expected: PASS。
**Step 5: Commit**
```bash
git add apps/lib/features/auth apps/lib/core/router/app_router.dart apps/test/features/auth/ui/forgot_password_screen_test.dart
git commit -m "feat(auth): add forgot password ui flow"
```
---
### Task 7: 注册体验优化(提示 + 邀请码)
**Files:**
- Modify: `apps/lib/features/auth/ui/screens/register_verification_screen.dart`
- Modify: `apps/lib/features/auth/ui/screens/register_screen.dart`
- Modify: `apps/lib/features/auth/presentation/cubits/register_cubit.dart`
- Modify: `apps/lib/features/auth/data/models/signup_request.dart`
- Test: `apps/test/features/auth/ui/register_screen_test.dart`(如不存在则创建)
**Step 1: 写失败测试**
覆盖:
- 验证码页首次进入显示提示 Toast
- 注册页存在邀请码输入并为可选
**Step 2: 跑测试确认失败**
Run: `flutter test apps/test/features/auth/ui/register_screen_test.dart`
Expected: FAIL。
**Step 3: 最小实现**
- `signup_request` 可选字段 `invite_code`
- 页面展示邀请码输入框,不做必填校验。
**Step 4: 跑测试确认通过**
Run: `flutter test apps/test/features/auth/ui/register_screen_test.dart`
Expected: PASS。
**Step 5: Commit**
```bash
git add apps/lib/features/auth/ui/screens/register_verification_screen.dart apps/lib/features/auth/ui/screens/register_screen.dart apps/lib/features/auth/presentation/cubits/register_cubit.dart apps/lib/features/auth/data/models/signup_request.dart apps/test/features/auth/ui/register_screen_test.dart
git commit -m "feat(auth): improve verification hint and invite code input"
```
---
## Phase 4: 前端 users 数据层迁移
### Task 8: 将 getByUsername 迁移为 searchUsers
**Files:**
- Modify: `apps/lib/features/users/data/users_api.dart`
- Modify: `apps/lib/features/users/data/users_repository.dart`
- Modify: `apps/lib/features/users/data/users_repository_impl.dart`
- Test: `apps/test/features/users/data/users_repository_test.dart`(如不存在则创建)
**Step 1: 写失败测试**
覆盖:
- `searchUsers(query)` 发送 `POST /api/v1/users/search`
- 返回列表模型映射正确
**Step 2: 跑测试确认失败**
Run: `flutter test apps/test/features/users/data/users_repository_test.dart`
Expected: FAIL。
**Step 3: 最小实现**
- 删除 `getByUsername`
- 新增 `searchUsers(String query)`
**Step 4: 跑测试确认通过**
Run: `flutter test apps/test/features/users/data/users_repository_test.dart`
Expected: PASS。
**Step 5: Commit**
```bash
git add apps/lib/features/users/data apps/test/features/users/data/users_repository_test.dart
git commit -m "refactor(users): migrate client to search endpoint"
```
---
## Phase 5: 文档与全量验证
### Task 9: 更新 API 文档并完成全量检查
**Files:**
- Modify: `docs/runtime/runtime-route.md`
**Step 1: 更新路由文档**
- 新增:
- `POST /auth/password-reset`
- `POST /auth/password-reset/confirm`
- `POST /users/search`
- 删除:
- `GET /users/{username}`
文档需包含:请求/响应 schema、状态码、错误格式(RFC 7807)。
**Step 2: 跑后端验证**
Run: `uv run pytest backend/tests -v && uv run basedpyright backend/src`
Expected: 全通过。
**Step 3: 跑前端验证**
Run: `flutter analyze apps/lib && flutter test`
Expected: 全通过。
**Step 4: 手动验收**
- 忘记密码完整链路(发码/确认改密/登录)
- 注册页邀请码与验证码提示
- `POST /users/search` 返回结果正确
**Step 5: Commit**
```bash
git add docs/runtime/runtime-route.md
git commit -m "docs: sync runtime routes for auth ux enhancement"
```
---
## 验收清单
- [ ] 所有新增测试先失败后通过(有 RED/GREEN 记录)
- [ ] 后端密码重置两步接口可用(confirm 内部完成验码 + 改密)
- [ ] 前端忘记密码流程可用
- [ ] 邀请码输入为选填且不破坏现有注册
- [ ] `GET /users/{username}` 全链路移除
- [ ] `POST /users/search` 前后端一致
- [ ] `docs/runtime/runtime-route.md` 已同步