2017-06-05 22:35:36 +00:00
|
|
|
|
const convict = require('convict');
|
2022-04-25 08:30:48 +00:00
|
|
|
|
const convict_format_with_validator = require('convict-format-with-validator');
|
2017-09-06 20:25:27 +00:00
|
|
|
|
const { tmpdir } = require('os');
|
|
|
|
|
const path = require('path');
|
|
|
|
|
const { randomBytes } = require('crypto');
|
2017-06-05 22:35:36 +00:00
|
|
|
|
|
2022-04-25 08:30:48 +00:00
|
|
|
|
convict.addFormats(convict_format_with_validator);
|
|
|
|
|
|
2021-05-19 05:39:14 +00:00
|
|
|
|
convict.addFormat({
|
|
|
|
|
name: 'positive-int-array',
|
2021-05-19 09:48:20 +00:00
|
|
|
|
coerce: ints => {
|
|
|
|
|
// can take: int[] | string[] | string (csv), returns -> int[]
|
|
|
|
|
const ints_arr = Array.isArray(ints) ? ints : ints.trim().split(',');
|
|
|
|
|
return ints_arr.map(int =>
|
|
|
|
|
typeof int === 'number'
|
|
|
|
|
? int
|
|
|
|
|
: parseInt(int.replace(/['"]+/g, '').trim(), 10)
|
|
|
|
|
);
|
2021-05-19 05:52:37 +00:00
|
|
|
|
},
|
2021-05-19 09:48:20 +00:00
|
|
|
|
validate: ints => {
|
|
|
|
|
// takes: int[], errors if any NaNs, negatives, or floats present
|
2021-05-19 05:41:22 +00:00
|
|
|
|
for (const int of ints) {
|
2021-05-19 09:48:20 +00:00
|
|
|
|
if (typeof int !== 'number' || isNaN(int) || int < 0 || int % 1 > 0)
|
|
|
|
|
throw new Error('must be a comma-separated list of positive integers');
|
2021-05-19 05:41:22 +00:00
|
|
|
|
}
|
2021-05-19 09:48:20 +00:00
|
|
|
|
}
|
2021-05-19 05:39:14 +00:00
|
|
|
|
});
|
|
|
|
|
|
2017-06-09 17:44:12 +00:00
|
|
|
|
const conf = convict({
|
2018-08-09 21:49:52 +00:00
|
|
|
|
s3_bucket: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'S3_BUCKET'
|
2018-08-08 18:07:09 +00:00
|
|
|
|
},
|
2019-11-08 16:58:33 +00:00
|
|
|
|
s3_endpoint: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'S3_ENDPOINT'
|
|
|
|
|
},
|
|
|
|
|
s3_use_path_style_endpoint: {
|
|
|
|
|
format: Boolean,
|
|
|
|
|
default: false,
|
|
|
|
|
env: 'S3_USE_PATH_STYLE_ENDPOINT'
|
|
|
|
|
},
|
2018-10-05 18:01:58 +00:00
|
|
|
|
gcs_bucket: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'GCS_BUCKET'
|
|
|
|
|
},
|
2018-08-08 18:07:09 +00:00
|
|
|
|
expire_times_seconds: {
|
2021-05-19 05:39:14 +00:00
|
|
|
|
format: 'positive-int-array',
|
2018-08-07 22:40:17 +00:00
|
|
|
|
default: [300, 3600, 86400, 604800],
|
2018-08-08 18:07:09 +00:00
|
|
|
|
env: 'EXPIRE_TIMES_SECONDS'
|
|
|
|
|
},
|
|
|
|
|
default_expire_seconds: {
|
|
|
|
|
format: Number,
|
|
|
|
|
default: 86400,
|
|
|
|
|
env: 'DEFAULT_EXPIRE_SECONDS'
|
|
|
|
|
},
|
|
|
|
|
max_expire_seconds: {
|
|
|
|
|
format: Number,
|
2018-08-07 22:40:17 +00:00
|
|
|
|
default: 86400 * 7,
|
2018-08-08 18:07:09 +00:00
|
|
|
|
env: 'MAX_EXPIRE_SECONDS'
|
2017-06-07 06:52:56 +00:00
|
|
|
|
},
|
2018-09-24 22:08:39 +00:00
|
|
|
|
download_counts: {
|
2021-05-19 05:39:14 +00:00
|
|
|
|
format: 'positive-int-array',
|
2019-03-01 00:31:37 +00:00
|
|
|
|
default: [1, 2, 3, 4, 5, 20, 50, 100],
|
2018-09-24 22:08:39 +00:00
|
|
|
|
env: 'DOWNLOAD_COUNTS'
|
|
|
|
|
},
|
2021-06-04 12:03:58 +00:00
|
|
|
|
default_downloads: {
|
|
|
|
|
format: Number,
|
|
|
|
|
default: 1,
|
|
|
|
|
env: 'DEFAULT_DOWNLOADS'
|
|
|
|
|
},
|
2018-08-07 22:40:17 +00:00
|
|
|
|
max_downloads: {
|
|
|
|
|
format: Number,
|
2019-03-01 00:31:37 +00:00
|
|
|
|
default: 100,
|
2018-08-07 22:40:17 +00:00
|
|
|
|
env: 'MAX_DOWNLOADS'
|
|
|
|
|
},
|
|
|
|
|
max_files_per_archive: {
|
|
|
|
|
format: Number,
|
|
|
|
|
default: 64,
|
|
|
|
|
env: 'MAX_FILES_PER_ARCHIVE'
|
|
|
|
|
},
|
|
|
|
|
max_archives_per_user: {
|
|
|
|
|
format: Number,
|
|
|
|
|
default: 16,
|
|
|
|
|
env: 'MAX_ARCHIVES_PER_USER'
|
|
|
|
|
},
|
2017-06-07 06:52:56 +00:00
|
|
|
|
redis_host: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: 'localhost',
|
2017-07-24 19:02:41 +00:00
|
|
|
|
env: 'REDIS_HOST'
|
2017-06-07 06:52:56 +00:00
|
|
|
|
},
|
2021-04-18 03:08:35 +00:00
|
|
|
|
redis_port: {
|
|
|
|
|
format: Number,
|
|
|
|
|
default: 6379,
|
|
|
|
|
env: 'REDIS_PORT'
|
|
|
|
|
},
|
2021-05-19 09:59:35 +00:00
|
|
|
|
redis_user: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'REDIS_USER'
|
|
|
|
|
},
|
2021-04-18 03:08:35 +00:00
|
|
|
|
redis_password: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'REDIS_PASSWORD'
|
|
|
|
|
},
|
2021-05-19 09:59:35 +00:00
|
|
|
|
redis_db: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'REDIS_DB'
|
|
|
|
|
},
|
2017-11-15 12:31:22 +00:00
|
|
|
|
redis_event_expire: {
|
|
|
|
|
format: Boolean,
|
|
|
|
|
default: false,
|
|
|
|
|
env: 'REDIS_EVENT_EXPIRE'
|
|
|
|
|
},
|
2020-04-21 20:30:39 +00:00
|
|
|
|
redis_retry_time: {
|
|
|
|
|
format: Number,
|
|
|
|
|
default: 10000,
|
|
|
|
|
env: 'REDIS_RETRY_TIME'
|
|
|
|
|
},
|
|
|
|
|
redis_retry_delay: {
|
|
|
|
|
format: Number,
|
|
|
|
|
default: 500,
|
|
|
|
|
env: 'REDIS_RETRY_DELAY'
|
|
|
|
|
},
|
2017-12-09 01:21:55 +00:00
|
|
|
|
listen_address: {
|
2018-01-24 18:23:13 +00:00
|
|
|
|
format: 'ipaddress',
|
|
|
|
|
default: '0.0.0.0',
|
|
|
|
|
env: 'IP_ADDRESS'
|
2017-12-09 01:21:55 +00:00
|
|
|
|
},
|
2017-06-07 06:52:56 +00:00
|
|
|
|
listen_port: {
|
|
|
|
|
format: 'port',
|
|
|
|
|
default: 1443,
|
|
|
|
|
arg: 'port',
|
2017-06-20 22:48:36 +00:00
|
|
|
|
env: 'PORT'
|
2017-06-06 17:24:58 +00:00
|
|
|
|
},
|
2017-06-22 21:50:57 +00:00
|
|
|
|
sentry_id: {
|
|
|
|
|
format: String,
|
2017-06-24 03:01:32 +00:00
|
|
|
|
default: '',
|
2017-07-24 19:02:41 +00:00
|
|
|
|
env: 'SENTRY_CLIENT'
|
2017-06-23 17:53:11 +00:00
|
|
|
|
},
|
|
|
|
|
sentry_dsn: {
|
|
|
|
|
format: String,
|
2017-06-24 03:01:32 +00:00
|
|
|
|
default: '',
|
2017-07-24 19:02:41 +00:00
|
|
|
|
env: 'SENTRY_DSN'
|
2017-06-22 21:50:57 +00:00
|
|
|
|
},
|
2017-06-06 17:24:58 +00:00
|
|
|
|
env: {
|
2017-06-19 21:34:12 +00:00
|
|
|
|
format: ['production', 'development', 'test'],
|
2017-06-06 17:24:58 +00:00
|
|
|
|
default: 'development',
|
|
|
|
|
env: 'NODE_ENV'
|
2017-07-20 19:50:20 +00:00
|
|
|
|
},
|
|
|
|
|
max_file_size: {
|
|
|
|
|
format: Number,
|
2019-03-01 00:31:37 +00:00
|
|
|
|
default: 1024 * 1024 * 1024 * 2.5,
|
2017-07-24 19:02:41 +00:00
|
|
|
|
env: 'MAX_FILE_SIZE'
|
2017-07-24 20:07:49 +00:00
|
|
|
|
},
|
2017-07-25 21:28:49 +00:00
|
|
|
|
l10n_dev: {
|
|
|
|
|
format: Boolean,
|
|
|
|
|
default: false,
|
|
|
|
|
env: 'L10N_DEV'
|
2017-08-11 21:02:44 +00:00
|
|
|
|
},
|
|
|
|
|
base_url: {
|
|
|
|
|
format: 'url',
|
|
|
|
|
default: 'https://send.firefox.com',
|
|
|
|
|
env: 'BASE_URL'
|
2017-09-06 20:25:27 +00:00
|
|
|
|
},
|
2022-08-07 22:37:17 +00:00
|
|
|
|
custom_title: {
|
2022-08-19 11:11:30 +00:00
|
|
|
|
format: String,
|
|
|
|
|
default: 'Send',
|
|
|
|
|
env: 'CUSTOM_TITLE'
|
2022-08-07 22:37:17 +00:00
|
|
|
|
},
|
|
|
|
|
custom_description: {
|
2022-08-19 11:11:30 +00:00
|
|
|
|
format: String,
|
|
|
|
|
default: 'Encrypt and send files with a link that automatically expires to ensure your important documents don’t stay online forever.',
|
|
|
|
|
env: 'CUSTOM_DESCRIPTION'
|
2022-08-07 22:37:17 +00:00
|
|
|
|
},
|
2021-05-06 04:15:02 +00:00
|
|
|
|
detect_base_url: {
|
|
|
|
|
format: Boolean,
|
|
|
|
|
default: false,
|
|
|
|
|
env: 'DETECT_BASE_URL'
|
|
|
|
|
},
|
2017-09-06 20:25:27 +00:00
|
|
|
|
file_dir: {
|
|
|
|
|
format: 'String',
|
|
|
|
|
default: `${tmpdir()}${path.sep}send-${randomBytes(4).toString('hex')}`,
|
|
|
|
|
env: 'FILE_DIR'
|
2018-08-07 22:40:17 +00:00
|
|
|
|
},
|
|
|
|
|
fxa_url: {
|
|
|
|
|
format: 'url',
|
2018-09-20 21:13:07 +00:00
|
|
|
|
default: 'https://send-fxa.dev.lcip.org',
|
2018-08-07 22:40:17 +00:00
|
|
|
|
env: 'FXA_URL'
|
|
|
|
|
},
|
|
|
|
|
fxa_client_id: {
|
|
|
|
|
format: String,
|
2018-09-24 20:04:29 +00:00
|
|
|
|
default: '', // disabled
|
2018-08-07 22:40:17 +00:00
|
|
|
|
env: 'FXA_CLIENT_ID'
|
2018-12-18 21:55:46 +00:00
|
|
|
|
},
|
|
|
|
|
fxa_key_scope: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: 'https://identity.mozilla.com/apps/send',
|
|
|
|
|
env: 'FXA_KEY_SCOPE'
|
2019-04-26 20:30:33 +00:00
|
|
|
|
},
|
2020-06-11 13:57:48 +00:00
|
|
|
|
fxa_csp_oauth_url: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'FXA_CSP_OAUTH_URL'
|
|
|
|
|
},
|
|
|
|
|
fxa_csp_content_url: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'FXA_CSP_CONTENT_URL'
|
|
|
|
|
},
|
|
|
|
|
fxa_csp_profile_url: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'FXA_CSP_PROFILE_URL'
|
|
|
|
|
},
|
|
|
|
|
fxa_csp_profileimage_url: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'FXA_CSP_PROFILEIMAGE_URL'
|
|
|
|
|
},
|
2019-04-26 20:30:33 +00:00
|
|
|
|
survey_url: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'SURVEY_URL'
|
2020-01-11 22:06:17 +00:00
|
|
|
|
},
|
|
|
|
|
ip_db: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'IP_DB'
|
2021-01-26 23:13:56 +00:00
|
|
|
|
},
|
|
|
|
|
footer_donate_url: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'SEND_FOOTER_DONATE_URL'
|
|
|
|
|
},
|
|
|
|
|
footer_cli_url: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: 'https://github.com/timvisee/ffsend',
|
|
|
|
|
env: 'SEND_FOOTER_CLI_URL'
|
|
|
|
|
},
|
|
|
|
|
footer_dmca_url: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'SEND_FOOTER_DMCA_URL'
|
|
|
|
|
},
|
|
|
|
|
footer_source_url: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: 'https://github.com/timvisee/send',
|
2021-02-05 01:24:48 +00:00
|
|
|
|
env: 'SEND_FOOTER_SOURCE_URL'
|
2022-04-12 13:58:58 +00:00
|
|
|
|
},
|
2022-08-11 21:04:45 +00:00
|
|
|
|
custom_footer_text: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'CUSTOM_FOOTER_TEXT'
|
|
|
|
|
},
|
|
|
|
|
custom_footer_url: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'CUSTOM_FOOTER_URL'
|
|
|
|
|
},
|
2022-04-12 13:58:58 +00:00
|
|
|
|
ui_color_primary: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '#0a84ff',
|
|
|
|
|
env: 'UI_COLOR_PRIMARY'
|
|
|
|
|
},
|
|
|
|
|
ui_color_accent: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '#003eaa',
|
|
|
|
|
env: 'UI_COLOR_ACCENT'
|
|
|
|
|
},
|
2022-08-13 00:25:19 +00:00
|
|
|
|
custom_locale: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'CUSTOM_LOCALE'
|
|
|
|
|
},
|
2022-04-12 13:58:58 +00:00
|
|
|
|
ui_custom_assets: {
|
|
|
|
|
android_chrome_192px: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'UI_CUSTOM_ASSETS_ANDROID_CHROME_192PX'
|
|
|
|
|
},
|
|
|
|
|
android_chrome_512px: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'UI_CUSTOM_ASSETS_ANDROID_CHROME_512PX'
|
|
|
|
|
},
|
|
|
|
|
apple_touch_icon: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'UI_CUSTOM_ASSETS_APPLE_TOUCH_ICON'
|
|
|
|
|
},
|
|
|
|
|
favicon_16px: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'UI_CUSTOM_ASSETS_FAVICON_16PX'
|
|
|
|
|
},
|
|
|
|
|
favicon_32px: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'UI_CUSTOM_ASSETS_FAVICON_32PX'
|
|
|
|
|
},
|
|
|
|
|
icon: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'UI_CUSTOM_ASSETS_ICON'
|
|
|
|
|
},
|
|
|
|
|
safari_pinned_tab: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'UI_CUSTOM_ASSETS_SAFARI_PINNED_TAB'
|
|
|
|
|
},
|
|
|
|
|
facebook: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'UI_CUSTOM_ASSETS_FACEBOOK'
|
|
|
|
|
},
|
|
|
|
|
twitter: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'UI_CUSTOM_ASSETS_TWITTER'
|
|
|
|
|
},
|
|
|
|
|
wordmark: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'UI_CUSTOM_ASSETS_WORDMARK'
|
2022-08-07 22:37:17 +00:00
|
|
|
|
},
|
2022-08-19 11:11:30 +00:00
|
|
|
|
custom_css: {
|
|
|
|
|
format: String,
|
|
|
|
|
default: '',
|
|
|
|
|
env: 'UI_CUSTOM_CSS'
|
|
|
|
|
}
|
2017-06-06 17:24:58 +00:00
|
|
|
|
}
|
|
|
|
|
});
|
2017-06-05 22:35:36 +00:00
|
|
|
|
|
2017-06-06 17:24:58 +00:00
|
|
|
|
// Perform validation
|
|
|
|
|
conf.validate({ allowed: 'strict' });
|
|
|
|
|
|
2017-06-09 17:44:12 +00:00
|
|
|
|
const props = conf.getProperties();
|
2021-05-06 04:15:02 +00:00
|
|
|
|
|
2021-05-07 11:06:59 +00:00
|
|
|
|
const deriveBaseUrl = req => {
|
|
|
|
|
if (!props.detect_base_url) {
|
2021-05-06 04:15:02 +00:00
|
|
|
|
return props.base_url;
|
|
|
|
|
}
|
2021-05-07 11:06:59 +00:00
|
|
|
|
|
|
|
|
|
const protocol = req.secure ? 'https://' : 'http://';
|
|
|
|
|
return `${protocol}${req.headers.host}`;
|
2021-05-06 04:15:02 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
|
...props,
|
2021-05-07 11:06:59 +00:00
|
|
|
|
deriveBaseUrl
|
2021-05-06 04:15:02 +00:00
|
|
|
|
};
|