flnxi-Wu/license-server/lib/__tests__/abuse-detection.test.ts
2026-05-26 16:47:57 +08:00

91 lines
2.6 KiB
TypeScript

jest.mock('../crypto', () => ({
hashFingerprint: jest.fn(() => 'a'.repeat(64)),
}));
import { enforceDeviceAbusePolicy } from '../abuse-detection';
import type { HardwareFingerprint } from '../types';
function createFingerprint(instanceId = 'instance-1'): HardwareFingerprint {
return {
machineId: 'machine-1',
hostname: 'nas-1',
macAddress: 'aa:bb:cc:dd:ee:ff',
instanceId,
};
}
function createPrismaMock(recentHeartbeats: Array<{ instanceId: string; fingerprintHash: string }>) {
return {
heartbeatLog: {
findMany: jest.fn().mockResolvedValue(recentHeartbeats),
},
alert: {
findFirst: jest.fn().mockResolvedValue(null),
create: jest.fn().mockResolvedValue({}),
},
};
}
describe('abuse-detection', () => {
it('免费版同许可证出现多个有效指纹时应阻断', async () => {
const prisma = createPrismaMock([
{ instanceId: 'instance-2', fingerprintHash: 'b'.repeat(64) },
]);
const result = await enforceDeviceAbusePolicy(prisma as any, {
licenseId: 'license-1',
licenseType: 'FREE',
instanceId: 'instance-1',
fingerprint: createFingerprint(),
});
expect(result).toMatchObject({ allowed: false, status: 403 });
expect(prisma.alert.create).toHaveBeenCalledWith(
expect.objectContaining({
data: expect.objectContaining({
alertType: 'free_multi_device_blocked',
}),
})
);
});
it('付费版多个有效指纹应告警但不直接阻断', async () => {
const prisma = createPrismaMock([
{ instanceId: 'instance-2', fingerprintHash: 'b'.repeat(64) },
{ instanceId: 'instance-3', fingerprintHash: 'c'.repeat(64) },
]);
const result = await enforceDeviceAbusePolicy(prisma as any, {
licenseId: 'license-1',
licenseType: 'PRO',
instanceId: 'instance-1',
fingerprint: createFingerprint(),
});
expect(result).toEqual({ allowed: true });
expect(prisma.alert.create).toHaveBeenCalledWith(
expect.objectContaining({
data: expect.objectContaining({
alertType: 'paid_multi_device_suspected',
}),
})
);
});
it('旧版本非哈希心跳记录不应导致免费版误判多设备', async () => {
const prisma = createPrismaMock([
{ instanceId: 'instance-legacy', fingerprintHash: 'machine-legacy' },
]);
const result = await enforceDeviceAbusePolicy(prisma as any, {
licenseId: 'license-1',
licenseType: 'FREE',
instanceId: 'instance-1',
fingerprint: createFingerprint(),
});
expect(result).toEqual({ allowed: true });
expect(prisma.alert.create).not.toHaveBeenCalled();
});
});