123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- const convict = require('convict');
- const convict_format_with_validator = require('convict-format-with-validator');
- const { tmpdir } = require('os');
- const path = require('path');
- const { randomBytes } = require('crypto');
- convict.addFormats(convict_format_with_validator);
- convict.addFormat({
- name: 'positive-int-array',
- 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)
- );
- },
- validate: ints => {
- // takes: int[], errors if any NaNs, negatives, or floats present
- for (const int of ints) {
- if (typeof int !== 'number' || isNaN(int) || int < 0 || int % 1 > 0)
- throw new Error('must be a comma-separated list of positive integers');
- }
- }
- });
- const conf = convict({
- s3_bucket: {
- format: String,
- default: '',
- env: 'S3_BUCKET'
- },
- s3_endpoint: {
- format: String,
- default: '',
- env: 'S3_ENDPOINT'
- },
- s3_use_path_style_endpoint: {
- format: Boolean,
- default: false,
- env: 'S3_USE_PATH_STYLE_ENDPOINT'
- },
- gcs_bucket: {
- format: String,
- default: '',
- env: 'GCS_BUCKET'
- },
- expire_times_seconds: {
- format: 'positive-int-array',
- default: [300, 3600, 86400, 604800],
- env: 'EXPIRE_TIMES_SECONDS'
- },
- default_expire_seconds: {
- format: Number,
- default: 86400,
- env: 'DEFAULT_EXPIRE_SECONDS'
- },
- max_expire_seconds: {
- format: Number,
- default: 86400 * 7,
- env: 'MAX_EXPIRE_SECONDS'
- },
- download_counts: {
- format: 'positive-int-array',
- default: [1, 2, 3, 4, 5, 20, 50, 100],
- env: 'DOWNLOAD_COUNTS'
- },
- default_downloads: {
- format: Number,
- default: 1,
- env: 'DEFAULT_DOWNLOADS'
- },
- max_downloads: {
- format: Number,
- default: 100,
- 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'
- },
- redis_host: {
- format: String,
- default: 'localhost',
- env: 'REDIS_HOST'
- },
- redis_port: {
- format: Number,
- default: 6379,
- env: 'REDIS_PORT'
- },
- redis_user: {
- format: String,
- default: '',
- env: 'REDIS_USER'
- },
- redis_password: {
- format: String,
- default: '',
- env: 'REDIS_PASSWORD'
- },
- redis_db: {
- format: String,
- default: '',
- env: 'REDIS_DB'
- },
- redis_event_expire: {
- format: Boolean,
- default: false,
- env: 'REDIS_EVENT_EXPIRE'
- },
- redis_retry_time: {
- format: Number,
- default: 10000,
- env: 'REDIS_RETRY_TIME'
- },
- redis_retry_delay: {
- format: Number,
- default: 500,
- env: 'REDIS_RETRY_DELAY'
- },
- listen_address: {
- format: 'ipaddress',
- default: '0.0.0.0',
- env: 'IP_ADDRESS'
- },
- listen_port: {
- format: 'port',
- default: 1443,
- arg: 'port',
- env: 'PORT'
- },
- sentry_id: {
- format: String,
- default: '',
- env: 'SENTRY_CLIENT'
- },
- sentry_dsn: {
- format: String,
- default: '',
- env: 'SENTRY_DSN'
- },
- env: {
- format: ['production', 'development', 'test'],
- default: 'development',
- env: 'NODE_ENV'
- },
- max_file_size: {
- format: Number,
- default: 1024 * 1024 * 1024 * 2.5,
- env: 'MAX_FILE_SIZE'
- },
- l10n_dev: {
- format: Boolean,
- default: false,
- env: 'L10N_DEV'
- },
- base_url: {
- format: 'url',
- default: 'https://send.example.com',
- env: 'BASE_URL'
- },
- custom_title: {
- format: String,
- default: 'Send',
- env: 'CUSTOM_TITLE'
- },
- custom_description: {
- 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'
- },
- detect_base_url: {
- format: Boolean,
- default: false,
- env: 'DETECT_BASE_URL'
- },
- file_dir: {
- format: 'String',
- default: `${tmpdir()}${path.sep}send-${randomBytes(4).toString('hex')}`,
- env: 'FILE_DIR'
- },
- fxa_url: {
- format: 'url',
- default: 'https://send-fxa.dev.lcip.org',
- env: 'FXA_URL'
- },
- fxa_client_id: {
- format: String,
- default: '', // disabled
- env: 'FXA_CLIENT_ID'
- },
- fxa_key_scope: {
- format: String,
- default: 'https://identity.mozilla.com/apps/send',
- env: 'FXA_KEY_SCOPE'
- },
- 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'
- },
- survey_url: {
- format: String,
- default: '',
- env: 'SURVEY_URL'
- },
- ip_db: {
- format: String,
- default: '',
- env: 'IP_DB'
- },
- 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',
- env: 'SEND_FOOTER_SOURCE_URL'
- },
- custom_footer_text: {
- format: String,
- default: '',
- env: 'CUSTOM_FOOTER_TEXT'
- },
- custom_footer_url: {
- format: String,
- default: '',
- env: 'CUSTOM_FOOTER_URL'
- },
- ui_color_primary: {
- format: String,
- default: '#0a84ff',
- env: 'UI_COLOR_PRIMARY'
- },
- ui_color_accent: {
- format: String,
- default: '#003eaa',
- env: 'UI_COLOR_ACCENT'
- },
- custom_locale: {
- format: String,
- default: '',
- env: 'CUSTOM_LOCALE'
- },
- 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'
- },
- custom_css: {
- format: String,
- default: '',
- env: 'UI_CUSTOM_CSS'
- }
- }
- });
- // Perform validation
- conf.validate({ allowed: 'strict' });
- const props = conf.getProperties();
- const deriveBaseUrl = req => {
- if (!props.detect_base_url) {
- return props.base_url;
- }
- const protocol = req.secure ? 'https://' : 'http://';
- return `${protocol}${req.headers.host}`;
- };
- module.exports = {
- ...props,
- deriveBaseUrl
- };
|