349 lines
12 KiB
JavaScript
349 lines
12 KiB
JavaScript
'use strict';
|
|
|
|
/**
|
|
* Partner System Configuration Helper
|
|
* Manages environment-based configuration for partner integrations
|
|
*/
|
|
|
|
const env = require('./env');
|
|
const utils = require('./utils');
|
|
const { AuthMethods } = require('./constants');
|
|
|
|
class PartnerConfig {
|
|
constructor() {
|
|
this.configs = {
|
|
SATLOC: {
|
|
apiEndpoint: env.SATLOC_API_ENDPOINT,
|
|
authMethod: AuthMethods.USERNAME_PASSWORD,
|
|
// Optional: Global fallback credentials (rarely used in production)
|
|
defaultApiKey: env.SATLOC_API_KEY || null,
|
|
defaultApiSecret: env.SATLOC_API_SECRET || null,
|
|
timeout: parseInt(env.SATLOC_API_TIMEOUT) || 30000,
|
|
retryAttempts: parseInt(env.SATLOC_RETRY_ATTEMPTS) || 3,
|
|
retryDelay: parseInt(env.SATLOC_RETRY_DELAY) || 1000,
|
|
rateLimit: {
|
|
requestsPerMinute: parseInt(env.SATLOC_RATE_LIMIT) || 60,
|
|
burstLimit: parseInt(env.SATLOC_BURST_LIMIT) || 10
|
|
},
|
|
features: {
|
|
supportsRealTime: utils.stringToBoolean(env.SATLOC_REALTIME_ENABLED),
|
|
supportsFileUpload: env.SATLOC_FILE_UPLOAD_ENABLED !== 'false',
|
|
maxFileSize: parseInt(env.SATLOC_MAX_FILE_SIZE) || 10485760 // 10MB
|
|
},
|
|
storage: {
|
|
basePath: env.SATLOC_STORAGE_PATH || '/data/partners/satloc',
|
|
tempPath: env.SATLOC_TEMP_PATH || '/tmp/satloc',
|
|
logFileExtensions: ['.log', '.LOG'],
|
|
maxFileAge: parseInt(env.SATLOC_MAX_FILE_AGE) || 7776000000 // 90 days in ms
|
|
}
|
|
},
|
|
AGIDRONEX: {
|
|
apiEndpoint: env.AGIDRONEX_API_ENDPOINT || 'https://api.agidronex.com/v1',
|
|
authMethod: AuthMethods.API_KEY,
|
|
// Optional: Global fallback credentials (rarely used in production)
|
|
defaultApiKey: env.AGIDRONEX_API_KEY || null,
|
|
defaultApiSecret: env.AGIDRONEX_API_SECRET || null,
|
|
defaultUsername: env.AGIDRONEX_USERNAME || null,
|
|
defaultPassword: env.AGIDRONEX_PASSWORD || null,
|
|
timeout: parseInt(env.AGIDRONEX_API_TIMEOUT) || 25000,
|
|
retryAttempts: parseInt(env.AGIDRONEX_RETRY_ATTEMPTS) || 3,
|
|
retryDelay: parseInt(env.AGIDRONEX_RETRY_DELAY) || 1500,
|
|
rateLimit: {
|
|
requestsPerMinute: parseInt(env.AGIDRONEX_RATE_LIMIT) || 100,
|
|
burstLimit: parseInt(env.AGIDRONEX_BURST_LIMIT) || 20
|
|
},
|
|
features: {
|
|
supportsRealTime: utils.stringToBoolean(env.AGIDRONEX_REALTIME_ENABLED),
|
|
supportsFileUpload: env.AGIDRONEX_FILE_UPLOAD_ENABLED !== 'false',
|
|
maxFileSize: parseInt(env.AGIDRONEX_MAX_FILE_SIZE) || 20971520 // 20MB
|
|
},
|
|
storage: {
|
|
basePath: env.AGIDRONEX_STORAGE_PATH || '/data/partners/agidronex',
|
|
tempPath: env.AGIDRONEX_TEMP_PATH || '/tmp/agidronex',
|
|
logFileExtensions: ['.log', '.LOG', '.txt', '.dat'],
|
|
maxFileAge: parseInt(env.AGIDRONEX_MAX_FILE_AGE) || 7776000000 // 90 days in ms
|
|
}
|
|
}
|
|
};
|
|
|
|
// Global partner system settings
|
|
this.globalConfig = {
|
|
syncInterval: parseInt(env.PARTNER_SYNC_INTERVAL) || 300000, // 5 minutes
|
|
healthCheckInterval: parseInt(env.PARTNER_HEALTH_CHECK_INTERVAL) || 60000, // 1 minute
|
|
maxConcurrentJobs: parseInt(env.PARTNER_MAX_CONCURRENT_JOBS) || 10,
|
|
jobTimeout: parseInt(env.PARTNER_JOB_TIMEOUT) || 1800000, // 30 minutes
|
|
enableMetrics: env.PARTNER_METRICS_ENABLED !== 'false',
|
|
enableDetailedLogging: utils.stringToBoolean(env.PARTNER_DETAILED_LOGGING),
|
|
encryptCredentials: env.PARTNER_ENCRYPT_CREDENTIALS !== 'false'
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Get configuration for a specific partner
|
|
* @param {string} partnerCode - Partner code (e.g., 'SATLOC', 'AGIDRONEX')
|
|
* @returns {object} Partner configuration
|
|
*/
|
|
getPartnerConfig(partnerCode) {
|
|
const config = this.configs[partnerCode.toUpperCase()];
|
|
if (!config) {
|
|
throw new Error(`Partner configuration not found for: ${partnerCode}`);
|
|
}
|
|
return { ...config };
|
|
}
|
|
|
|
/**
|
|
* Get global partner system configuration
|
|
* @returns {object} Global configuration
|
|
*/
|
|
getGlobalConfig() {
|
|
return { ...this.globalConfig };
|
|
}
|
|
|
|
/**
|
|
* Get API credentials for a partner system user
|
|
* @param {object} partnerSystemUser - Partner system user document
|
|
* @param {string} partnerCode - Partner code
|
|
* @returns {object} API credentials and endpoint
|
|
*/
|
|
getApiCredentials(partnerSystemUser, partnerCode) {
|
|
const partnerConfig = this.getPartnerConfig(partnerCode);
|
|
const authMethod = partnerConfig.authMethod || AuthMethods.API_KEY;
|
|
|
|
const credentials = {
|
|
endpoint: partnerConfig.apiEndpoint,
|
|
authMethod,
|
|
// Additional parameters for API calls
|
|
companyId: partnerSystemUser.companyId,
|
|
partnerUserId: partnerSystemUser.partnerUserId,
|
|
partnerUsername: partnerSystemUser.partnerUsername
|
|
};
|
|
|
|
// Handle different authentication methods
|
|
switch (authMethod) {
|
|
case AuthMethods.USERNAME_PASSWORD:
|
|
const username = partnerSystemUser.partnerUsername || partnerSystemUser.username;
|
|
const password = partnerSystemUser.password;
|
|
|
|
if (!username || !password) {
|
|
throw new Error(`Missing username/password credentials for ${partnerCode} user: ${partnerSystemUser.partnerUserId || partnerSystemUser._id}`);
|
|
}
|
|
|
|
credentials.username = username;
|
|
credentials.password = password;
|
|
// For SatLoc specifically, sometimes userId is used instead of username
|
|
credentials.userId = partnerSystemUser.partnerUserId || username;
|
|
break;
|
|
|
|
case AuthMethods.API_KEY:
|
|
const apiKey = partnerSystemUser.apiKey || partnerConfig.defaultApiKey;
|
|
const apiSecret = partnerSystemUser.apiSecret || partnerConfig.defaultApiSecret;
|
|
|
|
if (!apiKey || !apiSecret) {
|
|
throw new Error(`Missing API key/secret credentials for ${partnerCode} user: ${partnerSystemUser.partnerUserId || partnerSystemUser._id}`);
|
|
}
|
|
|
|
credentials.apiKey = apiKey;
|
|
credentials.apiSecret = apiSecret;
|
|
break;
|
|
|
|
case AuthMethods.OAUTH:
|
|
const accessToken = partnerSystemUser.accessToken;
|
|
const refreshToken = partnerSystemUser.refreshToken;
|
|
|
|
if (!accessToken) {
|
|
throw new Error(`Missing OAuth access token for ${partnerCode} user: ${partnerSystemUser.partnerUserId || partnerSystemUser._id}`);
|
|
}
|
|
|
|
credentials.accessToken = accessToken;
|
|
credentials.refreshToken = refreshToken;
|
|
break;
|
|
|
|
case AuthMethods.BEARER_TOKEN:
|
|
const bearerToken = partnerSystemUser.bearerToken || partnerSystemUser.accessToken;
|
|
|
|
if (!bearerToken) {
|
|
throw new Error(`Missing bearer token for ${partnerCode} user: ${partnerSystemUser.partnerUserId || partnerSystemUser._id}`);
|
|
}
|
|
|
|
credentials.bearerToken = bearerToken;
|
|
break;
|
|
|
|
default:
|
|
throw new Error(`Unsupported authentication method: ${authMethod} for ${partnerCode}`);
|
|
}
|
|
|
|
return credentials;
|
|
}
|
|
|
|
/**
|
|
* Get request configuration for API calls
|
|
* @param {string} partnerCode - Partner code
|
|
* @returns {object} Request configuration
|
|
*/
|
|
getRequestConfig(partnerCode) {
|
|
const config = this.getPartnerConfig(partnerCode);
|
|
|
|
return {
|
|
timeout: config.timeout,
|
|
retryAttempts: config.retryAttempts,
|
|
retryDelay: config.retryDelay,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'User-Agent': `AgMission-Integration/1.0 (${partnerCode})`
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Check if a feature is enabled for a partner
|
|
* @param {string} partnerCode - Partner code
|
|
* @param {string} feature - Feature name
|
|
* @returns {boolean} Whether feature is enabled
|
|
*/
|
|
isFeatureEnabled(partnerCode, feature) {
|
|
const config = this.getPartnerConfig(partnerCode);
|
|
return config.features[feature] || false;
|
|
}
|
|
|
|
/**
|
|
* Get rate limiting configuration for a partner
|
|
* @param {string} partnerCode - Partner code
|
|
* @returns {object} Rate limit configuration
|
|
*/
|
|
getRateLimitConfig(partnerCode) {
|
|
const config = this.getPartnerConfig(partnerCode);
|
|
return { ...config.rateLimit };
|
|
}
|
|
|
|
/**
|
|
* Validate partner configuration
|
|
* @param {string} partnerCode - Partner code
|
|
* @returns {object} Validation result
|
|
*/
|
|
validateConfig(partnerCode) {
|
|
try {
|
|
const config = this.getPartnerConfig(partnerCode);
|
|
const issues = [];
|
|
const authMethod = config.authMethod || AuthMethods.API_KEY;
|
|
|
|
if (!config.apiEndpoint) {
|
|
issues.push(`Missing API endpoint for ${partnerCode}`);
|
|
}
|
|
|
|
// Validate auth method
|
|
if (!Object.values(AuthMethods).includes(authMethod)) {
|
|
issues.push(`Unknown authentication method: ${authMethod} for ${partnerCode}`);
|
|
}
|
|
|
|
// Check if default credentials are available (optional warning)
|
|
switch (authMethod) {
|
|
case AuthMethods.USERNAME_PASSWORD:
|
|
if (!config.defaultUsername && !config.defaultPassword) {
|
|
issues.push(`No default username/password configured for ${partnerCode} (optional - credentials typically come from partner system users)`);
|
|
}
|
|
break;
|
|
case AuthMethods.API_KEY:
|
|
if (!config.defaultApiKey && !config.defaultApiSecret) {
|
|
issues.push(`No default API key/secret configured for ${partnerCode} (optional - credentials typically come from partner system users)`);
|
|
}
|
|
break;
|
|
case AuthMethods.OAUTH:
|
|
case AuthMethods.BEARER_TOKEN:
|
|
// These typically don't have default credentials
|
|
break;
|
|
}
|
|
|
|
if (config.timeout < 5000) {
|
|
issues.push(`Timeout too low for ${partnerCode}: ${config.timeout}ms`);
|
|
}
|
|
|
|
return {
|
|
valid: issues.length === 0,
|
|
issues,
|
|
config,
|
|
authMethod
|
|
};
|
|
} catch (error) {
|
|
return {
|
|
valid: false,
|
|
issues: [error.message],
|
|
config: null,
|
|
authMethod: null
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get environment variable names for a partner
|
|
* @param {string} partnerCode - Partner code
|
|
* @returns {array} Environment variable names
|
|
*/
|
|
getEnvVarNames(partnerCode) {
|
|
const prefix = partnerCode.toUpperCase();
|
|
return [
|
|
`${prefix}_API_ENDPOINT`,
|
|
`${prefix}_API_KEY`,
|
|
`${prefix}_API_SECRET`,
|
|
`${prefix}_USERNAME`,
|
|
`${prefix}_PASSWORD`,
|
|
`${prefix}_API_TIMEOUT`,
|
|
`${prefix}_RETRY_ATTEMPTS`,
|
|
`${prefix}_RETRY_DELAY`,
|
|
`${prefix}_RATE_LIMIT`,
|
|
`${prefix}_BURST_LIMIT`,
|
|
`${prefix}_REALTIME_ENABLED`,
|
|
`${prefix}_FILE_UPLOAD_ENABLED`,
|
|
`${prefix}_MAX_FILE_SIZE`
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Generate sample environment file content
|
|
* @returns {string} Sample .env content
|
|
*/
|
|
generateSampleEnv() {
|
|
return `
|
|
# Partner System Configuration
|
|
|
|
# Global Settings
|
|
PARTNER_SYNC_INTERVAL=300000
|
|
PARTNER_HEALTH_CHECK_INTERVAL=60000
|
|
PARTNER_MAX_CONCURRENT_JOBS=10
|
|
PARTNER_JOB_TIMEOUT=1800000
|
|
PARTNER_METRICS_ENABLED=true
|
|
PARTNER_DETAILED_LOGGING=false
|
|
PARTNER_ENCRYPT_CREDENTIALS=true
|
|
|
|
# SatLoc Configuration (Uses USERNAME_PASSWORD auth)
|
|
SATLOC_API_ENDPOINT=https://www.satloccloud.com/api/Satloc
|
|
# Optional: Global fallback credentials (each customer should have their own partner system user)
|
|
# SATLOC_USERNAME=your_global_satloc_username
|
|
# SATLOC_PASSWORD=your_global_satloc_password
|
|
SATLOC_API_TIMEOUT=30000
|
|
SATLOC_RETRY_ATTEMPTS=3
|
|
SATLOC_RETRY_DELAY=1000
|
|
SATLOC_RATE_LIMIT=60
|
|
SATLOC_BURST_LIMIT=10
|
|
SATLOC_REALTIME_ENABLED=false
|
|
SATLOC_FILE_UPLOAD_ENABLED=true
|
|
SATLOC_MAX_FILE_SIZE=10485760
|
|
|
|
# AgIDronex Configuration (Uses API_KEY auth)
|
|
AGIDRONEX_API_ENDPOINT=https://api.agidronex.com/v1
|
|
# Optional: Global fallback credentials (each customer should have their own partner system user)
|
|
# AGIDRONEX_API_KEY=your_global_agidronex_api_key
|
|
# AGIDRONEX_API_SECRET=your_global_agidronex_api_secret
|
|
AGIDRONEX_API_TIMEOUT=25000
|
|
AGIDRONEX_RETRY_ATTEMPTS=3
|
|
AGIDRONEX_RETRY_DELAY=1500
|
|
AGIDRONEX_RATE_LIMIT=100
|
|
AGIDRONEX_BURST_LIMIT=20
|
|
AGIDRONEX_REALTIME_ENABLED=true
|
|
AGIDRONEX_FILE_UPLOAD_ENABLED=true
|
|
AGIDRONEX_MAX_FILE_SIZE=20971520
|
|
`.trim();
|
|
}
|
|
}
|
|
|
|
module.exports = new PartnerConfig();
|