2013-07-26 05:46:16 +04:00
|
|
|
/* 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/. */
|
|
|
|
|
2017-03-08 19:40:21 +03:00
|
|
|
'use strict'
|
|
|
|
|
2017-11-13 19:11:53 +03:00
|
|
|
// This MUST be the first require in the program.
|
2016-09-02 20:31:49 +03:00
|
|
|
// Only `require()` the newrelic module if explicity enabled.
|
|
|
|
// If required, modules will be instrumented.
|
|
|
|
require('../lib/newrelic')()
|
|
|
|
|
2015-03-23 22:24:08 +03:00
|
|
|
var jwtool = require('fxa-jwtool')
|
2017-03-09 20:59:57 +03:00
|
|
|
var P = require('../lib/promise')
|
2013-07-26 00:18:19 +04:00
|
|
|
|
2016-08-16 02:07:05 +03:00
|
|
|
|
2017-03-23 08:51:18 +03:00
|
|
|
function run(config) {
|
|
|
|
var log = require('../lib/log')(config.log)
|
|
|
|
var getGeoData = require('../lib/geodb')(log)
|
2016-08-16 02:07:05 +03:00
|
|
|
// Force the geo to load and run at startup, not waiting for it to run on
|
|
|
|
// some route later.
|
2018-01-20 12:03:38 +03:00
|
|
|
const knownIp = '63.245.221.32' // Mozilla MTV
|
|
|
|
const location = getGeoData(knownIp)
|
|
|
|
log.info({ op: 'geodb.check', result: location })
|
2016-08-16 02:07:05 +03:00
|
|
|
|
2016-10-06 16:25:53 +03:00
|
|
|
// RegExp instances serialise to empty objects, display regex strings instead.
|
|
|
|
const stringifiedConfig =
|
|
|
|
JSON.stringify(config, (k, v) =>
|
|
|
|
v && v.constructor === RegExp ? v.toString() : v
|
|
|
|
)
|
|
|
|
|
2013-12-17 08:36:34 +04:00
|
|
|
if (config.env !== 'prod') {
|
2016-10-06 16:25:53 +03:00
|
|
|
log.info(stringifiedConfig, 'starting config')
|
2013-11-26 05:27:08 +04:00
|
|
|
}
|
2013-07-26 00:18:19 +04:00
|
|
|
|
2015-05-10 22:11:59 +03:00
|
|
|
var error = require('../lib/error')
|
2016-09-22 19:44:34 +03:00
|
|
|
var Token = require('../lib/tokens')(log, config)
|
2015-05-10 22:11:59 +03:00
|
|
|
var Password = require('../lib/crypto/password')(log, config)
|
2018-08-28 19:17:56 +03:00
|
|
|
var UnblockCode = require('../lib/crypto/random').base32(config.signinUnblock.codeLength)
|
2013-10-27 06:49:33 +04:00
|
|
|
|
2015-05-10 22:11:59 +03:00
|
|
|
var signer = require('../lib/signer')(config.secretKeyFile, config.domain)
|
2015-09-22 03:14:23 +03:00
|
|
|
var serverPublicKeys = {
|
|
|
|
primary: jwtool.JWK.fromFile(
|
|
|
|
config.publicKeyFile,
|
|
|
|
{
|
|
|
|
algorithm: 'RS',
|
|
|
|
use: 'sig',
|
|
|
|
kty: 'RSA'
|
|
|
|
}
|
|
|
|
),
|
|
|
|
secondary: config.oldPublicKeyFile ?
|
|
|
|
jwtool.JWK.fromFile(
|
|
|
|
config.oldPublicKeyFile,
|
|
|
|
{
|
|
|
|
algorithm: 'RS',
|
|
|
|
use: 'sig',
|
|
|
|
kty: 'RSA'
|
|
|
|
}
|
|
|
|
)
|
|
|
|
: null
|
|
|
|
}
|
2013-10-30 00:46:09 +04:00
|
|
|
|
2015-05-10 22:11:59 +03:00
|
|
|
var Customs = require('../lib/customs')(log, error)
|
2014-04-19 06:05:47 +04:00
|
|
|
|
2015-05-10 22:11:59 +03:00
|
|
|
var Server = require('../lib/server')
|
2013-10-30 00:46:09 +04:00
|
|
|
var server = null
|
2017-02-16 11:21:22 +03:00
|
|
|
var senders = null
|
2014-09-29 08:33:38 +04:00
|
|
|
var statsInterval = null
|
2014-06-09 04:19:34 +04:00
|
|
|
var database = null
|
|
|
|
var customs = null
|
2014-02-13 02:54:05 +04:00
|
|
|
|
2015-06-19 02:12:42 +03:00
|
|
|
function logStatInfo() {
|
|
|
|
log.stat(server.stat())
|
|
|
|
log.stat(Password.stat())
|
|
|
|
}
|
|
|
|
|
2017-03-09 20:59:57 +03:00
|
|
|
var DB = require('../lib/db')(
|
|
|
|
config,
|
|
|
|
log,
|
2017-03-24 05:12:39 +03:00
|
|
|
Token,
|
2017-03-09 20:59:57 +03:00
|
|
|
UnblockCode
|
|
|
|
)
|
2013-07-26 00:18:19 +04:00
|
|
|
|
2017-03-23 08:51:18 +03:00
|
|
|
return P.all([
|
2017-03-09 20:59:57 +03:00
|
|
|
DB.connect(config[config.db.backend]),
|
|
|
|
require('../lib/senders/translator')(config.i18n.supportedLanguages, config.i18n.defaultLanguage)
|
|
|
|
])
|
|
|
|
.spread(
|
|
|
|
(db, translator) => {
|
|
|
|
database = db
|
2017-03-28 20:06:29 +03:00
|
|
|
const bounces = require('../lib/bounces')(config, db)
|
2017-03-09 20:59:57 +03:00
|
|
|
|
2017-03-28 20:06:29 +03:00
|
|
|
return require('../lib/senders')(log, config, error, bounces, translator)
|
2017-03-09 20:59:57 +03:00
|
|
|
.then(result => {
|
|
|
|
senders = result
|
|
|
|
customs = new Customs(config.customsUrl)
|
|
|
|
var routes = require('../lib/routes')(
|
|
|
|
log,
|
|
|
|
serverPublicKeys,
|
|
|
|
signer,
|
|
|
|
db,
|
|
|
|
senders.email,
|
|
|
|
senders.sms,
|
|
|
|
Password,
|
|
|
|
config,
|
|
|
|
customs
|
|
|
|
)
|
2018-07-11 16:19:05 +03:00
|
|
|
|
2017-03-23 08:51:18 +03:00
|
|
|
statsInterval = setInterval(logStatInfo, 15000)
|
2017-03-09 20:59:57 +03:00
|
|
|
|
2018-07-11 16:19:05 +03:00
|
|
|
async function init() {
|
|
|
|
server = await Server.create(log, error, config, routes, db, translator)
|
|
|
|
try {
|
|
|
|
await server.start()
|
|
|
|
log.info({op: 'server.start.1', msg: 'running on ' + server.info.uri})
|
|
|
|
} catch (err) {
|
|
|
|
log.error(
|
|
|
|
{
|
|
|
|
op: 'server.start.1', msg: 'failed startup with error',
|
|
|
|
err: {message: err.message}
|
2017-03-23 08:51:18 +03:00
|
|
|
}
|
2018-07-11 16:19:05 +03:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
init()
|
|
|
|
|
2017-03-09 20:59:57 +03:00
|
|
|
})
|
|
|
|
},
|
|
|
|
function (err) {
|
|
|
|
log.error({ op: 'DB.connect', err: { message: err.message } })
|
|
|
|
process.exit(1)
|
2013-10-30 00:46:09 +04:00
|
|
|
}
|
|
|
|
)
|
2017-03-23 08:51:18 +03:00
|
|
|
.then(() => {
|
|
|
|
return {
|
|
|
|
log: log,
|
|
|
|
close() {
|
|
|
|
return new P((resolve) => {
|
|
|
|
log.info({ op: 'shutdown' })
|
|
|
|
clearInterval(statsInterval)
|
2018-07-11 16:19:05 +03:00
|
|
|
server.stop().then(() => {
|
|
|
|
customs.close()
|
|
|
|
try {
|
|
|
|
senders.email.stop()
|
|
|
|
} catch (e) {
|
|
|
|
// XXX: simplesmtp module may quit early and set socket to `false`, stopping it may fail
|
|
|
|
log.warn({op: 'shutdown', message: 'Mailer client already disconnected'})
|
2017-03-23 08:51:18 +03:00
|
|
|
}
|
2018-07-11 16:19:05 +03:00
|
|
|
database.close()
|
|
|
|
resolve()
|
|
|
|
})
|
2017-03-23 08:51:18 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2013-07-26 00:18:19 +04:00
|
|
|
|
2017-03-23 08:51:18 +03:00
|
|
|
function main() {
|
|
|
|
const config = require('../config').getProperties()
|
|
|
|
run(config).then(server => {
|
|
|
|
process.on('uncaughtException', (err) => {
|
|
|
|
server.log.fatal(err)
|
2014-01-15 10:29:34 +04:00
|
|
|
process.exit(8)
|
2017-03-23 08:51:18 +03:00
|
|
|
})
|
2017-06-29 01:10:22 +03:00
|
|
|
process.on('unhandledRejection', (reason, promise) => {
|
|
|
|
server.log.fatal({
|
|
|
|
op: 'promise.unhandledRejection',
|
|
|
|
error: reason
|
|
|
|
})
|
|
|
|
})
|
2017-03-23 08:51:18 +03:00
|
|
|
process.on('SIGINT', shutdown)
|
|
|
|
server.log.on('error', shutdown)
|
|
|
|
|
|
|
|
function shutdown() {
|
|
|
|
server.close().then(() => {
|
2015-07-30 01:05:29 +03:00
|
|
|
process.exit() //XXX: because of openid dep ಠ_ಠ
|
2017-03-23 08:51:18 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
2017-04-18 23:27:31 +03:00
|
|
|
.catch(process.exit.bind(null, 8))
|
2013-07-26 00:18:19 +04:00
|
|
|
}
|
|
|
|
|
2017-03-23 08:51:18 +03:00
|
|
|
if (require.main === module) {
|
|
|
|
main()
|
|
|
|
} else {
|
|
|
|
module.exports = run
|
|
|
|
}
|