"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createApp = void 0;
const bcrypt = require("bcryptjs");
const bodyParser = require("body-parser");
const buildInfo = require("./lib/build-info");
const configLoader = require("./lib/config-loader");
const apiRouter = require("./controllers/api");
const uiRouter = require("./controllers/ui");
const express = require("express");
const favicon = require("serve-favicon");
const helpers = require("./lib/helpers");
const moment = require("moment");
const path = require("path");
const express_session_1 = require("./lib/express-session");
const yargs = require("yargs");
function createApp(options) {
    options = options || {};
    let expressApp = express();
    expressApp.set('views', path.join(__dirname, 'views'));
    expressApp.engine('pug', require('pug').__express);
    expressApp.set('view engine', 'pug');
    expressApp.use(express_session_1.sessionSettings);
    expressApp.set('trust proxy', true);
    expressApp.use(bodyParser.json({ limit: '30mb' }));
    expressApp.use(bodyParser.urlencoded({ extended: true }));
    if (yargs.argv.trace) {
        expressApp.use(function (req, res, next) {
            var hasBody = (Object.keys(req.body).length > 0);
            console.log(helpers.format("{0} {1}://{2}{3}{4}", req.method, req.protocol, req.hostname, req.originalUrl, hasBody ? '\n' + JSON.stringify(req.body) : ''));
            next();
        });
    }
    const buildInfoObj = buildInfo.getBuildInfo();
    expressApp.locals.version = buildInfoObj.version;
    expressApp.locals.buildDate = buildInfoObj.buildDate;
    expressApp.locals.commitSha = buildInfoObj.commitSha;
    expressApp.locals.moment = moment;
    expressApp.use(function (req, res, next) {
        if (!req.session.timezone) {
            req.session.timezone = 'America/Chicago';
        }
        next();
    });
    // AUTHENTICATION MIDDLEWARE
    const authenticatedAccounts = {};
    expressApp.use((req, res, next) => __awaiter(this, void 0, void 0, function* () {
        const config = configLoader.getConfig();
        if (!config.adminLogin || (!config.adminPassword && !config.adminPasswordBcrypt)) {
            return next();
        }
        // Extract username and password from Authorization header
        const b64auth = (req.headers.authorization || '').split(' ')[1] || '';
        const userAndPass = Buffer.from(b64auth, 'base64').toString();
        const colonIndex = userAndPass.indexOf(':');
        const userName = userAndPass.substring(0, colonIndex);
        const userPassword = userAndPass.substring(colonIndex + 1);
        let accountIsAuthenticated = authenticatedAccounts[userName] == userPassword;
        if (!accountIsAuthenticated) {
            if (config.adminPassword) {
                if (config.adminLogin === userName && config.adminPassword === userPassword) {
                    accountIsAuthenticated = true;
                    authenticatedAccounts[userName] = userPassword;
                }
            }
            else if (config.adminPasswordBcrypt) {
                let hashMatchesPassword = false;
                try {
                    // Check user password against the hash value from config file
                    hashMatchesPassword = yield bcrypt.compare(userPassword, config.adminPasswordBcrypt);
                }
                catch (_a) {
                    console.log('ERROR: Failed to validate password hash');
                }
                if (config.adminLogin === userName && hashMatchesPassword) {
                    accountIsAuthenticated = true;
                    authenticatedAccounts[userName] = userPassword;
                }
            }
        }
        if (accountIsAuthenticated) {
            return next();
        }
        res.set('WWW-Authenticate', 'Basic realm="OpenTest server"');
        res.status(401).send('Authentication failed');
    }));
    const config = configLoader.getConfig();
    expressApp.use(config.urlPrefix, express.static(path.join(__dirname, 'public')));
    expressApp.use(config.urlPrefix, favicon(path.join(__dirname, 'public', 'favicon.ico')));
    expressApp.use(config.urlPrefix, uiRouter.createRouter(options));
    expressApp.use(`${config.urlPrefix}/api`, apiRouter.createRouter(options));
    return expressApp;
}
exports.createApp = createApp;
//# sourceMappingURL=express-app.js.map