- 新增 userService.js,包含用户认证、资料更新、token 刷新等功能 - 新增 wechatService.js,处理微信API交互,获取openid和手机号 - 新增 appError.js,封装应用错误处理 - 新增 logger.js,提供日志记录功能 - 新增 response.js,统一成功响应格式 - 新增 sanitize.js,提供输入数据清洗功能 - 更新 OpenAPI 文档,描述新增接口及请求响应格式 - 更新 PocketBase 数据库结构,调整用户表字段及索引策略 - 增强错误处理机制,确保错误信息可观测性 - 更新变更记录文档,详细记录本次变更内容
4.8 KiB
4.8 KiB
OpenSpec 变更记录:PocketBase Hooks 认证链路加固
日期
- 2026-03-23
范围
本次变更覆盖 pocket-base/ 下 PocketBase hooks 项目的微信登录、资料更新、token 刷新、认证落库、错误可观测性、索引策略与运行规范。
一、认证模型调整
1. 认证体系
- 保持 PocketBase 原生 auth token 作为唯一正式认证令牌。
- 登录与刷新响应统一通过
$apis.recordAuthResponse(...)返回 PocketBase 原生认证结果。 authMethod统一使用空字符串'',避免触发不必要的 MFA / login alerts 校验。
2. Header 规则
- 正式认证 Header 为:
Authorization: Bearer <token> - 非标准 Header
Open-Authorization不属于本项目接口定义。 users_wx_openidHeader 已从 active hooks 鉴权链路移除。
二、身份字段与数据模型约束
1. openid 作为唯一业务身份锚点
tbl_auth_users仅保留openid作为微信身份锚点。- 业务逻辑中不再使用
users_wx_openid。 - 用户查询、token 刷新、资料更新均基于 auth record 的
openid。
2. auth 集合兼容字段
由于 tbl_auth_users 当前为 PocketBase auth 集合,登录注册时为兼容 PocketBase 原生 auth 校验,新增以下兼容策略:
email使用占位格式:<openid>@wechat.local- 自动生成随机密码
- 自动补齐
passwordConfirm
说明:
- 占位
email仅用于满足 auth 集合保存条件,不代表用户真实邮箱。 - 业务主身份仍然是
openid。
3. 自定义字段可空策略
tbl_auth_users的自定义字段目标约束为:除openid外,其余业务字段均允许为空。- 已将 schema 脚本中的
user_id改为非必填。 - 其余业务字段保持非必填。
三、查询与排序修复
1. 移除无意义的 created 排序
在 hooks 查询中,以下查询原先使用 '-created' 排序:
- 按
openid查询用户 - 按
company_id查询公司 - 按
users_phone查询重复手机号
该写法在 PocketBase 当前运行场景下触发:
invalid sort field "created"
现已统一移除排序参数,改为空排序字符串,因为这些查询本质上均为精确匹配或去重检查,不依赖排序。
四、错误可观测性增强
1. 登录路由显式错误响应
POST /api/wechat/login 新增局部 try/catch:
- 保留业务状态码
- 返回
{ code, msg, data } - 写入
logger.error('微信登录失败', ...)
2. 全局错误包装顺序修正
routerUse(...)全局错误包装提前到路由注册前。- 统一兼容
err.statusCode/err.status。
3. auth 保存失败透传
新增 saveAuthUserRecord(record) 包装 $app.save(record):
- 失败时统一抛出
保存微信用户失败 - 附带
originalMessage与originalData
目的:
- 避免 PocketBase 默认
Something went wrong while processing your request.吞掉具体原因。
五、数据库索引策略修复
1. users_phone 索引调整
原设计:
users_phone唯一索引
问题:
- 新用户注册阶段手机号为空,多个空值会触发唯一约束冲突,导致注册失败。
现调整为:
users_phone普通索引
说明:
- 手机号唯一性改由业务逻辑在资料完善阶段校验。
- 允许多个未完善资料用户以空手机号存在。
六、接口契约同步结果
当前 active PocketBase hooks 契约如下:
POST /api/system/test-helloworldPOST /api/system/healthPOST /api/wechat/loginPOST /api/wechat/profilePOST /api/wechat/refresh-token
其中:
POST /api/wechat/login
- body 必填:
users_wx_code - 自动以微信 code 换取
openid - 若不存在 auth 用户则尝试创建
tbl_auth_users记录 - 成功时返回 PocketBase 原生 token + auth record + meta
POST /api/wechat/profile
- 需
Authorization - 基于当前 auth record 的
openid定位用户 - 服务端用
users_phone_code换取手机号后保存
POST /api/wechat/refresh-token
- 需
Authorization - 直接基于当前 auth record 返回新的 PocketBase 原生 token
七、当前已知边界
tbl_auth_users为 PocketBaseauth集合,因此仍受 PocketBase auth 内置规则影响。- 自定义字段“除 openid 外均可空”已在脚本层按目标放宽,但 auth 集合结构更新仍可能触发 PocketBase 服务端限制。
- 若线上仍返回 PocketBase 默认 400,需要确保最新 hooks 已部署并重启生效。
八、归档建议
部署时至少同步以下文件:
pocket-base/bai-api-main.pb.jspocket-base/bai_api_pb_hooks/script/pocketbase.newpb.js
并在 PocketBase 环境中执行 schema 同步后重启服务,再进行接口验证。