165 lines
5.0 KiB
TypeScript
165 lines
5.0 KiB
TypeScript
|
|
import { test, expect } from '../fixtures/auth.fixture';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 多租户数据隔离测试
|
||
|
|
* 验证不同租户之间的数据隔离
|
||
|
|
*/
|
||
|
|
|
||
|
|
test.describe('多租户数据隔离测试', () => {
|
||
|
|
|
||
|
|
const API_BASE = 'http://localhost:8580';
|
||
|
|
|
||
|
|
test.describe('用户数据隔离', () => {
|
||
|
|
|
||
|
|
test('TC-TENANT-001: 超管跨租户查询用户', async ({ request, loginViaAPI }) => {
|
||
|
|
// 使用超管账号登录
|
||
|
|
const { token } = await loginViaAPI('platform');
|
||
|
|
|
||
|
|
// 查询用户列表(超管应该能看到所有租户的用户)
|
||
|
|
const response = await request.get(`${API_BASE}/api/users`, {
|
||
|
|
headers: {
|
||
|
|
Authorization: `Bearer ${token}`,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
const data = await response.json();
|
||
|
|
expect(data.code).toBe(200);
|
||
|
|
|
||
|
|
console.log('✓ TC-TENANT-001 通过:超管跨租户查询用户');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('TC-TENANT-002: 租户查询本租户用户', async ({ request, loginViaAPI }) => {
|
||
|
|
// 使用租户账号登录
|
||
|
|
const { token, tenantCode } = await loginViaAPI('gdlib');
|
||
|
|
|
||
|
|
// 查询用户列表(租户应该只能看到本租户的用户)
|
||
|
|
const response = await request.get(`${API_BASE}/api/users`, {
|
||
|
|
headers: {
|
||
|
|
Authorization: `Bearer ${token}`,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
const data = await response.json();
|
||
|
|
expect(data.code).toBe(200);
|
||
|
|
|
||
|
|
// 验证返回的用户都属于当前租户
|
||
|
|
if (data.data && data.data.records) {
|
||
|
|
data.data.records.forEach((user: any) => {
|
||
|
|
expect(user.tenantCode).toBe(tenantCode);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
console.log('✓ TC-TENANT-002 通过:租户查询本租户用户');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('TC-TENANT-003: 租户查询他租户用户', async ({ request, loginViaAPI }) => {
|
||
|
|
// 使用 gdlib 租户账号登录
|
||
|
|
const { token } = await loginViaAPI('gdlib');
|
||
|
|
|
||
|
|
// 尝试查询其他租户的用户(应该返回空列表或无权限)
|
||
|
|
const response = await request.get(`${API_BASE}/api/users?tenantCode=platform`, {
|
||
|
|
headers: {
|
||
|
|
Authorization: `Bearer ${token}`,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
const data = await response.json();
|
||
|
|
|
||
|
|
// 应该返回空列表或无权限错误
|
||
|
|
if (data.code === 200 && data.data && data.data.records) {
|
||
|
|
expect(data.data.records.length).toBe(0);
|
||
|
|
} else {
|
||
|
|
// 或者返回无权限错误
|
||
|
|
expect(data.code).not.toBe(200);
|
||
|
|
}
|
||
|
|
|
||
|
|
console.log('✓ TC-TENANT-003 通过:租户查询他租户用户');
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
test.describe('角色数据隔离', () => {
|
||
|
|
|
||
|
|
test('租户只能查看本租户角色', async ({ request, loginViaAPI }) => {
|
||
|
|
// 使用租户账号登录
|
||
|
|
const { token, tenantCode } = await loginViaAPI('gdlib');
|
||
|
|
|
||
|
|
// 查询角色列表
|
||
|
|
const response = await request.get(`${API_BASE}/api/roles`, {
|
||
|
|
headers: {
|
||
|
|
Authorization: `Bearer ${token}`,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
const data = await response.json();
|
||
|
|
expect(data.code).toBe(200);
|
||
|
|
|
||
|
|
// 验证返回的角色都属于当前租户
|
||
|
|
if (data.data && data.data.records) {
|
||
|
|
data.data.records.forEach((role: any) => {
|
||
|
|
expect(role.tenantCode).toBe(tenantCode);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
console.log('✓ 租户只能查看本租户角色');
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
test.describe('菜单数据隔离', () => {
|
||
|
|
|
||
|
|
test('不同租户返回不同菜单', async ({ request, loginViaAPI }) => {
|
||
|
|
// 分别登录不同租户
|
||
|
|
const platformToken = await loginViaAPI('platform').then(r => r.token);
|
||
|
|
const gdlibToken = await loginViaAPI('gdlib').then(r => r.token);
|
||
|
|
|
||
|
|
// 获取菜单
|
||
|
|
const platformMenus = await request.get(`${API_BASE}/api/menus`, {
|
||
|
|
headers: { Authorization: `Bearer ${platformToken}` },
|
||
|
|
}).then(r => r.json());
|
||
|
|
|
||
|
|
const gdlibMenus = await request.get(`${API_BASE}/api/menus`, {
|
||
|
|
headers: { Authorization: `Bearer ${gdlibToken}` },
|
||
|
|
}).then(r => r.json());
|
||
|
|
|
||
|
|
// 验证菜单存在
|
||
|
|
expect(platformMenus.code).toBe(200);
|
||
|
|
expect(gdlibMenus.code).toBe(200);
|
||
|
|
|
||
|
|
console.log('✓ 不同租户返回菜单');
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
test.describe('权限验证', () => {
|
||
|
|
|
||
|
|
test('Token 包含租户信息', async ({ request, loginViaAPI }) => {
|
||
|
|
const { token, tenantCode } = await loginViaAPI('gdlib');
|
||
|
|
|
||
|
|
// 验证 Token 格式
|
||
|
|
expect(token).toBeTruthy();
|
||
|
|
expect(token.split('.').length).toBe(3);
|
||
|
|
|
||
|
|
// Token 中应该包含租户信息
|
||
|
|
const tokenBody = JSON.parse(
|
||
|
|
Buffer.from(token.split('.')[1], 'base64').toString('utf-8')
|
||
|
|
);
|
||
|
|
expect(tokenBody.tenantCode).toBe(tenantCode);
|
||
|
|
|
||
|
|
console.log('✓ Token 包含租户信息');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('超管标识验证', async ({ request, loginViaAPI }) => {
|
||
|
|
// 登录超管账号
|
||
|
|
const { token } = await loginViaAPI('platform');
|
||
|
|
|
||
|
|
// 解析 Token
|
||
|
|
const tokenBody = JSON.parse(
|
||
|
|
Buffer.from(token.split('.')[1], 'base64').toString('utf-8')
|
||
|
|
);
|
||
|
|
|
||
|
|
// 验证超管标识
|
||
|
|
expect(tokenBody.isSuperTenant).toBeTruthy();
|
||
|
|
|
||
|
|
console.log('✓ 超管标识验证通过');
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|