http://s3 hosts redirect to https; AWS SDK cannot follow PUT redirects, which caused XML parse errors.
127 lines
5.5 KiB
JavaScript
127 lines
5.5 KiB
JavaScript
// /config/config.js
|
|
|
|
const dotenv = require('dotenv');
|
|
const path = require('path');
|
|
|
|
dotenv.config({ path: path.resolve(process.cwd(), '.env') });
|
|
|
|
const parseBool = (value, defaultValue) => {
|
|
if (value === undefined || value === null || String(value).trim() === '') {
|
|
return defaultValue;
|
|
}
|
|
const normalized = String(value).trim().toLowerCase();
|
|
if (['true', '1', 'yes', 'on'].includes(normalized)) return true;
|
|
if (['false', '0', 'no', 'off'].includes(normalized)) return false;
|
|
return defaultValue;
|
|
};
|
|
|
|
const config = {
|
|
NODE_ENV: process.env.NODE_ENV || 'development',
|
|
PORT: parseInt(process.env.PORT, 10) || 3000,
|
|
MONGO_URI: process.env.MONGO_URI || 'mongodb://localhost:27017/teaching_institution_db',
|
|
|
|
JWT_ACCESS_SECRET: process.env.JWT_ACCESS_SECRET || 'default_super_secret_access_key_change_in_production',
|
|
JWT_REFRESH_SECRET: process.env.JWT_REFRESH_SECRET || 'default_super_secret_refresh_key_change_in_production',
|
|
JWT_ACCESS_EXPIRES_IN: process.env.JWT_ACCESS_EXPIRES_IN || '15m',
|
|
JWT_REFRESH_EXPIRES_IN: process.env.JWT_REFRESH_EXPIRES_IN || '7d',
|
|
|
|
CORS_ORIGIN: process.env.CORS_ORIGIN || '*',
|
|
DEFAULT_LANG: process.env.DEFAULT_LANG || 'en',
|
|
UPLOAD_PATH: process.env.UPLOAD_PATH || 'uploads',
|
|
|
|
// S3-compatible storage (MinIO locally, SeaweedFS in production)
|
|
// Accepts S3_* directly, or SeaweedFS/AWS service env aliases from the host platform.
|
|
// IMPORTANT: use https:// for public SeaweedFS — http:// gets a 307 that AWS SDK cannot follow on PUT.
|
|
S3_ENDPOINT: (() => {
|
|
const raw = (
|
|
process.env.S3_ENDPOINT
|
|
|| process.env.SERVICE_URL_S3
|
|
|| process.env.SERVICE_URL_S3_8333
|
|
|| 'http://localhost:9000'
|
|
).trim().replace(/\/$/, '');
|
|
|
|
// Upgrade plain http → https for non-local endpoints (Coolify/proxy 307 breaks PutObject)
|
|
const isLocal = /^(http:\/\/)?(localhost|127\.0\.0\.1|minio)(:|\/|$)/i.test(raw)
|
|
|| raw.startsWith('http://localhost')
|
|
|| raw.startsWith('http://127.0.0.1')
|
|
|| raw.startsWith('http://minio');
|
|
if (raw.startsWith('http://') && !isLocal) {
|
|
return `https://${raw.slice('http://'.length)}`;
|
|
}
|
|
return raw;
|
|
})(),
|
|
S3_REGION: process.env.S3_REGION || process.env.AWS_REGION || 'us-east-1',
|
|
S3_ACCESS_KEY:
|
|
process.env.S3_ACCESS_KEY
|
|
|| process.env.AWS_ACCESS_KEY_ID
|
|
|| process.env.SERVICE_USER_S3
|
|
|| 'minioadmin',
|
|
S3_SECRET_KEY:
|
|
process.env.S3_SECRET_KEY
|
|
|| process.env.AWS_SECRET_ACCESS_KEY
|
|
|| process.env.SERVICE_PASSWORD_S3
|
|
|| 'minioadmin',
|
|
S3_TEMP_BUCKET: process.env.S3_TEMP_BUCKET || 'temp',
|
|
// Legacy single storage bucket (kept as fallback)
|
|
S3_STORAGE_BUCKET: process.env.S3_STORAGE_BUCKET || process.env.S3_CERTIFICATES_BUCKET || 'certificates',
|
|
// Dedicated private buckets
|
|
S3_CERTIFICATES_BUCKET: process.env.S3_CERTIFICATES_BUCKET || 'certificates',
|
|
S3_DOCUMENTS_BUCKET: process.env.S3_DOCUMENTS_BUCKET || 'documents',
|
|
S3_FORCE_PATH_STYLE: parseBool(
|
|
process.env.S3_FORCE_PATH_STYLE,
|
|
true // required for SeaweedFS / MinIO path-style
|
|
),
|
|
SIGNED_URL_EXPIRES_IN: parseInt(process.env.SIGNED_URL_EXPIRES_IN, 10) || 900, // 15 minutes default
|
|
// Public base URL for public buckets only (private buckets leave fileUrl empty)
|
|
S3_PUBLIC_BASE_URL: (() => {
|
|
const raw = (
|
|
process.env.S3_PUBLIC_BASE_URL
|
|
|| process.env.SERVICE_URL_S3
|
|
|| ''
|
|
).trim().replace(/\/$/, '');
|
|
if (raw.startsWith('http://') && !/localhost|127\.0\.0\.1/i.test(raw)) {
|
|
return `https://${raw.slice('http://'.length)}`;
|
|
}
|
|
return raw;
|
|
})(),
|
|
S3_CERTIFICATES_PUBLIC: parseBool(process.env.S3_CERTIFICATES_PUBLIC, false),
|
|
S3_DOCUMENTS_PUBLIC: parseBool(process.env.S3_DOCUMENTS_PUBLIC, false),
|
|
// SeaweedFS admin console (optional; not used by the S3 SDK client)
|
|
SEAWEED_ADMIN_URL:
|
|
process.env.SERVICE_URL_ADMIN_23646
|
|
|| process.env.SERVICE_URL_ADMIN
|
|
|| '',
|
|
SEAWEED_USER_ADMIN: process.env.SEAWEED_USER_ADMIN || process.env.SERVICE_USER_ADMIN || '',
|
|
SEAWEED_PASSWORD_ADMIN: process.env.SEAWEED_PASSWORD_ADMIN || process.env.SERVICE_PASSWORD_ADMIN || '',
|
|
|
|
// SMTP Email Settings
|
|
SMTP_HOST: process.env.SMTP_HOST || 'smtp.mailtrap.io',
|
|
SMTP_PORT: parseInt(process.env.SMTP_PORT, 10) || 2525,
|
|
SMTP_USER: process.env.SMTP_USER || '',
|
|
SMTP_PASS: process.env.SMTP_PASS || '',
|
|
EMAIL_FROM: process.env.EMAIL_FROM || 'no-reply@institution.com',
|
|
|
|
// SMS Provider Settings (sms.ir)
|
|
SMS_ENABLED: process.env.SMS_ENABLED || 'false',
|
|
SMS_PANEL_TOKEN: process.env.SMS_PANEL_TOKEN || process.env.SMS_API_KEY || '',
|
|
SMS_API_KEY: process.env.SMS_PANEL_TOKEN || process.env.SMS_API_KEY || 'mock_sms_key',
|
|
SMS_SENDER_NUMBER: process.env.SMS_SENDER_NUMBER || '10001000',
|
|
// Template IDs configured in the sms.ir panel
|
|
SMS_TEMPLATE_ACCOUNT_CREATED: process.env.SMS_TEMPLATE_ACCOUNT_CREATED || '',
|
|
SMS_TEMPLATE_CLASS_REGISTERED: process.env.SMS_TEMPLATE_CLASS_REGISTERED || '',
|
|
SMS_TEMPLATE_CLASS_REMINDER: process.env.SMS_TEMPLATE_CLASS_REMINDER || '',
|
|
|
|
// Bale Messenger Bot Settings
|
|
BALE_BOT_TOKEN: process.env.BALE_BOT_TOKEN || 'mock_bale_bot_token',
|
|
|
|
// SuperAdmin bootstrap (credentials come from env only; no hardcoded secrets)
|
|
SUPERADMIN_ENABLED: parseBool(process.env.SUPERADMIN_ENABLED, true),
|
|
SUPERADMIN_USERNAME: process.env.SUPERADMIN_USERNAME || '',
|
|
SUPERADMIN_PASSWORD: process.env.SUPERADMIN_PASSWORD || '',
|
|
SUPERADMIN_EMAIL: process.env.SUPERADMIN_EMAIL || '',
|
|
SUPERADMIN_NATIONAL_ID: process.env.SUPERADMIN_NATIONAL_ID || '0000000000',
|
|
SUPERADMIN_PHONE: process.env.SUPERADMIN_PHONE || '09000000000'
|
|
};
|
|
|
|
module.exports = config;
|