让演示环境像真的:离线造数 176 条的安全网与一个「只看不动」的 demo 角色

导读

演示环境要拿给客户看,面前两只拦路虎:页面上没有成规模的历史数据,也没有一个”能看全部但什么都不许动”的演示账号。9 月 8 日一天解决掉两只——造数 176 条(44 条监控申请 + 132 条回放申请)直接写进线上库,同时落地一个精确到四个”查看”能力的 demo 角色。本篇记录造数的安全网四件套、五表闭环模型,以及角色决策里那个被知情接受的副作用。

前言

演示环境(demo)的尴尬人人都遇到过:功能做得再好,打开页面空空如也,讲的人就只能说”想象一下这里有数据”。这一天的任务就是让”想象”落地——把表单导出的历史视频监控申请 Excel 造成”已办结”数据写进线上库(215),让实时监控申请页面从 2023 年 8 月起每月都有数据可看;同时配一个专门的 demo 角色,让客户能随便翻,但删不掉、批不了。

一、demo 角色:精确四个”查看”,不多给一分

角色定义的第一条决策就是取舍:demo = 纯演示账号,不兼任审批人。已知副作用被摊开记录并知情接受——ADMIN_ALL 模式下 myTaskType 会被转成申请人/null,demo 用户在两个申请页看不到”待我审批”入口(既有行为,超管同此)。以后真要审批能力,前端 demo 分支再拉一趟 MY_RELATED 合并待办行,当时评估为中等改动,先不做

能力范围精确到四个查看,不继承其他超管权限:

  • 摄像头列表全量:listByPage 跳过园区/权限过滤;
  • 回放列表全量 + 播放他人录像;删除他人录像仍超管专属
  • 监控申请/回放申请 ADMIN_ALL 全局场景:后端回退判断 + 前端两页白名单 ['super_admin','demo']

实现上有一个值得抄的设计:admin-api 的 RoleClient 新增 checkRoleByCode(userId, roleCode) 通用角色码判断,mapper 复用现有角色码计数 SQL,且三处判定点统一 fail-closed——原本有一处连 logger 都没有,顺手补了静默兜底。权限代码的默认姿态就该是”出错即拒绝”,而不是”出错即放行”。

E2E 用绑了 demo 角色的 test 账号走网关实测六项全绿,其中两项最有说服力:摄像头列表 total=485 = 两园区之和(跨园区全量实锤);delete 他人录像被拒且录像仍在(删除保持超管专属)。

demo 角色:四扇窗全开,按钮上锁
图 1:demo 角色的姿态——看得见的全放开,动得到的都上锁

二、造数方法论:不碰 Flowable 的工单闭环

造历史工单数据,最大的诱惑是去模拟审批流引擎。这套方法论的第一条原则就是不依赖 Flowable ACT_ 表:只写业务表 + BPM 三表(bpm_business / bpm_handle / bpm_my_task),工单落库即是终态。引擎表是运行时状态,历史数据只需要”看起来走完过流程”,不需要真的走。

第二条是安全网四件套,缺一不可:

造数安全网四件套
① 所有新数据 update_name='demo'        —— 一眼识别造数,出问题好捞
② 回滚 SQL 单独生成,按本次插入的 id 精确 DELETE —— 不是按 update_name 扫全表
③ 整批 START TRANSACTION;…COMMIT;      —— 一次连接提交,不落半批
④ 默认 dry-run,写库前 y/n 终确认       —— 非交互下确认读 EOF 直接退出不写(防误写兜底)

第三条是真实感三来源:人员/审批关系从 Excel 导出的 302 组真实搭配里随机抽(不编固定值);摄像头从 security_camera_info 全楼层池每层随机取 2;每条时间随机偏移、事由用 6 种模板。最后固定随机种子(默认 7)——同库同种子输出完全一致,可复现、可重摇。

第四条是对账:写库前后各跑一遍计数 SQL,”预期增量 vs 实际增量”逐表对上才算完。

三、实例:44 + 132 条,五表闭环

监控申请(business_type=4)导入 44 条已办结 = Excel 真实 6 条 + 月度合成 38 条。每一单要闭环五张表:

五表闭环(每单行数)
building_through.security_video_apply         主表 status='4' 已办结          ×1
building_through.security_video_apply_camera  批准的摄像头                    ×2
building_bpm.bpm_business   工单 status='1' 已结束带 end_time                ×1
building_bpm.bpm_handle     审批轨迹:发起→部门→办公室→安防负责人(4 节点)    ×4
building_bpm.bpm_my_task    个人任务:审批人已办×2 + 处理人已办 + 发起人       ×4

四表对账结果:主表 +44、摄像头 +88(每单 2 个)、bpm_business +44、bpm_my_task +176(每单 4 行),全部与预期一致。同日第二批照抄骨架造了回放申请(business_type=5)132 条——多一张 security_video_user 表,且安防负责人是运行时从线上终态单现查的(回放流程是段超,监控流程是樊馨蔓,两流程处理人不同,写死常量只是兜底)。

五表闭环:一张主表带活四张伴随表
图 2:每一单造数要闭环五张表,对账逐表对上才算完

四、环境坑三连:1045 不是网络问题

内网环境(209 执行机双网卡无外网、215 跑 MySQL 容器)三个坑都值得通用化:

  1. root 授权只认 10 网段mysql.user 里 root 的 host 只有 10.152.%/10.182.5.%/localhost,从 172 段连必报 Access denied报 1045 说明 TCP 已通——是授权问题,别去查网络。连 10.182.5.215 让来源 IP 落在授权段里即可。
  2. 镜像缺第三方包:离线环境用 wheels 离线装——本机 pip download openpyxl -d wheels --only-binary :all:,目录拷过去,pip install --no-index --find-links /wheels
  3. pymysql 多语句:整批事务一次发要 CLIENT.MULTI_STATEMENTS,执行后 while cur.nextset(): pass 消费干净,否则下一条命令 commands out of sync

经验总结

  • 演示账号先做减法:能力列成清单精确放开,副作用摊开记录、知情接受,比”先给超管用着”安全得多;
  • 权限判定统一 fail-closed,顺手把连 logger 都没有的静默分支补上;
  • 历史工单造数别碰流程引擎表,业务表 + BPM 三表直接落终态;
  • 安全网四件套(标记、精确回滚、单事务、dry-run 确认)是写生产库的最低配置;
  • 造数的真实感来自真实池随机 + 固定种子,可复现和真实感可以兼得;
  • 1045 是授权不是网络——内网排查先分清错误层。

结语

一天下来,演示环境从”想象一下这里有数据”变成”从 2023 年 8 月起每月都有真实感的数据”。造数脚本和安全网沉淀成了通用手册,demo 角色的决策记录留好了将来加审批能力的入口——演示环境也是要维护的资产,不是一次性布景。