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

12 KiB
Raw Blame History

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

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

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

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

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

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

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

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

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

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 已同步