forked from wangziqi/gongxue-base
feat: add tenant role templates
This commit is contained in:
@@ -2348,8 +2348,63 @@ async function testTenantMemberPermissionsAndAudit() {
|
||||
userId: TENANT_ADMIN_USER_ID,
|
||||
});
|
||||
assert.ok(permissionMatrix.permissions?.some(item => item.key === 'marketing:write'), 'permission matrix should expose marketing permission');
|
||||
assert.ok(permissionMatrix.permissions?.some(item => item.key === 'roles:write'), 'permission matrix should expose role template permission');
|
||||
assert.ok(permissionMatrix.menuGroups?.some(item => item.key === 'sales'), 'permission matrix should expose menu groups');
|
||||
assert.ok(permissionMatrix.roleDefaults?.tenant_operator?.includes('marketing:*'), 'permission matrix should include role defaults');
|
||||
|
||||
const roleTemplate = await request('/api/tenant-admin/role-templates', {
|
||||
userId: TENANT_ADMIN_USER_ID,
|
||||
method: 'PUT',
|
||||
body: {
|
||||
code: 'ops-marketing',
|
||||
name: '运营活动模板',
|
||||
description: '允许运营维护活动内容,同时可配置前端菜单和字段可见性',
|
||||
baseRole: 'tenant_operator',
|
||||
permissions: {
|
||||
'marketing:*': true,
|
||||
'tenant:payment:write': true,
|
||||
},
|
||||
menuPermissions: {
|
||||
dashboard: true,
|
||||
marketing: true,
|
||||
settings: false,
|
||||
},
|
||||
modulePermissions: {
|
||||
banners: true,
|
||||
coupons: true,
|
||||
},
|
||||
fieldPermissions: {
|
||||
'student.phone': false,
|
||||
'order.amount': true,
|
||||
},
|
||||
dataScope: {
|
||||
mode: 'tenant',
|
||||
ownLeadsOnly: false,
|
||||
},
|
||||
sortOrder: 10,
|
||||
},
|
||||
});
|
||||
assert.equal(roleTemplate.item?.code, 'ops-marketing', 'tenant admin should upsert custom role template');
|
||||
assert.equal(roleTemplate.item?.menuPermissions?.marketing, true, 'role template should persist menu permissions');
|
||||
|
||||
const roleTemplates = await request('/api/tenant-admin/role-templates', {
|
||||
userId: TENANT_ADMIN_USER_ID,
|
||||
});
|
||||
assert.ok(roleTemplates.items?.some(item => item.id === roleTemplate.item.id), 'role template list should include custom template');
|
||||
|
||||
const wildcardTemplateDenied = await request('/api/tenant-admin/role-templates', {
|
||||
userId: TENANT_ADMIN_USER_ID,
|
||||
method: 'PUT',
|
||||
body: {
|
||||
code: 'super-admin-template',
|
||||
name: '危险全权限模板',
|
||||
baseRole: 'tenant_admin',
|
||||
permissions: { '*': true },
|
||||
},
|
||||
expectStatus: 403,
|
||||
});
|
||||
assert.equal(wildcardTemplateDenied.code, 'TENANT_OWNER_REQUIRED', 'tenant admin should not create owner/admin level role template');
|
||||
|
||||
const operator = await request('/api/tenant-admin/members', {
|
||||
userId: TENANT_ADMIN_USER_ID,
|
||||
method: 'PUT',
|
||||
@@ -2359,6 +2414,7 @@ async function testTenantMemberPermissionsAndAudit() {
|
||||
phone: '13800000003',
|
||||
name: 'Integration Operator',
|
||||
role: 'tenant_operator',
|
||||
roleTemplateId: roleTemplate.item.id,
|
||||
status: 'active',
|
||||
permissions: {
|
||||
'marketing:*': true,
|
||||
@@ -2367,12 +2423,20 @@ async function testTenantMemberPermissionsAndAudit() {
|
||||
},
|
||||
});
|
||||
assert.equal(operator.item?.role, 'tenant_operator', 'tenant admin should create operator membership');
|
||||
assert.equal(operator.item?.roleTemplateId, roleTemplate.item.id, 'member should bind custom role template');
|
||||
|
||||
const members = await request('/api/tenant-admin/members', {
|
||||
userId: TENANT_ADMIN_USER_ID,
|
||||
query: { keyword: 'Integration Operator' },
|
||||
});
|
||||
assert.ok(members.items?.some(item => item.userId === TENANT_OPERATOR_USER_ID), 'member list should find operator');
|
||||
assert.ok(members.items?.some(item => item.userId === TENANT_OPERATOR_USER_ID && item.roleTemplateCode === 'ops-marketing'), 'member list should expose role template binding');
|
||||
|
||||
const operatorPermissionMatrix = await request('/api/tenant-admin/permissions', {
|
||||
userId: TENANT_OPERATOR_USER_ID,
|
||||
});
|
||||
assert.equal(operatorPermissionMatrix.current?.roleTemplateCode, 'ops-marketing', 'current permission matrix should include role template');
|
||||
assert.equal(operatorPermissionMatrix.current?.menuPermissions?.marketing, true, 'current permission matrix should expose menu permissions');
|
||||
|
||||
const operatorBanner = await request('/api/tenant-admin/banners', {
|
||||
userId: TENANT_OPERATOR_USER_ID,
|
||||
@@ -2468,12 +2532,21 @@ async function testTenantMemberPermissionsAndAudit() {
|
||||
});
|
||||
assert.equal(disabledSalesDenied.code, 'TENANT_ADMIN_REQUIRED', 'disabled sales membership should lose tenant admin access');
|
||||
|
||||
const disabledTemplate = await request('/api/tenant-admin/role-templates/disable', {
|
||||
userId: TENANT_ADMIN_USER_ID,
|
||||
method: 'POST',
|
||||
body: { roleTemplateId: roleTemplate.item.id },
|
||||
});
|
||||
assert.equal(disabledTemplate.item?.status, 'disabled', 'tenant admin should disable custom role template');
|
||||
|
||||
const auditLogs = await request('/api/tenant-admin/audit-logs', {
|
||||
userId: TENANT_ADMIN_USER_ID,
|
||||
query: { action: 'tenant.member', limit: 20 },
|
||||
query: { action: 'tenant.', limit: 50 },
|
||||
});
|
||||
assert.ok(auditLogs.items?.some(item => item.action === 'tenant.member.upserted'), 'audit logs should include member upsert');
|
||||
assert.ok(auditLogs.items?.some(item => item.action === 'tenant.member.disabled'), 'audit logs should include member disable');
|
||||
assert.ok(auditLogs.items?.some(item => item.action === 'tenant.role_template.upserted'), 'audit logs should include role template upsert');
|
||||
assert.ok(auditLogs.items?.some(item => item.action === 'tenant.role_template.disabled'), 'audit logs should include role template disable');
|
||||
|
||||
const partnerAuditDenied = await request('/api/tenant-admin/audit-logs', {
|
||||
tenantId: PARTNER_TENANT_ID,
|
||||
|
||||
Reference in New Issue
Block a user