/* 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 crypto = require('crypto');
const url = require('url');

const convict = require('convict');

const conf = convict({
  publicUrl: {
    doc: 'The full, public-facing bridge URL. Include scheme, host, and port.',
    env: 'PUBLIC_URL',
    format: 'url',
    default: 'http://127.0.0.1:3000'
  },
  personaUrl : {
    doc: 'The full URL of the Persona service. Used to find JavaScript shims.',
    env: 'PERSONA_URL',
    format: function (raw) {
      var p = url.parse(raw);

      if (!/^https?:$/.test(p.protocol)) {
        throw new Error('must have http or https scheme');
      }

      if (!p.hostname) {
        throw new Error('must supply hostname or ip address');
      }

      if (p.path !== '/') { // url.parse normalizes path to '/' when omitted
        throw new Error('must not provide a path or query string');
      }

      if (p.hash) {
        throw new Error('must not provide an anchor');
      }
    },
    default: 'http://127.0.0.1:10002'
  },
  openidRealm: {
    doc: 'The openid realm.',
    env: 'OPENID_REALM',
    format: String,
    default: undefined // Derives from publicUrl by default.
  },
  listenPort: {
    doc: 'The port to listen on.',
    env: 'PORT',
    format: 'port',
    default: 3000
  },
  listenHost: {
    doc: 'The hostname or IP to bind to.',
    env: 'HOST',
    format: String,
    default: '127.0.0.1'
  },
  issuerDomain: {
    doc: 'The hostname used in the signed certificate.',
    env: 'ISSUER_DOMAIN',
    arg: 'issuer',
    format: String,
    default: undefined // Derives from publicUrl by default.
  },
  pubKeyPath: {
    doc: "Path to the public key to render the .well-known",
    env: "PUB_KEY_PATH",
    format: String,
    default: "var/key.publickey"
  },
  privKeyPath: {
    doc: "Path to the private key to sign certs.",
    env: "PRIV_KEY_PATH",
    format: String,
    default: "var/key.secretkey"
  },
  certMaxDuration: {
    doc: "Maximum duration in milliseconds of a signed certificate",
    env: "MAX_CERT_DURATION",
    format: "int",
    default: 1000 * 60 * 60 * 24 // 24 hours max
  },
  certMinDuration: {
    doc: "Default duration in milliseconds if client doesn't provide duration.",
    env: "MIN_CERT_DURATION",
    format: "int",
    default: 1000 * 60 * 5 // 5 minutes default
  },
  logPath: {
    doc: "Path to log file.",
    env: "LOG_PATH",
    format: String,
    default: '-' // Log to stdout / stderr.
  },
  sessionSecret: {
    doc: 'The secret used for signing cookies',
    env: 'SESSION_SECRET',
    format: String,
    default: String(crypto.randomBytes(256)) // Ephemeral. OVERRIDE THIS.
  },
  sessionDuration: {
    doc: 'The duration of session cookies, in milliseconds.',
    env: 'SESSION_DURATION',
    format: 'nat',
    default: 15 * 60 * 1000
  },
  localeList: {
    doc: 'An array of locales to enabled.',
    env: 'LOCALE_LIST',
    format: Array,
    default: ['en-US', 'it-CH']
  },
  localeDefault: {
    doc: 'The default locale.',
    env: 'LOCALE_DEFAULT',
    format: String,
    default: 'en-US'
  },
  localeDebug: {
    doc: 'The debug locale.',
    env: 'LOCALE_DEBUG',
    format: String,
    default: 'it-CH'
  },
  localeDir: {
    doc: 'The path to the directory containing translations.',
    env: 'LOCALE_DIR',
    format: String,
    default: 'locale'
  },
  proxyHost: {
    doc: 'Host for HTTP proxy of outgoing requests.',
    env: 'HTTP_PROXY_HOST',
    format: String,
    default: ''
  },
  proxyPort: {
    doc: 'Port for HTTP proxy of outgoing requests.',
    env: 'HTTP_PROXY_PORT',
    format: Number,
    default: 0
  },
  statsdEnabled: {
    doc: 'Whether statsd should record its data.',
    env: 'STATSD',
    format: Boolean,
    default: false
  },
  statsdHost: {
    doc: 'Host of statsd daemon.',
    env: 'STATSD_HOST',
    format: String,
    default: 'localhost'
  },
  statsdPort: {
    doc: 'Port of statsd daemon.',
    env: 'STATSD_PORT',
    format: 'port',
    default: 8125
  }
});

// Load configuration files specified in the environment
if (process.env.CONFIG_FILES) {
  conf.loadFile(process.env.CONFIG_FILES.split(','));
}

// Derive openid realm from publicUrl
//   https://foo.bar.example.com -> https://*.example.com
//   http://127.0.0.1:3000       -> http://127.0.0.1:3000
if (conf.get('openidRealm') === undefined) {
  // If only v8 supported lexical scoping...
  (function () {
    var publicUrl = url.parse(conf.get('publicUrl'));
    var basename = publicUrl.hostname.split('.').slice(-2).join('.');

    // Don't munge the realm in local development environment
    if ('port' in publicUrl) {
      conf.set('openidRealm', conf.get('publicUrl'));
    } else {
      conf.set('openidRealm', publicUrl.protocol + '//*.' + basename);
    }
  })();
}

// Derive default issuer from publicUrl
if (conf.get('issuer') === undefined) {
  conf.set('issuer', url.parse(conf.get('publicUrl')).hostname);
}

// Strip trailing slashes and whitespace from personaUrl and publicUrl
conf.set('personaUrl', conf.get('personaUrl').trim().replace(/[\s\/]*$/, ''));
conf.set('publicUrl', conf.get('publicUrl').trim().replace(/[\s\/]*$/, ''));

conf.validate();

if (conf.get('proxyHost')) {
  process.env.HTTP_PROXY_HOST = conf.get('proxyHost');
  process.env.HTTPS_PROXY_HOST = conf.get('proxyHost');
}
if (conf.get('proxyPort')) {
  process.env.HTTP_PROXY_PORT = conf.get('proxyPort');
  process.env.HTTPS_PROXY_PORT = conf.get('proxyPort');
}

module.exports = conf;

@@ -4305,24 +4305,252 @@
 t(','));%0A%7D%0A%0A
+// Strip trailing slashes and whitespace from personaUrl and publicUrl%0Aconf.set('personaUrl', conf.get('personaUrl').trim().replace(/%5B%5Cs%5C/%5D*$/, ''));%0Aconf.set('publicUrl', conf.get('publicUrl').trim().replace(/%5B%5Cs%5C/%5D*$/, ''));%0A%0A
 // Derive op
@@ -5323,236 +5323,8 @@
 %0A%7D%0A%0A
-// Strip trailing slashes and whitespace from personaUrl and publicUrl%0Aconf.set('personaUrl', conf.get('personaUrl').trim().replace(/%5B%5Cs%5C/%5D*$/, ''));%0Aconf.set('publicUrl', conf.get('publicUrl').trim().replace(/%5B%5Cs%5C/%5D*$/, ''));%0A%0A
 conf

Clean up urls before deriving values from them