update
This commit is contained in:
@@ -1,433 +0,0 @@
|
|||||||
/**
|
|
||||||
* Base configuration interface with common properties for all services
|
|
||||||
*/
|
|
||||||
export interface IBaseConfig {
|
|
||||||
/**
|
|
||||||
* Unique identifier for this configuration
|
|
||||||
* Used to track configuration versions and changes
|
|
||||||
*/
|
|
||||||
id?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configuration version
|
|
||||||
* Used for migration between different config formats
|
|
||||||
*/
|
|
||||||
version?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Environment this configuration is intended for
|
|
||||||
* (development, test, production, etc.)
|
|
||||||
*/
|
|
||||||
environment?: 'development' | 'test' | 'staging' | 'production';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display name for this configuration
|
|
||||||
*/
|
|
||||||
name?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether this configuration is enabled
|
|
||||||
* Services with disabled configuration shouldn't start
|
|
||||||
*/
|
|
||||||
enabled?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logging configuration
|
|
||||||
*/
|
|
||||||
logging?: {
|
|
||||||
/**
|
|
||||||
* Minimum log level to output
|
|
||||||
*/
|
|
||||||
level?: 'error' | 'warn' | 'info' | 'debug';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to include structured data in logs
|
|
||||||
*/
|
|
||||||
structured?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to enable correlation tracking in logs
|
|
||||||
*/
|
|
||||||
correlationTracking?: boolean;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base database configuration
|
|
||||||
*/
|
|
||||||
export interface IDatabaseConfig {
|
|
||||||
/**
|
|
||||||
* Database connection string or URL
|
|
||||||
*/
|
|
||||||
connectionString?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Database host
|
|
||||||
*/
|
|
||||||
host?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Database port
|
|
||||||
*/
|
|
||||||
port?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Database name
|
|
||||||
*/
|
|
||||||
database?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Database username
|
|
||||||
*/
|
|
||||||
username?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Database password
|
|
||||||
*/
|
|
||||||
password?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SSL configuration for database connection
|
|
||||||
*/
|
|
||||||
ssl?: boolean | {
|
|
||||||
/**
|
|
||||||
* Whether to reject unauthorized SSL connections
|
|
||||||
*/
|
|
||||||
rejectUnauthorized?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Path to CA certificate file
|
|
||||||
*/
|
|
||||||
ca?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Path to client certificate file
|
|
||||||
*/
|
|
||||||
cert?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Path to client key file
|
|
||||||
*/
|
|
||||||
key?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connection pool configuration
|
|
||||||
*/
|
|
||||||
pool?: {
|
|
||||||
/**
|
|
||||||
* Minimum number of connections in pool
|
|
||||||
*/
|
|
||||||
min?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum number of connections in pool
|
|
||||||
*/
|
|
||||||
max?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connection idle timeout in milliseconds
|
|
||||||
*/
|
|
||||||
idleTimeoutMillis?: number;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base TLS configuration interface
|
|
||||||
*/
|
|
||||||
export interface ITlsConfig {
|
|
||||||
/**
|
|
||||||
* Whether to enable TLS
|
|
||||||
*/
|
|
||||||
enabled?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The domain name for the certificate
|
|
||||||
*/
|
|
||||||
domain?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Path to certificate file
|
|
||||||
*/
|
|
||||||
certPath?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Path to private key file
|
|
||||||
*/
|
|
||||||
keyPath?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Path to CA certificate file
|
|
||||||
*/
|
|
||||||
caPath?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Minimum TLS version to support
|
|
||||||
*/
|
|
||||||
minVersion?: 'TLSv1.2' | 'TLSv1.3';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to auto-renew certificates
|
|
||||||
*/
|
|
||||||
autoRenew?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to reject unauthorized certificates
|
|
||||||
*/
|
|
||||||
rejectUnauthorized?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base retry configuration interface
|
|
||||||
*/
|
|
||||||
export interface IRetryConfig {
|
|
||||||
/**
|
|
||||||
* Maximum number of retry attempts
|
|
||||||
*/
|
|
||||||
maxAttempts?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base delay between retries in milliseconds
|
|
||||||
*/
|
|
||||||
baseDelay?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum delay between retries in milliseconds
|
|
||||||
*/
|
|
||||||
maxDelay?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Backoff factor for exponential backoff
|
|
||||||
*/
|
|
||||||
backoffFactor?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specific error codes that should trigger retries
|
|
||||||
*/
|
|
||||||
retryableErrorCodes?: string[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to add jitter to retry delays
|
|
||||||
*/
|
|
||||||
useJitter?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base rate limiting configuration interface
|
|
||||||
*/
|
|
||||||
export interface IRateLimitConfig {
|
|
||||||
/**
|
|
||||||
* Whether rate limiting is enabled
|
|
||||||
*/
|
|
||||||
enabled?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum number of operations per period
|
|
||||||
*/
|
|
||||||
maxPerPeriod?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Time period in milliseconds
|
|
||||||
*/
|
|
||||||
periodMs?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to apply per key (e.g., domain, user, etc.)
|
|
||||||
*/
|
|
||||||
perKey?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Number of burst tokens allowed
|
|
||||||
*/
|
|
||||||
burstTokens?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Basic HTTP server configuration
|
|
||||||
*/
|
|
||||||
export interface IHttpServerConfig {
|
|
||||||
/**
|
|
||||||
* Whether the HTTP server is enabled
|
|
||||||
*/
|
|
||||||
enabled?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Host to bind to
|
|
||||||
*/
|
|
||||||
host?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Port to listen on
|
|
||||||
*/
|
|
||||||
port?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Path prefix for all routes
|
|
||||||
*/
|
|
||||||
basePath?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CORS configuration
|
|
||||||
*/
|
|
||||||
cors?: boolean | {
|
|
||||||
/**
|
|
||||||
* Allowed origins
|
|
||||||
*/
|
|
||||||
origins?: string[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allowed methods
|
|
||||||
*/
|
|
||||||
methods?: string[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allowed headers
|
|
||||||
*/
|
|
||||||
headers?: string[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to allow credentials
|
|
||||||
*/
|
|
||||||
credentials?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TLS configuration
|
|
||||||
*/
|
|
||||||
tls?: ITlsConfig;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum request body size in bytes
|
|
||||||
*/
|
|
||||||
maxBodySize?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request timeout in milliseconds
|
|
||||||
*/
|
|
||||||
timeout?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Basic queue configuration
|
|
||||||
*/
|
|
||||||
export interface IQueueConfig {
|
|
||||||
/**
|
|
||||||
* Type of storage for the queue
|
|
||||||
*/
|
|
||||||
storageType?: 'memory' | 'disk' | 'redis';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Path for persistent storage
|
|
||||||
*/
|
|
||||||
persistentPath?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redis configuration for queue
|
|
||||||
*/
|
|
||||||
redis?: {
|
|
||||||
/**
|
|
||||||
* Redis host
|
|
||||||
*/
|
|
||||||
host?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redis port
|
|
||||||
*/
|
|
||||||
port?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redis password
|
|
||||||
*/
|
|
||||||
password?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redis database number
|
|
||||||
*/
|
|
||||||
db?: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum size of the queue
|
|
||||||
*/
|
|
||||||
maxSize?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum number of retry attempts
|
|
||||||
*/
|
|
||||||
maxRetries?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base delay between retries in milliseconds
|
|
||||||
*/
|
|
||||||
baseRetryDelay?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum delay between retries in milliseconds
|
|
||||||
*/
|
|
||||||
maxRetryDelay?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check interval for processing in milliseconds
|
|
||||||
*/
|
|
||||||
checkInterval?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum number of parallel processes
|
|
||||||
*/
|
|
||||||
maxParallelProcessing?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Basic monitoring configuration
|
|
||||||
*/
|
|
||||||
export interface IMonitoringConfig {
|
|
||||||
/**
|
|
||||||
* Whether monitoring is enabled
|
|
||||||
*/
|
|
||||||
enabled?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Metrics collection interval in milliseconds
|
|
||||||
*/
|
|
||||||
metricsInterval?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to expose Prometheus metrics
|
|
||||||
*/
|
|
||||||
exposePrometheus?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Port for Prometheus metrics
|
|
||||||
*/
|
|
||||||
prometheusPort?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to collect detailed metrics
|
|
||||||
*/
|
|
||||||
detailedMetrics?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Alert thresholds
|
|
||||||
*/
|
|
||||||
alertThresholds?: Record<string, number>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notification configuration
|
|
||||||
*/
|
|
||||||
notifications?: {
|
|
||||||
/**
|
|
||||||
* Whether to send notifications
|
|
||||||
*/
|
|
||||||
enabled?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Email address to send notifications to
|
|
||||||
*/
|
|
||||||
email?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Webhook URL to send notifications to
|
|
||||||
*/
|
|
||||||
webhook?: string;
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,159 +0,0 @@
|
|||||||
|
|
||||||
/**
|
|
||||||
* MIGRATION GUIDE:
|
|
||||||
* ================
|
|
||||||
* The IEmailConfig and IMtaConfig interfaces are deprecated.
|
|
||||||
* Please use IUnifiedEmailServerOptions from '../mail/routing/classes.unified.email.server.js' instead.
|
|
||||||
*
|
|
||||||
* Example migration:
|
|
||||||
*
|
|
||||||
* OLD:
|
|
||||||
* ```typescript
|
|
||||||
* const config: IEmailConfig = {
|
|
||||||
* ports: [25, 587],
|
|
||||||
* hostname: 'mail.example.com',
|
|
||||||
* domainRules: [...],
|
|
||||||
* defaultMode: 'forward'
|
|
||||||
* };
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* NEW:
|
|
||||||
* ```typescript
|
|
||||||
* const config: IUnifiedEmailServerOptions = {
|
|
||||||
* ports: [25, 587],
|
|
||||||
* hostname: 'mail.example.com',
|
|
||||||
* domains: ['example.com'],
|
|
||||||
* domainRules: [...],
|
|
||||||
* defaultMode: 'forward'
|
|
||||||
* };
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* The new interface consolidates all email configuration into a single, cleaner structure.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Email processing modes
|
|
||||||
*/
|
|
||||||
export type EmailProcessingMode = 'forward' | 'mta' | 'process';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Domain rule for email routing
|
|
||||||
*/
|
|
||||||
export interface IDomainRule {
|
|
||||||
/**
|
|
||||||
* Pattern to match (e.g., "*@example.com")
|
|
||||||
*/
|
|
||||||
pattern: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processing mode
|
|
||||||
*/
|
|
||||||
mode: EmailProcessingMode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Target server for forwarding mode
|
|
||||||
*/
|
|
||||||
target?: {
|
|
||||||
/**
|
|
||||||
* Target server hostname or IP
|
|
||||||
*/
|
|
||||||
server: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Target server port
|
|
||||||
*/
|
|
||||||
port?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to use TLS for forwarding
|
|
||||||
*/
|
|
||||||
useTls?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MTA options for mta mode
|
|
||||||
*/
|
|
||||||
mtaOptions?: {
|
|
||||||
/**
|
|
||||||
* Domain for MTA
|
|
||||||
*/
|
|
||||||
domain?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to sign with DKIM
|
|
||||||
*/
|
|
||||||
dkimSign?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DKIM options
|
|
||||||
*/
|
|
||||||
dkimOptions?: {
|
|
||||||
/**
|
|
||||||
* Domain name for DKIM
|
|
||||||
*/
|
|
||||||
domainName: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Key selector
|
|
||||||
*/
|
|
||||||
keySelector: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private key
|
|
||||||
*/
|
|
||||||
privateKey?: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to scan content in process mode
|
|
||||||
*/
|
|
||||||
contentScanning?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Content scanners to apply
|
|
||||||
*/
|
|
||||||
scanners?: Array<{
|
|
||||||
/**
|
|
||||||
* Scanner type
|
|
||||||
*/
|
|
||||||
type: 'spam' | 'virus' | 'attachment';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Threshold for scanner
|
|
||||||
*/
|
|
||||||
threshold?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Action to take
|
|
||||||
*/
|
|
||||||
action: 'tag' | 'reject';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Blocked file extensions for attachment scanner
|
|
||||||
*/
|
|
||||||
blockedExtensions?: string[];
|
|
||||||
}>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Email transformations to apply
|
|
||||||
*/
|
|
||||||
transformations?: Array<{
|
|
||||||
/**
|
|
||||||
* Transformation type
|
|
||||||
*/
|
|
||||||
type: 'addHeader';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Header name
|
|
||||||
*/
|
|
||||||
header?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Header value
|
|
||||||
*/
|
|
||||||
value?: string;
|
|
||||||
}>;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@@ -1,194 +0,0 @@
|
|||||||
/**
|
|
||||||
* Email Port Mapping Configuration
|
|
||||||
*
|
|
||||||
* Centralizes the logic for mapping external email ports to internal ports
|
|
||||||
* when running behind SmartProxy
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default email port mapping
|
|
||||||
* Maps external ports to internal ports for SmartProxy forwarding
|
|
||||||
*/
|
|
||||||
export const DEFAULT_EMAIL_PORT_MAPPING: Record<number, number> = {
|
|
||||||
25: 10025, // SMTP - Standard email delivery port
|
|
||||||
587: 10587, // Submission - Authenticated submission port
|
|
||||||
465: 10465, // SMTPS - Implicit TLS submission port
|
|
||||||
2525: 12525 // Alternative SMTP port (often used for testing)
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Email port configuration
|
|
||||||
*/
|
|
||||||
export interface IEmailPortConfig {
|
|
||||||
/**
|
|
||||||
* External port number
|
|
||||||
*/
|
|
||||||
external: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal port number (where the email server actually listens)
|
|
||||||
*/
|
|
||||||
internal: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Port description
|
|
||||||
*/
|
|
||||||
description: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TLS mode for this port
|
|
||||||
*/
|
|
||||||
tlsMode: 'none' | 'starttls' | 'implicit';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether authentication is required on this port
|
|
||||||
*/
|
|
||||||
requireAuth?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Standard email port configurations
|
|
||||||
*/
|
|
||||||
export const EMAIL_PORT_CONFIGS: Record<number, Omit<IEmailPortConfig, 'internal'>> = {
|
|
||||||
25: {
|
|
||||||
external: 25,
|
|
||||||
description: 'SMTP - Standard email delivery',
|
|
||||||
tlsMode: 'starttls',
|
|
||||||
requireAuth: false
|
|
||||||
},
|
|
||||||
587: {
|
|
||||||
external: 587,
|
|
||||||
description: 'Submission - Authenticated email submission',
|
|
||||||
tlsMode: 'starttls',
|
|
||||||
requireAuth: true
|
|
||||||
},
|
|
||||||
465: {
|
|
||||||
external: 465,
|
|
||||||
description: 'SMTPS - Implicit TLS submission',
|
|
||||||
tlsMode: 'implicit',
|
|
||||||
requireAuth: true
|
|
||||||
},
|
|
||||||
2525: {
|
|
||||||
external: 2525,
|
|
||||||
description: 'Alternative SMTP - Often used for testing',
|
|
||||||
tlsMode: 'starttls',
|
|
||||||
requireAuth: false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Map external ports to internal ports
|
|
||||||
* @param externalPorts Array of external ports
|
|
||||||
* @param customMapping Optional custom port mapping
|
|
||||||
* @returns Array of internal ports
|
|
||||||
*/
|
|
||||||
export function mapEmailPorts(
|
|
||||||
externalPorts: number[],
|
|
||||||
customMapping?: Record<number, number>
|
|
||||||
): number[] {
|
|
||||||
const mapping = { ...DEFAULT_EMAIL_PORT_MAPPING, ...customMapping };
|
|
||||||
|
|
||||||
return externalPorts.map(port => {
|
|
||||||
// Use custom mapping if available, otherwise add 10000 to the port
|
|
||||||
return mapping[port] || port + 10000;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get full port configuration including internal port mapping
|
|
||||||
* @param externalPort External port number
|
|
||||||
* @param customMapping Optional custom port mapping
|
|
||||||
* @returns Full port configuration
|
|
||||||
*/
|
|
||||||
export function getEmailPortConfig(
|
|
||||||
externalPort: number,
|
|
||||||
customMapping?: Record<number, number>
|
|
||||||
): IEmailPortConfig | undefined {
|
|
||||||
const config = EMAIL_PORT_CONFIGS[externalPort];
|
|
||||||
if (!config) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapping = { ...DEFAULT_EMAIL_PORT_MAPPING, ...customMapping };
|
|
||||||
const internalPort = mapping[externalPort] || externalPort + 10000;
|
|
||||||
|
|
||||||
return {
|
|
||||||
...config,
|
|
||||||
internal: internalPort
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate SmartProxy routes for email ports
|
|
||||||
* @param externalPorts Array of external ports to handle
|
|
||||||
* @param hostname Hostname for the email server
|
|
||||||
* @param customMapping Optional custom port mapping
|
|
||||||
* @returns Array of SmartProxy route configurations
|
|
||||||
*/
|
|
||||||
export function generateEmailProxyRoutes(
|
|
||||||
externalPorts: number[],
|
|
||||||
_hostname: string,
|
|
||||||
customMapping?: Record<number, number>
|
|
||||||
): plugins.smartproxy.IRouteConfig[] {
|
|
||||||
const routes: plugins.smartproxy.IRouteConfig[] = [];
|
|
||||||
|
|
||||||
for (const externalPort of externalPorts) {
|
|
||||||
const config = getEmailPortConfig(externalPort, customMapping);
|
|
||||||
if (!config) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create route for this email port
|
|
||||||
const route: plugins.smartproxy.IRouteConfig = {
|
|
||||||
name: `email-${config.description.toLowerCase().replace(/\s+/g, '-')}`,
|
|
||||||
match: {
|
|
||||||
ports: [externalPort]
|
|
||||||
},
|
|
||||||
action: {
|
|
||||||
type: 'forward',
|
|
||||||
target: {
|
|
||||||
host: 'localhost',
|
|
||||||
port: config.internal
|
|
||||||
},
|
|
||||||
tls: {
|
|
||||||
// For SMTP/Submission ports, use passthrough to let email server handle STARTTLS
|
|
||||||
// For SMTPS (465), SmartProxy handles TLS termination
|
|
||||||
mode: config.tlsMode === 'implicit' ? 'terminate' : 'passthrough',
|
|
||||||
certificate: config.tlsMode === 'implicit' ? 'auto' : undefined
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
routes.push(route);
|
|
||||||
}
|
|
||||||
|
|
||||||
return routes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate email port configuration
|
|
||||||
* @param ports Array of ports to validate
|
|
||||||
* @throws Error if invalid ports are specified
|
|
||||||
*/
|
|
||||||
export function validateEmailPorts(ports: number[]): void {
|
|
||||||
const invalidPorts = ports.filter(port => {
|
|
||||||
// Check if port is a valid number
|
|
||||||
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warn about non-standard ports
|
|
||||||
if (!EMAIL_PORT_CONFIGS[port]) {
|
|
||||||
console.warn(`Port ${port} is not a standard email port. Supported standard ports are: ${Object.keys(EMAIL_PORT_CONFIGS).join(', ')}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (invalidPorts.length > 0) {
|
|
||||||
throw new Error(`Invalid email ports specified: ${invalidPorts.join(', ')}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type imports to avoid circular dependencies
|
|
||||||
import type * as plugins from '../plugins.js';
|
|
@@ -1,54 +0,0 @@
|
|||||||
import type { IBaseConfig, IHttpServerConfig, IDatabaseConfig } from './base.config.js';
|
|
||||||
import type { ISmsConfig } from './sms.config.js';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Platform service configuration
|
|
||||||
* Root configuration that includes all service configurations
|
|
||||||
*/
|
|
||||||
export interface IPlatformConfig extends IBaseConfig {
|
|
||||||
/**
|
|
||||||
* HTTP server configuration
|
|
||||||
*/
|
|
||||||
server?: IHttpServerConfig;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Database configuration
|
|
||||||
*/
|
|
||||||
database?: IDatabaseConfig;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Email service configuration
|
|
||||||
* @deprecated - Use IUnifiedEmailServerOptions in DcRouter instead
|
|
||||||
*/
|
|
||||||
email?: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SMS service configuration
|
|
||||||
*/
|
|
||||||
sms?: ISmsConfig;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Path configuration
|
|
||||||
*/
|
|
||||||
paths?: {
|
|
||||||
/**
|
|
||||||
* Data directory path
|
|
||||||
*/
|
|
||||||
dataDir?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logs directory path
|
|
||||||
*/
|
|
||||||
logsDir?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Temporary directory path
|
|
||||||
*/
|
|
||||||
tempDir?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Email templates directory path
|
|
||||||
*/
|
|
||||||
emailTemplatesDir?: string;
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,770 +0,0 @@
|
|||||||
import type { ValidationSchema } from './validator.js';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base TLS configuration schema
|
|
||||||
*/
|
|
||||||
export const tlsConfigSchema: ValidationSchema = {
|
|
||||||
enabled: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
domain: {
|
|
||||||
type: 'string',
|
|
||||||
required: false
|
|
||||||
},
|
|
||||||
certPath: {
|
|
||||||
type: 'string',
|
|
||||||
required: false
|
|
||||||
},
|
|
||||||
keyPath: {
|
|
||||||
type: 'string',
|
|
||||||
required: false
|
|
||||||
},
|
|
||||||
caPath: {
|
|
||||||
type: 'string',
|
|
||||||
required: false
|
|
||||||
},
|
|
||||||
minVersion: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
enum: ['TLSv1.2', 'TLSv1.3'],
|
|
||||||
default: 'TLSv1.2'
|
|
||||||
},
|
|
||||||
autoRenew: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
rejectUnauthorized: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP server configuration schema
|
|
||||||
*/
|
|
||||||
export const httpServerSchema: ValidationSchema = {
|
|
||||||
enabled: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
host: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
default: '0.0.0.0'
|
|
||||||
},
|
|
||||||
port: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 3000,
|
|
||||||
min: 1,
|
|
||||||
max: 65535
|
|
||||||
},
|
|
||||||
basePath: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
cors: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
tls: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: tlsConfigSchema
|
|
||||||
},
|
|
||||||
maxBodySize: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 1024 * 1024 // 1MB
|
|
||||||
},
|
|
||||||
timeout: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 30000 // 30 seconds
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rate limit configuration schema
|
|
||||||
*/
|
|
||||||
export const rateLimitSchema: ValidationSchema = {
|
|
||||||
enabled: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
maxPerPeriod: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 100,
|
|
||||||
min: 1
|
|
||||||
},
|
|
||||||
periodMs: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 60000, // 1 minute
|
|
||||||
min: 1000
|
|
||||||
},
|
|
||||||
perKey: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
burstTokens: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 5,
|
|
||||||
min: 0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Queue configuration schema
|
|
||||||
*/
|
|
||||||
export const queueSchema: ValidationSchema = {
|
|
||||||
storageType: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
enum: ['memory', 'disk', 'redis'],
|
|
||||||
default: 'memory'
|
|
||||||
},
|
|
||||||
persistentPath: {
|
|
||||||
type: 'string',
|
|
||||||
required: false
|
|
||||||
},
|
|
||||||
redis: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: {
|
|
||||||
host: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
default: 'localhost'
|
|
||||||
},
|
|
||||||
port: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 6379,
|
|
||||||
min: 1,
|
|
||||||
max: 65535
|
|
||||||
},
|
|
||||||
password: {
|
|
||||||
type: 'string',
|
|
||||||
required: false
|
|
||||||
},
|
|
||||||
db: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 0,
|
|
||||||
min: 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
maxSize: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 10000,
|
|
||||||
min: 1
|
|
||||||
},
|
|
||||||
maxRetries: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 3,
|
|
||||||
min: 0
|
|
||||||
},
|
|
||||||
baseRetryDelay: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 1000, // 1 second
|
|
||||||
min: 1
|
|
||||||
},
|
|
||||||
maxRetryDelay: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 60000, // 1 minute
|
|
||||||
min: 1
|
|
||||||
},
|
|
||||||
checkInterval: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 1000, // 1 second
|
|
||||||
min: 100
|
|
||||||
},
|
|
||||||
maxParallelProcessing: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 5,
|
|
||||||
min: 1
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SMS service configuration schema
|
|
||||||
*/
|
|
||||||
export const smsConfigSchema: ValidationSchema = {
|
|
||||||
apiGatewayApiToken: {
|
|
||||||
type: 'string',
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
defaultSender: {
|
|
||||||
type: 'string',
|
|
||||||
required: false
|
|
||||||
},
|
|
||||||
rateLimit: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: {
|
|
||||||
...rateLimitSchema,
|
|
||||||
maxPerRecipientPerDay: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 10,
|
|
||||||
min: 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
provider: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: {
|
|
||||||
type: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
enum: ['gateway', 'twilio', 'other'],
|
|
||||||
default: 'gateway'
|
|
||||||
},
|
|
||||||
config: {
|
|
||||||
type: 'object',
|
|
||||||
required: false
|
|
||||||
},
|
|
||||||
fallback: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: {
|
|
||||||
enabled: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
type: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
enum: ['gateway', 'twilio', 'other']
|
|
||||||
},
|
|
||||||
config: {
|
|
||||||
type: 'object',
|
|
||||||
required: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
verification: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: {
|
|
||||||
codeLength: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 6,
|
|
||||||
min: 4,
|
|
||||||
max: 10
|
|
||||||
},
|
|
||||||
expirationSeconds: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 300, // 5 minutes
|
|
||||||
min: 60
|
|
||||||
},
|
|
||||||
maxAttempts: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 3,
|
|
||||||
min: 1
|
|
||||||
},
|
|
||||||
cooldownSeconds: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 60, // 1 minute
|
|
||||||
min: 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MTA configuration schema
|
|
||||||
*/
|
|
||||||
export const mtaConfigSchema: ValidationSchema = {
|
|
||||||
smtp: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: {
|
|
||||||
enabled: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
port: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 25,
|
|
||||||
min: 1,
|
|
||||||
max: 65535
|
|
||||||
},
|
|
||||||
hostname: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
default: 'mta.lossless.one'
|
|
||||||
},
|
|
||||||
maxSize: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 10 * 1024 * 1024, // 10MB
|
|
||||||
min: 1024
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tls: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: tlsConfigSchema
|
|
||||||
},
|
|
||||||
outbound: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: {
|
|
||||||
concurrency: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 5,
|
|
||||||
min: 1
|
|
||||||
},
|
|
||||||
retries: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: {
|
|
||||||
max: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 3,
|
|
||||||
min: 0
|
|
||||||
},
|
|
||||||
delay: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 300000, // 5 minutes
|
|
||||||
min: 1000
|
|
||||||
},
|
|
||||||
useBackoff: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
rateLimit: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: rateLimitSchema
|
|
||||||
},
|
|
||||||
warmup: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: {
|
|
||||||
enabled: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
ipAddresses: {
|
|
||||||
type: 'array',
|
|
||||||
required: false,
|
|
||||||
items: {
|
|
||||||
type: 'string'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
targetDomains: {
|
|
||||||
type: 'array',
|
|
||||||
required: false,
|
|
||||||
items: {
|
|
||||||
type: 'string'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
allocationPolicy: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
default: 'balanced'
|
|
||||||
},
|
|
||||||
fallbackPercentage: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 50,
|
|
||||||
min: 0,
|
|
||||||
max: 100
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
reputation: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: {
|
|
||||||
enabled: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
updateFrequency: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 24 * 60 * 60 * 1000, // 1 day
|
|
||||||
min: 60000
|
|
||||||
},
|
|
||||||
alertThresholds: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: {
|
|
||||||
minReputationScore: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 70,
|
|
||||||
min: 0,
|
|
||||||
max: 100
|
|
||||||
},
|
|
||||||
maxComplaintRate: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 0.1, // 0.1%
|
|
||||||
min: 0,
|
|
||||||
max: 100
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
security: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: {
|
|
||||||
useDkim: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
verifyDkim: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
verifySpf: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
verifyDmarc: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
enforceDmarc: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
useTls: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
requireValidCerts: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
securityLogLevel: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
enum: ['info', 'warn', 'error'],
|
|
||||||
default: 'warn'
|
|
||||||
},
|
|
||||||
checkIPReputation: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
scanContent: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
maliciousContentAction: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
enum: ['tag', 'quarantine', 'reject'],
|
|
||||||
default: 'tag'
|
|
||||||
},
|
|
||||||
threatScoreThreshold: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 50,
|
|
||||||
min: 0,
|
|
||||||
max: 100
|
|
||||||
},
|
|
||||||
rejectHighRiskIPs: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
domains: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: {
|
|
||||||
local: {
|
|
||||||
type: 'array',
|
|
||||||
required: false,
|
|
||||||
items: {
|
|
||||||
type: 'string'
|
|
||||||
},
|
|
||||||
default: ['lossless.one']
|
|
||||||
},
|
|
||||||
autoCreateDnsRecords: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
dkimSelector: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
default: 'mta'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
queue: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: queueSchema
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Email service configuration schema
|
|
||||||
*/
|
|
||||||
export const emailConfigSchema: ValidationSchema = {
|
|
||||||
useMta: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
mtaConfig: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: mtaConfigSchema
|
|
||||||
},
|
|
||||||
templateConfig: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: {
|
|
||||||
from: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
default: 'no-reply@lossless.one'
|
|
||||||
},
|
|
||||||
replyTo: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
default: 'support@lossless.one'
|
|
||||||
},
|
|
||||||
footerHtml: {
|
|
||||||
type: 'string',
|
|
||||||
required: false
|
|
||||||
},
|
|
||||||
footerText: {
|
|
||||||
type: 'string',
|
|
||||||
required: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
loadTemplatesFromDir: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
templatesDir: {
|
|
||||||
type: 'string',
|
|
||||||
required: false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Database configuration schema
|
|
||||||
*/
|
|
||||||
export const databaseConfigSchema: ValidationSchema = {
|
|
||||||
connectionString: {
|
|
||||||
type: 'string',
|
|
||||||
required: false
|
|
||||||
},
|
|
||||||
host: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
default: 'localhost'
|
|
||||||
},
|
|
||||||
port: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 5432,
|
|
||||||
min: 1,
|
|
||||||
max: 65535
|
|
||||||
},
|
|
||||||
database: {
|
|
||||||
type: 'string',
|
|
||||||
required: false
|
|
||||||
},
|
|
||||||
username: {
|
|
||||||
type: 'string',
|
|
||||||
required: false
|
|
||||||
},
|
|
||||||
password: {
|
|
||||||
type: 'string',
|
|
||||||
required: false
|
|
||||||
},
|
|
||||||
ssl: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
pool: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: {
|
|
||||||
min: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 2,
|
|
||||||
min: 1
|
|
||||||
},
|
|
||||||
max: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 10,
|
|
||||||
min: 1
|
|
||||||
},
|
|
||||||
idleTimeoutMillis: {
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
default: 30000,
|
|
||||||
min: 1000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Platform service configuration schema
|
|
||||||
*/
|
|
||||||
export const platformConfigSchema: ValidationSchema = {
|
|
||||||
id: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
default: 'platform-service-config'
|
|
||||||
},
|
|
||||||
version: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
default: '1.0.0'
|
|
||||||
},
|
|
||||||
environment: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
enum: ['development', 'test', 'staging', 'production'],
|
|
||||||
default: 'production'
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
default: 'PlatformService'
|
|
||||||
},
|
|
||||||
enabled: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
logging: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: {
|
|
||||||
level: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
enum: ['error', 'warn', 'info', 'debug'],
|
|
||||||
default: 'info'
|
|
||||||
},
|
|
||||||
structured: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
correlationTracking: {
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
default: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
server: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: httpServerSchema
|
|
||||||
},
|
|
||||||
database: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: databaseConfigSchema
|
|
||||||
},
|
|
||||||
email: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: emailConfigSchema
|
|
||||||
},
|
|
||||||
sms: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: smsConfigSchema
|
|
||||||
},
|
|
||||||
paths: {
|
|
||||||
type: 'object',
|
|
||||||
required: false,
|
|
||||||
schema: {
|
|
||||||
dataDir: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
default: 'data'
|
|
||||||
},
|
|
||||||
logsDir: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
default: 'logs'
|
|
||||||
},
|
|
||||||
tempDir: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
default: 'temp'
|
|
||||||
},
|
|
||||||
emailTemplatesDir: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
default: 'templates/email'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
@@ -1,86 +0,0 @@
|
|||||||
import type { IBaseConfig, IRateLimitConfig } from './base.config.js';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SMS service configuration
|
|
||||||
*/
|
|
||||||
export interface ISmsConfig extends IBaseConfig {
|
|
||||||
/**
|
|
||||||
* API token for the gateway service
|
|
||||||
*/
|
|
||||||
apiGatewayApiToken: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default sender ID or phone number
|
|
||||||
*/
|
|
||||||
defaultSender?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SMS rate limiting
|
|
||||||
*/
|
|
||||||
rateLimit?: IRateLimitConfig & {
|
|
||||||
/**
|
|
||||||
* Maximum messages per recipient per day
|
|
||||||
*/
|
|
||||||
maxPerRecipientPerDay?: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SMS provider configuration
|
|
||||||
*/
|
|
||||||
provider?: {
|
|
||||||
/**
|
|
||||||
* Provider type
|
|
||||||
*/
|
|
||||||
type?: 'gateway' | 'twilio' | 'other';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provider-specific configuration
|
|
||||||
*/
|
|
||||||
config?: Record<string, any>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fallback provider configuration
|
|
||||||
*/
|
|
||||||
fallback?: {
|
|
||||||
/**
|
|
||||||
* Whether to use fallback provider
|
|
||||||
*/
|
|
||||||
enabled?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provider type
|
|
||||||
*/
|
|
||||||
type?: 'gateway' | 'twilio' | 'other';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provider-specific configuration
|
|
||||||
*/
|
|
||||||
config?: Record<string, any>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verification code settings
|
|
||||||
*/
|
|
||||||
verification?: {
|
|
||||||
/**
|
|
||||||
* Code length
|
|
||||||
*/
|
|
||||||
codeLength?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Code expiration time in seconds
|
|
||||||
*/
|
|
||||||
expirationSeconds?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum number of attempts
|
|
||||||
*/
|
|
||||||
maxAttempts?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cooldown period in seconds
|
|
||||||
*/
|
|
||||||
cooldownSeconds?: number;
|
|
||||||
};
|
|
||||||
}
|
|
Reference in New Issue
Block a user