From c3d9c4530197eb097f1ec4a163294475c85c9069 Mon Sep 17 00:00:00 2001 From: rob Date: Sat, 1 Oct 2022 15:53:35 -0400 Subject: [PATCH] introduced HTTPS config and startup --- app/views/components/off-canvas.pug | 3 +- client/js/index.js | 4 +- config/http.js | 3 ++ config/https.js | 25 +++++++++ dtp-webapp.js | 1 + gulpfile.js | 12 ++--- lib/site-platform.js | 79 +++++++++++++++++++++++++---- 7 files changed, 107 insertions(+), 20 deletions(-) create mode 100644 config/https.js diff --git a/app/views/components/off-canvas.pug b/app/views/components/off-canvas.pug index 2296d56..ffdf930 100644 --- a/app/views/components/off-canvas.pug +++ b/app/views/components/off-canvas.pug @@ -85,6 +85,7 @@ mixin renderMenuItem (iconClass, label) i.fas.fa-balance-scale .uk-width-expand Privacy Policy - .uk-text-small.uk-text-muted.uk-margin-medium + .uk-text-small.uk-margin-medium + div #{pkg.name} v#{pkg.version} div © #{moment().format('YYYY')} #{site.company} div Made In USA 🇺🇸 \ No newline at end of file diff --git a/client/js/index.js b/client/js/index.js index 0be660f..cb321bc 100644 --- a/client/js/index.js +++ b/client/js/index.js @@ -10,7 +10,7 @@ const dtp = window. dtp = window.dtp || { }; import DtpSiteApp from './site-app.js'; import DtpWebLog from 'dtp/dtp-log.js'; -import UIkit from 'uikit'; +// import UIkit from 'uikit'; /** * Monkeypatch to count characters instead of .length's code point count. @@ -32,7 +32,7 @@ window.addEventListener('load', async ( ) => { dtp.log.info('load', 'service worker startup complete', { scope: dtp.registration.scope }); } catch (error) { console.log('service worker startup failed', { error }); - UIkit.modal.alert(`Service worker startup failed: ${error.message}`); + // UIkit.modal.alert(`Service worker startup failed: ${error.message}`); } } diff --git a/config/http.js b/config/http.js index 59e82a1..e303327 100644 --- a/config/http.js +++ b/config/http.js @@ -1,3 +1,6 @@ +// config/http.js +// Copyright (C) 2022 DTP Technologies, LLC +// License: Apache-2.0 'use strict'; diff --git a/config/https.js b/config/https.js new file mode 100644 index 0000000..a1a5529 --- /dev/null +++ b/config/https.js @@ -0,0 +1,25 @@ +// config/https.js +// Copyright (C) 2022 DTP Technologies, LLC +// License: Apache-2.0 + +'use strict'; + +if (process.env.HTTPS_ENABLE === 'enabled') { + if (!process.env.HTTPS_SSL_CRT) { + throw new Error('Must specify HTTPS_SSL_CRT in .env (HTTPS is enabled)'); + } + if (!process.env.HTTPS_SSL_KEY) { + throw new Error('Must specify HTTPS_SSL_KEY in .env (HTTPS is enabled)'); + } +} + +module.exports = { + enabled: process.env.HTTPS_ENABLE === 'enabled', + scheme: 'https', + address: process.env.HTTPS_BIND_ADDRESS || "127.0.0.1", + port: parseInt(process.env.HTTPS_BIND_PORT || "3400", 10), + options: { + crt: process.env.HTTPS_SSL_CRT, + key: process.env.HTTPS_SSL_KEY, + }, +}; \ No newline at end of file diff --git a/dtp-webapp.js b/dtp-webapp.js index 057fae8..23e3354 100644 --- a/dtp-webapp.js +++ b/dtp-webapp.js @@ -20,6 +20,7 @@ module.config = { component: DTP_COMPONENT, site: require(path.join(module.rootPath, 'config', 'site')), http: require(path.join(module.rootPath, 'config', 'http')), + https: require(path.join(module.rootPath, 'config', 'https')), }; module.log = new SiteLog(module, module.config.component); diff --git a/gulpfile.js b/gulpfile.js index b381058..e812596 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -22,19 +22,19 @@ function util_start_browsersync ( ) { return new Promise((resolve, reject) => { browserSync.init({ proxy: { - target: 'http://localhost:3010', + target: 'https://localhost:3410', ws: true, }, host: 'localhost', open: 'local', - // https: { - // key: path.join(__dirname, 'ssl', 'dtp-webapp.key'), - // cert: path.join(__dirname, 'ssl', 'dtp-webapp.crt'), - // }, + https: { + key: path.join(__dirname, 'ssl', 'dtp-webapp.key'), + cert: path.join(__dirname, 'ssl', 'dtp-webapp.crt'), + }, port: 3310, cors: true, ui: { - port: 3410, + port: 3610, }, notify: false, ghostMode: { diff --git a/lib/site-platform.js b/lib/site-platform.js index 3ac27de..2ac6c1a 100644 --- a/lib/site-platform.js +++ b/lib/site-platform.js @@ -5,6 +5,7 @@ 'use strict'; const path = require('path'); +const fs = require('fs'); const glob = require('glob'); const express = require('express'); @@ -300,8 +301,8 @@ module.exports.startWebServer = async (dtp) => { domain: process.env.DTP_SITE_DOMAIN, path: '/', httpOnly: true, - secure: false, - sameSite: 'strict', + secure: process.env.HTTP_COOKIE_SECURE === 'enabled', + sameSite: process.env.HTTP_COOKIE_SAMESITE || false, expires: SESSION_DURATION, }, store: null, @@ -309,7 +310,6 @@ module.exports.startWebServer = async (dtp) => { module.sessionConfig.store = sessionStore; if (process.env.NODE_ENV === 'production') { module.app.set('trust proxy', 1); - // module.sessionConfig.cookie.secure = true; } module.app.use(session(module.sessionConfig)); @@ -369,21 +369,78 @@ module.exports.startWebServer = async (dtp) => { }); }); + if (process.env.HTTP_ENABLE === 'enabled') { + await module.createHttpServer(dtp); + } + if (process.env.HTTPS_ENABLE === 'enabled') { + await module.createHttpsServer(dtp); + } + + // prefer to attach Socket.io to the HTTPS server and fall back to HTTP + await module.createSocketServer(dtp, module.https || module.http); + + if (module.http) { + module.log.info('starting HTTP server', { + port: dtp.config.http.port, + bind: dtp.config.http.address, + }); + await module.startHttpServer(dtp, module.http, dtp.config.http); + } + if (module.https) { + module.log.info('starting HTTPS server', { + port: dtp.config.https.port, + bind: dtp.config.https.address, + }); + await module.startHttpServer(dtp, module.https, dtp.config.https); + } + + module.log.info(`${dtp.config.component.name} platform online`, { + http: dtp.config.http.port, + https: dtp.config.https.port, + }); +}; + +module.createHttpServer = async (/* dtp */) => { module.log.info('creating HTTP server'); module.http = require('http').createServer(module.app); +}; + +module.createHttpsServer = async (dtp) => { + const httpsOptions = { + cert: await fs.promises.readFile( + process.env.HTTPS_SSL_CRT || path.join(dtp.config.root, 'ssl', 'dtp-webapp.crt') + ), + key: await fs.promises.readFile( + process.env.HTTPS_SSL_KEY || path.join(dtp.config.root, 'ssl', 'dtp-webapp.key') + ), + }; + module.log.info('creating HTTPS server'); + module.https = require('https').createServer(httpsOptions, module.app); + + return module.https; +}; + +module.startHttpServer = async (dtp, server, config) => { + return new Promise((resolve, reject) => { + module.log.info('starting HTTP server', { port: config.port, bind: config.address }); + server.listen(config.port, config.address, (err) => { + if (err) { + return reject(err); + } + return resolve(); + }); + }); +}; + +module.createSocketServer = async (dtp, http) => { module.log.info('creating Socket.io server'); const { SiteIoServer } = require(path.join(__dirname, 'site-ioserver')); + module.io = new SiteIoServer(dtp); - await module.io.start(module.http); + await module.io.start(http); - module.log.info('starting HTTP server', { - port: dtp.config.http.port, - bind: dtp.config.http.address, - }); - module.http.listen(dtp.config.http.port, dtp.config.http.address, ( ) => { - module.log.info(`${dtp.config.component.name} platform online`, { port: dtp.config.http.port }); - }); + return module.io; }; module.exports.shutdown = async ( ) => {