mirror of
https://github.com/PretendoNetwork/account.git
synced 2025-04-02 11:02:15 -04:00
273 lines
No EOL
10 KiB
TypeScript
273 lines
No EOL
10 KiB
TypeScript
import fs from 'fs-extra';
|
|
import mongoose from 'mongoose';
|
|
import dotenv from 'dotenv';
|
|
import isValidHostname from 'is-valid-hostname';
|
|
import { LOG_INFO, LOG_WARN, LOG_ERROR, formatHostnames } from '@/logger';
|
|
import { type Config, domainServices, optionalDomainServices } from '@/types/common/config';
|
|
|
|
dotenv.config();
|
|
|
|
export const disabledFeatures = {
|
|
redis: false,
|
|
email: false,
|
|
captcha: false,
|
|
s3: false,
|
|
datastore: false
|
|
};
|
|
|
|
const hexadecimalStringRegex = /^[0-9a-f]+$/i;
|
|
|
|
LOG_INFO('Loading config');
|
|
|
|
let mongooseConnectOptions: mongoose.ConnectOptions = {};
|
|
|
|
if (process.env.PN_ACT_CONFIG_MONGOOSE_CONNECT_OPTIONS_PATH) {
|
|
mongooseConnectOptions = fs.readJSONSync(process.env.PN_ACT_CONFIG_MONGOOSE_CONNECT_OPTIONS_PATH);
|
|
}
|
|
|
|
if (process.env.PN_ACT_CONFIG_EMAIL_SECURE) {
|
|
if (process.env.PN_ACT_CONFIG_EMAIL_SECURE !== 'true' && process.env.PN_ACT_CONFIG_EMAIL_SECURE !== 'false') {
|
|
LOG_ERROR(`PN_ACT_CONFIG_EMAIL_SECURE must be either true or false, got ${process.env.PN_ACT_CONFIG_EMAIL_SECURE}`);
|
|
process.exit(0);
|
|
}
|
|
}
|
|
|
|
export const config: Config = {
|
|
http: {
|
|
port: Number(process.env.PN_ACT_CONFIG_HTTP_PORT || '')
|
|
},
|
|
mongoose: {
|
|
connection_string: process.env.PN_ACT_CONFIG_MONGO_CONNECTION_STRING || '',
|
|
options: mongooseConnectOptions
|
|
},
|
|
redis: {
|
|
client: {
|
|
url: process.env.PN_ACT_CONFIG_REDIS_URL || ''
|
|
}
|
|
},
|
|
email: {
|
|
ses: {
|
|
region: process.env.PN_ACT_CONFIG_EMAIL_SES_REGION || '',
|
|
key: process.env.PN_ACT_CONFIG_EMAIL_SES_ACCESS_KEY || '',
|
|
secret: process.env.PN_ACT_CONFIG_EMAIL_SES_SECRET_KEY || ''
|
|
},
|
|
from: process.env.PN_ACT_CONFIG_EMAIL_FROM || ''
|
|
},
|
|
s3: {
|
|
bucket: process.env.PN_ACT_CONFIG_S3_BUCKET || '',
|
|
endpoint: process.env.PN_ACT_CONFIG_S3_ENDPOINT || '',
|
|
key: process.env.PN_ACT_CONFIG_S3_ACCESS_KEY || '',
|
|
secret: process.env.PN_ACT_CONFIG_S3_ACCESS_SECRET || '',
|
|
region: process.env.PN_ACT_CONFIG_S3_REGION || '',
|
|
forcePathStyle: process.env.PN_ACT_CONFIG_S3_FORCE_PATH_STYLE === 'true'
|
|
},
|
|
hcaptcha: {
|
|
secret: process.env.PN_ACT_CONFIG_HCAPTCHA_SECRET || ''
|
|
},
|
|
cdn: {
|
|
subdomain: process.env.PN_ACT_CONFIG_CDN_SUBDOMAIN,
|
|
disk_path: process.env.PN_ACT_CONFIG_CDN_DISK_PATH || '',
|
|
base_url: process.env.PN_ACT_CONFIG_CDN_BASE_URL || ''
|
|
},
|
|
website_base: process.env.PN_ACT_CONFIG_WEBSITE_BASE || '',
|
|
aes_key: process.env.PN_ACT_CONFIG_AES_KEY || '',
|
|
grpc: {
|
|
master_api_keys: {
|
|
account: process.env.PN_ACT_CONFIG_GRPC_MASTER_API_KEY_ACCOUNT || '',
|
|
api: process.env.PN_ACT_CONFIG_GRPC_MASTER_API_KEY_API || '',
|
|
},
|
|
port: Number(process.env.PN_ACT_CONFIG_GRPC_PORT || ''),
|
|
},
|
|
server_environment: process.env.PN_ACT_CONFIG_SERVER_ENVIRONMENT || '',
|
|
datastore: {
|
|
signature_secret: process.env.PN_ACT_CONFIG_DATASTORE_SIGNATURE_SECRET || ''
|
|
},
|
|
domains: {
|
|
api: (process.env.PN_ACT_CONFIG_DOMAINS_API || 'api.pretendo.cc').split(','),
|
|
assets: (process.env.PN_ACT_CONFIG_DOMAINS_ASSETS || 'assets.pretendo.cc').split(','),
|
|
cbvc: (process.env.PN_ACT_CONFIG_DOMAINS_CBVC || 'cbvc.cdn.pretendo.cc').split(','),
|
|
conntest: (process.env.PN_ACT_CONFIG_DOMAINS_CONNTEST || 'conntest.pretendo.cc').split(','),
|
|
datastore: (process.env.PN_ACT_CONFIG_DOMAINS_DATASTORE || 'datastore.pretendo.cc').split(','),
|
|
local_cdn: (process.env.PN_ACT_CONFIG_DOMAINS_LOCAL_CDN || '').split(','),
|
|
nasc: (process.env.PN_ACT_CONFIG_DOMAINS_NASC || 'nasc.pretendo.cc').split(','),
|
|
nnas: (process.env.PN_ACT_CONFIG_DOMAINS_NNAS || 'c.account.pretendo.cc,account.pretendo.cc').split(','),
|
|
}
|
|
};
|
|
|
|
if (process.env.PN_ACT_CONFIG_STRIPE_SECRET_KEY) {
|
|
config.stripe = {
|
|
secret_key: process.env.PN_ACT_CONFIG_STRIPE_SECRET_KEY
|
|
};
|
|
}
|
|
|
|
// * Add the old config option for backwards compatibility
|
|
if (config.cdn.subdomain) {
|
|
config.domains.local_cdn.push(config.cdn.subdomain);
|
|
}
|
|
|
|
let configValid = true;
|
|
|
|
LOG_INFO('Config loaded, checking integrity');
|
|
|
|
for (const service of domainServices) {
|
|
const validDomains: string[] = [];
|
|
const invalidDomains: string[] = [];
|
|
|
|
const uniqueDomains = [...new Set(config.domains[service])];
|
|
|
|
for (const domain of uniqueDomains) {
|
|
isValidHostname(domain) ? validDomains.push(domain) : invalidDomains.push(domain);
|
|
}
|
|
|
|
if (validDomains.length === 0 && !optionalDomainServices.includes(service)) {
|
|
LOG_ERROR(`No valid domains found for ${service}. Set the PN_ACT_CONFIG_DOMAINS_${service.toUpperCase()} environment variable to a valid domain`);
|
|
configValid = false;
|
|
}
|
|
|
|
if (invalidDomains.length) {
|
|
LOG_WARN(`Invalid domain(s) skipped for ${service}: ${formatHostnames(invalidDomains)}`);
|
|
}
|
|
|
|
config.domains[service] = validDomains;
|
|
}
|
|
|
|
if (!config.http.port) {
|
|
LOG_ERROR('Failed to find HTTP port. Set the PN_ACT_CONFIG_HTTP_PORT environment variable');
|
|
configValid = false;
|
|
}
|
|
|
|
if (!config.mongoose.connection_string) {
|
|
LOG_ERROR('Failed to find MongoDB connection string. Set the PN_ACT_CONFIG_MONGO_CONNECTION_STRING environment variable');
|
|
configValid = false;
|
|
}
|
|
|
|
if (!config.cdn.base_url) {
|
|
LOG_ERROR('Failed to find asset CDN base URL. Set the PN_ACT_CONFIG_CDN_BASE_URL environment variable');
|
|
configValid = false;
|
|
}
|
|
|
|
if (!config.redis.client.url) {
|
|
LOG_WARN('Failed to find Redis connection url. Disabling feature and using in-memory cache. To enable feature set the PN_ACT_CONFIG_REDIS_URL environment variable');
|
|
disabledFeatures.redis = true;
|
|
}
|
|
|
|
if (!config.email.ses.region) {
|
|
LOG_WARN('Failed to find AWS SES region. Disabling feature. To enable feature set the PN_ACT_CONFIG_EMAIL_SES_REGION environment variable');
|
|
disabledFeatures.email = true;
|
|
}
|
|
|
|
if (!config.email.ses.key) {
|
|
LOG_WARN('Failed to find AWS SES access key. Disabling feature. To enable feature set the PN_ACT_CONFIG_EMAIL_SES_ACCESS_KEY environment variable');
|
|
disabledFeatures.email = true;
|
|
}
|
|
|
|
if (!config.email.ses.secret) {
|
|
LOG_WARN('Failed to find AWS SES secret key. Disabling feature. To enable feature set the PN_ACT_CONFIG_EMAIL_SES_SECRET_KEY environment variable');
|
|
disabledFeatures.email = true;
|
|
}
|
|
|
|
if (!config.email.from) {
|
|
LOG_WARN('Failed to find email from config. Disabling feature. To enable feature set the PN_ACT_CONFIG_EMAIL_FROM environment variable');
|
|
disabledFeatures.email = true;
|
|
}
|
|
|
|
if (!disabledFeatures.email) {
|
|
if (!config.website_base) {
|
|
LOG_ERROR('Email sending is enabled and no website base was configured. Set the PN_ACT_CONFIG_WEBSITE_BASE environment variable');
|
|
configValid = false;
|
|
}
|
|
}
|
|
|
|
if (!config.hcaptcha.secret) {
|
|
LOG_WARN('Failed to find captcha secret config. Disabling feature. To enable feature set the PN_ACT_CONFIG_HCAPTCHA_SECRET environment variable');
|
|
disabledFeatures.captcha = true;
|
|
}
|
|
|
|
if (!config.s3.bucket) {
|
|
LOG_WARN('Failed to find S3 bucket config. Disabling feature. To enable feature set the PN_ACT_CONFIG_S3_BUCKET environment variable');
|
|
disabledFeatures.s3 = true;
|
|
}
|
|
|
|
if (!config.s3.endpoint) {
|
|
LOG_WARN('Failed to find S3 endpoint config. Disabling feature. To enable feature set the PN_ACT_CONFIG_S3_ENDPOINT environment variable');
|
|
disabledFeatures.s3 = true;
|
|
}
|
|
|
|
if (!config.s3.key) {
|
|
LOG_WARN('Failed to find S3 access key config. Disabling feature. To enable feature set the PN_ACT_CONFIG_S3_ACCESS_KEY environment variable');
|
|
disabledFeatures.s3 = true;
|
|
}
|
|
|
|
if (!config.s3.secret) {
|
|
LOG_WARN('Failed to find S3 secret key config. Disabling feature. To enable feature set the PN_ACT_CONFIG_S3_ACCESS_SECRET environment variable');
|
|
disabledFeatures.s3 = true;
|
|
}
|
|
|
|
if (!config.s3.region) {
|
|
LOG_WARN('Failed to find S3 region config. Disabling feature. To enable feature set the PN_ACT_CONFIG_S3_REGION environment variable');
|
|
disabledFeatures.s3 = true;
|
|
}
|
|
|
|
if (!config.server_environment) {
|
|
LOG_WARN('Failed to find server environment. To change the environment, set the PN_ACT_CONFIG_SERVER_ENVIRONMENT environment variable. Defaulting to prod');
|
|
config.server_environment = 'prod';
|
|
}
|
|
|
|
if (disabledFeatures.s3) {
|
|
if (config.domains.local_cdn.length === 0) {
|
|
LOG_ERROR('S3 file storage is disabled and no CDN domain was set. Set the PN_ACT_CONFIG_DOMAINS_LOCAL_CDN environment variable');
|
|
configValid = false;
|
|
}
|
|
|
|
if (!config.cdn.disk_path) {
|
|
LOG_ERROR('S3 file storage is disabled and no CDN disk path was set. Set the PN_ACT_CONFIG_CDN_DISK_PATH environment variable');
|
|
configValid = false;
|
|
}
|
|
|
|
if (configValid) {
|
|
LOG_WARN(`S3 file storage disabled. Using disk-based file storage. Please ensure cdn.base_url config or PN_ACT_CONFIG_CDN_BASE env variable is set to point to this server with the domain being one of ${formatHostnames(config.domains.local_cdn)}`);
|
|
|
|
if (disabledFeatures.redis) {
|
|
LOG_WARN('Both S3 and Redis are disabled. Large CDN files will use the in-memory cache, which may result in high memory use. Please enable S3 if you\'re running a production server.');
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!config.aes_key) {
|
|
LOG_ERROR('Token AES key is not set. Set the PN_ACT_CONFIG_AES_KEY environment variable to your AES-256-CBC key');
|
|
configValid = false;
|
|
}
|
|
|
|
if (!config.grpc.master_api_keys.account) {
|
|
LOG_ERROR('Master gRPC API key for the account service is not set. Set the PN_ACT_CONFIG_GRPC_MASTER_API_KEY_ACCOUNT environment variable');
|
|
configValid = false;
|
|
}
|
|
|
|
if (!config.grpc.master_api_keys.api) {
|
|
LOG_ERROR('Master gRPC API key for the api service is not set. Set the PN_ACT_CONFIG_GRPC_MASTER_API_KEY_API environment variable');
|
|
configValid = false;
|
|
}
|
|
|
|
if (!config.grpc.port) {
|
|
LOG_ERROR('Failed to find gRPC port. Set the PN_ACT_CONFIG_GRPC_PORT environment variable');
|
|
configValid = false;
|
|
}
|
|
|
|
if (!config.stripe?.secret_key) {
|
|
LOG_WARN('Failed to find Stripe api key! If a PNID is deleted with an active subscription, the subscription will *NOT* be canceled! Set the PN_ACT_CONFIG_STRIPE_SECRET_KEY environment variable to enable');
|
|
}
|
|
|
|
if (!config.datastore.signature_secret) {
|
|
LOG_WARN('Datastore signature secret key is not set. Disabling feature. To enable feature set the PN_ACT_CONFIG_DATASTORE_SIGNATURE_SECRET environment variable');
|
|
disabledFeatures.datastore = true;
|
|
} else {
|
|
if (config.datastore.signature_secret.length !== 32 || !hexadecimalStringRegex.test(config.datastore.signature_secret)) {
|
|
LOG_ERROR('Datastore signature secret key must be a 32-character hexadecimal string.');
|
|
configValid = false;
|
|
}
|
|
}
|
|
|
|
if (!configValid) {
|
|
LOG_ERROR('Config is invalid. Exiting');
|
|
process.exit(0);
|
|
} |