chore: migrated settings to esm6 (#7062)

* chore: migrated settings to esm6

* chore: fixed frontends

* chore: fixed missing usage of specialpages

* chore: fixed last errors for settings

* chore: fixed favicon test
This commit is contained in:
SamTV12345 2025-08-04 22:42:50 +02:00 committed by GitHub
parent 920308a627
commit 8588d99f12
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
57 changed files with 698 additions and 562 deletions

View file

@ -18,7 +18,7 @@ import process from "node:process";
process.on('unhandledRejection', (err) => { throw err; });
const settings = require('ep_etherpad-lite/node/utils/Settings');
import settings from 'ep_etherpad-lite/node/utils/Settings';
(async () => {
axios.defaults.baseURL = `http://${settings.ip}:${settings.port}`;
const api = axios;

View file

@ -3,13 +3,13 @@
// As of v14, Node.js does not exit when there is an unhandled Promise rejection. Convert an
// unhandled rejection into an uncaught exception, which does cause Node.js to exit.
import util from "node:util";
const fs = require('fs');
import fs from 'node:fs';
import log4js from 'log4js';
import readline from 'readline';
import {Database} from "ueberdb2";
import {Database, DatabaseType} from "ueberdb2";
import process from "node:process";
const settings = require('ep_etherpad-lite/node/utils/Settings');
import settings from 'ep_etherpad-lite/node/utils/Settings';
process.on('unhandledRejection', (err) => { throw err; });
const startTime = Date.now();
@ -58,7 +58,7 @@ const unescape = (val: string) => {
json: false, // data is already json encoded
};
const db = new Database( // eslint-disable-line new-cap
settings.dbType,
settings.dbType as DatabaseType,
settings.dbSettings,
dbWrapperSettings,
log4js.getLogger('ueberDB'));

View file

@ -2,7 +2,7 @@
import {readFileSync} from 'node:fs'
import {Database, DatabaseType} from "ueberdb2";
import path from "node:path";
const settings = require('ep_etherpad-lite/node/utils/Settings');
import settings from 'ep_etherpad-lite/node/utils/Settings';
// file1 = source, file2 = target

View file

@ -1,10 +1,9 @@
'use strict';
import process from 'node:process';
import {Database} from "ueberdb2";
import {Database, DatabaseType} from "ueberdb2";
import log4js from 'log4js';
import util from 'util';
const settings = require('ep_etherpad-lite/node/utils/Settings');
import settings from 'ep_etherpad-lite/node/utils/Settings';
// As of v14, Node.js does not exit when there is an unhandled Promise rejection. Convert an
// unhandled rejection into an uncaught exception, which does cause Node.js to exit.
@ -24,7 +23,7 @@ process.on('unhandledRejection', (err) => { throw err; });
writeInterval: 0, // Write directly to the database, don't buffer
};
const db = new Database( // eslint-disable-line new-cap
settings.dbType,
settings.dbType as DatabaseType,
settings.dbSettings,
dbWrapperSettings,
log4js.getLogger('ueberDB'));

View file

@ -1,5 +1,3 @@
'use strict';
/*
This is a repair tool. It rebuilds an old pad at a new pad location up to a
known "good" revision.

31
pnpm-lock.yaml generated
View file

@ -105,7 +105,7 @@ importers:
dependencies:
axios:
specifier: ^1.10.0
version: 1.10.0
version: 1.11.0
ep_etherpad-lite:
specifier: workspace:../src
version: link:../src
@ -288,6 +288,12 @@ importers:
'@types/cookie-parser':
specifier: ^1.4.9
version: 1.4.9(@types/express@5.0.3)
'@types/cross-spawn':
specifier: ^6.0.6
version: 6.0.6
'@types/ejs':
specifier: ^3.1.5
version: 3.1.5
'@types/express':
specifier: ^5.0.0
version: 5.0.3
@ -1564,12 +1570,18 @@ packages:
'@types/cors@2.8.17':
resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==}
'@types/cross-spawn@6.0.6':
resolution: {integrity: sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==}
'@types/debug@4.1.12':
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
'@types/deep-eql@4.0.2':
resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
'@types/ejs@3.1.5':
resolution: {integrity: sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==}
'@types/estree@1.0.7':
resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==}
@ -2171,9 +2183,6 @@ packages:
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
engines: {node: '>= 0.4'}
axios@1.10.0:
resolution: {integrity: sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==}
axios@1.11.0:
resolution: {integrity: sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==}
@ -5996,12 +6005,18 @@ snapshots:
dependencies:
'@types/node': 24.1.0
'@types/cross-spawn@6.0.6':
dependencies:
'@types/node': 24.1.0
'@types/debug@4.1.12':
dependencies:
'@types/ms': 2.1.0
'@types/deep-eql@4.0.2': {}
'@types/ejs@3.1.5': {}
'@types/estree@1.0.7': {}
'@types/estree@1.0.8': {}
@ -6678,14 +6693,6 @@ snapshots:
dependencies:
possible-typed-array-names: 1.1.0
axios@1.10.0:
dependencies:
follow-redirects: 1.15.9
form-data: 4.0.3
proxy-from-env: 1.1.0
transitivePeerDependencies:
- debug
axios@1.11.0:
dependencies:
follow-redirects: 1.15.9

View file

@ -21,8 +21,8 @@
* limitations under the License.
*/
import {Database} from 'ueberdb2';
const settings = require('../utils/Settings');
import {Database, DatabaseType} from 'ueberdb2';
import settings from '../utils/Settings';
import log4js from 'log4js';
const stats = require('../stats')
@ -37,7 +37,7 @@ exports.db = null;
* Initializes the database with the settings provided by the settings module
*/
exports.init = async () => {
exports.db = new Database(settings.dbType, settings.dbSettings, null, logger);
exports.db = new Database(settings.dbType as DatabaseType, settings.dbSettings, null, logger);
await exports.db.init();
if (exports.db.metrics != null) {
for (const [metric, value] of Object.entries(exports.db.metrics)) {

View file

@ -14,7 +14,7 @@ import AttributePool from '../../static/js/AttributePool';
const Stream = require('../utils/Stream');
const assert = require('assert').strict;
const db = require('./DB');
const settings = require('../utils/Settings');
import settings from '../utils/Settings';
const authorManager = require('./AuthorManager');
const padManager = require('./PadManager');
const padMessageHandler = require('../handler/PadMessageHandler');

View file

@ -25,7 +25,7 @@ import {PadType} from "../types/PadType";
const CustomError = require('../utils/customError');
const Pad = require('../db/Pad');
const db = require('./DB');
const settings = require('../utils/Settings');
import settings from '../utils/Settings';
/**
* A cache of all loaded Pads.

View file

@ -26,7 +26,7 @@ const hooks = require('../../static/js/pluginfw/hooks');
const padManager = require('./PadManager');
import readOnlyManager from './ReadOnlyManager';
const sessionManager = require('./SessionManager');
const settings = require('../utils/Settings');
import settings from '../utils/Settings';
const webaccess = require('../hooks/express/webaccess');
const log4js = require('log4js');
const authLogger = log4js.getLogger('auth');

View file

@ -20,12 +20,13 @@
* require("./index").require("./path/to/template.ejs")
*/
const ejs = require('ejs');
const fs = require('fs');
import ejs from 'ejs';
import fs from 'fs';
const hooks = require('../../static/js/pluginfw/hooks');
const path = require('path');
const resolve = require('resolve');
const settings = require('../utils/Settings');
import path from 'node:path';
// @ts-ignore
import resolve from 'resolve';
import settings from '../utils/Settings';
import {pluginInstallPath} from '../../static/js/pluginfw/installer'
const templateCache = new Map();

View file

@ -23,7 +23,7 @@ import {MapArrayType} from "../types/MapType";
import { jwtDecode } from "jwt-decode";
const api = require('../db/API');
const padManager = require('../db/PadManager');
const settings = require('../utils/Settings');
import settings from '../utils/Settings';
import createHTTPError from 'http-errors';
import {Http2ServerRequest} from "node:http2";
import {publicKeyExported} from "../security/OAuth2Provider";
@ -183,7 +183,7 @@ exports.handle = async function (apiVersion: string, functionName: string, field
throw new createHTTPError.Unauthorized('no or wrong API Key');
}
try {
const clientIds: string[] = settings.sso.clients?.map((client: {client_id: string}) => client.client_id);
const clientIds: string[] = settings.sso.clients?.map((client: {client_id: string}) => client.client_id) ?? [];
const jwtToCheck = req.headers.authorization.replace("Bearer ", "")
const payload = jwtDecode(jwtToCheck)
// client_credentials

View file

@ -1,9 +1,9 @@
const absolutePaths = require('../utils/AbsolutePaths');
import * as absolutePaths from '../utils/AbsolutePaths';
import fs from 'fs';
import log4js from 'log4js';
import randomString from '../utils/randomstring';
const argv = require('../utils/Cli').argv;
const settings = require('../utils/Settings');
import {argv} from '../utils/Cli'
import settings from '../utils/Settings';
const apiHandlerLogger = log4js.getLogger('APIHandler');

View file

@ -24,7 +24,7 @@ const exporthtml = require('../utils/ExportHtml');
const exporttxt = require('../utils/ExportTxt');
const exportEtherpad = require('../utils/ExportEtherpad');
import fs from 'fs';
const settings = require('../utils/Settings');
import settings from '../utils/Settings';
import os from 'os';
const hooks = require('../../static/js/pluginfw/hooks');
import util from 'util';

View file

@ -25,7 +25,7 @@ const padManager = require('../db/PadManager');
const padMessageHandler = require('./PadMessageHandler');
import {promises as fs} from 'fs';
import path from 'path';
const settings = require('../utils/Settings');
import settings from '../utils/Settings';
const {Formidable} = require('formidable');
import os from 'os';
const importHtml = require('../utils/ImportHtml');

View file

@ -30,7 +30,11 @@ const AttributeManager = require('../../static/js/AttributeManager');
const authorManager = require('../db/AuthorManager');
import padutils from '../../static/js/pad_utils';
import readOnlyManager from '../db/ReadOnlyManager';
const settings = require('../utils/Settings');
import settings, {
exportAvailable,
abiwordAvailable,
sofficeAvailable
} from '../utils/Settings';
const securityManager = require('../db/SecurityManager');
const plugins = require('../../static/js/pluginfw/plugin_defs');
import log4js from 'log4js';
@ -1021,9 +1025,9 @@ const handleClientReady = async (socket:any, message: ClientReadyMessage) => {
serverTimestamp: Date.now(),
sessionRefreshInterval: settings.cookie.sessionRefreshInterval,
userId: sessionInfo.author,
abiwordAvailable: settings.abiwordAvailable(),
sofficeAvailable: settings.sofficeAvailable(),
exportAvailable: settings.exportAvailable(),
abiwordAvailable: abiwordAvailable(),
sofficeAvailable: sofficeAvailable(),
exportAvailable: exportAvailable(),
plugins: {
plugins: plugins.plugins,
parts: plugins.parts,

View file

@ -8,7 +8,7 @@ const apiHandler = require('./APIHandler')
import {serve, setup} from 'swagger-ui-express'
import express from "express";
const settings = require('../utils/Settings')
import settings from '../utils/Settings';
type RestAPIMapping = {

View file

@ -22,8 +22,8 @@
import {MapArrayType} from "../types/MapType";
import {SocketModule} from "../types/SocketModule";
const log4js = require('log4js');
const settings = require('../utils/Settings');
import log4js from 'log4js';
import settings from '../utils/Settings';
const stats = require('../../node/stats')
const logger = log4js.getLogger('socket.io');

View file

@ -12,7 +12,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 settings, {getEpVersion, getGitCommit} from '../utils/Settings';
const stats = require('../stats')
import util from 'util';
const webaccess = require('./express/webaccess');
@ -67,9 +67,9 @@ const closeServer = async () => {
exports.createServer = async () => {
console.log('Report bugs at https://github.com/ether/etherpad-lite/issues');
serverName = `Etherpad ${settings.getGitCommit()} (https://etherpad.org)`;
serverName = `Etherpad ${getGitCommit()} (https://etherpad.org)`;
console.log(`Your Etherpad version is ${settings.getEpVersion()} (${settings.getGitCommit()})`);
console.log(`Your Etherpad version is ${getEpVersion()} (${getGitCommit()})`);
await exports.restartServer();
@ -176,7 +176,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.
if (!(settings.loglevel === 'WARN' && settings.loglevel === 'ERROR')) {
if (!(settings.loglevel === 'WARN' || settings.loglevel === 'ERROR')) {
app.use(log4js.connectLogger(logger, {
level: log4js.levels.DEBUG.levelStr,
format: ':status, :method :url',
@ -189,7 +189,12 @@ exports.restartServer = async () => {
secretRotator = new SecretRotator(
'expressSessionSecrets', keyRotationInterval, sessionLifetime, settings.sessionKey);
await secretRotator.start();
secret = secretRotator.secrets;
const secrets = secretRotator.secrets;
if (Array.isArray(secrets)) {
secret = secrets[0];
} else {
secret = secretRotator.secrets as unknown as string;
}
}
if (!secret) throw new Error('missing cookie signing secret');
@ -206,7 +211,7 @@ exports.restartServer = async () => {
// cleaner :)
name: 'express_sid',
cookie: {
maxAge: sessionLifetime || null, // Convert 0 to null.
maxAge: sessionLifetime || undefined, // Convert 0 to null.
sameSite: settings.cookie.sameSite,
// The automatic express-session mechanism for determining if the application is being served

View file

@ -2,10 +2,9 @@
import {ArgsExpressType} from "../../types/ArgsExpressType";
import path from "path";
import fs from "fs";
import * as url from "node:url";
import {MapArrayType} from "../../types/MapType";
const settings = require('ep_etherpad-lite/node/utils/Settings');
import settings from 'ep_etherpad-lite/node/utils/Settings';
const ADMIN_PATH = path.join(settings.root, 'src', 'templates');
const PROXY_HEADER = "x-proxy-path"

View file

@ -7,7 +7,7 @@ import log4js from 'log4js';
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 settings, {getEpVersion, getGitCommit, reloadSettings} from '../../utils/Settings';
import {getLatestVersion} from '../../utils/UpdateCheck';
const padManager = require('../../db/PadManager');
const api = require('../../db/API');
@ -73,8 +73,8 @@ exports.socketio = (hookName: string, {io}: any) => {
socket.on('help', () => {
const gitCommit = settings.getGitCommit();
const epVersion = settings.getEpVersion();
const gitCommit = getGitCommit();
const epVersion = getEpVersion();
const hooks: Map<string, Map<string, string>> = plugins.getHooks('hooks', false);
const clientHooks: Map<string, Map<string, string>> = plugins.getHooks('client_hooks', false);
@ -287,7 +287,7 @@ exports.socketio = (hookName: string, {io}: any) => {
socket.on('restartServer', async () => {
logger.info('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');

View file

@ -3,7 +3,7 @@
import {ArgsExpressType} from "../../types/ArgsExpressType";
const hasPadAccess = require('../../padaccess');
const settings = require('../../utils/Settings');
import settings, {exportAvailable} from '../../utils/Settings';
const exportHandler = require('../../handler/ExportHandler');
const importHandler = require('../../handler/ImportHandler');
const padManager = require('../../db/PadManager');
@ -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');

View file

@ -24,9 +24,9 @@ const cloneDeep = require('lodash.clonedeep');
const createHTTPError = require('http-errors');
const apiHandler = require('../../handler/APIHandler');
const settings = require('../../utils/Settings');
import settings from '../../utils/Settings';
const log4js = require('log4js');
import log4js from 'log4js';
const logger = log4js.getLogger('API');
// https://github.com/OAI/OpenAPI-Specification/tree/master/schemas/v3.0

View file

@ -1,5 +1,5 @@
import {ArgsExpressType} from "../../types/ArgsExpressType";
const settings = require('../../utils/Settings');
import settings from '../../utils/Settings';
const pwa = {
name: settings.title || "Etherpad",

View file

@ -6,7 +6,7 @@ import events from 'events';
const express = require('../express');
import log4js from 'log4js';
const proxyaddr = require('proxy-addr');
const settings = require('../../utils/Settings');
import settings from '../../utils/Settings';
import {Server, Socket} from 'socket.io'
const socketIORouter = require('../../handler/SocketIORouter');
const hooks = require('../../../static/js/pluginfw/hooks');

View file

@ -6,7 +6,7 @@ import fs from 'node:fs';
const fsp = fs.promises;
const toolbar = require('../../utils/toolbar');
const hooks = require('../../../static/js/pluginfw/hooks');
const settings = require('../../utils/Settings');
import settings, {getEpVersion} from '../../utils/Settings';
import util from 'node:util';
const webaccess = require('./webaccess');
const plugins = require('../../../static/js/pluginfw/plugin_defs');
@ -20,14 +20,14 @@ exports.socketio = (hookName: string, {io}: any) => {
}
exports.expressPreSession = async (hookName:string, {app, settings}:ArgsExpressType) => {
exports.expressPreSession = async (hookName:string, {app}:ArgsExpressType) => {
// This endpoint is intended to conform to:
// https://www.ietf.org/archive/id/draft-inadarei-api-health-check-06.html
app.get('/health', (req:any, res:any) => {
res.set('Content-Type', 'application/health+json');
res.json({
status: 'pass',
releaseId: settings.getEpVersion(),
releaseId: getEpVersion(),
});
});
@ -43,6 +43,10 @@ exports.expressPreSession = async (hookName:string, {app, settings}:ArgsExpressT
});
app.get('/robots.txt', (req:any, res:any) => {
if (!settings.skinName) {
// if no skin is set, send the default robots.txt
return res.sendFile(path.join(settings.root, 'src', 'static', 'robots.txt'));
}
let filePath =
path.join(settings.root, 'src', 'static', 'skins', settings.skinName, 'robots.txt');
res.sendFile(filePath, (err:any) => {
@ -66,11 +70,13 @@ exports.expressPreSession = async (hookName:string, {app, settings}:ArgsExpressT
}
console.log("Favicon is", settings.favicon)
const fns = [
...(settings.favicon ? [path.resolve(settings.root, settings.favicon)] : []),
path.join(settings.root, 'src', 'static', 'skins', settings.skinName, 'favicon.ico'),
settings.skinName && path.join(settings.root, 'src', 'static', 'skins', settings.skinName, 'favicon.ico'),
path.join(settings.root, 'src', 'static', 'favicon.ico'),
];
].filter(f=>f != null);
console.log('FNS are', fns)
for (const fn of fns) {
try {
await fsp.access(fn, fs.constants.R_OK);
@ -178,7 +184,8 @@ const handleLiveReload = async (args: ArgsExpressType, padString: string, timeSl
req,
toolbar,
isReadOnly,
entrypoint: '/watch/pad?hash=' + hash
entrypoint: '/watch/pad?hash=' + hash,
settings: settings.getPublicSettings()
})
res.send(content);
})
@ -207,7 +214,8 @@ const handleLiveReload = async (args: ArgsExpressType, padString: string, timeSl
req,
toolbar,
isReadOnly,
entrypoint: '/watch/timeslider?hash=' + hash
entrypoint: '/watch/timeslider?hash=' + hash,
settings: settings.getPublicSettings()
})
res.send(content);
})
@ -334,7 +342,8 @@ exports.expressCreateServer = async (_hookName: string, args: ArgsExpressType, c
req,
toolbar,
isReadOnly,
entrypoint: "../"+fileNamePad
entrypoint: "../"+fileNamePad,
settings: settings.getPublicSettings()
})
res.send(content);
});
@ -348,7 +357,8 @@ exports.expressCreateServer = async (_hookName: string, args: ArgsExpressType, c
res.send(eejs.require('ep_etherpad-lite/templates/timeslider.html', {
req,
toolbar,
entrypoint: "../../"+fileNameTimeSlider
entrypoint: "../../"+fileNameTimeSlider,
settings: settings.getPublicSettings()
}));
});
} else {

View file

@ -8,7 +8,7 @@ import {minify} from '../../utils/Minify';
import path from 'node:path';
import {ArgsExpressType} from "../../types/ArgsExpressType";
const plugins = require('../../../static/js/pluginfw/plugin_defs');
const settings = require('../../utils/Settings');
import settings from '../../utils/Settings';
// Rewrite tar to include modules with no extensions and proper rooted paths.
const getTar = async () => {

View file

@ -6,7 +6,7 @@ import {SocketClientRequest} from "../../types/SocketClientRequest";
import {WebAccessTypes} from "../../types/WebAccessTypes";
import {SettingsUser} from "../../types/SettingsUser";
const httpLogger = log4js.getLogger('http');
const settings = require('../../utils/Settings');
import settings from '../../utils/Settings';
const hooks = require('../../../static/js/pluginfw/hooks');
import readOnlyManager from '../../db/ReadOnlyManager';

View file

@ -4,12 +4,12 @@ import type {MapArrayType} from "../types/MapType";
import {I18nPluginDefs} from "../types/I18nPluginDefs";
const languages = require('languages4translatewiki');
const fs = require('fs');
const path = require('path');
const _ = require('underscore');
import fs from 'fs';
import path from 'path';
import _ from 'underscore';
const pluginDefs = require('../../static/js/pluginfw/plugin_defs');
import existsSync from '../utils/path_exists';
const settings = require('../utils/Settings');
import settings from '../utils/Settings';
// returns all existing messages merged together and grouped by langcode
// {es: {"foo": "string"}, en:...}
@ -73,7 +73,7 @@ const getAllLocales = () => {
'for Customization for Administrators, under Localization.');
if (settings.customLocaleStrings) {
if (typeof settings.customLocaleStrings !== 'object') throw wrongFormatErr;
_.each(settings.customLocaleStrings, (overrides:MapArrayType<string> , langcode:string) => {
_.each(settings.customLocaleStrings, (overrides , langcode) => {
if (typeof overrides !== 'object') throw wrongFormatErr;
_.each(overrides, (localeString:string|object, key:string) => {
if (typeof localeString !== 'string') throw wrongFormatErr;

View file

@ -3,7 +3,7 @@ import Provider, {Account, Configuration} from 'oidc-provider';
import {generateKeyPair, exportJWK, CryptoKey} from 'jose'
import MemoryAdapter from "./OIDCAdapter";
import path from "path";
const settings = require('../utils/Settings');
import settings from '../utils/Settings';
import {IncomingForm} from 'formidable'
import express from 'express';
import {format} from 'url'
@ -138,7 +138,7 @@ export const expressCreateServer = async (hookName: string, args: ArgsExpressTyp
} else if (token.kind === "ClientCredentials") {
let extraParams: MapArrayType<string> = {}
settings.sso.clients
settings.sso.clients && settings.sso.clients
.filter((client:any) => client.client_id === token.clientId)
.forEach((client:any) => {
if(client.extraParams !== undefined) {

View file

@ -29,7 +29,7 @@ import pkg from '../package.json';
import {checkForMigration} from "../static/js/pluginfw/installer";
import axios from "axios";
const settings = require('./utils/Settings');
import settings from './utils/Settings';
let wtfnode: any;
if (settings.dumpOnUncleanExit) {

View file

@ -1,9 +1,10 @@
import {Express} from "express";
import {MapArrayType} from "./MapType";
import {SettingsType} from "../utils/Settings";
export type ArgsExpressType = {
app:Express,
io: any,
server:any
settings: MapArrayType<any>
settings: SettingsType
}

View file

@ -24,7 +24,7 @@ import {AsyncQueueTask} from "../types/AsyncQueueTask";
const spawn = require('child_process').spawn;
const async = require('async');
const settings = require('./Settings');
import settings from './Settings';
const os = require('os');
// on windows we have to spawn a process for each convertion,

View file

@ -18,9 +18,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const log4js = require('log4js');
const path = require('path');
const _ = require('underscore');
import log4js from 'log4js';
import path from 'path';
import _ from 'underscore';
const absPathLogger = log4js.getLogger('AbsolutePaths');
@ -74,7 +74,7 @@ const popIfEndsWith = (stringArray: string[], lastDesiredElements: string[]): st
* @return {string} The identified absolute base path. If such path cannot be
* identified, prints a log and exits the application.
*/
exports.findEtherpadRoot = () => {
export const findEtherpadRoot = () => {
if (etherpadRoot != null) {
return etherpadRoot;
}
@ -130,12 +130,12 @@ exports.findEtherpadRoot = () => {
* it is returned unchanged. Otherwise it is interpreted
* relative to exports.root.
*/
exports.makeAbsolute = (somePath: string) => {
export const makeAbsolute = (somePath: string) => {
if (path.isAbsolute(somePath)) {
return somePath;
}
const rewrittenPath = path.join(exports.findEtherpadRoot(), somePath);
const rewrittenPath = path.join(findEtherpadRoot(), somePath);
absPathLogger.debug(`Relative path "${somePath}" can be rewritten to "${rewrittenPath}"`);
return rewrittenPath;
@ -149,7 +149,7 @@ exports.makeAbsolute = (somePath: string) => {
* a subdirectory of the base one
* @return {boolean}
*/
exports.isSubdir = (parent: string, arbitraryDir: string): boolean => {
export const isSubdir = (parent: string, arbitraryDir: string): boolean => {
// modified from: https://stackoverflow.com/questions/37521893/determine-if-a-path-is-subdirectory-of-another-in-node-js#45242825
const relative = path.relative(parent, arbitraryDir);
return !!relative && !relative.startsWith('..') && !path.isAbsolute(relative);

View file

@ -21,32 +21,33 @@
*/
// An object containing the parsed command-line options
exports.argv = {};
const argv = process.argv.slice(2);
export const argv: Record<string, string> = {};
const argvInternal = process.argv.slice(2);
let arg, prevArg;
// Loop through args
for (let i = 0; i < argv.length; i++) {
arg = argv[i];
for (let i = 0; i < argvInternal.length; i++) {
arg = argvInternal[i];
// Override location of settings.json file
if (prevArg === '--settings' || prevArg === '-s') {
exports.argv.settings = arg;
if (prevArg && prevArg === '--settings' || prevArg === '-s') {
argv.settings = arg;
}
// Override location of credentials.json file
if (prevArg === '--credentials') {
if (prevArg && prevArg === '--credentials') {
exports.argv.credentials = arg;
}
// Override location of settings.json file
if (prevArg === '--sessionkey') {
if (prevArg && prevArg === '--sessionkey') {
exports.argv.sessionkey = arg;
}
// Override location of APIKEY.txt file
if (prevArg === '--apikey') {
if (prevArg && prevArg === '--apikey') {
exports.argv.apikey = arg;
}

View file

@ -23,7 +23,7 @@ const log4js = require('log4js');
const os = require('os');
const path = require('path');
const runCmd = require('./run_cmd');
const settings = require('./Settings');
import settings from './Settings';
const logger = log4js.getLogger('LibreOffice');

View file

@ -26,7 +26,7 @@ import mime from 'mime-types';
import log4js from 'log4js';
import {compressCSS, compressJS} from './MinifyWorker'
const settings = require('./Settings');
import settings from './Settings';
import {promises as fs} from 'fs';
import path from 'node:path';
const plugins = require('../../static/js/pluginfw/plugin_defs');

File diff suppressed because it is too large Load diff

View file

@ -1,9 +1,9 @@
'use strict';
import semver from 'semver';
const settings = require('./Settings');
import settings, {getEpVersion} from './Settings';
import axios from 'axios';
const headers = {
'User-Agent': 'Etherpad/' + settings.getEpVersion(),
'User-Agent': 'Etherpad/' + getEpVersion(),
}
type Infos = {
@ -45,7 +45,7 @@ export const getLatestVersion = () => {
const needsUpdate = async (cb?: Function) => {
try {
const info = await loadEtherpadInformations()
if (semver.gt(info!.latestVersion, settings.getEpVersion())) {
if (semver.gt(info!.latestVersion, getEpVersion())) {
if (cb) return cb(true);
}
} catch (err) {

View file

@ -5,10 +5,10 @@ import {ChildProcess} from "node:child_process";
import {PromiseWithStd} from "../types/PromiseWithStd";
import {Readable} from "node:stream";
const spawn = require('cross-spawn');
const log4js = require('log4js');
const path = require('path');
const settings = require('./Settings');
import spawn from 'cross-spawn';
import log4js from 'log4js';
import path from 'path';
import settings from './Settings';
const logger = log4js.getLogger('runCmd');
@ -123,7 +123,7 @@ module.exports = exports = (args: string[], opts:RunCMDOptions = {}) => {
// process's `exit` handler so that we get a useful stack trace.
const procFailedErr: Error & ErrorExtended = new Error();
const proc: ChildProcess = spawn(args[0], args.slice(1), opts);
const proc: ChildProcess = spawn(args[0], args.slice(1), opts as any);
const streams:[undefined, Readable|null, Readable|null] = [undefined, proc.stdout, proc.stderr];
let px: { reject: any; resolve: any; };

View file

@ -85,6 +85,8 @@
"@playwright/test": "^1.54.1",
"@types/async": "^3.2.24",
"@types/cookie-parser": "^1.4.9",
"@types/cross-spawn": "^6.0.6",
"@types/ejs": "^3.1.5",
"@types/express": "^5.0.0",
"@types/express-session": "^1.18.2",
"@types/formidable": "^3.4.5",

View file

@ -4,7 +4,7 @@ import {node_modules, pluginInstallPath} from "./installer";
import {accessSync, constants, rmSync, symlinkSync, unlinkSync} from "node:fs";
import {dependencies, name} from '../../../package.json'
import {pathToFileURL} from 'node:url';
const settings = require('../../../node/utils/Settings');
import settings from '../../../node/utils/Settings';
import {readFileSync} from "fs";
export class LinkInstaller {

View file

@ -13,10 +13,13 @@ import {promises as fs} from "fs";
const plugins = require('./plugins');
const hooks = require('./hooks');
const runCmd = require('../../../node/utils/run_cmd');
const settings = require('../../../node/utils/Settings');
import settings, {
getEpVersion,
reloadSettings
} from '../../../node/utils/Settings';
import {LinkInstaller} from "./LinkInstaller";
const {findEtherpadRoot} = require('../../../node/utils/AbsolutePaths');
import {findEtherpadRoot} from '../../../node/utils/AbsolutePaths';
const logger = log4js.getLogger('plugins');
export const pluginInstallPath = path.join(settings.root, 'src','plugin_packages');
@ -27,13 +30,13 @@ export const installedPluginsPath = path.join(settings.root, 'var/installed_plug
const onAllTasksFinished = async () => {
await plugins.update();
await persistInstalledPlugins();
settings.reloadSettings();
reloadSettings();
await hooks.aCallAll('loadSettings', {settings});
await hooks.aCallAll('restartServer');
};
const headers = {
'User-Agent': `Etherpad/${settings.getEpVersion()}`,
'User-Agent': `Etherpad/${getEpVersion()}`,
};
let tasks = 0;

View file

@ -9,7 +9,9 @@ const runCmd = require('../../../node/utils/run_cmd');
const tsort = require('./tsort');
const pluginUtils = require('./shared');
const defs = require('./plugin_defs');
const settings = require('../../../node/utils/Settings');
import settings, {
getEpVersion,
} from '../../../node/utils/Settings';
const logger = log4js.getLogger('plugins');
@ -136,7 +138,7 @@ exports.getPackages = async () => {
newDependencies['ep_etherpad-lite'] = {
name: 'ep_etherpad-lite',
version: settings.getEpVersion(),
version: getEpVersion(),
path: path.join(settings.root, 'node_modules/ep_etherpad-lite'),
realPath: path.join(settings.root, 'src'),
};

View file

@ -1,6 +1,5 @@
<%
var settings = require("ep_etherpad-lite/node/utils/Settings")
, langs = require("ep_etherpad-lite/node/hooks/i18n").availableLangs
var langs = require("ep_etherpad-lite/node/hooks/i18n").availableLangs
, pluginUtils = require('ep_etherpad-lite/static/js/pluginfw/shared')
;
%>
@ -168,7 +167,7 @@
<h2 data-l10n-id="pad.settings.about">About</h2>
<span data-l10n-id="pad.settings.poweredBy">Powered by</span>
<a href="https://etherpad.org" target="_blank" referrerpolicy="no-referrer" rel="noopener">Etherpad</a>
<% if (settings.exposeVersion) { %>(commit <%=settings.getGitCommit()%>)<% } %>
<% if (settings.exposeVersion) { %>(commit <%=settings.gitVersion()%>)<% } %>
</div></div>

View file

@ -1,6 +1,5 @@
<%
var settings = require("ep_etherpad-lite/node/utils/Settings")
, langs = require("ep_etherpad-lite/node/hooks/i18n").availableLangs
var langs = require("ep_etherpad-lite/node/hooks/i18n").availableLangs
%>
<!doctype html>
<html translate="no" class="pad <%=settings.skinVariants%>">

View file

@ -10,7 +10,7 @@ import padutils from '../../static/js/pad_utils';
const process = require('process');
const server = require('../../node/server');
const setCookieParser = require('set-cookie-parser');
const settings = require('../../node/utils/Settings');
import settings from '../../node/utils/Settings';
import supertest from 'supertest';
import TestAgent from "supertest/lib/agent";
import {Http2Server} from "node:http2";

View file

@ -9,7 +9,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 settings from '../../../node/utils/Settings';
describe(__filename, function () {
const backups:MapArrayType<any> = {};

View file

@ -11,7 +11,7 @@ import TestAgent from "supertest/lib/agent";
const assert = require('assert').strict;
const common = require('../../common');
const fs = require('fs');
const settings = require('../../../../node/utils/Settings');
import settings from '../../../../node/utils/Settings';
const superagent = require('superagent');
const padManager = require('../../../../node/db/PadManager');
const plugins = require('../../../../static/js/pluginfw/plugin_defs');

View file

@ -4,7 +4,7 @@ import {MapArrayType} from "../../../node/types/MapType";
const common = require('../common');
const padManager = require('../../../node/db/PadManager');
const settings = require('../../../node/utils/Settings');
import settings from '../../../node/utils/Settings';
describe(__filename, function () {
let agent:any;

View file

@ -7,7 +7,7 @@ const common = require('../common');
const fs = require('fs');
const fsp = fs.promises;
const path = require('path');
const settings = require('../../../node/utils/Settings');
import settings from '../../../node/utils/Settings';
const superagent = require('superagent');
describe(__filename, function () {
@ -29,10 +29,13 @@ describe(__filename, function () {
backupSettings = {...settings};
skinDir = await fsp.mkdtemp(path.join(settings.root, 'src', 'static', 'skins', 'test-'));
settings.skinName = path.basename(skinDir);
});
afterEach(async function () {
// @ts-ignore
delete settings.favicon;
// @ts-ignore
delete settings.skinName;
Object.assign(settings, backupSettings);
try {

View file

@ -4,7 +4,9 @@ import {MapArrayType} from "../../../node/types/MapType";
const assert = require('assert').strict;
const common = require('../common');
const settings = require('../../../node/utils/Settings');
import settings, {
getEpVersion
} from '../../../node/utils/Settings';
const superagent = require('superagent');
describe(__filename, function () {
@ -25,6 +27,7 @@ describe(__filename, function () {
beforeEach(async function () {
backup.settings = {};
for (const setting of ['requireAuthentication', 'requireAuthorization']) {
// @ts-ignore
backup.settings[setting] = settings[setting];
}
});
@ -36,7 +39,7 @@ describe(__filename, function () {
it('/health works', async function () {
const res = await getHealth();
assert.equal(res.body.status, 'pass');
assert.equal(res.body.releaseId, settings.getEpVersion());
assert.equal(res.body.releaseId, getEpVersion());
});
it('auth is not required', async function () {

View file

@ -3,7 +3,7 @@
const assert = require('assert').strict;
const common = require('../common');
const padManager = require('../../../node/db/PadManager');
const settings = require('../../../node/utils/Settings');
import settings from '../../../node/utils/Settings';
describe(__filename, function () {
let agent:any;

View file

@ -1,7 +1,7 @@
'use strict';
const assert = require('assert').strict;
const {parseSettings} = require('../../../node/utils/Settings').exportedForTestingOnly;
import {exportedForTestingOnly} from '../../../node/utils/Settings'
import path from 'path';
import process from 'process';
@ -21,7 +21,7 @@ describe(__filename, function () {
before(async function () {
for (const tc of envVarSubstTestCases) process.env[tc.var] = tc.val;
delete process.env.UNSET_VAR;
settings = parseSettings(path.join(__dirname, 'settings.json'), true);
settings = exportedForTestingOnly.parseSettings(path.join(__dirname, 'settings.json'), true);
assert(settings != null);
});
@ -67,26 +67,26 @@ describe(__filename, function () {
})
it('should parse plugin settings', async function () {
let settings = parseSettings(path.join(__dirname, 'settings.json'), true);
assert.equal(settings.ADMIN.PASSWORD, "test");
let settings = exportedForTestingOnly.parseSettings(path.join(__dirname, 'settings.json'), true);
assert.equal(settings!.ADMIN.PASSWORD, "test");
})
it('should bundle settings with same path', async function () {
process.env["EP__ADMIN__USERNAME"] = "test"
let settings = parseSettings(path.join(__dirname, 'settings.json'), true);
assert.deepEqual(settings.ADMIN, {PASSWORD: "test", USERNAME: "test"});
let settings = exportedForTestingOnly.parseSettings(path.join(__dirname, 'settings.json'), true);
assert.deepEqual(settings!.ADMIN, {PASSWORD: "test", USERNAME: "test"});
})
it("Can set the ep themes", async function () {
process.env["EP__ep_themes__default_theme"] = "hacker"
let settings = parseSettings(path.join(__dirname, 'settings.json'), true);
assert.deepEqual(settings.ep_themes, {"default_theme": "hacker"});
let settings = exportedForTestingOnly.parseSettings(path.join(__dirname, 'settings.json'), true);
assert.deepEqual(settings!.ep_themes, {"default_theme": "hacker"});
})
it("can set the ep_webrtc settings", async function () {
process.env["EP__ep_webrtc__enabled"] = "true"
let settings = parseSettings(path.join(__dirname, 'settings.json'), true);
assert.deepEqual(settings.ep_webrtc, {"enabled": true});
let settings = exportedForTestingOnly.parseSettings(path.join(__dirname, 'settings.json'), true);
assert.deepEqual(settings!.ep_webrtc, {"enabled": true});
})
})
});

View file

@ -7,7 +7,7 @@ const common = require('../common');
const padManager = require('../../../node/db/PadManager');
const plugins = require('../../../static/js/pluginfw/plugin_defs');
import readOnlyManager from '../../../node/db/ReadOnlyManager';
const settings = require('../../../node/utils/Settings');
import settings from '../../../node/utils/Settings';
const socketIoRouter = require('../../../node/handler/SocketIORouter');
describe(__filename, function () {
@ -35,6 +35,7 @@ describe(__filename, function () {
}
backups.settings = {};
for (const setting of ['editOnly', 'requireAuthentication', 'requireAuthorization', 'users']) {
// @ts-ignore
backups.settings[setting] = settings[setting];
}
settings.editOnly = false;

View file

@ -3,7 +3,7 @@
import {MapArrayType} from "../../../node/types/MapType";
const common = require('../common');
const settings = require('../../../node/utils/Settings');
import settings from '../../../node/utils/Settings';
@ -15,6 +15,7 @@ describe(__filename, function () {
beforeEach(async function () {
backups.settings = {};
for (const setting of ['requireAuthentication', 'requireAuthorization']) {
// @ts-ignore
backups.settings[setting] = settings[setting];
}
settings.requireAuthentication = false;

View file

@ -7,7 +7,7 @@ import {SettingsUser} from "../../../node/types/SettingsUser";
const assert = require('assert').strict;
const common = require('../common');
const plugins = require('../../../static/js/pluginfw/plugin_defs');
const settings = require('../../../node/utils/Settings');
import settings from '../../../node/utils/Settings';
describe(__filename, function () {
this.timeout(30000);
@ -32,6 +32,7 @@ describe(__filename, function () {
}
backups.settings = {};
for (const setting of ['requireAuthentication', 'requireAuthorization', 'users']) {
// @ts-ignore
backups.settings[setting] = settings[setting];
}
settings.requireAuthentication = false;