96 lines
2.6 KiB
TypeScript
96 lines
2.6 KiB
TypeScript
|
|
import { logger } from '../logger.js';
|
||
|
|
import type { ReferenceResolver } from './classes.reference-resolver.js';
|
||
|
|
import type { IRouteSecurity } from '../../ts_interfaces/data/route-management.js';
|
||
|
|
|
||
|
|
export interface ISeedData {
|
||
|
|
profiles?: Array<{
|
||
|
|
name: string;
|
||
|
|
description?: string;
|
||
|
|
security: IRouteSecurity;
|
||
|
|
extendsProfiles?: string[];
|
||
|
|
}>;
|
||
|
|
targets?: Array<{
|
||
|
|
name: string;
|
||
|
|
description?: string;
|
||
|
|
host: string | string[];
|
||
|
|
port: number;
|
||
|
|
}>;
|
||
|
|
}
|
||
|
|
|
||
|
|
export class DbSeeder {
|
||
|
|
constructor(private referenceResolver: ReferenceResolver) {}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Check if DB is empty and seed if configured.
|
||
|
|
* Called once during ConfigManagers service startup, after initialize().
|
||
|
|
*/
|
||
|
|
public async seedIfEmpty(
|
||
|
|
seedOnEmpty?: boolean,
|
||
|
|
seedData?: ISeedData,
|
||
|
|
): Promise<void> {
|
||
|
|
if (!seedOnEmpty) return;
|
||
|
|
|
||
|
|
const existingProfiles = this.referenceResolver.listProfiles();
|
||
|
|
const existingTargets = this.referenceResolver.listTargets();
|
||
|
|
|
||
|
|
if (existingProfiles.length > 0 || existingTargets.length > 0) {
|
||
|
|
logger.log('info', 'DB already contains profiles/targets, skipping seed');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
logger.log('info', 'Seeding database with initial profiles and targets...');
|
||
|
|
|
||
|
|
const profilesToSeed: NonNullable<ISeedData['profiles']> = seedData?.profiles ?? DEFAULT_PROFILES;
|
||
|
|
const targetsToSeed: NonNullable<ISeedData['targets']> = seedData?.targets ?? DEFAULT_TARGETS;
|
||
|
|
|
||
|
|
for (const p of profilesToSeed) {
|
||
|
|
await this.referenceResolver.createProfile({
|
||
|
|
name: p.name,
|
||
|
|
description: p.description,
|
||
|
|
security: p.security,
|
||
|
|
extendsProfiles: p.extendsProfiles,
|
||
|
|
createdBy: 'system-seed',
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
for (const t of targetsToSeed) {
|
||
|
|
await this.referenceResolver.createTarget({
|
||
|
|
name: t.name,
|
||
|
|
description: t.description,
|
||
|
|
host: t.host,
|
||
|
|
port: t.port,
|
||
|
|
createdBy: 'system-seed',
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
logger.log('info', `Seeded ${profilesToSeed.length} profile(s) and ${targetsToSeed.length} target(s)`);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const DEFAULT_PROFILES: Array<NonNullable<ISeedData['profiles']>[number]> = [
|
||
|
|
{
|
||
|
|
name: 'PUBLIC',
|
||
|
|
description: 'Allow all traffic — no IP restrictions',
|
||
|
|
security: {
|
||
|
|
ipAllowList: ['*'],
|
||
|
|
},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: 'STANDARD',
|
||
|
|
description: 'Standard internal access with common private subnets',
|
||
|
|
security: {
|
||
|
|
ipAllowList: ['192.168.0.0/16', '10.0.0.0/8', '127.0.0.1', '::1'],
|
||
|
|
maxConnections: 1000,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
];
|
||
|
|
|
||
|
|
const DEFAULT_TARGETS: Array<NonNullable<ISeedData['targets']>[number]> = [
|
||
|
|
{
|
||
|
|
name: 'LOCALHOST',
|
||
|
|
description: 'Local machine on port 443',
|
||
|
|
host: '127.0.0.1',
|
||
|
|
port: 443,
|
||
|
|
},
|
||
|
|
];
|