CRM 账户同步本地验收
CRM 账户同步本地验收
Section titled “CRM 账户同步本地验收”使用独立测试数据库。IAM 复用 verification 表保存十分钟的签名请求防重放记录,无新增认证 schema;CRM 新增角色映射配置、审计表和 mapping_version 列,需要执行 php artisan migrate。保留此前 IAM 相关 migrations。
IAM 在应用详情配置同步连接,凭据绑定当前 Client ID。CRM 的 IAM_OIDC_CLIENT_ID 必须与此客户端一致。IAM 执行 pnpm db:migrate 创建通用开通配置表,CRM 执行 php artisan migrate 创建角色规则及同步字段。
CRM 部门和职位规则以网页配置为准,不再导入 IAM_ROLE_MAPPING_JSON。历史映射会备份并暂停,管理员配置新规则后再启用。
四个终端分别运行:
- IAM API:在 IAM 执行
pnpm dev:server,端口 8787。 - IAM 网页:在 IAM 执行
pnpm dev:web,端口 3000。 - CRM API:在 crm-api 执行
php artisan serve --host=localhost --port=8000。 - CRM 网页:在 crm-web 执行
pnpm dev -- --port 5173。
IAM 应用详情 → 访问控制 → 账户与访问权限同步,接收地址填写 http://localhost:8000/api/internal/iam/provisioning/users。先保持停用并保存,将生成的 Key ID、密钥填入 CRM 后再启用。测试时只授权少量人员,不要勾选公司根部门。
CRM API 配置:
IAM_OIDC_ISSUER=http://localhost:8787/api/authIAM_OIDC_CLIENT_ID=<同一测试客户端ID>IAM_OIDC_CLIENT_SECRET=<测试客户端密钥>IAM_OIDC_REDIRECT_URI=http://localhost:8000/api/auth/iam/callbackIAM_FRONTEND_CALLBACK=http://localhost:5173/iam/callbackIAM_PROVISIONING_HMAC_KEY_ID=<IAM页面生成的Key_ID>IAM_PROVISIONING_HMAC_SECRET=<与IAM相同的测试密钥>IAM_SNAPSHOT_FALLBACK_ENABLED=trueIAM_SNAPSHOT_URL=http://localhost:8787/api/internal/provisioning/snapshotIAM_ROLE_SYNC_ENABLED=trueCRM 前端配置 VITE_SERVICE_URL=http://localhost:8000/api、VITE_HASH_ROUTE=N。本地 IAM 基础配置参考 .dev.vars.example,Issuer 必须与实际 Discovery 完全一致。CRM 改环境后执行 php artisan config:clear。
角色映射与重算
Section titled “角色映射与重算”使用已有 Leader 管理员登录 CRM,从头像菜单进入“部门 / 职位角色规则”,或访问 /iam/role-mapping。添加企微职位“销售专员”到 Sales 的规则,可限定企业微信部门 ID。IAM 仅授权测试部门或人员,无需分配应用内角色。
保存先处理最多 100 个待更新账户;剩余账户通过 Laravel scheduler 每分钟重试。生产需要已有的 schedule:run 调度,本地可另开终端运行 php artisan schedule:work。也可在网页点击“重试权限更新”,或执行 php artisan iam:reconcile-roles,每次处理最多 200 个。失败账户保留旧 mapping_version 供重试,页面显示待更新数量,异常写入 Laravel 日志。
自动规则只回收此前自动授予的角色,保留人工授予的其他角色;历史账户不被接管。关闭同步保留现有角色,重新启用后应用当前映射。团队与客户范围不自动分配。
- 使用已同步且 active 的测试员工登录,确认只创建一个 CRM 用户,获得 Sales 角色。
- 将“销售专员”规则改为另一个已有业务角色并保存;无需改变 IAM 授权或 revision,即可更新自动账户角色。
- 关闭同步、修改映射并保存,确认原角色保留;再次启用,确认应用新映射。
- 清空映射并保存,确认自动账户进入待配置状态,业务 API 拒绝访问;恢复映射,待配置页点击“刷新权限”即可恢复。
- 普通 Sales 请求
/api/user/create和/api/admin/iam-role-mapping应返回 403;已有 CRM 账户的角色不被映射更新。 - 撤销 IAM 授权,确认 CRM 旧 Token 失效;之后发送旧版本开通事件不能恢复访问。
- 使用其他 Client ID 的签名快照请求应返回 403,重放同一已成功签名请求返回 409。
Node 本地模式没有 Cloudflare Cron 自动触发;首次登录快照仍可兜底。要验收异步定时投递恢复,需显式触发测试维护流程或使用 Worker scheduled 测试环境。真实企微扫码及通讯录回调需企业微信允许的可访问域名。
# IAMpnpm checkpnpm --filter @IAM/auth exec vitest run src/provisioning.test.ts src/provisioning-hmac.test.ts src/app-authorization.test.tspnpm --filter server exec vitest run src/provisioning-snapshot.test.ts src/index.test.ts
# CRM APIphp vendor/bin/phpunit --do-not-cache-result --filter Iam
# CRM 前端pnpm typecheckpnpm exec vitest run src/store/modules/auth/index.spec.ts src/utils/auth/iam-callback-error.test.ts src/service/api/auth.spec.tspnpm exec playwright test tests/e2e/iam-callback.spec.ts --project=chromium-no-auth浏览器用例模拟后端响应,不能代替真实三服务联调。普通数据库用例也不能代替多连接并发验证。CRM 增加双进程 PostgreSQL 测试:配置 IAM_TEST_PG_DATABASE、IAM_TEST_PG_HOST、IAM_TEST_PG_PORT、IAM_TEST_PG_USER、IAM_TEST_PG_PASSWORD 后运行 php vendor/bin/phpunit --do-not-cache-result --filter IamPostgresConcurrencyTest。该测试只创建并清理随机 schema;未配置专用测试库会明确跳过。CRM 生产 MySQL 的多连接行为仍应在对应测试环境验证。
通用应用开通配置(新版)
Section titled “通用应用开通配置(新版)”新增业务表 provisioning_connection,首次启动新版前运行 pnpm db:migrate(确认指向待验收数据库)。本次没有修改 Better Auth 认证 schema。迁移文件是 0013_brave_cammi.sql。
平台管理员进入 OAuth 应用详情的“访问控制”页,填写账号开通接收地址,先保持停用保存,复制仅当次显示的 Key ID / HMAC Secret 到接收系统,再启用。CRM 对应 IAM_PROVISIONING_HMAC_KEY_ID 和 IAM_PROVISIONING_HMAC_SECRET;CRM 的 IAM_OIDC_CLIENT_ID 仍使用该 OAuth 应用的 Client ID。
接收系统要实现的签名头、规范串、事件负载与快照接口见账户与访问权限同步协议;下面第 7 条验收的 403 / 409 就是该协议的 CLIENT_MISMATCH 与 REPLAY。
新应用直接在自己的详情页配置,不需要在 IAM 增加 ERP_PROVISIONING_* 等变量。接收系统仍需实现现有开通与快照协议。应用可见范围和角色授权继续由应用授权配置决定。
旧版 CRM 配齐 URL、Secret、明确绑定的 Client ID 时,首次读取开通配置会自动导入;OA 仅在旧类型唯一时导入。已有数据库记录(包括停用)不会被环境变量覆盖。确认导入后可以移除旧开通变量;只有 Client ID、没有 URL / Secret 时不会自动产生可用连接。
凭据使用服务端 BETTER_AUTH_SECRET 派生密钥加密存储,查询和审计不返回密文或明文。更换该根密钥前必须用旧密钥解密并重新加密已有连接,不能直接替换后继续使用旧密文。轮换应用凭据会立即撤销旧 Key ID,建议先停用、轮换、更新接收方、再启用。
验收步骤:
- 配置 CRM 后,确认详情查询不返回 Secret;刷新页面不再显示一次性凭据。
- 新建普通类型的测试应用,配置独立接收地址;确认无需改 IAM 环境变量。
- 用一个应用的快照凭据请求另一个 Client ID,预期 403。
- 停用连接,确认不再发送开通请求且快照凭据不可用;启用后待同步记录重新排队。
- 轮换凭据,确认旧 Key ID 无效,新凭据可用。
代码回归测试使用隔离测试数据库;完整企业微信登录、CRM 接收和角色落地仍需启动两端后联调验收。
企业微信部门 / 职位规则
Section titled “企业微信部门 / 职位规则”CRM 不再根据 IAM app_role 分配业务权限。IAM 的开通事件和快照增加 user.position、user.departmentIds(直接所属部门)、user.departmentAncestorIds(上级部门)。职位明确清空会同步清空并生成新修订。
CRM 执行 php artisan migrate,应用新增迁移 2026_09_08_000002_add_iam_employment_rules.php。历史映射备份到 iam_role_mapping_settings.legacy_mapping,旧规则暂停且现有权限保留;不会将 sales 猜测成企微职位。配置新的职位规则后再开启同步。
推荐顺序:先迁移并升级 CRM API,再升级 IAM 和 CRM Web,在 IAM 通讯录页执行全量同步,确认开通投递成功,然后进入 CRM 头像菜单「部门 / 职位角色规则」配置并启用。IAM 本次没有新增数据库迁移。不要将 IAM_ROLE_MAPPING_JSON 中的旧应用角色映射继续作为新规则使用。
规则职位必填,去除首尾空格后精确匹配;部门可填写企业微信部门 ID(不是 CRM 部门 ID),留空表示所有部门。支持包含下级部门,多条命中规则合并角色。未匹配到规则不授予自动角色;人工已有角色仍保留。只有自动创建的 IAM 托管账户参与规则同步。管理员角色禁止规则自动授予。
验收:职位为「销售专员」、部门 100 的员工匹配 Sales;将职位清空或调至其他部门后,确认 Sales 被撤回。额外人工授予的其他角色保留。暂停同步保留角色,恢复同步重新计算。未同步的新字段不会回退使用旧 app_role。