2026-09-21 14:57:05 +08:00
|
|
|
|
-- ============================================================================
|
|
|
|
|
|
-- Migration: 015_dms_package_a_hardening.sql
|
|
|
|
|
|
-- Description: Package A.1 DMS 一致性加固与最小权限拆分
|
2026-09-24 01:22:03 +08:00
|
|
|
|
-- 1. 权限最小化拆分:新增 2194 (train:access:credential),从 train_admin 移除 2192 (train:access:manage) 并保证保留 2263 (train:accommodation:edit)
|
2026-09-21 16:14:07 +08:00
|
|
|
|
-- 2. 外部操作状态加固:确保 train_external_operation 支持 DISPATCHING 与 AMBIGUOUS
|
2026-09-21 14:57:05 +08:00
|
|
|
|
-- 3. 幂等与断言校验
|
|
|
|
|
|
-- ============================================================================
|
|
|
|
|
|
|
|
|
|
|
|
\set ON_ERROR_STOP on
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN;
|
|
|
|
|
|
|
|
|
|
|
|
-- 1. 注册 2194 (train:access:credential) 门禁凭据下发与注销专用权限
|
|
|
|
|
|
INSERT INTO public.sys_menu
|
|
|
|
|
|
(menu_id, menu_name, parent_id, order_num, path, component, query, is_frame, is_cache,
|
|
|
|
|
|
menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
|
|
|
|
|
SELECT 2194, '门禁凭据操作', 2060, 4, '#', '', '', 1, 0,
|
|
|
|
|
|
'F', '0', '0', 'train:access:credential', '#', 'admin', CURRENT_TIMESTAMP, '', NULL, '门禁凭据下发与注销权限'
|
|
|
|
|
|
WHERE NOT EXISTS (SELECT 1 FROM public.sys_menu WHERE menu_id = 2194);
|
|
|
|
|
|
|
|
|
|
|
|
-- 2. 超级管理员角色 (role_id = 1) 授予 2194
|
|
|
|
|
|
INSERT INTO public.sys_role_menu (role_id, menu_id)
|
|
|
|
|
|
SELECT 1, 2194
|
|
|
|
|
|
WHERE NOT EXISTS (SELECT 1 FROM public.sys_role_menu WHERE role_id = 1 AND menu_id = 2194);
|
|
|
|
|
|
|
|
|
|
|
|
-- 3. 培训管理员角色 (role_id = 3) 调整权限 (MIN-09):
|
|
|
|
|
|
-- 授予 2194 (train:access:credential)
|
|
|
|
|
|
INSERT INTO public.sys_role_menu (role_id, menu_id)
|
|
|
|
|
|
SELECT 3, 2194
|
|
|
|
|
|
WHERE NOT EXISTS (SELECT 1 FROM public.sys_role_menu WHERE role_id = 3 AND menu_id = 2194);
|
|
|
|
|
|
|
|
|
|
|
|
-- 从 train_admin (role_id = 3) 回收 2192 (train:access:manage,硬件映射与维护权限)
|
|
|
|
|
|
DELETE FROM public.sys_role_menu
|
|
|
|
|
|
WHERE role_id = 3 AND menu_id = 2192;
|
|
|
|
|
|
|
2026-09-24 01:22:03 +08:00
|
|
|
|
-- 确保培训管理员 (role_id = 3) 拥有 2263 (train:accommodation:edit,办理入住/退宿/调房)
|
|
|
|
|
|
INSERT INTO public.sys_role_menu (role_id, menu_id)
|
|
|
|
|
|
SELECT 3, 2263
|
|
|
|
|
|
WHERE NOT EXISTS (SELECT 1 FROM public.sys_role_menu WHERE role_id = 3 AND menu_id = 2263);
|
2026-09-21 14:57:05 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-09-21 16:14:07 +08:00
|
|
|
|
|
|
|
|
|
|
-- 5. 状态机约束兼容性加固 (train_external_operation)
|
2026-09-21 14:57:05 +08:00
|
|
|
|
-- 确保 operation_status 允许 DISPATCHING 与 AMBIGUOUS
|
2026-09-21 16:14:07 +08:00
|
|
|
|
ALTER TABLE train_external_operation DROP CONSTRAINT IF EXISTS chk_external_operation_status;
|
|
|
|
|
|
|
|
|
|
|
|
ALTER TABLE train_external_operation ADD CONSTRAINT chk_external_operation_status
|
|
|
|
|
|
CHECK (operation_status IN ('CREATED','DISPATCHING','REQUESTED','ACCEPTED','PENDING','RETRY_WAIT','AMBIGUOUS','SUCCESS','FAILED','TIMEOUT'));
|
2026-09-21 14:57:05 +08:00
|
|
|
|
|
|
|
|
|
|
-- 6. 后置断言验证
|
|
|
|
|
|
DO $$
|
|
|
|
|
|
BEGIN
|
|
|
|
|
|
-- 断言 1: 2194 已正确注册
|
|
|
|
|
|
IF (SELECT count(*) FROM public.sys_menu WHERE menu_id = 2194 AND perms = 'train:access:credential' AND status = '0') <> 1 THEN
|
|
|
|
|
|
RAISE EXCEPTION 'Assertion failed: menu 2194 train:access:credential not found or invalid';
|
|
|
|
|
|
END IF;
|
|
|
|
|
|
|
|
|
|
|
|
-- 断言 2: train_admin (role_id = 3) 拥有 2194 (train:access:credential)
|
|
|
|
|
|
IF (SELECT count(*) FROM public.sys_role_menu WHERE role_id = 3 AND menu_id = 2194) <> 1 THEN
|
|
|
|
|
|
RAISE EXCEPTION 'Assertion failed: role 3 not granted menu 2194';
|
|
|
|
|
|
END IF;
|
|
|
|
|
|
|
|
|
|
|
|
-- 断言 3: train_admin (role_id = 3) 不得拥有 2192 (train:access:manage)
|
|
|
|
|
|
IF (SELECT count(*) FROM public.sys_role_menu WHERE role_id = 3 AND menu_id = 2192) <> 0 THEN
|
|
|
|
|
|
RAISE EXCEPTION 'Assertion failed: role 3 still has menu 2192 (train:access:manage)';
|
|
|
|
|
|
END IF;
|
|
|
|
|
|
|
2026-09-24 01:22:03 +08:00
|
|
|
|
-- 断言 4: train_admin (role_id = 3) 必须拥有 2263 (train:accommodation:edit,办理入住/退宿/调房)
|
|
|
|
|
|
IF (SELECT count(*) FROM public.sys_role_menu WHERE role_id = 3 AND menu_id = 2263) <> 1 THEN
|
|
|
|
|
|
RAISE EXCEPTION 'Assertion failed: role 3 missing menu 2263 (train:accommodation:edit)';
|
|
|
|
|
|
END IF;
|
|
|
|
|
|
|
|
|
|
|
|
-- 断言 4b: train_admin (role_id = 3) 严禁拥有破坏性删除权限 train:accommodation:remove
|
|
|
|
|
|
IF (SELECT count(*) FROM public.sys_role_menu rm
|
|
|
|
|
|
JOIN public.sys_menu m ON m.menu_id = rm.menu_id
|
|
|
|
|
|
WHERE rm.role_id = 3 AND m.perms = 'train:accommodation:remove') <> 0 THEN
|
|
|
|
|
|
RAISE EXCEPTION 'Security violation: role 3 has forbidden permission train:accommodation:remove';
|
2026-09-21 14:57:05 +08:00
|
|
|
|
END IF;
|
|
|
|
|
|
|
|
|
|
|
|
-- 断言 5: train_admin 拥有 2264 (train:accommodation:add)
|
|
|
|
|
|
IF (SELECT count(*) FROM public.sys_role_menu WHERE role_id = 3 AND menu_id = 2264) <> 1 THEN
|
|
|
|
|
|
RAISE EXCEPTION 'Assertion failed: role 3 missing menu 2264 (train:accommodation:add)';
|
|
|
|
|
|
END IF;
|
2026-09-21 16:14:07 +08:00
|
|
|
|
|
|
|
|
|
|
-- 断言 6: operation_status CHECK 约束已生效且包含 DISPATCHING 与 AMBIGUOUS
|
|
|
|
|
|
IF NOT EXISTS (
|
|
|
|
|
|
SELECT 1 FROM pg_constraint
|
|
|
|
|
|
WHERE conrelid = 'train_external_operation'::regclass
|
|
|
|
|
|
AND contype = 'c'
|
|
|
|
|
|
AND pg_get_constraintdef(oid) LIKE '%DISPATCHING%'
|
|
|
|
|
|
AND pg_get_constraintdef(oid) LIKE '%AMBIGUOUS%'
|
|
|
|
|
|
) THEN
|
|
|
|
|
|
RAISE EXCEPTION 'Assertion failed: operation_status constraint invalid or missing DISPATCHING/AMBIGUOUS';
|
|
|
|
|
|
END IF;
|
2026-09-21 14:57:05 +08:00
|
|
|
|
END $$;
|
|
|
|
|
|
|
|
|
|
|
|
COMMIT;
|