packages/fxa-payments-server/server/config/index.js (464 lines of code) (raw):
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const fs = require('fs');
const path = require('path');
const convict = require('convict');
const { tracingConfig } = require('fxa-shared/tracing/config');
convict.addFormats(require('convict-format-with-moment'));
convict.addFormats(require('convict-format-with-validator'));
const conf = convict({
featureFlags: {
useFirestoreProductConfigs: {
default: false,
doc: 'Feature flag on whether to expect Firestore (and not Stripe metadata) based product and plan configurations',
env: 'SUBSCRIPTIONS_FIRESTORE_CONFIGS_ENABLED',
format: Boolean,
},
useStripeAutomaticTax: {
default: false,
doc: 'Feature flag on whether Stripe automatic tax is enabled',
env: 'SUBSCRIPTIONS_STRIPE_TAX_ENABLED',
format: Boolean,
},
},
amplitude: {
enabled: {
default: true,
doc: 'Enable amplitude events',
env: 'AMPLITUDE_ENABLED',
format: Boolean,
},
schemaValidation: {
default: true,
doc: 'Validate events against a JSON schema',
env: 'AMPLITUDE_SCHEMA_VALIDATION',
format: Boolean,
},
rawEvents: {
default: false,
doc: 'Log raw Amplitude events',
env: 'AMPLITUDE_RAW_EVENTS',
format: Boolean,
},
},
clientAddressDepth: {
default: 3,
doc: 'location of the client ip address in the remote address chain',
env: 'CLIENT_ADDRESS_DEPTH',
format: Number,
},
clientMetrics: {
maxEventOffset: {
default: '2 days',
doc: 'Maximum event offset',
env: 'CLIENT_METRICS_MAX_EVENT_OFFSET',
format: 'duration',
},
},
csp: {
enabled: {
default: true,
doc: 'Send "Content-Security-Policy" header',
env: 'CSP_ENABLED',
},
reportUri: {
default: 'https://accounts.firefox.com/_/csp-violation',
doc: 'Location of "report-uri" for full, blocking CSP rules',
env: 'CSP_REPORT_URI',
},
reportOnlyEnabled: {
default: false,
doc: 'Send "Content-Security-Policy-Report-Only" header',
env: 'CSP_REPORT_ONLY_ENABLED',
},
reportOnlyUri: {
default: 'https://accounts.firefox.com/_/csp-violation-report-only',
doc: 'Location of "report-uri" for report-only CSP rules',
env: 'CSP_REPORT_ONLY_URI',
},
extraImgSrc: {
default: [],
doc: 'Additional hosts to allow as image sources',
env: 'CSP_EXTRA_IMG_SRC',
},
},
env: {
default: 'production',
doc: 'The current node.js environment',
env: 'NODE_ENV',
format: ['development', 'production', 'test'],
},
flow_id_expiry: {
default: '2 hours',
doc: 'Time after which flow ids are considered stale',
env: 'FLOW_ID_EXPIRY',
format: 'duration',
},
googleAnalytics: {
enabled: {
default: false,
doc: 'Toggle Google Analytics enabled',
env: 'GA_ENABLED',
format: Boolean,
},
measurementId: {
default: '',
doc: 'Google Analytics measurement ID',
env: 'GA_MEASUREMENT_ID',
format: String,
},
supportedProductIds: {
default: 'prod_GqM9ToKK62qjkK',
doc: 'Comma separated string of supported Stripe Product IDs',
env: 'GA_SUPPORTED_STRIPE_PRODUCT_IDS',
format: String,
},
debugMode: {
default: false,
doc: 'Toggle Google Analytics gtag debug mode. (Not to be confused with library react-ga testMode',
env: 'GA_TEST_MODE',
format: Boolean,
},
},
geodb: {
dbPath: {
default: path.resolve(__dirname, '../../../fxa-geodb/db/cities-db.mmdb'),
doc: 'Path to maxmind database file',
env: 'GEODB_DBPATH',
format: String,
},
enabled: {
default: true,
doc: 'Feature flag for geolocation',
env: 'GEODB_ENABLED',
format: Boolean,
},
locationOverride: {
doc: 'override for forcing location',
format: Object,
default: {},
env: 'GEODB_LOCATION_OVERRIDE',
},
},
hstsEnabled: {
default: true,
doc: 'Send a Strict-Transport-Security header',
env: 'HSTS_ENABLED',
format: Boolean,
},
hstsMaxAge: {
default: 31536000, // a year
doc: 'Max age of the STS directive in seconds',
// Note: This format is a number because the value needs to be in seconds
format: Number,
},
legalDocLinks: {
privacyNotice: {
default: 'https://www.mozilla.org/privacy/firefox-private-network',
doc: 'Link to Privacy Notice',
env: 'PAYMENT_PRIVACY_NOTICE',
format: 'url',
},
termsOfService: {
default:
'https://www.mozilla.org/about/legal/terms/firefox-private-network',
doc: 'Link to Terms of Service',
env: 'PAYMENT_TERMS_OF_SERVCIE',
format: 'url',
},
cdnFqdn: {
default: 'accounts-static.cdn.mozilla.net',
doc: 'The domain name where the legal doc downloads are hosted.',
env: 'PAYMENT_LEGAL_DOWNLOAD_FQDN',
format: String,
},
httpResCacheLimit: {
default: 65536,
doc: 'The max number of entries in the redirect endpoint HTTP results cache. 0 means unlimited and the memory usage on the cache could reach the max of Map (1GB on V8)',
env: 'PAYMENT_LEGAL_DOWNLOAD_CACHE_LIMIT',
format: Number,
},
},
listen: {
host: {
default: '0.0.0.0',
doc: 'The ip address the server should bind',
env: 'IP_ADDRESS',
format: String,
},
port: {
default: 3031,
doc: 'The port the server should bind',
env: 'PORT',
format: 'port',
},
publicUrl: {
default: 'http://localhost:3031',
env: 'PUBLIC_URL',
format: 'url',
},
useHttps: {
default: false,
doc: 'set to true to serve directly over https',
env: 'USE_TLS',
},
},
logging: {
app: { default: 'fxa-payments-server' },
fmt: {
default: 'heka',
env: 'LOGGING_FORMAT',
format: ['heka', 'pretty'],
},
level: {
default: 'info',
env: 'LOG_LEVEL',
},
routes: {
enabled: {
default: true,
doc: 'Enable route logging. Set to false to trimming CI logs.',
env: 'ENABLE_ROUTE_LOGGING',
},
format: {
default: 'default_fxa',
format: ['default_fxa', 'dev_fxa', 'default', 'dev', 'short', 'tiny'],
},
},
},
oauth_client_id_map: {
default: {
dcdb5ae7add825d2: '123done',
'325b4083e32fe8e7': '321done',
},
doc: 'Mappings from client id to service name: { "id1": "name-1", "id2": "name-2" }',
env: 'OAUTH_CLIENT_IDS',
format: Object,
},
productRedirectURLs: {
default: {
'123doneProProduct': 'http://localhost:8080/',
fortressProProduct: 'http://localhost:9292/download',
prod_FUUNYnlDso7FeB: 'https://fortress-latest.dev.lcip.org/',
prod_GqM9ToKK62qjkK: 'https://123done-latest.dev.lcip.org/',
// todo get new prod_id for 123done stage
prod_FfiuDs9u11ESbD: 'https://123done-stage.dev.lcip.org',
},
doc: 'Mapping between product IDs and post-subscription redirect URLs',
env: 'PRODUCT_REDIRECT_URLS',
format: Object,
},
proxyStaticResourcesFrom: {
default: '',
doc: 'Instead of loading static resources from disk, get them by proxy from this URL (typically a special reloading dev server)',
env: 'PROXY_STATIC_RESOURCES_FROM',
format: String,
},
sentry: {
dsn: {
default: '',
doc: 'Sentry DSN',
env: 'SENTRY_DSN',
format: 'String',
},
env: {
doc: 'Environment name to report to sentry',
default: 'local',
format: ['local', 'ci', 'dev', 'stage', 'prod'],
env: 'SENTRY_ENV',
},
url: {
default: 'https://sentry.prod.mozaws.net/444',
doc: 'Sentry URL',
env: 'SENTRY_URL',
format: 'String',
},
sampleRate: {
default: 1.0,
doc: 'Rate at which errors are sampled.',
env: 'SENTRY_SAMPLE_RATE',
format: 'Number',
},
serverName: {
doc: 'Name used by sentry to identify the server.',
default: 'fxa-payments-broker',
format: 'String',
env: 'SENTRY_SERVER_NAME',
},
clientName: {
doc: 'Name used by sentry to identify the client.',
default: 'fxa-payments-client',
format: 'String',
env: 'SENTRY_CLIENT_NAME',
},
tracesSampleRate: {
doc: 'Rate at which sentry traces are captured',
default: 0,
format: 'Number',
env: 'SENTRY_TRACES_SAMPLE_RATE',
},
},
servers: {
auth: {
url: {
default: 'http://localhost:9000',
doc: 'The url of the fxa-auth-server instance',
env: 'AUTH_SERVER_URL',
format: 'url',
},
},
content: {
url: {
default: 'http://localhost:3030',
doc: 'The url of the corresponding fxa-content-server instance',
env: 'CONTENT_SERVER_URL',
format: 'url',
},
},
oauth: {
url: {
default: 'http://localhost:9000',
doc: 'The url of the corresponding fxa-oauth-server instance',
env: 'OAUTH_SERVER_URL',
format: 'url',
},
clientId: {
default: '59cceb6f8c32317c',
doc: 'The Payments frontend OAuth client id.',
env: 'OAUTH_SUBSCRIPTIONS_CLIENT_ID',
format: 'String',
},
},
profile: {
url: {
default: 'http://localhost:1111',
doc: 'The url of the corresponding fxa-profile-server instance',
env: 'PROFILE_SERVER_URL',
format: 'url',
},
},
profileImages: {
url: {
default: 'http://localhost:1112',
doc: 'The url of the Firefox Account Profile Image Server',
env: 'FXA_PROFILE_IMAGES_URL',
format: 'url',
},
},
accountsCdn: {
url: {
default: 'https://accounts-static.cdn.mozilla.net',
doc: 'The URL of the Mozilla Accounts static content CDN',
env: 'FXA_STATIC_CDN_URL',
format: 'url',
},
},
},
staticResources: {
directory: {
default: 'build',
doc: 'Directory where static resources are located',
env: 'STATIC_DIRECTORY',
format: String,
},
maxAge: {
default: '10 minutes',
doc: 'Cache max age for static assets, in ms',
env: 'STATIC_MAX_AGE',
format: 'duration',
},
url: {
default: 'http://localhost:3031',
doc: 'The origin of the static resources',
env: 'STATIC_RESOURCE_URL',
format: 'url',
},
},
statsd: {
enabled: {
doc: 'Enable StatsD',
format: Boolean,
default: false,
env: 'STATSD_ENABLE',
},
sampleRate: {
doc: 'Sampling rate for StatsD',
format: Number,
default: 1,
env: 'STATSD_SAMPLE_RATE',
},
maxBufferSize: {
doc: 'StatsD message buffer size in number of characters',
format: Number,
default: 500,
env: 'STATSD_BUFFER_SIZE',
},
host: {
doc: 'StatsD host to report to',
format: String,
default: 'localhost',
env: 'DD_AGENT_HOST',
},
port: {
doc: 'Port number of StatsD server',
format: Number,
default: 8125,
env: 'DD_DOGSTATSD_PORT',
},
prefix: {
doc: 'StatsD metrics name prefix',
format: String,
default: 'fxa-payments.',
env: 'STATSD_PREFIX',
},
},
paypal: {
clientId: {
default: 'sb',
doc: 'The PayPal client ID',
env: 'PAYPAL_CLIENT_ID',
format: String,
},
apiUrl: {
default: 'https://www.sandbox.paypal.com',
doc: 'The PAYPAL API url',
env: 'PAYPAL_API_URL',
format: 'url',
},
scriptUrl: {
default: 'https://www.paypal.com',
doc: 'The PayPal script url',
env: 'PAYPAL_SCRIPT_URL',
format: 'url',
},
},
stripe: {
apiKey: {
default: 'pk_test_VNpCidC0a2TJJB3wqXq7drhN00sF8r9mhs',
doc: 'API key for Stripe',
env: 'STRIPE_API_KEY',
format: String,
},
apiUrl: {
default: 'https://api.stripe.com',
doc: 'The Stripe API url',
env: 'STRIPE_API_URL',
format: 'url',
},
hooksUrl: {
default: 'https://hooks.stripe.com',
doc: 'The Stripe hooks url',
env: 'STRIPE_HOOKS_URL',
format: 'url',
},
scriptUrl: {
default: 'https://js.stripe.com',
doc: 'The Stripe script url',
env: 'STRIPE_SCRIPT_URL',
format: 'url',
},
},
tracing: tracingConfig,
});
// handle configuration files. you can specify a CSV list of configuration
// files to process, which will be overlayed in order, in the CONFIG_FILES
// environment variable.
let envConfig = path.join(__dirname, `${conf.get('env')}.json`);
envConfig = `${envConfig},${process.env.CONFIG_FILES || ''}`;
const files = envConfig.split(',').filter(fs.existsSync);
conf.loadFile(files);
conf.validate({ allowed: 'strict' });
module.exports = conf;