feat(postgres): add tenant seckill permission seed script

This commit is contained in:
2026-03-02 13:08:28 +08:00
parent de7aefd0ff
commit 5da102c97c
2 changed files with 278 additions and 0 deletions

View File

@@ -6,6 +6,7 @@
- `create_databases.sql`:创建四个业务库与对应角色(可多次执行,存在则跳过)。 - `create_databases.sql`:创建四个业务库与对应角色(可多次执行,存在则跳过)。
- `bootstrap.ps1`PowerShell 包装脚本,调用 `psql` 执行 SQL。 - `bootstrap.ps1`PowerShell 包装脚本,调用 `psql` 执行 SQL。
- `seed_tenant_seckill_permissions.sql`:补齐租户端秒杀活动权限码、菜单权限与角色授权映射(可重复执行)。
## 前置条件 ## 前置条件
@@ -38,6 +39,20 @@ cd deploy/postgres
- 如需修改密码或新增库,编辑 `create_databases.sql` 后重新运行脚本。 - 如需修改密码或新增库,编辑 `create_databases.sql` 后重新运行脚本。
- 若在本地拉起测试库,可把 `Host` 指向 `localhost`,其余参数保持一致。 - 若在本地拉起测试库,可把 `Host` 指向 `localhost`,其余参数保持一致。
## 秒杀权限补齐
`takeout_identity_db` 执行:
```powershell
psql -h <host> -p <port> -U identity_user -d takeout_identity_db -f .\seed_tenant_seckill_permissions.sql
```
脚本会完成:
1. 新增/修正 `tenant:marketing:seckill:*` 权限码。
2. 更新秒杀菜单 (`/marketing/seckill/index`) 的 `RequiredPermissions``MetaPermissions``AuthListJson`
3. 参考满减权限映射,补齐角色模板与租户角色的秒杀权限授权。
## 常见问题 ## 常见问题
| 问题 | 处理方式 | | 问题 | 处理方式 |

View File

