const path = require('path'); const fs = require('fs'); const fsp = require('fs-promise'); // Default Config // Do not edit this, generate a config..js for your NODE_ENV // or use ENV-VARS like PSITRANSFER_PORT=8000 const config = { "uploadDir": path.resolve(__dirname + '/data'), // admin settings (name, logo, ...) are stored here, default: /.settings "settingsDir": '', // set to serve the app from a sub-path "baseUrl": '/', // use to set custom upload url (subfolder to baseUrl) "uploadAppPath": '/', "iface": '0.0.0.0', // set to false to disable HTTP "port": 3000, // HTTPS, set all 3 values to enable "sslPort": 8443, "sslKeyFile": false, "sslCertFile": false, // Force redirect to https // can be true or a specific url like https://example.com:8443 // keep empty to disable "forceHttps": '', // Use trust proxy to show real IP on logs when reverse proxy are used // see https://expressjs.com/en/guide/behind-proxies.html for options "trustProxy": '', // retention options in seconds:label "retentions": { "one-time": "one time download", "3600": "1 Hour", "21600": "6 Hours", "86400": "1 Day", "259200": "3 Days", "432000": "5 Days", "604800": "7 Days", "1209600": "2 Weeks", "2419200": "4 Weeks", "4838400": "8 Weeks" }, // retentions shown as buttons, all others are offered in a list box "quickRetentions": ['one-time', '86400', '259200', '432000', '604800'], // admin password, set to false to disable /admin page // to enable /admin page set your password like this: // "adminPass": "YourSecurePassword", "adminPass": false, // upload password, set to false to disable "uploadPass": false, // lifetime of the login token issued after a successful upload login (seconds) // the token is renewed on every use "tokenTtl": 60 * 60 * 24 * 7, // secret to sign login tokens. When empty it is derived from uploadPass and adminPass, // so changing one of the passwords invalidates all issued tokens "tokenSecret": '', // a bucket-password is mandatory, except for one-time downloads "requireBucketPassword": true, "defaultRetention": "604800", // expire every file after maxAge (eg never downloaded one-time files) "maxAge": 3600 * 24 * 75, // 75 days // maximum file-size for text previews in byte "maxPreviewSize": Math.pow(2, 20) * 2, // 2MB "mailTemplate": 'mailto:?subject=파일 전달&body=다운로드 링크: %%URL%%', // see https://github.com/expressjs/morgan // set to false to disable logging "accessLog": ':date[iso] :method :url :status :response-time :remote-addr', // event webhooks // invokes an HTTP POST to a url whenever a file is downloaded // for more info, see the webhooks section of docs/configuration.md "fileDownloadedWebhook": null, "fileUploadedWebhook": null, // Fallback language "defaultLanguage": "ko", // Limit upload size "maxFileSize": null, // Math.pow(2, 30) * 2, // 2GB "maxBucketSize": null, // Math.pow(2, 30) * 2, // 10GB "plugins": ['file-downloaded-webhook', 'file-uploaded-webhook'], // Disable the QR code button for download url sharing, set to true to disable "disableQrCode": false, // Defaults for the branding, each of them can be changed on the admin settings page "appName": 'Dodo Transfer', "appOwner": '아진산업(주) 전장선행개발팀', "appFromYear": 2026, }; // Load NODE_ENV specific config const envConfFile = path.resolve(__dirname, `config.${ process.env.NODE_ENV }.js`); if (process.env.NODE_ENV && fsp.existsSync(envConfFile)) { Object.assign(config, require(envConfFile)); } // Load config from ENV VARS const BOOLEAN_KEYS = ['requireBucketPassword', 'disableQrCode']; let envName; for (let k in config) { envName = 'PSITRANSFER_' + k.replace(/([A-Z])/g, $1 => "_" + $1).toUpperCase(); if (process.env[envName]) { const raw = process.env[envName]; if (typeof config[k] === 'number') { config[k] = parseInt(raw, 10); } else if (BOOLEAN_KEYS.includes(k)) { // other keys that default to false (passwords, ssl files, ...) take a string config[k] = ['true', '1', 'yes', 'on'].includes(raw.trim().toLowerCase()); } else if (Array.isArray(config[k])) { config[k] = raw.split(',').map(s => s.trim()).filter(Boolean); } else if (config[k] === null) { // null defaults are numbers (limits) or strings (urls) try { config[k] = JSON.parse(raw); } catch (e) { config[k] = raw; } } else if (typeof config[k] === 'object') { config[k] = JSON.parse(raw); } else { config[k] = raw; } } } if (!config.baseUrl.endsWith('/')) config.baseUrl = config.baseUrl + '/'; if (!config.uploadAppPath.endsWith('/')) config.uploadAppPath = config.uploadAppPath + '/'; config.uploadAppPath = config.baseUrl.substr(0, config.baseUrl.length - 1) + config.uploadAppPath; config.uploadDir = path.resolve(config.uploadDir); if (!config.settingsDir) config.settingsDir = path.join(config.uploadDir, '.settings'); // Retention sanity: ignore unknown keys instead of showing broken buttons config.quickRetentions = config.quickRetentions.filter(key => { const known = Object.prototype.hasOwnProperty.call(config.retentions, key); if (!known) console.warn(`config: quickRetentions entry "${ key }" is not in retentions, ignored`); return known; }); if (!Object.prototype.hasOwnProperty.call(config.retentions, String(config.defaultRetention))) { const fallback = Object.keys(config.retentions).find(k => k !== 'one-time'); console.warn(`config: defaultRetention "${ config.defaultRetention }" is not in retentions, using "${ fallback }"`); config.defaultRetention = fallback; } // Load language files: English is the base, every other language overrides it const langDir = path.resolve(__dirname, 'lang'); const base = require('./lang/en'); config.languages = {}; fs.readdirSync(langDir).forEach(file => { if (!file.endsWith('.js')) return; const code = file.replace(/\.js$/, ''); config.languages[code] = code === 'en' ? base : { ...base, ...require(`./lang/${ code }`) }; }); if (!config.languages[config.defaultLanguage]) { console.warn(`config: defaultLanguage "${ config.defaultLanguage }" not found, using "en"`); config.defaultLanguage = 'en'; } module.exports = config;