From 71c74bc633e0fa31ddb3554b2af6c7cadc6cdec7 Mon Sep 17 00:00:00 2001 From: SamTV12345 <40429738+samtv12345@users.noreply.github.com> Date: Wed, 21 Feb 2024 19:56:50 +0100 Subject: [PATCH] Moved settings.js to ts. --- src/bin/createUserSession.js | 2 +- src/bin/extractPadData.js | 1 - src/bin/importSqlFile.js | 2 +- src/bin/migrateDirtyDBtoRealDB.js | 2 +- src/bin/repairPad.js | 4 +- src/node/db/DB.ts | 5 +- src/node/db/Pad.js | 2 +- src/node/db/PadManager.js | 2 +- src/node/db/SecurityManager.js | 2 +- src/node/eejs/index.js | 2 +- src/node/handler/ExportHandler.js | 2 +- src/node/handler/ImportHandler.js | 2 +- src/node/handler/PadMessageHandler.js | 4 +- src/node/handler/SocketIORouter.js | 2 +- src/node/hooks/express.ts | 3 +- src/node/hooks/express/adminplugins.ts | 2 +- src/node/hooks/express/adminsettings.ts | 11 +- src/node/hooks/express/importexport.ts | 6 +- src/node/hooks/express/openapi.ts | 4 +- src/node/hooks/express/socketio.ts | 3 +- src/node/hooks/express/specialpages.js | 2 +- src/node/hooks/express/static.js | 2 +- src/node/hooks/express/tests.js | 2 +- src/node/hooks/express/webaccess.js | 2 +- src/node/hooks/i18n.ts | 14 +- src/node/security/SecretRotator.ts | 2 +- src/node/server.ts | 9 +- src/node/utils/Abiword.ts | 22 +- src/node/utils/LibreOffice.js | 4 +- src/node/utils/{Settings.js => Settings.ts} | 279 +++++++++--------- src/node/utils/randomstring.ts | 4 +- src/package.json | 1 + src/tests/backend/specs/Pad.js | 2 +- .../backend/specs/api/importexportGetPost.js | 2 +- src/tests/backend/specs/caching_middleware.js | 2 +- src/tests/backend/specs/export.js | 2 +- src/tests/backend/specs/favicon.js | 2 +- src/tests/backend/specs/health.js | 2 +- src/tests/backend/specs/specialpages.js | 2 +- src/tests/backend/specs/webaccess.js | 2 +- 40 files changed, 217 insertions(+), 205 deletions(-) rename src/node/utils/{Settings.js => Settings.ts} (78%) diff --git a/src/bin/createUserSession.js b/src/bin/createUserSession.js index 33dcac18e..cf04dd4e3 100644 --- a/src/bin/createUserSession.js +++ b/src/bin/createUserSession.js @@ -12,7 +12,7 @@ process.on('unhandledRejection', (err) => { throw err; }); const fs = require('fs'); const path = require('path'); const querystring = require('querystring'); -const settings = require('../node/utils/Settings'); +import * as settings from '../node/utils/Settings'; const supertest = require('supertest'); (async () => { diff --git a/src/bin/extractPadData.js b/src/bin/extractPadData.js index b0d0212d7..07a0c996d 100644 --- a/src/bin/extractPadData.js +++ b/src/bin/extractPadData.js @@ -19,7 +19,6 @@ const padId = process.argv[2]; (async () => { // initialize database - require('../node/utils/Settings'); const db = require('../node/db/DB'); await db.init(); diff --git a/src/bin/importSqlFile.js b/src/bin/importSqlFile.js index 148503e8d..517d11ec8 100644 --- a/src/bin/importSqlFile.js +++ b/src/bin/importSqlFile.js @@ -49,7 +49,7 @@ const unescape = (val) => { const fs = require('fs'); const log4js = require('log4js'); const readline = require('readline'); - const settings = require('../node/utils/Settings'); + import * as settings from '../node/utils/Settings'; const ueberDB = require('ueberdb2'); const dbWrapperSettings = { diff --git a/src/bin/migrateDirtyDBtoRealDB.js b/src/bin/migrateDirtyDBtoRealDB.js index 75f6cc677..25b5d85af 100644 --- a/src/bin/migrateDirtyDBtoRealDB.js +++ b/src/bin/migrateDirtyDBtoRealDB.js @@ -14,7 +14,7 @@ process.on('unhandledRejection', (err) => { throw err; }); const dirtyDb = require('dirty'); const log4js = require('log4js'); - const settings = require('../node/utils/Settings'); + import * as settings from '../node/utils/Settings'; const ueberDB = require('ueberdb2'); const util = require('util'); diff --git a/src/bin/repairPad.js b/src/bin/repairPad.js index ed1d83659..afb5a3207 100644 --- a/src/bin/repairPad.js +++ b/src/bin/repairPad.js @@ -19,7 +19,7 @@ let valueCount = 0; (async () => { // initialize database - require('../node/utils/Settings'); + import * as settings from '../node/utils/Settings'; const db = require('../node/db/DB'); await db.init(); @@ -45,7 +45,7 @@ let valueCount = 0; // now fetch and reinsert every key console.log('Fetch and reinsert every key'); for (const key of neededDBValues) { - if (valueCount % 100 === 0) console.log(valueCount + "/" + neededDBValues.length); + if (valueCount % 100 === 0) console.log(`${valueCount}/${neededDBValues.length}`); const value = await db.get(key); // if it isn't a globalAuthor value which we want to ignore.. // console.log(`Key: ${key}, value: ${JSON.stringify(value)}`); diff --git a/src/node/db/DB.ts b/src/node/db/DB.ts index 1daab8dd3..f248003dc 100644 --- a/src/node/db/DB.ts +++ b/src/node/db/DB.ts @@ -21,8 +21,9 @@ * limitations under the License. */ +import {dbSettings, dbType} from "../utils/Settings"; + const ueberDB = require('ueberdb2'); -const settings = require('../utils/Settings'); const log4js = require('log4js'); const stats = require('../stats') @@ -37,7 +38,7 @@ exports.db = null; * Initializes the database with the settings provided by the settings module */ exports.init = async () => { - exports.db = new ueberDB.Database(settings.dbType, settings.dbSettings, null, logger); + exports.db = new ueberDB.Database(dbType, dbSettings, null, logger); await exports.db.init(); if (exports.db.metrics != null) { for (const [metric, value] of Object.entries(exports.db.metrics)) { diff --git a/src/node/db/Pad.js b/src/node/db/Pad.js index 884b420f0..5bdd0915a 100644 --- a/src/node/db/Pad.js +++ b/src/node/db/Pad.js @@ -10,7 +10,7 @@ const AttributePool = require('../../static/js/AttributePool'); const Stream = require('../utils/Stream'); const assert = require('assert').strict; const db = require('./DB'); -const settings = require('../utils/Settings'); +import * as settings from '../utils/Settings'; const authorManager = require('./AuthorManager'); const padManager = require('./PadManager'); const padMessageHandler = require('../handler/PadMessageHandler'); diff --git a/src/node/db/PadManager.js b/src/node/db/PadManager.js index 7c4021541..28eca950c 100644 --- a/src/node/db/PadManager.js +++ b/src/node/db/PadManager.js @@ -22,7 +22,7 @@ const CustomError = require('../utils/customError'); const Pad = require('../db/Pad'); const db = require('./DB'); -const settings = require('../utils/Settings'); +import * as settings from '../utils/Settings'; /** * A cache of all loaded Pads. diff --git a/src/node/db/SecurityManager.js b/src/node/db/SecurityManager.js index 0e5b2c77c..694f77cb2 100644 --- a/src/node/db/SecurityManager.js +++ b/src/node/db/SecurityManager.js @@ -24,7 +24,7 @@ const hooks = require('../../static/js/pluginfw/hooks.js'); const padManager = require('./PadManager'); const readOnlyManager = require('./ReadOnlyManager'); const sessionManager = require('./SessionManager'); -const settings = require('../utils/Settings'); +import * as settings from '../utils/Settings'; const webaccess = require('../hooks/express/webaccess'); const log4js = require('log4js'); const authLogger = log4js.getLogger('auth'); diff --git a/src/node/eejs/index.js b/src/node/eejs/index.js index 31ff2c1a5..f8165f3a3 100644 --- a/src/node/eejs/index.js +++ b/src/node/eejs/index.js @@ -25,7 +25,7 @@ const fs = require('fs'); const hooks = require('../../static/js/pluginfw/hooks.js'); const path = require('path'); const resolve = require('resolve'); -const settings = require('../utils/Settings'); +import * as settings from '../utils/Settings' const templateCache = new Map(); diff --git a/src/node/handler/ExportHandler.js b/src/node/handler/ExportHandler.js index 250221d18..64f64b95d 100644 --- a/src/node/handler/ExportHandler.js +++ b/src/node/handler/ExportHandler.js @@ -24,7 +24,7 @@ const exporthtml = require('../utils/ExportHtml'); const exporttxt = require('../utils/ExportTxt'); const exportEtherpad = require('../utils/ExportEtherpad'); const fs = require('fs'); -const settings = require('../utils/Settings'); +import * as settings from '../utils/Settings'; const os = require('os'); const hooks = require('../../static/js/pluginfw/hooks'); const util = require('util'); diff --git a/src/node/handler/ImportHandler.js b/src/node/handler/ImportHandler.js index 35ceddfdd..f24d04644 100644 --- a/src/node/handler/ImportHandler.js +++ b/src/node/handler/ImportHandler.js @@ -25,7 +25,7 @@ const padManager = require('../db/PadManager'); const padMessageHandler = require('./PadMessageHandler'); const fs = require('fs').promises; const path = require('path'); -const settings = require('../utils/Settings'); +import * as settings from '../utils/Settings'; const {Formidable} = require('formidable'); const os = require('os'); const importHtml = require('../utils/ImportHtml'); diff --git a/src/node/handler/PadMessageHandler.js b/src/node/handler/PadMessageHandler.js index 8b9d6e068..4123b3925 100644 --- a/src/node/handler/PadMessageHandler.js +++ b/src/node/handler/PadMessageHandler.js @@ -28,7 +28,7 @@ const AttributeManager = require('../../static/js/AttributeManager'); const authorManager = require('../db/AuthorManager'); const {padutils} = require('../../static/js/pad_utils'); const readOnlyManager = require('../db/ReadOnlyManager'); -const settings = require('../utils/Settings'); +import * as settings from '../utils/Settings'; const securityManager = require('../db/SecurityManager'); const plugins = require('../../static/js/pluginfw/plugin_defs.js'); const log4js = require('log4js'); @@ -1240,7 +1240,7 @@ const _getRoomSockets = (padID) => { // it does here, but synchronously to avoid a race condition. This code will have to change when // we update to socket.io v3. const room = ns.adapter.rooms?.get(padID); - + if (!room) return []; return Array.from(room) diff --git a/src/node/handler/SocketIORouter.js b/src/node/handler/SocketIORouter.js index e34a16603..43581ae8f 100644 --- a/src/node/handler/SocketIORouter.js +++ b/src/node/handler/SocketIORouter.js @@ -21,7 +21,7 @@ */ const log4js = require('log4js'); -const settings = require('../utils/Settings'); +import * as settings from '../utils/Settings'; const stats = require('../../node/stats') const logger = log4js.getLogger('socket.io'); diff --git a/src/node/hooks/express.ts b/src/node/hooks/express.ts index b273887d6..23d0b30a2 100644 --- a/src/node/hooks/express.ts +++ b/src/node/hooks/express.ts @@ -14,7 +14,7 @@ import fs from 'fs'; const hooks = require('../../static/js/pluginfw/hooks'); import log4js from 'log4js'; const SessionStore = require('../db/SessionStore'); -const settings = require('../utils/Settings'); +import * as settings from '../utils/Settings'; const stats = require('../stats') import util from 'util'; const webaccess = require('./express/webaccess'); @@ -177,6 +177,7 @@ exports.restartServer = async () => { // starts listening to requests as reported in issue #158. Not installing the log4js connect // logger when the log level has a higher severity than INFO since it would not log at that level // anyway. + // @ts-ignore if (!(settings.loglevel === 'WARN' && settings.loglevel === 'ERROR')) { app.use(log4js.connectLogger(logger, { level: log4js.levels.DEBUG.levelStr, diff --git a/src/node/hooks/express/adminplugins.ts b/src/node/hooks/express/adminplugins.ts index ad1795e17..0a550abbf 100644 --- a/src/node/hooks/express/adminplugins.ts +++ b/src/node/hooks/express/adminplugins.ts @@ -7,7 +7,7 @@ import {QueryType} from "../../types/QueryType"; import {PluginType} from "../../types/Plugin"; const eejs = require('../../eejs'); -const settings = require('../../utils/Settings'); +import * as settings from '../../utils/Settings'; const installer = require('../../../static/js/pluginfw/installer'); const pluginDefs = require('../../../static/js/pluginfw/plugin_defs'); const plugins = require('../../../static/js/pluginfw/plugins'); diff --git a/src/node/hooks/express/adminsettings.ts b/src/node/hooks/express/adminsettings.ts index 900bfd479..4db29bc78 100644 --- a/src/node/hooks/express/adminsettings.ts +++ b/src/node/hooks/express/adminsettings.ts @@ -4,7 +4,8 @@ const eejs = require('../../eejs'); const fsp = require('fs').promises; const hooks = require('../../../static/js/pluginfw/hooks'); const plugins = require('../../../static/js/pluginfw/plugins'); -const settings = require('../../utils/Settings'); +import {reloadSettings, settingsFilename, showSettingsInAdminPage} from '../../utils/Settings'; +import * as settings from '../../utils/Settings'; exports.expressCreateServer = (hookName:string, {app}:any) => { app.get('/admin/settings', (req:any, res:any) => { @@ -25,12 +26,12 @@ exports.socketio = (hookName:string, {io}:any) => { socket.on('load', async (query:string):Promise => { let data; try { - data = await fsp.readFile(settings.settingsFilename, 'utf8'); + data = await fsp.readFile(settingsFilename, 'utf8'); } catch (err) { return console.log(err); } // if showSettingsInAdminPage is set to false, then return NOT_ALLOWED in the result - if (settings.showSettingsInAdminPage === false) { + if (!showSettingsInAdminPage) { socket.emit('settings', {results: 'NOT_ALLOWED'}); } else { socket.emit('settings', {results: data}); @@ -38,13 +39,13 @@ exports.socketio = (hookName:string, {io}:any) => { }); socket.on('saveSettings', async (newSettings:string) => { - await fsp.writeFile(settings.settingsFilename, newSettings); + await fsp.writeFile(settingsFilename, newSettings); socket.emit('saveprogress', 'saved'); }); socket.on('restartServer', async () => { console.log('Admin request to restart server through a socket on /admin/settings'); - settings.reloadSettings(); + reloadSettings(); await plugins.update(); await hooks.aCallAll('loadSettings', {settings}); await hooks.aCallAll('restartServer'); diff --git a/src/node/hooks/express/importexport.ts b/src/node/hooks/express/importexport.ts index 898606e49..329356fe1 100644 --- a/src/node/hooks/express/importexport.ts +++ b/src/node/hooks/express/importexport.ts @@ -3,7 +3,7 @@ import {ArgsExpressType} from "../../types/ArgsExpressType"; const hasPadAccess = require('../../padaccess'); -const settings = require('../../utils/Settings'); +import {exportAvailable, importExportRateLimiting} from '../../utils/Settings'; const exportHandler = require('../../handler/ExportHandler'); const importHandler = require('../../handler/ImportHandler'); const padManager = require('../../db/PadManager'); @@ -14,7 +14,7 @@ const webaccess = require('./webaccess'); exports.expressCreateServer = (hookName:string, args:ArgsExpressType, cb:Function) => { const limiter = rateLimit({ - ...settings.importExportRateLimiting, + ...importExportRateLimiting, handler: (request:any) => { if (request.rateLimit.current === request.rateLimit.limit + 1) { // when the rate limiter triggers, write a warning in the logs @@ -35,7 +35,7 @@ exports.expressCreateServer = (hookName:string, args:ArgsExpressType, cb:Functio } // if abiword is disabled, and this is a format we only support with abiword, output a message - if (settings.exportAvailable() === 'no' && + if (exportAvailable() === 'no' && ['odt', 'pdf', 'doc'].indexOf(req.params.type) !== -1) { console.error(`Impossible to export pad "${req.params.pad}" in ${req.params.type} format.` + ' There is no converter configured'); diff --git a/src/node/hooks/express/openapi.ts b/src/node/hooks/express/openapi.ts index aa2f1e483..1434d5b51 100644 --- a/src/node/hooks/express/openapi.ts +++ b/src/node/hooks/express/openapi.ts @@ -24,7 +24,7 @@ const cloneDeep = require('lodash.clonedeep'); const createHTTPError = require('http-errors'); const apiHandler = require('../../handler/APIHandler'); -const settings = require('../../utils/Settings'); +import {ssl} from '../../utils/Settings'; const log4js = require('log4js'); const logger = log4js.getLogger('API'); @@ -724,5 +724,5 @@ const getApiRootForVersion = (version:string, style:any = APIPathStyle.FLAT): st const generateServerForApiVersion = (apiRoot:string, req:any): { url:string } => ({ - url: `${settings.ssl ? 'https' : 'http'}://${req.headers.host}${apiRoot}`, + url: `${ssl ? 'https' : 'http'}://${req.headers.host}${apiRoot}`, }); diff --git a/src/node/hooks/express/socketio.ts b/src/node/hooks/express/socketio.ts index c97ceeea8..87df60050 100644 --- a/src/node/hooks/express/socketio.ts +++ b/src/node/hooks/express/socketio.ts @@ -6,7 +6,7 @@ const events = require('events'); const express = require('../express'); const log4js = require('log4js'); const proxyaddr = require('proxy-addr'); -const settings = require('../../utils/Settings'); +import * as settings from '../../utils/Settings'; import {Server} from 'socket.io' const socketIORouter = require('../../handler/SocketIORouter'); const hooks = require('../../../static/js/pluginfw/hooks'); @@ -71,6 +71,7 @@ exports.expressCreateServer = (hookName:string, args:ArgsExpressType, cb:Functio // transports in this list at once // e.g. XHR is disabled in IE by default, so in IE it should use jsonp-polling io = new Server(args.server, { + // @ts-ignore transports: settings.socketTransportProtocols, }).listen(args.server, { /* diff --git a/src/node/hooks/express/specialpages.js b/src/node/hooks/express/specialpages.js index 18a17988a..cf7debdfb 100644 --- a/src/node/hooks/express/specialpages.js +++ b/src/node/hooks/express/specialpages.js @@ -6,7 +6,7 @@ const fs = require('fs'); const fsp = fs.promises; const toolbar = require('../../utils/toolbar'); const hooks = require('../../../static/js/pluginfw/hooks'); -const settings = require('../../utils/Settings'); +import * as settings from '../../utils/Settings'; const util = require('util'); const webaccess = require('./webaccess'); diff --git a/src/node/hooks/express/static.js b/src/node/hooks/express/static.js index 26c18995a..d6608cd60 100644 --- a/src/node/hooks/express/static.js +++ b/src/node/hooks/express/static.js @@ -4,7 +4,7 @@ const fs = require('fs').promises; const minify = require('../../utils/Minify'); const path = require('path'); const plugins = require('../../../static/js/pluginfw/plugin_defs'); -const settings = require('../../utils/Settings'); +import * as settings from '../../utils/Settings'; const CachingMiddleware = require('../../utils/caching_middleware'); const Yajsml = require('etherpad-yajsml'); diff --git a/src/node/hooks/express/tests.js b/src/node/hooks/express/tests.js index 66b47d2af..7959a9ca7 100644 --- a/src/node/hooks/express/tests.js +++ b/src/node/hooks/express/tests.js @@ -4,7 +4,7 @@ const path = require('path'); const fsp = require('fs').promises; const plugins = require('../../../static/js/pluginfw/plugin_defs'); const sanitizePathname = require('../../utils/sanitizePathname'); -const settings = require('../../utils/Settings'); +import * as settings from '../../utils/Settings'; // Returns all *.js files under specDir (recursively) as relative paths to specDir, using '/' // instead of path.sep to separate pathname components. diff --git a/src/node/hooks/express/webaccess.js b/src/node/hooks/express/webaccess.js index e0a5bd084..38e683d76 100644 --- a/src/node/hooks/express/webaccess.js +++ b/src/node/hooks/express/webaccess.js @@ -3,7 +3,7 @@ const assert = require('assert').strict; const log4js = require('log4js'); const httpLogger = log4js.getLogger('http'); -const settings = require('../../utils/Settings'); +import * as settings from '../../utils/Settings'; const hooks = require('../../../static/js/pluginfw/hooks'); const readOnlyManager = require('../../db/ReadOnlyManager'); diff --git a/src/node/hooks/i18n.ts b/src/node/hooks/i18n.ts index 500f1f887..37ecefbf4 100644 --- a/src/node/hooks/i18n.ts +++ b/src/node/hooks/i18n.ts @@ -9,7 +9,7 @@ const path = require('path'); const _ = require('underscore'); const pluginDefs = require('../../static/js/pluginfw/plugin_defs.js'); const existsSync = require('../utils/path_exists'); -const settings = require('../utils/Settings'); +import {customLocaleStrings, maxAge, root} from '../utils/Settings'; // returns all existing messages merged together and grouped by langcode // {es: {"foo": "string"}, en:...} @@ -40,7 +40,7 @@ const getAllLocales = () => { }; // add core supported languages first - extractLangs(path.join(settings.root, 'src/locales')); + extractLangs(path.join(root, 'src/locales')); // add plugins languages (if any) for (const {package: {path: pluginPath}} of Object.values(pluginDefs.plugins)) { @@ -71,9 +71,9 @@ const getAllLocales = () => { const wrongFormatErr = Error( 'customLocaleStrings in wrong format. See documentation ' + 'for Customization for Administrators, under Localization.'); - if (settings.customLocaleStrings) { - if (typeof settings.customLocaleStrings !== 'object') throw wrongFormatErr; - _.each(settings.customLocaleStrings, (overrides:MapArrayType , langcode:string) => { + if (customLocaleStrings) { + if (typeof customLocaleStrings !== 'object') throw wrongFormatErr; + _.each(customLocaleStrings, (overrides:MapArrayType , langcode:string) => { if (typeof overrides !== 'object') throw wrongFormatErr; _.each(overrides, (localeString:string|object, key:string) => { if (typeof localeString !== 'string') throw wrongFormatErr; @@ -133,7 +133,7 @@ exports.expressPreSession = async (hookName:string, {app}:any) => { // works with /locale/en and /locale/en.json requests const locale = req.params.locale.split('.')[0]; if (Object.prototype.hasOwnProperty.call(exports.availableLangs, locale)) { - res.setHeader('Cache-Control', `public, max-age=${settings.maxAge}`); + res.setHeader('Cache-Control', `public, max-age=${maxAge}`); res.setHeader('Content-Type', 'application/json; charset=utf-8'); res.send(`{"${locale}":${JSON.stringify(locales[locale])}}`); } else { @@ -142,7 +142,7 @@ exports.expressPreSession = async (hookName:string, {app}:any) => { }); app.get('/locales.json', (req: any, res:any) => { - res.setHeader('Cache-Control', `public, max-age=${settings.maxAge}`); + res.setHeader('Cache-Control', `public, max-age=${maxAge}`); res.setHeader('Content-Type', 'application/json; charset=utf-8'); res.send(localeIndex); }); diff --git a/src/node/security/SecretRotator.ts b/src/node/security/SecretRotator.ts index ee5bec772..62431e6ad 100644 --- a/src/node/security/SecretRotator.ts +++ b/src/node/security/SecretRotator.ts @@ -81,7 +81,7 @@ export class SecretRotator { * rotation. If the oldest known secret starts after `lifetime` ago, this secret will cover * the time period starting `lifetime` ago and ending at the start of that secret. */ - constructor(dbPrefix: string, interval: number, lifetime: number, legacyStaticSecret:string|null = null) { + constructor(dbPrefix: string, interval: number, lifetime: number, legacyStaticSecret:string | string[] | null = null) { /** * The secrets. The first secret in this array is the one that should be used to generate new * MACs. All of the secrets in this array should be used when attempting to authenticate an diff --git a/src/node/server.ts b/src/node/server.ts index 76ffd3a6a..3804c29cd 100755 --- a/src/node/server.ts +++ b/src/node/server.ts @@ -26,14 +26,13 @@ import {PluginType} from "./types/Plugin"; import {ErrorCaused} from "./types/ErrorCaused"; -import {PromiseHooks} from "node:v8"; - import log4js from 'log4js'; -const settings = require('./utils/Settings'); +import {dumpOnUncleanExit} from './utils/Settings'; +import * as settings from './utils/Settings'; let wtfnode: any; -if (settings.dumpOnUncleanExit) { +if (dumpOnUncleanExit) { // wtfnode should be loaded after log4js.replaceConsole() so that it uses log4js for logging, and // it should be above everything else so that it can hook in before resources are used. wtfnode = require('wtfnode'); @@ -267,7 +266,7 @@ exports.exit = async (err: ErrorCaused|string|null = null) => { logger.error('Something that should have been cleaned up during the shutdown hook (such as ' + 'a timer, worker thread, or open connection) is preventing Node.js from exiting'); - if (settings.dumpOnUncleanExit) { + if (dumpOnUncleanExit) { wtfnode.dump(); } else { logger.error('Enable `dumpOnUncleanExit` setting to get a dump of objects preventing a ' + diff --git a/src/node/utils/Abiword.ts b/src/node/utils/Abiword.ts index c0937fcd9..01c1df77c 100644 --- a/src/node/utils/Abiword.ts +++ b/src/node/utils/Abiword.ts @@ -24,19 +24,19 @@ import {AsyncQueueTask} from "../types/AsyncQueueTask"; const spawn = require('child_process').spawn; const async = require('async'); -const settings = require('./Settings'); +import {abiword} from './Settings'; const os = require('os'); // on windows we have to spawn a process for each convertion, // cause the plugin abicommand doesn't exist on this platform if (os.type().indexOf('Windows') > -1) { exports.convertFile = async (srcFile: string, destFile: string, type: string) => { - const abiword = spawn(settings.abiword, [`--to=${destFile}`, srcFile]); + const _abiword = spawn(abiword, [`--to=${destFile}`, srcFile]); let stdoutBuffer = ''; - abiword.stdout.on('data', (data: string) => { stdoutBuffer += data.toString(); }); - abiword.stderr.on('data', (data: string) => { stdoutBuffer += data.toString(); }); + _abiword.stdout.on('data', (data: string) => { stdoutBuffer += data.toString(); }); + _abiword.stderr.on('data', (data: string) => { stdoutBuffer += data.toString(); }); await new Promise((resolve, reject) => { - abiword.on('exit', (code: number) => { + _abiword.on('exit', (code: number) => { if (code !== 0) return reject(new Error(`Abiword died with exit code ${code}`)); if (stdoutBuffer !== '') { console.log(stdoutBuffer); @@ -49,21 +49,21 @@ if (os.type().indexOf('Windows') > -1) { // communicate with it via stdin/stdout // thats much faster, about factor 10 } else { - let abiword: ChildProcess; + let _abiword: ChildProcess; let stdoutCallback: Function|null = null; const spawnAbiword = () => { - abiword = spawn(settings.abiword, ['--plugin', 'AbiCommand']); + _abiword = spawn(abiword, ['--plugin', 'AbiCommand']); let stdoutBuffer = ''; let firstPrompt = true; - abiword.stderr!.on('data', (data) => { stdoutBuffer += data.toString(); }); - abiword.on('exit', (code) => { + _abiword.stderr!.on('data', (data) => { stdoutBuffer += data.toString(); }); + _abiword.on('exit', (code) => { spawnAbiword(); if (stdoutCallback != null) { stdoutCallback(new Error(`Abiword died with exit code ${code}`)); stdoutCallback = null; } }); - abiword.stdout!.on('data', (data) => { + _abiword.stdout!.on('data', (data) => { stdoutBuffer += data.toString(); // we're searching for the prompt, cause this means everything we need is in the buffer if (stdoutBuffer.search('AbiWord:>') !== -1) { @@ -80,7 +80,7 @@ if (os.type().indexOf('Windows') > -1) { spawnAbiword(); const queue = async.queue((task: AsyncQueueTask, callback:Function) => { - abiword.stdin!.write(`convert ${task.srcFile} ${task.destFile} ${task.type}\n`); + _abiword.stdin!.write(`convert ${task.srcFile} ${task.destFile} ${task.type}\n`); stdoutCallback = (err: string) => { if (err != null) console.error('Abiword File failed to convert', err); callback(err); diff --git a/src/node/utils/LibreOffice.js b/src/node/utils/LibreOffice.js index 339209194..e42016aa5 100644 --- a/src/node/utils/LibreOffice.js +++ b/src/node/utils/LibreOffice.js @@ -23,14 +23,14 @@ const log4js = require('log4js'); const os = require('os'); const path = require('path'); const runCmd = require('./run_cmd'); -const settings = require('./Settings'); +import {soffice} from './Settings'; const logger = log4js.getLogger('LibreOffice'); const doConvertTask = async (task) => { const tmpDir = os.tmpdir(); const p = runCmd([ - settings.soffice, + soffice, '--headless', '--invisible', '--nologo', diff --git a/src/node/utils/Settings.js b/src/node/utils/Settings.ts similarity index 78% rename from src/node/utils/Settings.js rename to src/node/utils/Settings.ts index 48955f291..370492b71 100644 --- a/src/node/utils/Settings.js +++ b/src/node/utils/Settings.ts @@ -27,18 +27,19 @@ * limitations under the License. */ +import {MapArrayType} from "../types/MapType"; +import fs from 'fs'; +import os from 'os'; +import path from 'path'; +import jsonminify from 'jsonminify'; +import log4js from 'log4js'; +import randomString from './randomstring'; +import _ from 'underscore'; + const absolutePaths = require('./AbsolutePaths'); -const deepEqual = require('fast-deep-equal/es6'); -const fs = require('fs'); -const os = require('os'); -const path = require('path'); const argv = require('./Cli').argv; -const jsonminify = require('jsonminify'); -const log4js = require('log4js'); -const randomString = require('./randomstring'); const suppressDisableMsg = ' -- To suppress these warning messages change ' + 'suppressErrorsInPadText to true in your settings.json\n'; -const _ = require('underscore'); const logger = log4js.getLogger('settings'); @@ -48,16 +49,18 @@ const nonSettings = [ 'settingsFilename', ]; + + // This is a function to make it easy to create a new instance. It is important to not reuse a // config object after passing it to log4js.configure() because that method mutates the object. :( -const defaultLogConfig = (level) => ({appenders: {console: {type: 'console'}}, +const defaultLogConfig = (level: string) => ({appenders: {console: {type: 'console'}}, categories: { default: {appenders: ['console'], level}, }}); const defaultLogLevel = 'INFO'; -const initLogging = (logLevel, config) => { - // log4js.configure() modifies exports.logconfig so check for equality first. +const initLogging = (config:any) => { + // log4js.configure() modifies logconfig so check for equality first. log4js.configure(config); log4js.getLogger('console'); @@ -70,19 +73,19 @@ const initLogging = (logLevel, config) => { // Initialize logging as early as possible with reasonable defaults. Logging will be re-initialized // with the user's chosen log level and logger config after the settings have been loaded. -initLogging(defaultLogLevel, defaultLogConfig(defaultLogLevel)); +initLogging(defaultLogConfig(defaultLogLevel)); /* Root path of the installation */ -exports.root = absolutePaths.findEtherpadRoot(); +export const root = absolutePaths.findEtherpadRoot(); logger.info('All relative paths will be interpreted relative to the identified ' + - `Etherpad base dir: ${exports.root}`); -exports.settingsFilename = absolutePaths.makeAbsolute(argv.settings || 'settings.json'); -exports.credentialsFilename = absolutePaths.makeAbsolute(argv.credentials || 'credentials.json'); + `Etherpad base dir: ${root}`); +export const settingsFilename = absolutePaths.makeAbsolute(argv.settings || 'settings.json'); +export const credentialsFilename = absolutePaths.makeAbsolute(argv.credentials || 'credentials.json'); /** * The app title, visible e.g. in the browser window */ -exports.title = 'Etherpad'; +export const title = 'Etherpad'; /** * Pathname of the favicon you want to use. If null, the skin's favicon is @@ -90,7 +93,7 @@ exports.title = 'Etherpad'; * is used. If this is a relative path it is interpreted as relative to the * Etherpad root directory. */ -exports.favicon = null; +export let favicon = null; /* * Skin name. @@ -98,37 +101,41 @@ exports.favicon = null; * Initialized to null, so we can spot an old configuration file and invite the * user to update it before falling back to the default. */ -exports.skinName = null; +export let skinName:string|null = null; -exports.skinVariants = 'super-light-toolbar super-light-editor light-background'; +export const skinVariants = 'super-light-toolbar super-light-editor light-background'; /** * The IP ep-lite should listen to */ -exports.ip = '0.0.0.0'; +export const ip:string = '0.0.0.0'; /** * The Port ep-lite should listen to */ -exports.port = process.env.PORT || 9001; +export const port = process.env.PORT || 9001; /** * Should we suppress Error messages from being in Pad Contents */ -exports.suppressErrorsInPadText = false; +export const suppressErrorsInPadText = false; /** * The SSL signed server key and the Certificate Authority's own certificate * default case: ep-lite does *not* use SSL. A signed server key is not required in this case. */ -exports.ssl = false; +export const ssl:false|{ + key: string; + cert: string; + ca: string[]; +} = false; /** * socket.io transport methods **/ -exports.socketTransportProtocols = ['websocket', 'polling']; +export const socketTransportProtocols = ['websocket', 'polling']; -exports.socketIo = { +export const socketIo = { /** * Maximum permitted client message size (in bytes). * @@ -143,16 +150,16 @@ exports.socketIo = { /* * The Type of the database */ -exports.dbType = 'dirty'; +export const dbType = 'dirty'; /** * This setting is passed with dbType to ueberDB to set up the database */ -exports.dbSettings = {filename: path.join(exports.root, 'var/dirty.db')}; +export const dbSettings = {filename: path.join(root, 'var/dirty.db')}; /** * The default Text of a new pad */ -exports.defaultPadText = [ +export let defaultPadText = [ 'Welcome to Etherpad!', '', 'This pad text is synchronized as you type, so that everyone viewing this page sees the same ' + @@ -164,7 +171,7 @@ exports.defaultPadText = [ /** * The default Pad Settings for a user (Can be overridden by changing the setting */ -exports.padOptions = { +export const padOptions = { noColors: false, showControls: true, showChat: true, @@ -181,7 +188,7 @@ exports.padOptions = { /** * Whether certain shortcut keys are enabled for a user in the pad */ -exports.padShortcutEnabled = { +export const padShortcutEnabled = { altF9: true, altC: true, delete: true, @@ -209,7 +216,7 @@ exports.padShortcutEnabled = { /** * The toolbar buttons and order. */ -exports.toolbar = { +export const toolbar = { left: [ ['bold', 'italic', 'underline', 'strikethrough'], ['orderedlist', 'unorderedlist', 'indent', 'outdent'], @@ -229,87 +236,87 @@ exports.toolbar = { /** * A flag that requires any user to have a valid session (via the api) before accessing a pad */ -exports.requireSession = false; +export const requireSession = false; /** * A flag that prevents users from creating new pads */ -exports.editOnly = false; +export const editOnly = false; /** * Max age that responses will have (affects caching layer). */ -exports.maxAge = 1000 * 60 * 60 * 6; // 6 hours +export const maxAge = 1000 * 60 * 60 * 6; // 6 hours /** * A flag that shows if minification is enabled or not */ -exports.minify = true; +export const minify = true; /** * The path of the abiword executable */ -exports.abiword = null; +export let abiword = null; /** * The path of the libreoffice executable */ -exports.soffice = null; +export let soffice = null; /** * Should we support none natively supported file types on import? */ -exports.allowUnknownFileEnds = true; +export const allowUnknownFileEnds = true; /** * The log level of log4js */ -exports.loglevel = defaultLogLevel; +export const loglevel:string = defaultLogLevel; /** * Disable IP logging */ -exports.disableIPlogging = false; +export const disableIPlogging = false; /** * Number of seconds to automatically reconnect pad */ -exports.automaticReconnectionTimeout = 0; +export const automaticReconnectionTimeout = 0; /** * Disable Load Testing */ -exports.loadTest = false; +export const loadTest = false; /** * Disable dump of objects preventing a clean exit */ -exports.dumpOnUncleanExit = false; +export const dumpOnUncleanExit = false; /** * Enable indentation on new lines */ -exports.indentationOnNewLine = true; +export const indentationOnNewLine = true; /* * log4js appender configuration */ -exports.logconfig = null; +export let logconfig:any = null; /* * Deprecated cookie signing key. */ -exports.sessionKey = null; +export let sessionKey:string|null|string[] = null; /* - * Trust Proxy, whether or not trust the x-forwarded-for header. + * Trust Proxy, whether trust the x-forwarded-for header. */ -exports.trustProxy = false; +export const trustProxy = false; /* * Settings controlling the session cookie issued by Etherpad. */ -exports.cookie = { +export const cookie = { keyRotationInterval: 1 * 24 * 60 * 60 * 1000, /* * Value of the SameSite cookie property. "Lax" is recommended unless @@ -332,20 +339,20 @@ exports.cookie = { * authorization. Note: /admin always requires authentication, and * either authorization by a module, or a user with is_admin set */ -exports.requireAuthentication = false; -exports.requireAuthorization = false; -exports.users = {}; +export let requireAuthentication = false; +export let requireAuthorization = false; +export const users = {}; /* * Show settings in admin page, by default it is true */ -exports.showSettingsInAdminPage = true; +export const showSettingsInAdminPage = true; /* * By default, when caret is moved out of viewport, it scrolls the minimum * height needed to make this line visible. */ -exports.scrollWhenFocusLineIsOutOfViewport = { +export const scrollWhenFocusLineIsOutOfViewport = { /* * Percentage of viewport height to be additionally scrolled. */ @@ -378,12 +385,12 @@ exports.scrollWhenFocusLineIsOutOfViewport = { * * Do not enable on production machines. */ -exports.exposeVersion = false; +export const exposeVersion = false; /* * Override any strings found in locale directories */ -exports.customLocaleStrings = {}; +export const customLocaleStrings = {}; /* * From Etherpad 1.8.3 onwards, import and export of pads is always rate @@ -394,7 +401,7 @@ exports.customLocaleStrings = {}; * * See https://github.com/nfriedly/express-rate-limit for more options */ -exports.importExportRateLimiting = { +export const importExportRateLimiting = { // duration of the rate limit window (milliseconds) windowMs: 90000, @@ -410,7 +417,7 @@ exports.importExportRateLimiting = { * * See https://github.com/animir/node-rate-limiter-flexible/wiki/Overall-example#websocket-single-connection-prevent-flooding for more options */ -exports.commitRateLimiting = { +export const commitRateLimiting = { // duration of the rate limit window (seconds) duration: 1, @@ -424,39 +431,39 @@ exports.commitRateLimiting = { * * File size is specified in bytes. Default is 50 MB. */ -exports.importMaxFileSize = 50 * 1024 * 1024; +export const importMaxFileSize = 50 * 1024 * 1024; /* * Disable Admin UI tests */ -exports.enableAdminUITests = false; +export const enableAdminUITests = false; /* * Enable auto conversion of pad Ids to lowercase. * e.g. /p/EtHeRpAd to /p/etherpad */ -exports.lowerCasePadIds = false; +export const lowerCasePadIds = false; // checks if abiword is avaiable -exports.abiwordAvailable = () => { - if (exports.abiword != null) { +export const abiwordAvailable = () => { + if (abiword != null) { return os.type().indexOf('Windows') !== -1 ? 'withoutPDF' : 'yes'; } else { return 'no'; } }; -exports.sofficeAvailable = () => { - if (exports.soffice != null) { +export const sofficeAvailable = () => { + if (soffice != null) { return os.type().indexOf('Windows') !== -1 ? 'withoutPDF' : 'yes'; } else { return 'no'; } }; -exports.exportAvailable = () => { - const abiword = exports.abiwordAvailable(); - const soffice = exports.sofficeAvailable(); +export const exportAvailable = () => { + const abiword = abiwordAvailable(); + const soffice = sofficeAvailable(); if (abiword === 'no' && soffice === 'no') { return 'no'; @@ -469,10 +476,10 @@ exports.exportAvailable = () => { }; // Provide git version if available -exports.getGitCommit = () => { +export const getGitCommit = () => { let version = ''; try { - let rootPath = exports.root; + let rootPath = root; if (fs.lstatSync(`${rootPath}/.git`).isFile()) { rootPath = fs.readFileSync(`${rootPath}/.git`, 'utf8'); rootPath = rootPath.split(' ').pop().trim(); @@ -487,14 +494,14 @@ exports.getGitCommit = () => { version = ref; } version = version.substring(0, 7); - } catch (e) { + } catch (e: any) { logger.warn(`Can't get git version for server header\n${e.message}`); } return version; }; // Return etherpad version from package.json -exports.getEpVersion = () => require('../../package.json').version; +export const getEpVersion = () => require('../../package.json').version; /** * Receives a settingsObj and, if the property name is a valid configuration @@ -503,7 +510,7 @@ exports.getEpVersion = () => require('../../package.json').version; * This code refactors a previous version that copied & pasted the same code for * both "settings.json" and "credentials.json". */ -const storeSettings = (settingsObj) => { +const storeSettings = (settingsObj:MapArrayType) => { for (const i of Object.keys(settingsObj || {})) { if (nonSettings.includes(i)) { logger.warn(`Ignoring setting: '${i}'`); @@ -515,7 +522,9 @@ const storeSettings = (settingsObj) => { logger.warn(`Settings should start with a lowercase character: '${i}'`); } - // we know this setting, so we overwrite it + console.log(globalThis) + + // we know this setting, so we overwrite it, // or it's a settings hash, specific to a plugin if (exports[i] !== undefined || i.indexOf('ep_') === 0) { if (_.isObject(settingsObj[i]) && !Array.isArray(settingsObj[i])) { @@ -542,8 +551,9 @@ const storeSettings = (settingsObj) => { * short syntax "${ABIWORD}", and not "${ABIWORD:null}": the latter would result * in the literal string "null", instead. */ -const coerceValue = (stringValue) => { +const coerceValue = (stringValue: string) => { // cooked from https://stackoverflow.com/questions/175739/built-in-way-in-javascript-to-check-if-a-string-is-a-valid-number + // @ts-ignore const isNumeric = !isNaN(stringValue) && !isNaN(parseFloat(stringValue) && isFinite(stringValue)); if (isNumeric) { @@ -597,7 +607,7 @@ const coerceValue = (stringValue) => { * * see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_replacer_parameter */ -const lookupEnvironmentVariables = (obj) => { +const lookupEnvironmentVariables = (obj: object) => { const stringifiedAndReplaced = JSON.stringify(obj, (key, value) => { /* * the first invocation of replacer() is with an empty key. Just go on, or @@ -669,12 +679,10 @@ const lookupEnvironmentVariables = (obj) => { logger.debug( `Configuration key "${key}" will be read from environment variable "${envVarName}"`); - return coerceValue(envVarValue); + return coerceValue(envVarValue!); }); - const newSettings = JSON.parse(stringifiedAndReplaced); - - return newSettings; + return JSON.parse(stringifiedAndReplaced); }; /** @@ -685,7 +693,7 @@ const lookupEnvironmentVariables = (obj) => { * * The isSettings variable only controls the error logging. */ -const parseSettings = (settingsFilename, isSettings) => { +const parseSettings = (settingsFilename: string, isSettings: boolean) => { let settingsStr = ''; let settingsType, notFoundMessage, notFoundFunction; @@ -717,10 +725,8 @@ const parseSettings = (settingsFilename, isSettings) => { logger.info(`${settingsType} loaded from: ${settingsFilename}`); - const replacedSettings = lookupEnvironmentVariables(settings); - - return replacedSettings; - } catch (e) { + return lookupEnvironmentVariables(settings); + } catch (e:any) { logger.error(`There was an error processing your ${settingsType} ` + `file from ${settingsFilename}: ${e.message}`); @@ -728,98 +734,100 @@ const parseSettings = (settingsFilename, isSettings) => { } }; -exports.reloadSettings = () => { - const settings = parseSettings(exports.settingsFilename, true); - const credentials = parseSettings(exports.credentialsFilename, false); +export let randomVersionString: string | undefined + +export const reloadSettings = () => { + const settings = parseSettings(settingsFilename, true); + const credentials = parseSettings(credentialsFilename, false); storeSettings(settings); storeSettings(credentials); // Init logging config - exports.logconfig = defaultLogConfig(exports.loglevel ? exports.loglevel : defaultLogLevel); - initLogging(exports.loglevel, exports.logconfig); + logconfig = defaultLogConfig(loglevel ? loglevel : defaultLogLevel); + initLogging(logconfig); - if (!exports.skinName) { + if (!skinName) { logger.warn('No "skinName" parameter found. Please check out settings.json.template and ' + 'update your settings.json. Falling back to the default "colibris".'); - exports.skinName = 'colibris'; + skinName = 'colibris'; } // checks if skinName has an acceptable value, otherwise falls back to "colibris" - if (exports.skinName) { - const skinBasePath = path.join(exports.root, 'src', 'static', 'skins'); - const countPieces = exports.skinName.split(path.sep).length; + if (skinName) { + const skinBasePath = path.join(root, 'src', 'static', 'skins'); + const countPieces = skinName.split(path.sep).length; if (countPieces !== 1) { logger.error(`skinName must be the name of a directory under "${skinBasePath}". This is ` + - `not valid: "${exports.skinName}". Falling back to the default "colibris".`); + `not valid: "${skinName}". Falling back to the default "colibris".`); - exports.skinName = 'colibris'; + skinName = 'colibris'; } // informative variable, just for the log messages - let skinPath = path.join(skinBasePath, exports.skinName); + let skinPath = path.join(skinBasePath, skinName); // what if someone sets skinName == ".." or "."? We catch him! if (absolutePaths.isSubdir(skinBasePath, skinPath) === false) { logger.error(`Skin path ${skinPath} must be a subdirectory of ${skinBasePath}. ` + 'Falling back to the default "colibris".'); - exports.skinName = 'colibris'; - skinPath = path.join(skinBasePath, exports.skinName); + skinName = 'colibris'; + skinPath = path.join(skinBasePath, skinName); } - if (fs.existsSync(skinPath) === false) { + if (!fs.existsSync(skinPath)) { logger.error(`Skin path ${skinPath} does not exist. Falling back to the default "colibris".`); - exports.skinName = 'colibris'; - skinPath = path.join(skinBasePath, exports.skinName); + skinName = 'colibris'; + skinPath = path.join(skinBasePath, skinName); } - logger.info(`Using skin "${exports.skinName}" in dir: ${skinPath}`); + logger.info(`Using skin "${skinName}" in dir: ${skinPath}`); } - if (exports.abiword) { + if (abiword) { // Check abiword actually exists - if (exports.abiword != null) { - fs.exists(exports.abiword, (exists) => { + if (abiword != null) { + fs.exists(abiword, (exists) => { if (!exists) { const abiwordError = 'Abiword does not exist at this path, check your settings file.'; - if (!exports.suppressErrorsInPadText) { - exports.defaultPadText += `\nError: ${abiwordError}${suppressDisableMsg}`; + if (!suppressErrorsInPadText) { + defaultPadText += `\nError: ${abiwordError}${suppressDisableMsg}`; } - logger.error(`${abiwordError} File location: ${exports.abiword}`); - exports.abiword = null; + logger.error(`${abiwordError} File location: ${abiword}`); + abiword = null; } }); } } - if (exports.soffice) { - fs.exists(exports.soffice, (exists) => { + if (soffice) { + fs.exists(soffice, (exists) => { if (!exists) { const sofficeError = 'soffice (libreoffice) does not exist at this path, check your settings file.'; - if (!exports.suppressErrorsInPadText) { - exports.defaultPadText += `\nError: ${sofficeError}${suppressDisableMsg}`; + if (!suppressErrorsInPadText) { + defaultPadText += `\nError: ${sofficeError}${suppressDisableMsg}`; } - logger.error(`${sofficeError} File location: ${exports.soffice}`); - exports.soffice = null; + logger.error(`${sofficeError} File location: ${soffice}`); + soffice = null; } }); } const sessionkeyFilename = absolutePaths.makeAbsolute(argv.sessionkey || './SESSIONKEY.txt'); - if (!exports.sessionKey) { + if (!sessionKey) { try { - exports.sessionKey = fs.readFileSync(sessionkeyFilename, 'utf8'); + sessionKey = fs.readFileSync(sessionkeyFilename, 'utf8'); logger.info(`Session key loaded from: ${sessionkeyFilename}`); } catch (err) { /* ignored */ } - const keyRotationEnabled = exports.cookie.keyRotationInterval && exports.cookie.sessionLifetime; - if (!exports.sessionKey && !keyRotationEnabled) { + const keyRotationEnabled = cookie.keyRotationInterval && cookie.sessionLifetime; + if (!sessionKey && !keyRotationEnabled) { logger.info( `Session key file "${sessionkeyFilename}" not found. Creating with random contents.`); - exports.sessionKey = randomString(32); - fs.writeFileSync(sessionkeyFilename, exports.sessionKey, 'utf8'); + sessionKey = randomString(32); + fs.writeFileSync(sessionkeyFilename, sessionKey, 'utf8'); } } else { logger.warn('Declaring the sessionKey in the settings.json is deprecated. ' + @@ -827,22 +835,22 @@ exports.reloadSettings = () => { 'If you are seeing this error after restarting using the Admin User ' + 'Interface then you can ignore this message.'); } - if (exports.sessionKey) { + if (sessionKey) { logger.warn(`The sessionKey setting and ${sessionkeyFilename} file are deprecated; ` + 'use automatic key rotation instead (see the cookie.keyRotationInterval setting).'); } - if (exports.dbType === 'dirty') { + if (dbType === 'dirty') { const dirtyWarning = 'DirtyDB is used. This is not recommended for production.'; - if (!exports.suppressErrorsInPadText) { - exports.defaultPadText += `\nWarning: ${dirtyWarning}${suppressDisableMsg}`; + if (!suppressErrorsInPadText) { + defaultPadText += `\nWarning: ${dirtyWarning}${suppressDisableMsg}`; } - exports.dbSettings.filename = absolutePaths.makeAbsolute(exports.dbSettings.filename); - logger.warn(`${dirtyWarning} File location: ${exports.dbSettings.filename}`); + dbSettings.filename = absolutePaths.makeAbsolute(dbSettings.filename); + logger.warn(`${dirtyWarning} File location: ${dbSettings.filename}`); } - if (exports.ip === '') { + if (ip === '') { // using Unix socket for connectivity logger.warn('The settings file contains an empty string ("") for the "ip" parameter. The ' + '"port" parameter will be interpreted as the path to a Unix socket to bind at.'); @@ -859,14 +867,15 @@ exports.reloadSettings = () => { * ACHTUNG: this may prevent caching HTTP proxies to work * TODO: remove the "?v=randomstring" parameter, and replace with hashed filenames instead */ - exports.randomVersionString = randomString(4); - logger.info(`Random string used for versioning assets: ${exports.randomVersionString}`); + randomVersionString = randomString(4); + logger.info(`Random string used for versioning assets: ${randomVersionString}`); }; -exports.exportedForTestingOnly = { + +export const exportedForTestingOnly = { parseSettings, }; // initially load settings -exports.reloadSettings(); +reloadSettings(); diff --git a/src/node/utils/randomstring.ts b/src/node/utils/randomstring.ts index a86d28566..a3f0d31fe 100644 --- a/src/node/utils/randomstring.ts +++ b/src/node/utils/randomstring.ts @@ -3,8 +3,8 @@ * Generates a random String with the given length. Is needed to generate the * Author, Group, readonly, session Ids */ -const cryptoMod = require('crypto'); +import cryptoMod from 'crypto'; const randomString = (len: number) => cryptoMod.randomBytes(len).toString('hex'); -module.exports = randomString; +export default randomString; diff --git a/src/package.json b/src/package.json index 784efd9f6..bb00ee08a 100644 --- a/src/package.json +++ b/src/package.json @@ -81,6 +81,7 @@ "devDependencies": { "@types/async": "^3.2.24", "@types/express": "^4.17.21", + "@types/jsonminify": "^0.4.3", "@types/node": "^20.11.19", "@types/underscore": "^1.11.15", "cypress": "^13.6.4", diff --git a/src/tests/backend/specs/Pad.js b/src/tests/backend/specs/Pad.js index ec5c24631..a5e01b655 100644 --- a/src/tests/backend/specs/Pad.js +++ b/src/tests/backend/specs/Pad.js @@ -6,7 +6,7 @@ const authorManager = require('../../../node/db/AuthorManager'); const common = require('../common'); const padManager = require('../../../node/db/PadManager'); const plugins = require('../../../static/js/pluginfw/plugin_defs'); -const settings = require('../../../node/utils/Settings'); +import * as settings from '../../../node/utils/Settings'; describe(__filename, function () { const backups = {}; diff --git a/src/tests/backend/specs/api/importexportGetPost.js b/src/tests/backend/specs/api/importexportGetPost.js index e69f0d120..4d21cbe38 100644 --- a/src/tests/backend/specs/api/importexportGetPost.js +++ b/src/tests/backend/specs/api/importexportGetPost.js @@ -7,7 +7,7 @@ const assert = require('assert').strict; const common = require('../../common'); const fs = require('fs'); -const settings = require('../../../../node/utils/Settings'); +import * as settings from '../../../../node/utils/Settings'; const superagent = require('superagent'); const padManager = require('../../../../node/db/PadManager'); const plugins = require('../../../../static/js/pluginfw/plugin_defs'); diff --git a/src/tests/backend/specs/caching_middleware.js b/src/tests/backend/specs/caching_middleware.js index ebfd65d9f..c5ef605fc 100644 --- a/src/tests/backend/specs/caching_middleware.js +++ b/src/tests/backend/specs/caching_middleware.js @@ -9,7 +9,7 @@ const common = require('../common'); const assert = require('../assert-legacy').strict; const queryString = require('querystring'); -const settings = require('../../../node/utils/Settings'); +import * as settings from '../../../node/utils/Settings'; let agent; diff --git a/src/tests/backend/specs/export.js b/src/tests/backend/specs/export.js index d2fcde131..e202eab6d 100644 --- a/src/tests/backend/specs/export.js +++ b/src/tests/backend/specs/export.js @@ -2,7 +2,7 @@ const common = require('../common'); const padManager = require('../../../node/db/PadManager'); -const settings = require('../../../node/utils/Settings'); +import * as settings from '../../../node/utils/Settings'; describe(__filename, function () { let agent; diff --git a/src/tests/backend/specs/favicon.js b/src/tests/backend/specs/favicon.js index 98c308061..0a2594a28 100644 --- a/src/tests/backend/specs/favicon.js +++ b/src/tests/backend/specs/favicon.js @@ -5,7 +5,7 @@ const common = require('../common'); const fs = require('fs'); const fsp = fs.promises; const path = require('path'); -const settings = require('../../../node/utils/Settings'); +import * as settings from '../../../node/utils/Settings' const superagent = require('superagent'); describe(__filename, function () { diff --git a/src/tests/backend/specs/health.js b/src/tests/backend/specs/health.js index 0090aedbb..582c36a99 100644 --- a/src/tests/backend/specs/health.js +++ b/src/tests/backend/specs/health.js @@ -2,7 +2,7 @@ const assert = require('assert').strict; const common = require('../common'); -const settings = require('../../../node/utils/Settings'); +import * as settings from '../../../node/utils/Settings'; const superagent = require('superagent'); describe(__filename, function () { diff --git a/src/tests/backend/specs/specialpages.js b/src/tests/backend/specs/specialpages.js index 93c8b3bc4..0b691368e 100644 --- a/src/tests/backend/specs/specialpages.js +++ b/src/tests/backend/specs/specialpages.js @@ -1,7 +1,7 @@ 'use strict'; const common = require('../common'); -const settings = require('../../../node/utils/Settings'); +import * as settings from '../../../node/utils/Settings'; describe(__filename, function () { this.timeout(30000); diff --git a/src/tests/backend/specs/webaccess.js b/src/tests/backend/specs/webaccess.js index 23cd2d889..353f4ca3c 100644 --- a/src/tests/backend/specs/webaccess.js +++ b/src/tests/backend/specs/webaccess.js @@ -3,7 +3,7 @@ const assert = require('assert').strict; const common = require('../common'); const plugins = require('../../../static/js/pluginfw/plugin_defs'); -const settings = require('../../../node/utils/Settings'); +import * as settings from '../../../node/utils/Settings'; describe(__filename, function () { this.timeout(30000);