mirror of
https://github.com/hpd840321/starRiverProperty.git
synced 2026-06-10 17:00:30 +08:00
Initial commit: reorganized source tree
- backend/: 13 Maven modules (cw-elevator-application, cloudwalk-cloud, intelligent-cwoscomponent, ninca-crk, etc.) - frontend/: 4 Vue projects (elevator-front, cwos-portal, alarm-front, front_acs) + decompiled + scripts - scripts/: build, test-env, tools (Docker Compose, service templates, API parity) - docs/: AGENTS.md, superpowers specs, architecture docs - .gitignore: standard Java/Maven exclusions Moved from legacy maven-*/ root layout to backend/ organized structure.
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
release-visitor-noauth-verify-v20260430/
|
||||
├── README.md
|
||||
├── 操作手册.md
|
||||
├── 执行流程设计-简化版.md
|
||||
├── 打包说明.txt
|
||||
├── MANIFEST.txt
|
||||
├── python/
|
||||
│ ├── quick_verify_visitor_floor_policy.py
|
||||
│ ├── requirements.txt
|
||||
│ └── requirements-min.txt
|
||||
├── report/
|
||||
│ └── .gitkeep
|
||||
└── sql/
|
||||
├── 黄平访客ID手工查询.sql
|
||||
├── 租户访客策略基线核查.sql
|
||||
├── 批量样本筛选-多公司多部门.sql
|
||||
├── 人工核查最终楼层结果.sql
|
||||
├── 标准批量25访客-执行后核验.sql
|
||||
└── batch_cases.csv
|
||||
@@ -0,0 +1,105 @@
|
||||
# 访客无鉴权策略验证发布包(v20260430)
|
||||
|
||||
## 1. 发布目标
|
||||
|
||||
本目录为“黄平访问蒙海文”无鉴权策略验证的**版本化发布包**,用于生产执行、结果留痕与归档。
|
||||
|
||||
当前对应代码发布版本:`cw-elevator-application-2.0.9`
|
||||
|
||||
## 2. 包内文件
|
||||
|
||||
- `README.md`:发布说明(本文件)
|
||||
- `操作手册.md`:完整操作步骤与判定规则
|
||||
- `执行流程设计-简化版.md`:先明确流程再执行的最小闭环方案(推荐先读)
|
||||
- `sql/黄平访客ID手工查询.sql`:生产手工查询黄平访客 ID 的 SQL
|
||||
- `sql/批量样本筛选-多公司多部门.sql`:筛选多个公司/多个部门被访人样本 SQL
|
||||
- `sql/人工核查最终楼层结果.sql`:自定义访客 ID 集合时执行后核验
|
||||
- `sql/标准批量25访客-执行后核验.sql`:§4.0 单行命令固定 25 名访客号段后的执行后核验
|
||||
- `python/quick_verify_visitor_floor_policy.py`:执行脚本快照(支持纯 HTTP;可选连组织库/电梯库)
|
||||
- `python/requirements.txt`:`requests` + `pymysql`(预置样本拉取、`--verify-local-db`)
|
||||
- `python/requirements-min.txt`:仅 `requests`(不连库时)
|
||||
- `report/`:脚本输出 JSON 汇总(打包时排除 `*.json` 历史文件)
|
||||
- `打包说明.txt`:生产机 `pip install`、一键 zip、全量预置命令示例
|
||||
- `MANIFEST.txt`:交付清单
|
||||
|
||||
## 3. 关键基线参数
|
||||
|
||||
- 被访人(蒙海文)`personId=964454497399468032`
|
||||
- 访客(黄平)`personId=1102270499947507712`
|
||||
- 租户 `businessId=2524639890ba4f2cba9ba1a4eeaa4015`
|
||||
- 策略语义(**规范**):未传 **`floorIds`** 时,生效楼层为 **`PersonService.detail` → `floorList`**;租户策略须已在组织 **`detail`** 中以 **`allow_zone_ids` 替代**写入(**非** ∩)。详见 [`visitor-registration-business-flow.md`](../visitor-registration-business-flow.md)、[`租户组织人员访客-数据模型与用例.md`](../../architecture/租户组织人员访客-数据模型与用例.md)、[`2026-05-06` 规格](../../superpowers/specs/2026-05-06-tenant-visitor-policy-organization-implementation.md)。
|
||||
|
||||
## 4. 测试执行(一行命令)
|
||||
|
||||
以下参数已由交付侧与现场环境对齐:**组织** `http://10.0.22.207:8089`,**电梯** `http://10.0.22.207:16112`;**25 名测试访客** `personId` 为连续号段 `9199000100000000001`~`9199000100000000025`(预置脚本内置 25 个被访人样本,本命令**不访问 MySQL**)。
|
||||
|
||||
**操作:** 打开解压后的发布包目录(能看到子目录 `python/`),**只粘贴下面整行**,回车执行(自动安装缺失的 `requests` 并跑预置 25 人批量无鉴权探测):
|
||||
|
||||
```bash
|
||||
python3 -m pip install -q -r python/requirements-min.txt && python3 python/quick_verify_visitor_floor_policy.py --mode noauth-probe --org-base-url "http://10.0.22.207:8089" --elevator-base-url "http://10.0.22.207:16112" --use-preset-cases --visitor-person-ids "$(python3 -c 'print(",".join(str(9199000100000000000+i) for i in range(1,26)))')" --probe-with-businessid --batch-output-summary "batch-preset-static-$(date +%Y%m%d-%H%M%S).json"
|
||||
```
|
||||
|
||||
汇总 JSON:`report/` 目录下文件名形如 `batch-preset-static-<时间戳>.json`。
|
||||
|
||||
**执行后须查库分析:** 在目标环境 **`cw-elevator-application`** 库运行 `sql/标准批量25访客-执行后核验.sql`,将每名访客的 **`active_row_count`、`zone_id`** 与 JSON 中的 `derived.floor_count`、`derived.floors` 对齐;具体操作与判定要点见 **`操作手册.md` §4.0.1、§4.6**。
|
||||
|
||||
---
|
||||
|
||||
### 附录 A:单样本(广发基金基线)
|
||||
|
||||
```bash
|
||||
python3 python/quick_verify_visitor_floor_policy.py \
|
||||
--mode noauth-probe \
|
||||
--org-base-url "http://10.0.22.207:8089" \
|
||||
--elevator-base-url "http://10.0.22.207:16112" \
|
||||
--business-id "2524639890ba4f2cba9ba1a4eeaa4015" \
|
||||
--meng-person-id "964454497399468032" \
|
||||
--visitor-person-id "1102270499947507712" \
|
||||
--probe-with-businessid
|
||||
```
|
||||
|
||||
该访客为存量人员:库表核验易与历史 `image_rule_ref` 混在一起;若以「本轮新增访客 + 证据」为目标,请以 **§4 一行批量号段 `919900…`** 为主。**操作手册 §4.2** 对上述边界有全文说明。
|
||||
|
||||
### 附录 B:连 MySQL 拉样本 / 库表比对
|
||||
|
||||
需与 HTTP 同属一套库的地址与账号由运维另行提供,不由本 README 承载;禁止使用与目标环境不一致的数据库串联验证。
|
||||
|
||||
### 附录 C:`sql/batch_cases.csv` 批量
|
||||
|
||||
```bash
|
||||
python3 python/quick_verify_visitor_floor_policy.py \
|
||||
--mode noauth-probe \
|
||||
--org-base-url "http://10.0.22.207:8089" \
|
||||
--elevator-base-url "http://10.0.22.207:16112" \
|
||||
--batch-input-csv "sql/batch_cases.csv" \
|
||||
--visitor-person-ids "1102270499947507712,1102270499947507713,1102270499947507714" \
|
||||
--visitor-names "黄志平A,黄志平B,黄志平C" \
|
||||
--probe-with-businessid \
|
||||
--batch-output-summary "batch-from-csv-$(date +%Y%m%d-%H%M%S).json"
|
||||
```
|
||||
|
||||
### 附录 D:人员导出 CSV 自动筛选
|
||||
|
||||
```bash
|
||||
python3 python/quick_verify_visitor_floor_policy.py \
|
||||
--mode noauth-probe \
|
||||
--org-base-url "http://10.0.22.207:8089" \
|
||||
--elevator-base-url "http://10.0.22.207:16112" \
|
||||
--batch-source-person-csv "../_cw_is_person__202604302030.csv" \
|
||||
--exclude-business-ids "2524639890ba4f2cba9ba1a4eeaa4015" \
|
||||
--sample-companies 3 \
|
||||
--sample-persons-per-company 2 \
|
||||
--visitor-person-ids "1102270499947507712,1102270499947507713,1102270499947507714" \
|
||||
--visitor-names "黄志平A,黄志平B,黄志平C" \
|
||||
--probe-with-businessid \
|
||||
--batch-output-summary "batch-from-export-$(date +%Y%m%d-%H%M%S).json"
|
||||
```
|
||||
|
||||
说明:导出 CSV 需含列 `BUSINESS_ID`,`ID`,`IS_DEL`,`NAME`(等);无部门列时汇总中 `department` 可能为空。
|
||||
|
||||
## 5. 输出位置
|
||||
|
||||
脚本输出(均在发布包下 `report/` 目录):
|
||||
- 单样本:`quick-verify-<timestamp>.json`
|
||||
- 标准批量:见 §4,`batch-preset-static-*.json`
|
||||
- 其他批量:`--batch-output-summary` 指定名;默认 `batch-summary.json`
|
||||
+1045
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
# 仅调用组织/电梯 HTTP,不连 MySQL
|
||||
requests>=2.28.0,<3
|
||||
@@ -0,0 +1,5 @@
|
||||
# 生产验证机:Python 3.8+
|
||||
# 仅 HTTP 探测:pip install -r requirements-min.txt
|
||||
requests>=2.28.0,<3
|
||||
# 可选(--fetch-preset-from-org-db / --verify-local-db)
|
||||
pymysql>=1.0.0,<2
|
||||
+2375
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
business_id,meng_person_id,company,department
|
||||
2524639890ba4f2cba9ba1a4eeaa4015,964454497399468032,广发基金,示例部门A
|
||||
replace-business-id-2,replace-person-id-2,示例公司2,示例部门B
|
||||
replace-business-id-3,replace-person-id-3,示例公司3,示例部门C
|
||||
|
@@ -0,0 +1,49 @@
|
||||
-- 用途:脚本执行后,人工核查访客最终楼层权限
|
||||
-- 说明:
|
||||
-- * 「已授权楼层」= image_rule_ref 中 person_delete = 0 的行(与 passRule/image 可查到的楼层一致)
|
||||
-- * person_delete = 1 为撤销/作废,不参与当前授权
|
||||
-- 将 IN (...) 中的访客 person_id 替换为本次执行的访客集合
|
||||
|
||||
-- 主查:仅已授权楼层(推荐与接口 / JSON derived.floors 对拍)
|
||||
SELECT
|
||||
irr.person_id,
|
||||
irr.business_id,
|
||||
irr.zone_id,
|
||||
irr.zone_name,
|
||||
irr.last_update_time
|
||||
FROM `cw-elevator-application`.`image_rule_ref` irr
|
||||
WHERE irr.person_id IN (
|
||||
'1102270499947507712'
|
||||
-- ,'替换为其他访客personId'
|
||||
)
|
||||
AND irr.person_delete = 0
|
||||
ORDER BY irr.person_id, irr.zone_id;
|
||||
|
||||
-- 明细(含已撤销历史行,核对 person_delete / 时间线时用)
|
||||
SELECT
|
||||
irr.person_id,
|
||||
irr.business_id,
|
||||
irr.zone_id,
|
||||
irr.zone_name,
|
||||
irr.person_delete,
|
||||
irr.create_time,
|
||||
irr.last_update_time
|
||||
FROM `cw-elevator-application`.`image_rule_ref` irr
|
||||
WHERE irr.person_id IN (
|
||||
'1102270499947507712'
|
||||
-- ,'替换为其他访客personId'
|
||||
)
|
||||
ORDER BY irr.person_id, irr.last_update_time DESC, irr.zone_id;
|
||||
|
||||
-- 可选:统计每个访客当前「已授权」楼层数量(person_delete = 0)
|
||||
SELECT
|
||||
irr.person_id,
|
||||
COUNT(1) AS floor_count
|
||||
FROM `cw-elevator-application`.`image_rule_ref` irr
|
||||
WHERE irr.person_id IN (
|
||||
'1102270499947507712'
|
||||
-- ,'替换为其他访客personId'
|
||||
)
|
||||
AND irr.person_delete = 0
|
||||
GROUP BY irr.person_id
|
||||
ORDER BY irr.person_id;
|
||||
@@ -0,0 +1,35 @@
|
||||
-- 用途:从组织库筛选“多个公司 + 多个部门”的被访人样本
|
||||
-- MySQL:连接主机/端口/账号按**当前环境**填写(开发与生产分离;不要用开发库导出的样本去打生产)
|
||||
--
|
||||
-- 已与 component-organization 典型结构对齐(2026-04-30 开发库 INFORMATION_SCHEMA 核对):
|
||||
-- cw_is_person 人员主键列为 ID(无 person_id);删除标记 IS_DEL(无 deleted);
|
||||
-- 无 labels/business_name/organization_name 列;访客身份通过 cw_is_person_label_ref + cw_is_label 识别。
|
||||
-- 连接参数可复制 maven-cw-elevator-application/tools/visitor_floor_verification/.env.visitor_verify(勿提交密钥)。
|
||||
|
||||
SELECT
|
||||
p.BUSINESS_ID AS business_id,
|
||||
p.ID AS meng_person_id,
|
||||
COALESCE(parent_org.NAME, '') AS company,
|
||||
COALESCE(o.NAME, '') AS department
|
||||
FROM `component-organization`.`cw_is_person` p
|
||||
INNER JOIN `component-organization`.`cw_is_person_organization_ref` r ON r.PERSON_ID = p.ID
|
||||
LEFT JOIN `component-organization`.`cw_is_organization` o ON o.ID = r.ORG_ID
|
||||
LEFT JOIN `component-organization`.`cw_is_organization` parent_org ON parent_org.ID = o.PARENT_ID
|
||||
WHERE (p.IS_DEL = 0 OR p.IS_DEL IS NULL)
|
||||
AND p.BUSINESS_ID IS NOT NULL
|
||||
AND p.BUSINESS_ID <> ''
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM `component-organization`.`cw_is_person_label_ref` lr
|
||||
INNER JOIN `component-organization`.`cw_is_label` lb ON lb.ID = lr.LABEL_ID
|
||||
WHERE lr.PERSON_ID = p.ID
|
||||
AND lb.BUSINESS_ID = p.BUSINESS_ID
|
||||
AND lb.NAME = '访客'
|
||||
)
|
||||
ORDER BY p.BUSINESS_ID, department, p.LAST_UPDATE_TIME DESC;
|
||||
|
||||
-- 建议导出后人工抽样:
|
||||
-- 1) 至少 3 个 business_id
|
||||
-- 2) 每个 business_id 至少 2 个不同 department
|
||||
-- 3) 生成 batch_cases.csv,列头固定为:
|
||||
-- business_id,meng_person_id,company,department
|
||||
@@ -0,0 +1,58 @@
|
||||
-- 用途:`README`/操作手册 §4.0 标准单行批量跑完后,在电梯库核查写库是否与接口侧一致
|
||||
-- 库:`cw-elevator-application`
|
||||
-- 表:`image_rule_ref`(访客 person_id 维度楼层规则)
|
||||
-- 访客清单:与本包约定的 9199000100000000001~9199000100000000025 完全一致;若现场改用其它 personId,请改下方 expected 子查询或直接用 `sql/人工核查最终楼层结果.sql`。
|
||||
|
||||
-- ------------------------------------------------------------------
|
||||
-- A) 每名访客当前「有效」规则行数 + 最近一次更新时间(核对 JSON 里的 floor_count / 时间点)
|
||||
-- ------------------------------------------------------------------
|
||||
SELECT
|
||||
e.visitor_person_id,
|
||||
SUM(CASE WHEN irr.person_delete = 0 THEN 1 ELSE 0 END) AS active_row_count,
|
||||
MAX(CASE WHEN irr.person_delete = 0 THEN irr.last_update_time END) AS latest_active_update_ms
|
||||
FROM (
|
||||
SELECT '9199000100000000001' AS visitor_person_id
|
||||
UNION ALL SELECT '9199000100000000002'
|
||||
UNION ALL SELECT '9199000100000000003'
|
||||
UNION ALL SELECT '9199000100000000004'
|
||||
UNION ALL SELECT '9199000100000000005'
|
||||
UNION ALL SELECT '9199000100000000006'
|
||||
UNION ALL SELECT '9199000100000000007'
|
||||
UNION ALL SELECT '9199000100000000008'
|
||||
UNION ALL SELECT '9199000100000000009'
|
||||
UNION ALL SELECT '9199000100000000010'
|
||||
UNION ALL SELECT '9199000100000000011'
|
||||
UNION ALL SELECT '9199000100000000012'
|
||||
UNION ALL SELECT '9199000100000000013'
|
||||
UNION ALL SELECT '9199000100000000014'
|
||||
UNION ALL SELECT '9199000100000000015'
|
||||
UNION ALL SELECT '9199000100000000016'
|
||||
UNION ALL SELECT '9199000100000000017'
|
||||
UNION ALL SELECT '9199000100000000018'
|
||||
UNION ALL SELECT '9199000100000000019'
|
||||
UNION ALL SELECT '9199000100000000020'
|
||||
UNION ALL SELECT '9199000100000000021'
|
||||
UNION ALL SELECT '9199000100000000022'
|
||||
UNION ALL SELECT '9199000100000000023'
|
||||
UNION ALL SELECT '9199000100000000024'
|
||||
UNION ALL SELECT '9199000100000000025'
|
||||
) e
|
||||
LEFT JOIN `cw-elevator-application`.`image_rule_ref` irr
|
||||
ON irr.person_id = e.visitor_person_id
|
||||
GROUP BY e.visitor_person_id
|
||||
ORDER BY e.visitor_person_id;
|
||||
|
||||
-- ------------------------------------------------------------------
|
||||
-- B) 有效规则明细(与报告 `derived.floors` 比对 zone_id;按人+时间排序)
|
||||
-- ------------------------------------------------------------------
|
||||
SELECT
|
||||
irr.person_id,
|
||||
irr.zone_id,
|
||||
irr.zone_name,
|
||||
irr.person_delete,
|
||||
irr.business_id,
|
||||
irr.create_time,
|
||||
irr.last_update_time
|
||||
FROM `cw-elevator-application`.`image_rule_ref` irr
|
||||
WHERE irr.person_id BETWEEN '9199000100000000001' AND '9199000100000000025'
|
||||
ORDER BY irr.person_id, irr.last_update_time DESC, irr.zone_id;
|
||||
@@ -0,0 +1,43 @@
|
||||
-- 租户访客楼层策略最小核查 SQL(执行前确认数据库实例为电梯业务库)
|
||||
-- 目标租户:广发基金 business_id = 2524639890ba4f2cba9ba1a4eeaa4015
|
||||
|
||||
-- 1) 表结构与索引确认
|
||||
SHOW CREATE TABLE tenant_visitor_floor_policy;
|
||||
|
||||
-- 2) 广发租户策略主检查
|
||||
SELECT id,
|
||||
business_id,
|
||||
policy_type,
|
||||
allow_zone_ids,
|
||||
building_id,
|
||||
enabled,
|
||||
policy_version,
|
||||
updated_at,
|
||||
remark
|
||||
FROM tenant_visitor_floor_policy
|
||||
WHERE business_id = '2524639890ba4f2cba9ba1a4eeaa4015'
|
||||
ORDER BY updated_at DESC, policy_version DESC;
|
||||
|
||||
-- 3) 同租户是否存在多条默认策略(building_id 为空)
|
||||
SELECT business_id, COUNT(*) AS cnt
|
||||
FROM tenant_visitor_floor_policy
|
||||
WHERE business_id = '2524639890ba4f2cba9ba1a4eeaa4015'
|
||||
AND (building_id IS NULL OR building_id = '')
|
||||
GROUP BY business_id
|
||||
HAVING COUNT(*) > 1;
|
||||
|
||||
-- 4) enabled 与 policy_type 分布
|
||||
SELECT policy_type, enabled, COUNT(*) AS cnt
|
||||
FROM tenant_visitor_floor_policy
|
||||
WHERE business_id = '2524639890ba4f2cba9ba1a4eeaa4015'
|
||||
GROUP BY policy_type, enabled
|
||||
ORDER BY cnt DESC;
|
||||
|
||||
-- 5) allow_zone_ids 是否包含 28F zone_id
|
||||
SELECT id, allow_zone_ids
|
||||
FROM tenant_visitor_floor_policy
|
||||
WHERE business_id = '2524639890ba4f2cba9ba1a4eeaa4015'
|
||||
AND enabled = 1
|
||||
AND policy_type = 'INTERSECT_ALLOWLIST'
|
||||
AND allow_zone_ids LIKE '%605560545117995008%';
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
-- 访客:黄平(手机号 13926442944)手工查询 SQL
|
||||
-- 已确认库表:component-organization.cw_is_person
|
||||
|
||||
SELECT
|
||||
person_id,
|
||||
name,
|
||||
mobile,
|
||||
business_id,
|
||||
labels,
|
||||
deleted,
|
||||
create_time,
|
||||
update_time
|
||||
FROM `component-organization`.`cw_is_person`
|
||||
WHERE business_id = '2524639890ba4f2cba9ba1a4eeaa4015'
|
||||
AND name = '黄平'
|
||||
AND mobile = '13926442944'
|
||||
ORDER BY update_time DESC;
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
发布包目录(源码内):
|
||||
docs/testing/release-visitor-noauth-verify-v20260430
|
||||
|
||||
一、测试执行(单行,与 README「4」一致;在解压后的发布包根目录执行,须有子目录 python/)
|
||||
|
||||
python3 -m pip install -q -r python/requirements-min.txt && python3 python/quick_verify_visitor_floor_policy.py --mode noauth-probe --org-base-url "http://10.0.22.207:8089" --elevator-base-url "http://10.0.22.207:16112" --use-preset-cases --visitor-person-ids "$(python3 -c 'print(",".join(str(9199000100000000000+i) for i in range(1,26)))')" --probe-with-businessid --batch-output-summary "batch-preset-static-$(date +%Y%m%d-%H%M%S).json"
|
||||
|
||||
二、一键打包(在仓库根「源码」目录执行,排除本地 report 里的 JSON 痕迹与 __pycache__)
|
||||
|
||||
STAMP=$(date +%Y%m%d-%H%M%S)
|
||||
OUT="docs/testing/release-visitor-noauth-verify-v20260430-prod-${STAMP}.zip"
|
||||
zip -r "$OUT" docs/testing/release-visitor-noauth-verify-v20260430 \
|
||||
-x 'docs/testing/release-visitor-noauth-verify-v20260430/report/*.json' \
|
||||
-x '*.pyc' -x '*__pycache__*' -x '*.pyo'
|
||||
unzip -l "$OUT" | tail -5
|
||||
echo "written: $OUT"
|
||||
|
||||
三、解压到测试机后的目录示例
|
||||
|
||||
mkdir -p ~/visitor-noauth-verify && cd ~/visitor-noauth-verify
|
||||
unzip -q release-visitor-noauth-verify-v20260430-prod-*.zip
|
||||
cd docs/testing/release-visitor-noauth-verify-v20260430
|
||||
(在此目录执行上文「一行命令」)
|
||||
|
||||
四、打包前自检
|
||||
|
||||
1) python/quick_verify_visitor_floor_policy.py、requirements*.txt 存在
|
||||
2) sql/、README.md 与交付地址/访客号段约定一致
|
||||
3) MANIFEST.txt 与目录一致
|
||||
|
||||
五、选配:连 MySQL 等参数由运维另表提供,不写死于此文件;勿用开发与目标不一致的库串联 HTTP。
|
||||
@@ -0,0 +1,90 @@
|
||||
# 访客楼层策略验证执行流程(简化版)
|
||||
|
||||
## 1. 目标
|
||||
|
||||
按固定顺序完成两组验证,并输出汇总结果:
|
||||
|
||||
1. **基线组(广发基金)**:新增“黄平访客 -> 被访人蒙海文(`personId=964454497399468032`)”,再查询该访客楼层权限;
|
||||
2. **对照组(其他公司多样本)**:从数据库筛选多个公司/多个部门被访人,分别新增“黄志平访客”,再查询各自楼层权限;
|
||||
3. 最终输出“每个样本是否成功、楼层数量与楼层清单”。
|
||||
|
||||
> 说明:本流程强调顺序和可复核性,不再依赖复杂自动推断。
|
||||
|
||||
## 2. 统一原则
|
||||
|
||||
- 只以 `personId` 作为最终查询键,不以姓名直接判定权限。
|
||||
- 姓名查询仅用于“定位候选人”,不用于最终业务判定。
|
||||
- 判定顺序固定:**先写(add/visitor),再读(passRule/image)**。
|
||||
|
||||
## 3. 执行总流程(必须按顺序)
|
||||
|
||||
### 步骤A:准备参数与样本
|
||||
|
||||
- 访客固定:黄平/黄志平(按现场实际确认对应 `visitorPersonId`)
|
||||
- 先准备两类样本:
|
||||
- 样本1(广发基金基线):`businessId=252463...`,被访人 `964454497399468032`
|
||||
- 样本2(多公司多部门对照):在**与目标验证环境一致**的组织库/MySQL 上筛选多个公司和部门被访人(禁止使用开发库数据去打生产接口)
|
||||
|
||||
### 步骤B:执行样本1(广发基金基线)
|
||||
|
||||
1. 调 `add/visitor` 新增访客;
|
||||
2. 紧接着调 `passRule/image` 查询楼层;
|
||||
3. 记录基线组结果(期望仅 `28F`,若策略开启)。
|
||||
|
||||
### 步骤C:执行样本2(多公司多部门)
|
||||
|
||||
对每个被访人样本重复:
|
||||
|
||||
1. 调 `add/visitor` 新增“黄志平访客”;
|
||||
2. 调 `passRule/image` 查询该访客楼层;
|
||||
3. 记录结果到汇总表。
|
||||
|
||||
### 步骤D:输出总结果
|
||||
|
||||
按样本输出字段:
|
||||
- 公司
|
||||
- 部门
|
||||
- 被访人 `personId`
|
||||
- 访客 `personId`
|
||||
- `add/visitor` 结果码
|
||||
- 楼层数量
|
||||
- 楼层清单
|
||||
|
||||
## 4. 异常分流(必须遵守)
|
||||
|
||||
### 4.1 add/visitor 失败(任何样本)
|
||||
|
||||
结论:该样本不具备“策略生效验证条件”。
|
||||
|
||||
动作:
|
||||
1. 查同时间窗口服务日志;
|
||||
2. 定位具体失败点(远程超时、依赖服务不可用、SQL异常等);
|
||||
3. 修复后仅重跑失败样本。
|
||||
|
||||
### 4.2 add/visitor 成功但楼层不符
|
||||
|
||||
动作:
|
||||
1. 查策略读取日志(`policyDecision`、`allowFloorSize`、`effectiveFloorSize`);
|
||||
2. 查策略表配置是否匹配租户;
|
||||
3. 查 `image_rule_ref` 当前 `person_delete=0` 记录是否包含历史残留。
|
||||
|
||||
## 5. 为什么采用该顺序
|
||||
|
||||
- 先做广发基金基线,可快速判断策略主路径是否正常;
|
||||
- 再做多公司多部门对照,可评估是否存在租户间差异或历史规则干扰;
|
||||
- 最后统一汇总,避免单条日志或单个样本误导结论。
|
||||
|
||||
## 6. 推荐命令模板(单样本)
|
||||
|
||||
```bash
|
||||
python3 python/quick_verify_visitor_floor_policy.py \
|
||||
--mode noauth-probe \
|
||||
--org-base-url "http://10.0.22.207:8089" \
|
||||
--elevator-base-url "http://10.0.22.207:16112" \
|
||||
--business-id "2524639890ba4f2cba9ba1a4eeaa4015" \
|
||||
--meng-person-id "964454497399468032" \
|
||||
--visitor-person-id "1102270499947507712" \
|
||||
--probe-with-businessid
|
||||
```
|
||||
|
||||
> 多样本场景建议外层脚本循环调用本命令,并将结果JSON汇总为一张表。
|
||||
@@ -0,0 +1,194 @@
|
||||
# 访客无鉴权策略验证-操作手册(发布版)
|
||||
|
||||
## 1. 适用范围
|
||||
|
||||
- 目标:验证无鉴权模式下访客接口是否可调用,以及“黄平访问蒙海文”是否触发策略。
|
||||
- 环境:生产环境(建议低峰时段执行)。
|
||||
- 对应版本:`cw-elevator-application-2.0.9`
|
||||
- 建议先读:`执行流程设计-简化版.md`(先定流程,再执行)
|
||||
|
||||
## 2. 前置条件
|
||||
|
||||
1. Python 3.8+
|
||||
2. **推荐(与 §4.0 一致)**:`python3 -m pip install -r python/requirements-min.txt`(安装 `requests`)。若仅单笔安装亦可:`python3 -m pip install requests`。
|
||||
|
||||
3. 关键参数确认:
|
||||
|
||||
- `businessId=2524639890ba4f2cba9ba1a4eeaa4015`
|
||||
- `蒙海文personId=964454497399468032`
|
||||
- `黄平personId=1102270499947507712`
|
||||
- `黄平姓名=黄平`、`手机号=13926442944`(仅用于人工核对)
|
||||
|
||||
说明:
|
||||
- 被访者ID参数为 `--meng-person-id`,默认即 `964454497399468032`,可按现场覆盖。
|
||||
|
||||
## 3. 手工 SQL(访客 ID 复核)
|
||||
|
||||
见:`sql/黄平访客ID手工查询.sql`
|
||||
|
||||
## 3.1 策略基线核查 SQL(必须先执行)
|
||||
|
||||
见:`sql/租户访客策略基线核查.sql`
|
||||
|
||||
重点核验:
|
||||
|
||||
- `business_id='2524639890ba4f2cba9ba1a4eeaa4015'`
|
||||
- `policy_type='INTERSECT_ALLOWLIST'`
|
||||
- `enabled=1`
|
||||
- `allow_zone_ids` 包含 `605560545117995008`(28F)
|
||||
- 同租户 `building_id` 为空的默认策略仅 1 条
|
||||
- 策略语义(**规范**):启用策略时 **`allow_zone_ids` 在组织 `detail` 以「替代」写入 `floorList`**;电梯 **`addVisitor`** 仅透传 **`detail.floorList`**(UC-01)或请求 **`floorIds`**(UC-02),**不与 allow 求交**。失效场景以 **`76260531`** 等为准(历史 **`76260532`** 交集失败路径已废止)。详见 [`visitor-registration-business-flow.md`](../visitor-registration-business-flow.md)、[`租户组织人员访客-数据模型与用例.md`](../../architecture/租户组织人员访客-数据模型与用例.md)。
|
||||
|
||||
## 3.2 多公司多部门样本筛选 SQL(第二步)
|
||||
|
||||
见:`sql/批量样本筛选-多公司多部门.sql`
|
||||
|
||||
筛选结果请保存为 `sql/batch_cases.csv`,列头要求:
|
||||
|
||||
`business_id,meng_person_id,company,department`
|
||||
|
||||
## 4. 执行步骤
|
||||
|
||||
### 4.0 标准预置 25 人批量(推荐,单行命令)
|
||||
|
||||
在发布包根目录(见 4.1)下**复制整行**执行即可(与 `README.md` §4 相同;不写占位符:组织/电梯 URL 与访客号段已由交付对齐):
|
||||
|
||||
```bash
|
||||
python3 -m pip install -q -r python/requirements-min.txt && python3 python/quick_verify_visitor_floor_policy.py --mode noauth-probe --org-base-url "http://10.0.22.207:8089" --elevator-base-url "http://10.0.22.207:16112" --use-preset-cases --visitor-person-ids "$(python3 -c 'print(",".join(str(9199000100000000000+i) for i in range(1,26)))')" --probe-with-businessid --batch-output-summary "batch-preset-static-$(date +%Y%m%d-%H%M%S).json"
|
||||
```
|
||||
|
||||
结果见 `report/batch-preset-static-*.json`。
|
||||
|
||||
### 4.0.1 执行后数据库核验(必须)
|
||||
|
||||
在完成 §4.0 且已拿到批量 JSON 后,于**与本环境电梯服务写入同一套库的** MySQL(`cw-elevator-application`)执行:
|
||||
|
||||
`sql/标准批量25访客-执行后核验.sql`
|
||||
|
||||
**如何对照判断「是否跑成功」**
|
||||
|
||||
1. 打开本轮 `report/batch-preset-static-*.json`,对每条样本看 `steps.add_visitor.business_ok`、`derived.floor_count`、`grade`。
|
||||
2. 对 **`add_visitor` 业务成功** 且 `passRule/image` HTTP 大体正常的样本,在同一库中期望:查询 **A** 中该行访客的 **`active_row_count` ≥ 1**(租户策略或写库链路正常时,`person_delete=0` 的规则行应与接口返回楼层有对应);**全部为 0** 则重点排查写库延迟、租户/访客 ID 不真实、或网关虽 200 实际未打到目标实例。
|
||||
3. 查询 **B** 与 JSON 内 `derived.floors[].zoneId` 做逐项比对;若库中 `person_delete=1` 的历史行较多,结合 `last_update_time` 看是否为本次执行产生的新生效行。
|
||||
4. 若访客号段与本包约定不一致(非 `919900…`),请改用 `sql/人工核查最终楼层结果.sql`,将 `IN (...)` 换为当天 JSON 中全部 `resolved_visitor_person_id`。
|
||||
|
||||
### 4.1 进入发布目录
|
||||
|
||||
```bash
|
||||
cd docs/testing/release-visitor-noauth-verify-v20260430
|
||||
```
|
||||
|
||||
### 4.2 样本1(广发基金基线)执行
|
||||
|
||||
本节「黄平 + 蒙海文」样本用于:**无鉴权下探针是否可走通**,以及 **`passRule/image` 返回是否与租户策略语义一致**。它**不是用来**证明「在本次执行中产出了全新访客主数据」——`add/visitor` 传入的是已在组织/电梯侧建档的访客 `personId` 时,写库常为**续约/补齐规则**,`image_rule_ref` 里的行常与**历史登记**混在一起。
|
||||
|
||||
若验收目标是「必须先有真实新增访客,再验证派梯」,请:
|
||||
|
||||
- **优先**:走 **§4.0** 约定号段 **`9199000100000000001`~`…0025`** 的批量预置链路(租户内已预置对应用人,`image_rule_ref` 证据与 JSON 对齐);
|
||||
- 或:业务流程上**新开一名访客**,再将其 `visitorPersonId` 交给本脚本;查库时对 `last_update_time` 与脚本 JSON 顶层 **`started_at`** 做对时(仅能辅助说明「本轮是否写过」)。
|
||||
|
||||
```bash
|
||||
python3 python/quick_verify_visitor_floor_policy.py \
|
||||
--mode noauth-probe \
|
||||
--org-base-url "http://10.0.22.207:8089" \
|
||||
--elevator-base-url "http://10.0.22.207:16112" \
|
||||
--business-id "2524639890ba4f2cba9ba1a4eeaa4015" \
|
||||
--meng-person-id "964454497399468032" \
|
||||
--visitor-person-id "1102270499947507712" \
|
||||
--probe-with-businessid
|
||||
```
|
||||
|
||||
### 4.3 样本2(其他公司多部门)执行
|
||||
|
||||
在与**当前验证目标环境一致**的 MySQL 上执行 `sql/批量样本筛选-多公司多部门.sql`(或等价查询),导出被访人到 `sql/batch_cases.csv`。**禁止**用开发环境数据库导出样本却去打生产 HTTP。**开发环境快照仅可用于开发联调**,生产走查必须使用生产侧数据或手写/审批过的样本 CSV。
|
||||
|
||||
```bash
|
||||
python3 python/quick_verify_visitor_floor_policy.py \
|
||||
--mode noauth-probe \
|
||||
--org-base-url "http://10.0.22.207:8089" \
|
||||
--elevator-base-url "http://10.0.22.207:16112" \
|
||||
--batch-input-csv "sql/batch_cases.csv" \
|
||||
--visitor-person-ids "<访客ID1>,<访客ID2>,<访客ID3>" \
|
||||
--visitor-names "黄志平A,黄志平B,黄志平C" \
|
||||
--probe-with-businessid
|
||||
```
|
||||
|
||||
建议最少覆盖:
|
||||
- 3 个不同公司;
|
||||
- 每公司 2 个不同部门被访人。
|
||||
|
||||
若已导出 `docs/testing/_cw_is_person__202604302030.csv`,可直接自动筛选(排除广发基金):
|
||||
|
||||
```bash
|
||||
python3 python/quick_verify_visitor_floor_policy.py \
|
||||
--mode noauth-probe \
|
||||
--org-base-url "http://10.0.22.207:8089" \
|
||||
--elevator-base-url "http://10.0.22.207:16112" \
|
||||
--batch-source-person-csv "../_cw_is_person__202604302030.csv" \
|
||||
--exclude-business-ids "2524639890ba4f2cba9ba1a4eeaa4015" \
|
||||
--sample-companies 3 \
|
||||
--sample-persons-per-company 2 \
|
||||
--visitor-person-ids "<访客ID1>,<访客ID2>,<访客ID3>" \
|
||||
--visitor-names "黄志平A,黄志平B,黄志平C" \
|
||||
--probe-with-businessid
|
||||
```
|
||||
|
||||
说明:
|
||||
- 自动筛选依赖列:`BUSINESS_ID`,`ID`,`NAME`;若存在 **`IS_DEL`**,脚本会**跳过已删除行**(`IS_DEL≠0` 或与 `true`/`1` 等价)。
|
||||
- 该 CSV 若无标准部门列,汇总中 `department` 将为空。
|
||||
|
||||
### 4.4 结果判定
|
||||
|
||||
脚本 `noauth-probe` 对每条样本计算 `grade`(单样本写入 `quick-verify-*.json`;批量写入每条 `results[]`):
|
||||
|
||||
- `grade=high_risk`:任一步均未出现 401/403,且 **`add/visitor` 的 HTTP 成功(<300)且接口业务码判定为成功**(`business_ok`),判定高风险放开(安全问题成立)。若仅 HTTP 200 但业务失败,归为 `needs_review`,不是 `high_risk`。
|
||||
- `grade=expected_block`:**人员详情、`add/visitor`、`passRule/image` 任一步**出现 401/403,视为无鉴权被拦截,符合安全预期。
|
||||
- `grade=needs_review`:未出现 401/403,但未达到上述「放行且业务成功」条件(例如网关超时、业务码失败等),需人工复核。
|
||||
- `grade=failed`(批量中单条可出现):访客 `personId` 无法解析且无内置兜底等情况,脚本未完成调链;不按上述安全三档解释,需先看 `summary`/JSON 报错原因。
|
||||
|
||||
### 4.5 汇总输出(必须)
|
||||
|
||||
最终按样本输出表格(建议 CSV/Markdown;字段可从批量 JSON **`results[]`** 各条中取):
|
||||
|
||||
- 公司:`sample.company`
|
||||
- 部门:`sample.department`
|
||||
- 被访人 `personId`:`args.meng_person_id`
|
||||
- 访客 `personId`:`args.resolved_visitor_person_id`
|
||||
- **`add/visitor` 业务码**:`steps.add_visitor.business_code`(及 `http_status`)
|
||||
- **`passRule/image`**:`steps.passrule_image` 内的 `business_code` / `http_status`
|
||||
- 楼层数量:`derived.floor_count`
|
||||
- 楼层清单:`derived.floors`(元素含 `zoneId`/`zoneName`)
|
||||
- 安全分档:`grade`、`summary`
|
||||
|
||||
控制台会摘要打印 `company/department`、`addCode`、`floorCount`;完整以 JSON 为准。
|
||||
|
||||
批量汇总文件:**默认** `report/batch-summary.json`;若使用了 `--batch-output-summary`(如 §4.0 的 `batch-preset-static-*.json`),则路径为 **`report/` + 传入文件名**。
|
||||
|
||||
### 4.6 人工 SQL 核查最终结果(最后一步)
|
||||
|
||||
- §4.0 固定 25 号段:**优先**执行 `sql/标准批量25访客-执行后核验.sql`。
|
||||
- 其它访客清单或单笔核对:执行 `sql/人工核查最终楼层结果.sql`,自行替换 `IN (...)`。
|
||||
|
||||
核查要点:
|
||||
- 按本次访客ID集合过滤,确认 `person_delete=0` 的有效规则;
|
||||
- 对比 `zone_id` 与脚本输出楼层清单;
|
||||
- 如存在历史残留,结合 `create_time` / **`last_update_time`**(`image_rule_ref`)判定最新记录。
|
||||
|
||||
### 4.7 业务侧整改后关键日志检查点
|
||||
|
||||
本版整改聚焦业务策略链路,不调整鉴权逻辑。应用日志需出现:
|
||||
|
||||
- 策略决策日志(`PersonRuleServiceImpl`)含字段:
|
||||
- `policyDecision`、`hostFloorSize`、`allowFloorSize`、`effectiveFloorSize`(有一条覆盖生效日志中占位名为 `effectiveSize`,与同次决策中的楼层数量一致)、`policyId`、`policyVersion`
|
||||
|
||||
失败路径上的告警亦多为 `WARN`/`INFO`(如「访客派梯楼层决策失败-…」「allow_zone_ids JSON 无效」),便于在无 DEBUG 前提下排查。**是否仍存在「仅为探针、且仍为 DEBUG」的日志行,请以当前发布包镜像实际 `logback` 与源码为准逐项核对**。
|
||||
|
||||
## 5. 证据留档
|
||||
|
||||
至少归档以下内容:
|
||||
|
||||
1. 执行命令
|
||||
2. 脚本输出摘要(控制台)
|
||||
3. 生成的 JSON:**单样本** `report/quick-verify-*.json`;**标准批量** `report/batch-preset-static-*.json` 或其他 `--batch-output-summary` 指定名
|
||||
4. **`sql/标准批量25访客-执行后核验.sql`(或等价)查询导出**与其它 SQL 核验结果一并留档
|
||||
5. 关键接口返回截图/日志
|
||||
Reference in New Issue
Block a user