packages/fxa-auth-server/lib/routes/index.js (278 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/. */ 'use strict'; const url = require('url'); const tracing = require('fxa-shared/tracing/node-tracing'); module.exports = function ( log, serverPublicKeys, signer, db, mailer, Password, config, customs, zendeskClient, statsd, profile, stripeHelper, redis, glean, push, pushbox, authServerCacheRedis ) { // Various extra helpers. const devicesImpl = require('../devices')(log, db, push, pushbox); const cadReminders = require('../cad-reminders')(config, log); const signinUtils = require('./utils/signin')( log, config, customs, db, mailer, cadReminders, glean, statsd ); const clientUtils = require('./utils/clients')(log, config); const verificationReminders = require('../verification-reminders')( log, config ); const subscriptionAccountReminders = require('../subscription-account-reminders')(log, config); const signupUtils = require('./utils/signup')( log, db, mailer, push, verificationReminders, glean ); // The routing modules themselves. const defaults = require('./defaults')(log, config, db); const idp = require('./idp')(log, serverPublicKeys); const grant = require('../oauth/grant'); const oauthRawDB = require('../oauth/db'); grant.setStripeHelper(stripeHelper); const { accountRoutes } = require('./account'); const account = accountRoutes( log, db, mailer, Password, config, customs, signinUtils, signupUtils, push, verificationReminders, subscriptionAccountReminders, oauthRawDB, stripeHelper, pushbox, glean, statsd ); const oauth = require('./oauth')( log, config, db, mailer, devicesImpl, statsd, glean ); const devicesSessions = require('./devices-and-sessions')( log, db, oauthRawDB, config, customs, push, pushbox, devicesImpl, clientUtils, redis ); const attachedClients = require('./attached-clients')( log, db, devicesImpl, clientUtils ); const emails = require('./emails')( log, db, mailer, config, customs, push, verificationReminders, cadReminders, signupUtils, zendeskClient, stripeHelper, statsd ); const password = require('./password')( log, db, Password, config.smtp.redirectDomain, mailer, config.verifierVersion, customs, signinUtils, push, config, oauthRawDB, glean, authServerCacheRedis, statsd ); const recoveryPhone = require('./recovery-phone').recoveryPhoneRoutes( customs, db, glean, log, mailer, statsd, config ); const securityEvents = require('./security-events')(log, db, config); const session = require('./session')( log, db, Password, config, signinUtils, signupUtils, mailer, push, customs, glean, statsd ); const unblockCodes = require('./unblock-codes')( log, db, mailer, config.signinUnblock, customs ); const totp = require('./totp')( log, db, mailer, customs, config.totp, glean, profile, config.sentry.env, statsd ); const recoveryCodes = require('./recovery-codes')( log, db, config.totp, customs, mailer, glean ); const recoveryKey = require('./recovery-key')( log, db, Password, config.verifierVersion, customs, mailer, glean ); const subscriptions = require('./subscriptions').default( log, db, config, customs, push, mailer, profile, stripeHelper, zendeskClient ); const newsletters = require('./newsletters')(log, db); const util = require('./util')(log, config, config.smtp.redirectDomain); const { linkedAccountRoutes } = require('./linked-accounts'); const linkedAccounts = linkedAccountRoutes( log, db, config, mailer, profile, statsd, glean ); const { cloudTaskRoutes } = require('./cloud-tasks'); const cloudTasks = cloudTaskRoutes(log, config, statsd); const { cloudSchedulerRoutes } = require('./cloud-scheduler'); const cloudScheduler = cloudSchedulerRoutes(log, config, statsd); let basePath = url.parse(config.publicUrl).path; if (basePath === '/') { basePath = ''; } const v1Routes = [].concat( account, oauth, devicesSessions, attachedClients, emails, password, recoveryCodes, recoveryPhone, securityEvents, session, totp, unblockCodes, util, recoveryKey, subscriptions, newsletters, linkedAccounts, cloudTasks, cloudScheduler ); function optionallyIgnoreTrace(fn) { return async function (request, ...args) { // Only authenticated routes or routes that specify an uid/email // can be traced because those routes can look a user up const canOptOut = request.auth || (request.payload && request.payload.uid) || (request.payload && request.payload.email); if (canOptOut) { const isMetricsEnabled = await request.app.isMetricsEnabled; if (!isMetricsEnabled) { // We need to create a parent context that suppresses traces. // Hapi's auto instrumentation inherits from the parent context and therefore // will get this. return tracing.suppressTrace(() => { return fn(request, ...args); }); } } return fn(request, ...args); }; } v1Routes.forEach((r) => { r.path = `${basePath}/v${config.apiVersion}${r.path}`; if (tracing.isInitialized()) { if (r.handler) { r.handler = optionallyIgnoreTrace(r.handler); } } }); defaults.forEach((r) => { r.path = basePath + r.path; }); const allRoutes = defaults.concat(idp, v1Routes); allRoutes.forEach((r) => { // Default auth.payload to 'optional' for all authenticated routes. // We'll validate the payload hash if the client provides it, // but allow them to skip it if they can't or don't want to. const auth = r.options && r.options.auth; // eslint-disable-next-line no-prototype-builtins if (auth && !auth.hasOwnProperty('payload')) { auth.payload = 'optional'; } // Remove custom `apidoc` key which we use for generating docs, // but which Hapi doesn't like if it's there at runtime. delete r.apidoc; }); return allRoutes; };