2025-06-08 07:04:35 +00:00
|
|
|
import * as plugins from '../../plugins.js';
|
|
|
|
import type { OpsServer } from '../classes.opsserver.js';
|
|
|
|
import * as interfaces from '../../../ts_interfaces/index.js';
|
2025-06-08 07:19:31 +00:00
|
|
|
import { requireAdminIdentity } from '../helpers/guards.js';
|
2025-06-08 07:04:35 +00:00
|
|
|
|
|
|
|
export class ConfigHandler {
|
|
|
|
public typedrouter = new plugins.typedrequest.TypedRouter();
|
|
|
|
|
|
|
|
constructor(private opsServerRef: OpsServer) {
|
|
|
|
// Add this handler's router to the parent
|
|
|
|
this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
|
|
|
|
this.registerHandlers();
|
|
|
|
}
|
|
|
|
|
|
|
|
private registerHandlers(): void {
|
|
|
|
// Get Configuration Handler
|
|
|
|
this.typedrouter.addTypedHandler(
|
|
|
|
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetConfiguration>(
|
|
|
|
'getConfiguration',
|
|
|
|
async (dataArg, toolsArg) => {
|
|
|
|
const config = await this.getConfiguration(dataArg.section);
|
|
|
|
return {
|
|
|
|
config,
|
|
|
|
section: dataArg.section,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
// Update Configuration Handler
|
|
|
|
this.typedrouter.addTypedHandler(
|
|
|
|
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_UpdateConfiguration>(
|
|
|
|
'updateConfiguration',
|
|
|
|
async (dataArg, toolsArg) => {
|
|
|
|
try {
|
2025-06-08 07:19:31 +00:00
|
|
|
// Require admin access to update configuration
|
|
|
|
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
|
|
|
2025-06-08 07:04:35 +00:00
|
|
|
const updatedConfig = await this.updateConfiguration(dataArg.section, dataArg.config);
|
|
|
|
return {
|
|
|
|
updated: true,
|
|
|
|
config: updatedConfig,
|
|
|
|
};
|
|
|
|
} catch (error) {
|
2025-06-08 07:19:31 +00:00
|
|
|
if (error instanceof plugins.typedrequest.TypedResponseError) {
|
|
|
|
throw error;
|
|
|
|
}
|
2025-06-08 07:04:35 +00:00
|
|
|
return {
|
|
|
|
updated: false,
|
|
|
|
config: null,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
private async getConfiguration(section?: string): Promise<{
|
|
|
|
email: {
|
|
|
|
enabled: boolean;
|
|
|
|
ports: number[];
|
|
|
|
maxMessageSize: number;
|
|
|
|
rateLimits: {
|
|
|
|
perMinute: number;
|
|
|
|
perHour: number;
|
|
|
|
perDay: number;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
dns: {
|
|
|
|
enabled: boolean;
|
|
|
|
port: number;
|
|
|
|
nameservers: string[];
|
|
|
|
caching: boolean;
|
|
|
|
ttl: number;
|
|
|
|
};
|
|
|
|
proxy: {
|
|
|
|
enabled: boolean;
|
|
|
|
httpPort: number;
|
|
|
|
httpsPort: number;
|
|
|
|
maxConnections: number;
|
|
|
|
};
|
|
|
|
security: {
|
|
|
|
blockList: string[];
|
|
|
|
rateLimit: boolean;
|
|
|
|
spamDetection: boolean;
|
|
|
|
tlsRequired: boolean;
|
|
|
|
};
|
|
|
|
}> {
|
|
|
|
const dcRouter = this.opsServerRef.dcRouterRef;
|
|
|
|
|
|
|
|
return {
|
|
|
|
email: {
|
|
|
|
enabled: !!dcRouter.emailServer,
|
|
|
|
ports: dcRouter.emailServer ? [25, 465, 587, 2525] : [],
|
|
|
|
maxMessageSize: 10 * 1024 * 1024, // 10MB default
|
|
|
|
rateLimits: {
|
|
|
|
perMinute: 10,
|
|
|
|
perHour: 100,
|
|
|
|
perDay: 1000,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
dns: {
|
|
|
|
enabled: !!dcRouter.dnsServer,
|
|
|
|
port: 53,
|
|
|
|
nameservers: dcRouter.options.dnsNsDomains || [],
|
|
|
|
caching: true,
|
|
|
|
ttl: 300,
|
|
|
|
},
|
|
|
|
proxy: {
|
|
|
|
enabled: !!dcRouter.smartProxy,
|
|
|
|
httpPort: 80,
|
|
|
|
httpsPort: 443,
|
|
|
|
maxConnections: 1000,
|
|
|
|
},
|
|
|
|
security: {
|
|
|
|
blockList: [],
|
|
|
|
rateLimit: true,
|
|
|
|
spamDetection: true,
|
|
|
|
tlsRequired: false,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
private async updateConfiguration(section: string, config: any): Promise<any> {
|
|
|
|
// TODO: Implement actual configuration updates
|
|
|
|
// This would involve:
|
|
|
|
// 1. Validating the configuration changes
|
|
|
|
// 2. Applying them to the running services
|
|
|
|
// 3. Persisting them to storage
|
|
|
|
// 4. Potentially restarting affected services
|
|
|
|
|
|
|
|
// For now, just validate and return the config
|
|
|
|
if (section === 'email' && config.maxMessageSize && config.maxMessageSize < 1024) {
|
|
|
|
throw new Error('Maximum message size must be at least 1KB');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (section === 'dns' && config.ttl && (config.ttl < 0 || config.ttl > 86400)) {
|
|
|
|
throw new Error('DNS TTL must be between 0 and 86400 seconds');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (section === 'proxy' && config.maxConnections && config.maxConnections < 1) {
|
|
|
|
throw new Error('Maximum connections must be at least 1');
|
|
|
|
}
|
|
|
|
|
|
|
|
// In a real implementation, apply the changes here
|
|
|
|
// For now, return the current configuration
|
|
|
|
const currentConfig = await this.getConfiguration(section);
|
|
|
|
return currentConfig;
|
|
|
|
}
|
|
|
|
}
|