feat(routes): collect desired routes from enabled clients

This commit is contained in:
noderaven 2026-06-24 17:46:22 +00:00
parent 7b7adefd64
commit f2dc0e7bf9
2 changed files with 94 additions and 1 deletions

View file

@ -67,7 +67,40 @@ function isManageable(cidr: string, version: IpVersion): boolean {
return true;
}
/**
* Build the desired managed routes (per IP family) from enabled clients'
* Server Allowed IPs. IPv6 is dropped when IPv6 is disabled.
*/
function collectDesiredRoutes(
clients: RoutesClient[],
options: { enableIpv6: boolean }
): DesiredRoutes {
const desired: DesiredRoutes = { 4: new Set(), 6: new Set() };
for (const client of clients) {
if (!client.enabled) {
continue;
}
for (const entry of client.serverAllowedIps ?? []) {
const normalized = normalizeRoute(entry);
if (!normalized) {
continue;
}
if (!isManageable(normalized.cidr, normalized.version)) {
continue;
}
if (normalized.version === 6 && !options.enableIpv6) {
continue;
}
desired[normalized.version].add(normalized.cidr);
}
}
return desired;
}
export const routesTestExports = {
normalizeRoute,
isManageable,
collectDesiredRoutes,
};

View file

@ -2,7 +2,8 @@ import { describe, expect, test } from 'vitest';
import { routesTestExports } from '#server/utils/routes';
const { normalizeRoute, isManageable } = routesTestExports;
const { normalizeRoute, isManageable, collectDesiredRoutes } =
routesTestExports;
describe('routes', () => {
describe('normalizeRoute', () => {
@ -50,4 +51,63 @@ describe('routes', () => {
expect(isManageable('2001:db8::/64', 6)).toBe(true);
});
});
describe('collectDesiredRoutes', () => {
test('unions enabled clients and splits by family', () => {
const result = collectDesiredRoutes(
[
{
enabled: true,
serverAllowedIps: ['192.168.120.0/22', '2001:db8::/64'],
},
{ enabled: true, serverAllowedIps: ['10.10.0.0/24'] },
],
{ enableIpv6: true }
);
expect([...result[4]].sort()).toEqual([
'10.10.0.0/24',
'192.168.120.0/22',
]);
expect([...result[6]]).toEqual(['2001:db8::/64']);
});
test('ignores disabled clients', () => {
const result = collectDesiredRoutes(
[{ enabled: false, serverAllowedIps: ['192.168.120.0/22'] }],
{ enableIpv6: true }
);
expect(result[4].size).toBe(0);
});
test('dedupes and normalizes host bits across clients', () => {
const result = collectDesiredRoutes(
[
{ enabled: true, serverAllowedIps: ['192.168.120.5/22'] },
{ enabled: true, serverAllowedIps: ['192.168.120.99/22'] },
],
{ enableIpv6: true }
);
expect([...result[4]]).toEqual(['192.168.120.0/22']);
});
test('drops default routes', () => {
const result = collectDesiredRoutes(
[{ enabled: true, serverAllowedIps: ['0.0.0.0/0', '::/0'] }],
{ enableIpv6: true }
);
expect(result[4].size).toBe(0);
expect(result[6].size).toBe(0);
});
test('drops IPv6 when disabled', () => {
const result = collectDesiredRoutes(
[{ enabled: true, serverAllowedIps: ['2001:db8::/64'] }],
{ enableIpv6: false }
);
expect(result[6].size).toBe(0);
});
test('skips unparseable entries', () => {
const result = collectDesiredRoutes(
[{ enabled: true, serverAllowedIps: ['garbage', '10.0.0.0/24'] }],
{ enableIpv6: true }
);
expect([...result[4]]).toEqual(['10.0.0.0/24']);
});
});
});