@@ -0,0 +1,263 @@
-- 文件职责:补齐 Tenant 端秒杀活动权限与菜单权限绑定(可重复执行)。
-- 执行范围takeout_identity 数据库Portal=1Tenant 端)。
BEGIN;
-- 1) 新增/修正营销中心秒杀权限码
WITH seckill_permissions(code, name, sort_order) AS (
VALUES
('tenant:marketing:seckill:view', '查看秒杀活动', 29),
('tenant:marketing:seckill:create', '创建秒杀活动', 30),
('tenant:marketing:seckill:update', '编辑秒杀活动', 31),
('tenant:marketing:seckill:delete', '删除秒杀活动', 32),
('tenant:marketing:seckill:status', '切换秒杀状态', 33)
),
missing AS (
SELECT
s.code,
s.name,
s.sort_order,
ROW_NUMBER() OVER (ORDER BY s.sort_order, s.code) AS rn
FROM seckill_permissions s
LEFT JOIN public.permissions p
ON p."Code" = s.code
WHERE p."Id" IS NULL
),
base AS (
SELECT COALESCE(MAX("Id"), 820000000000000000) AS max_id
FROM public.permissions
)
INSERT INTO public.permissions
(
"Id", "Name", "Code", "Description", "CreatedAt", "UpdatedAt", "DeletedAt",
"CreatedBy", "UpdatedBy", "DeletedBy", "ParentId", "SortOrder", "Type", "Portal"
)
SELECT
base.max_id + missing.rn,
missing.name,
missing.code,
NULL,
NOW(),
NULL,
NULL,
NULL,
NULL,
NULL,
820000000000000005,
missing.sort_order,
'leaf',
1
FROM missing
CROSS JOIN base;
WITH seckill_permissions(code, name, sort_order) AS (
VALUES
('tenant:marketing:seckill:view', '查看秒杀活动', 29),
('tenant:marketing:seckill:create', '创建秒杀活动', 30),
('tenant:marketing:seckill:update', '编辑秒杀活动', 31),
('tenant:marketing:seckill:delete', '删除秒杀活动', 32),
('tenant:marketing:seckill:status', '切换秒杀状态', 33)
)
UPDATE public.permissions p
SET
"Name" = s.name,
"ParentId" = 820000000000000005,
"SortOrder" = s.sort_order,
"Type" = 'leaf',
"Portal" = 1,
"DeletedAt" = NULL,
"DeletedBy" = NULL,
"UpdatedAt" = NOW()
FROM seckill_permissions s
WHERE p."Code" = s.code;
-- 2) 绑定秒杀菜单的访问权限与按钮权限
UPDATE public.menu_definitions
SET
"RequiredPermissions" = 'tenant:marketing:seckill:view',
"MetaPermissions" = 'tenant:marketing:seckill:view,tenant:marketing:seckill:create,tenant:marketing:seckill:update,tenant:marketing:seckill:delete,tenant:marketing:seckill:status',
"AuthListJson" = '[{"title":"创建","authMark":"tenant:marketing:seckill:create"},{"title":"编辑","authMark":"tenant:marketing:seckill:update"},{"title":"删除","authMark":"tenant:marketing:seckill:delete"},{"title":"停启用","authMark":"tenant:marketing:seckill:status"}]',
"UpdatedAt" = NOW()
WHERE
"Portal" = 1
AND ("Path" = 'seckill' OR "Component" = '/marketing/seckill/index');
-- 3) 给角色模板补齐秒杀权限(按满减权限映射)
WITH code_mapping(source_code, target_code) AS (
VALUES
('tenant:marketing:full-reduction:view', 'tenant:marketing:seckill:view'),
('tenant:marketing:full-reduction:create', 'tenant:marketing:seckill:create'),
('tenant:marketing:full-reduction:update', 'tenant:marketing:seckill:update'),
('tenant:marketing:full-reduction:delete', 'tenant:marketing:seckill:delete'),
('tenant:marketing:full-reduction:update', 'tenant:marketing:seckill:status')
),
candidates AS (
SELECT DISTINCT
rtp."RoleTemplateId",
mapping.target_code
FROM public.role_template_permissions rtp
INNER JOIN code_mapping mapping
ON mapping.source_code = rtp."PermissionCode"
WHERE rtp."DeletedAt" IS NULL
),
missing AS (
SELECT
c."RoleTemplateId",
c.target_code,
ROW_NUMBER() OVER (ORDER BY c."RoleTemplateId", c.target_code) AS rn
FROM candidates c
LEFT JOIN public.role_template_permissions existing
ON existing."RoleTemplateId" = c."RoleTemplateId"
AND existing."PermissionCode" = c.target_code
WHERE existing."Id" IS NULL
),
base AS (
SELECT COALESCE(MAX("Id"), 820000000000000000) AS max_id
FROM public.role_template_permissions
)
INSERT INTO public.role_template_permissions
(
"Id", "RoleTemplateId", "PermissionCode", "CreatedAt", "UpdatedAt", "DeletedAt",
"CreatedBy", "UpdatedBy", "DeletedBy"
)
SELECT
base.max_id + missing.rn,
missing."RoleTemplateId",
missing.target_code,
NOW(),
NULL,
NULL,
NULL,
NULL,
NULL
FROM missing
CROSS JOIN base;
WITH code_mapping(source_code, target_code) AS (
VALUES
('tenant:marketing:full-reduction:view', 'tenant:marketing:seckill:view'),
('tenant:marketing:full-reduction:create', 'tenant:marketing:seckill:create'),
('tenant:marketing:full-reduction:update', 'tenant:marketing:seckill:update'),
('tenant:marketing:full-reduction:delete', 'tenant:marketing:seckill:delete'),
('tenant:marketing:full-reduction:update', 'tenant:marketing:seckill:status')
)
UPDATE public.role_template_permissions target
SET
"DeletedAt" = NULL,
"DeletedBy" = NULL,
"UpdatedAt" = NOW()
FROM public.role_template_permissions source
INNER JOIN code_mapping mapping
ON mapping.source_code = source."PermissionCode"
WHERE
source."RoleTemplateId" = target."RoleTemplateId"
AND target."PermissionCode" = mapping.target_code;
-- 4) 给租户角色补齐秒杀权限(按满减权限映射)
WITH code_mapping(source_code, target_code) AS (
VALUES
('tenant:marketing:full-reduction:view', 'tenant:marketing:seckill:view'),
('tenant:marketing:full-reduction:create', 'tenant:marketing:seckill:create'),
('tenant:marketing:full-reduction:update', 'tenant:marketing:seckill:update'),
('tenant:marketing:full-reduction:delete', 'tenant:marketing:seckill:delete'),
('tenant:marketing:full-reduction:update', 'tenant:marketing:seckill:status')
),
source_rows AS (
SELECT DISTINCT
rp."RoleId",
rp."TenantId",
rp."Portal",
mapping.target_code
FROM public.role_permissions rp
INNER JOIN public.permissions source_permission
ON source_permission."Id" = rp."PermissionId"
INNER JOIN code_mapping mapping
ON mapping.source_code = source_permission."Code"
WHERE rp."DeletedAt" IS NULL
AND rp."Portal" = 1
),
candidates AS (
SELECT DISTINCT
s."RoleId",
s."TenantId",
s."Portal",
target_permission."Id" AS target_permission_id
FROM source_rows s
INNER JOIN public.permissions target_permission
ON target_permission."Code" = s.target_code
),
missing AS (
SELECT
c."RoleId",
c."TenantId",
c."Portal",
c.target_permission_id,
ROW_NUMBER() OVER (
ORDER BY c."TenantId", c."RoleId", c.target_permission_id
) AS rn
FROM candidates c
LEFT JOIN public.role_permissions existing
ON existing."RoleId" = c."RoleId"
AND existing."PermissionId" = c.target_permission_id
AND existing."Portal" = c."Portal"
AND (
(existing."TenantId" IS NULL AND c."TenantId" IS NULL)
OR existing."TenantId" = c."TenantId"
)
WHERE existing."Id" IS NULL
),
base AS (
SELECT COALESCE(MAX("Id"), 830000000000000000) AS max_id
FROM public.role_permissions
)
INSERT INTO public.role_permissions
(
"Id", "RoleId", "PermissionId", "CreatedAt", "UpdatedAt", "DeletedAt",
"CreatedBy", "UpdatedBy", "DeletedBy", "TenantId", "Portal"
)
SELECT
base.max_id + missing.rn,
missing."RoleId",
missing.target_permission_id,
NOW(),
NULL,
NULL,
NULL,
NULL,
NULL,
missing."TenantId",
missing."Portal"
FROM missing
CROSS JOIN base;
WITH code_mapping(source_code, target_code) AS (
VALUES
('tenant:marketing:full-reduction:view', 'tenant:marketing:seckill:view'),
('tenant:marketing:full-reduction:create', 'tenant:marketing:seckill:create'),
('tenant:marketing:full-reduction:update', 'tenant:marketing:seckill:update'),
('tenant:marketing:full-reduction:delete', 'tenant:marketing:seckill:delete'),
('tenant:marketing:full-reduction:update', 'tenant:marketing:seckill:status')
)
UPDATE public.role_permissions target
SET
"DeletedAt" = NULL,
"DeletedBy" = NULL,
"UpdatedAt" = NOW()
FROM public.role_permissions source
INNER JOIN public.permissions source_permission
ON source_permission."Id" = source."PermissionId"
INNER JOIN code_mapping mapping
ON mapping.source_code = source_permission."Code"
INNER JOIN public.permissions target_permission
ON target_permission."Code" = mapping.target_code
WHERE
source."Portal" = 1
AND target."Portal" = source."Portal"
AND target."RoleId" = source."RoleId"
AND target."PermissionId" = target_permission."Id"
AND (
(target."TenantId" IS NULL AND source."TenantId" IS NULL)
OR target."TenantId" = source."TenantId"
);
COMMIT;