flnxi-Wu/license-server/lib/__tests__/module-grants.test.ts
2026-06-02 19:25:48 +08:00

135 lines
4.3 KiB
TypeScript

type GrantRecord = {
licenseId: string;
moduleId: string;
status: 'active' | 'disabled' | 'revoked';
image?: string | null;
version?: string | null;
digest?: string | null;
expiresAt?: Date | null;
revokedAt?: Date | null;
};
function createFakePrisma(initial: GrantRecord[] = []) {
const grants = new Map<string, GrantRecord>();
for (const grant of initial) {
grants.set(`${grant.licenseId}:${grant.moduleId}`, grant);
}
return {
grants,
licenseModuleGrant: {
findUnique: jest.fn(async ({ where }) => {
const key = `${where.licenseId_moduleId.licenseId}:${where.licenseId_moduleId.moduleId}`;
return grants.get(key) || null;
}),
findMany: jest.fn(async ({ where, orderBy }) => {
const now = where.OR?.[1]?.expiresAt?.gt;
const result = Array.from(grants.values()).filter((grant) => {
if (grant.licenseId !== where.licenseId) return false;
if (grant.status !== where.status) return false;
if (where.revokedAt === null && grant.revokedAt) return false;
if (!grant.expiresAt) return true;
return now ? grant.expiresAt > now : true;
});
if (orderBy?.moduleId === 'asc') {
result.sort((left, right) => left.moduleId.localeCompare(right.moduleId));
}
return result;
}),
create: jest.fn(async ({ data }) => {
const record = { ...data, revokedAt: null } as GrantRecord;
grants.set(`${record.licenseId}:${record.moduleId}`, record);
return record;
}),
},
};
}
describe('module-grants', () => {
beforeEach(() => {
process.env.PREMIUM_MODULE_REGISTRY_BASE = 'registry.test/flnxi/premium';
process.env.PREMIUM_MODULE_VERSION = '1.0.0';
});
afterEach(() => {
delete process.env.PREMIUM_MODULE_REGISTRY_BASE;
delete process.env.PREMIUM_MODULE_VERSION;
});
it('应按许可证版本初始化默认模块授权台账', async () => {
const { ensureDefaultModuleGrants } = await import('../module-grants');
const prisma = createFakePrisma();
await ensureDefaultModuleGrants(prisma, {
id: 'license-1',
licenseType: 'STANDARD',
expiresAt: null,
});
expect(prisma.licenseModuleGrant.create).toHaveBeenCalledTimes(2);
expect(Array.from(prisma.grants.keys()).sort()).toEqual([
'license-1:custom-templates-core',
'license-1:license-limits-core',
]);
});
it('已禁用的模块授权不应被默认初始化重新启用', async () => {
const { ensureDefaultModuleGrants, getAuthorizedModuleGrant } = await import('../module-grants');
const prisma = createFakePrisma([
{
licenseId: 'license-1',
moduleId: 'custom-templates-core',
status: 'disabled',
image: 'registry.test/flnxi/premium/custom-templates-core:1.0.0',
version: '1.0.0',
digest: null,
expiresAt: null,
revokedAt: null,
},
]);
const license = { id: 'license-1', licenseType: 'STANDARD' as const, expiresAt: null };
await ensureDefaultModuleGrants(prisma, license);
expect(prisma.grants.get('license-1:custom-templates-core')?.status).toBe('disabled');
await expect(getAuthorizedModuleGrant(prisma, license, 'custom-templates-core')).resolves.toBeNull();
});
it('被吊销或过期的模块不应出现在授权清单里', async () => {
const { listAuthorizedModuleGrants } = await import('../module-grants');
const prisma = createFakePrisma([
{
licenseId: 'license-1',
moduleId: 'license-limits-core',
status: 'active',
expiresAt: null,
revokedAt: null,
},
{
licenseId: 'license-1',
moduleId: 'custom-templates-core',
status: 'active',
expiresAt: null,
revokedAt: new Date('2026-05-01T00:00:00.000Z'),
},
{
licenseId: 'license-1',
moduleId: 'intranet-penetration-core',
status: 'active',
expiresAt: new Date('2026-05-30T00:00:00.000Z'),
revokedAt: null,
},
]);
const grants = await listAuthorizedModuleGrants(
prisma,
{ id: 'license-1', licenseType: 'PRO', expiresAt: null },
new Date('2026-06-02T00:00:00.000Z')
);
expect(grants.map((grant) => grant.moduleId)).toEqual(['license-limits-core']);
});
});