mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-04-20 23:46:14 -04:00
Migrated settings to es6
This commit is contained in:
parent
6ed711a4d8
commit
154e67315c
39 changed files with 710 additions and 702 deletions
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
|
@ -297,6 +297,9 @@ importers:
|
||||||
'@types/jsdom':
|
'@types/jsdom':
|
||||||
specifier: ^21.1.7
|
specifier: ^21.1.7
|
||||||
version: 21.1.7
|
version: 21.1.7
|
||||||
|
'@types/jsonminify':
|
||||||
|
specifier: ^0.4.3
|
||||||
|
version: 0.4.3
|
||||||
'@types/jsonwebtoken':
|
'@types/jsonwebtoken':
|
||||||
specifier: ^9.0.6
|
specifier: ^9.0.6
|
||||||
version: 9.0.6
|
version: 9.0.6
|
||||||
|
@ -1516,6 +1519,9 @@ packages:
|
||||||
'@types/json5@0.0.29':
|
'@types/json5@0.0.29':
|
||||||
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
|
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
|
||||||
|
|
||||||
|
'@types/jsonminify@0.4.3':
|
||||||
|
resolution: {integrity: sha512-+oz7EbPz1Nwmn/sr3UztgXpRhdFpvFrjGi5ictEYxUri5ZvQMTcdTi36MTfD/gCb1A5xhJKdH8Hwz2uz5k6s9A==}
|
||||||
|
|
||||||
'@types/jsonwebtoken@9.0.6':
|
'@types/jsonwebtoken@9.0.6':
|
||||||
resolution: {integrity: sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw==}
|
resolution: {integrity: sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw==}
|
||||||
|
|
||||||
|
@ -5703,6 +5709,8 @@ snapshots:
|
||||||
|
|
||||||
'@types/json5@0.0.29': {}
|
'@types/json5@0.0.29': {}
|
||||||
|
|
||||||
|
'@types/jsonminify@0.4.3': {}
|
||||||
|
|
||||||
'@types/jsonwebtoken@9.0.6':
|
'@types/jsonwebtoken@9.0.6':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 22.4.0
|
'@types/node': 22.4.0
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Database} from 'ueberdb2';
|
import {Database} from 'ueberdb2';
|
||||||
const settings = require('../utils/Settings');
|
import settings from '../utils/Settings';
|
||||||
import log4js from 'log4js';
|
import log4js from 'log4js';
|
||||||
const stats = require('../stats')
|
const stats = require('../stats')
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ import AttributePool from '../../static/js/AttributePool';
|
||||||
const Stream = require('../utils/Stream');
|
const Stream = require('../utils/Stream');
|
||||||
const assert = require('assert').strict;
|
const assert = require('assert').strict;
|
||||||
const db = require('./DB');
|
const db = require('./DB');
|
||||||
const settings = require('../utils/Settings');
|
import settings from '../utils/Settings';
|
||||||
const authorManager = require('./AuthorManager');
|
const authorManager = require('./AuthorManager');
|
||||||
const padManager = require('./PadManager');
|
const padManager = require('./PadManager');
|
||||||
const padMessageHandler = require('../handler/PadMessageHandler');
|
const padMessageHandler = require('../handler/PadMessageHandler');
|
||||||
|
|
|
@ -25,7 +25,7 @@ import {PadType} from "../types/PadType";
|
||||||
const CustomError = require('../utils/customError');
|
const CustomError = require('../utils/customError');
|
||||||
const Pad = require('../db/Pad');
|
const Pad = require('../db/Pad');
|
||||||
const db = require('./DB');
|
const db = require('./DB');
|
||||||
const settings = require('../utils/Settings');
|
import settings from '../utils/Settings';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A cache of all loaded Pads.
|
* A cache of all loaded Pads.
|
||||||
|
|
|
@ -26,7 +26,7 @@ const hooks = require('../../static/js/pluginfw/hooks');
|
||||||
const padManager = require('./PadManager');
|
const padManager = require('./PadManager');
|
||||||
const readOnlyManager = require('./ReadOnlyManager');
|
const readOnlyManager = require('./ReadOnlyManager');
|
||||||
const sessionManager = require('./SessionManager');
|
const sessionManager = require('./SessionManager');
|
||||||
const settings = require('../utils/Settings');
|
import settings from '../utils/Settings';
|
||||||
const webaccess = require('../hooks/express/webaccess');
|
const webaccess = require('../hooks/express/webaccess');
|
||||||
const log4js = require('log4js');
|
const log4js = require('log4js');
|
||||||
const authLogger = log4js.getLogger('auth');
|
const authLogger = log4js.getLogger('auth');
|
||||||
|
|
|
@ -25,7 +25,7 @@ const fs = require('fs');
|
||||||
const hooks = require('../../static/js/pluginfw/hooks');
|
const hooks = require('../../static/js/pluginfw/hooks');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const resolve = require('resolve');
|
const resolve = require('resolve');
|
||||||
const settings = require('../utils/Settings');
|
import settings from '../utils/Settings';
|
||||||
import {pluginInstallPath} from '../../static/js/pluginfw/installer'
|
import {pluginInstallPath} from '../../static/js/pluginfw/installer'
|
||||||
|
|
||||||
const templateCache = new Map();
|
const templateCache = new Map();
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
const absolutePaths = require('../utils/AbsolutePaths');
|
const absolutePaths = require('../utils/AbsolutePaths');
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import log4js from 'log4js';
|
import log4js from 'log4js';
|
||||||
const randomString = require('../utils/randomstring');
|
import randomString from '../utils/randomstring';
|
||||||
const argv = require('../utils/Cli').argv;
|
import {argvP} from '../utils/Cli'
|
||||||
const settings = require('../utils/Settings');
|
import settings from '../utils/Settings';
|
||||||
|
|
||||||
const apiHandlerLogger = log4js.getLogger('APIHandler');
|
const apiHandlerLogger = log4js.getLogger('APIHandler');
|
||||||
|
|
||||||
// ensure we have an apikey
|
// ensure we have an apikey
|
||||||
export let apikey:string|null = null;
|
export let apikey:string|null = null;
|
||||||
const apikeyFilename = absolutePaths.makeAbsolute(argv.apikey || './APIKEY.txt');
|
const apikeyFilename = absolutePaths.makeAbsolute(argvP.apikey || './APIKEY.txt');
|
||||||
|
|
||||||
|
|
||||||
if(settings.authenticationMethod === 'apikey') {
|
if(settings.authenticationMethod === 'apikey') {
|
||||||
|
|
|
@ -25,7 +25,7 @@ const padManager = require('../db/PadManager');
|
||||||
const padMessageHandler = require('./PadMessageHandler');
|
const padMessageHandler = require('./PadMessageHandler');
|
||||||
import {promises as fs} from 'fs';
|
import {promises as fs} from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
const settings = require('../utils/Settings');
|
import settings from '../utils/Settings';
|
||||||
const {Formidable} = require('formidable');
|
const {Formidable} = require('formidable');
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
const importHtml = require('../utils/ImportHtml');
|
const importHtml = require('../utils/ImportHtml');
|
||||||
|
|
|
@ -30,7 +30,7 @@ const AttributeManager = require('../../static/js/AttributeManager');
|
||||||
const authorManager = require('../db/AuthorManager');
|
const authorManager = require('../db/AuthorManager');
|
||||||
import padutils from '../../static/js/pad_utils';
|
import padutils from '../../static/js/pad_utils';
|
||||||
const readOnlyManager = require('../db/ReadOnlyManager');
|
const readOnlyManager = require('../db/ReadOnlyManager');
|
||||||
const settings = require('../utils/Settings');
|
import settings from '../utils/Settings';
|
||||||
const securityManager = require('../db/SecurityManager');
|
const securityManager = require('../db/SecurityManager');
|
||||||
const plugins = require('../../static/js/pluginfw/plugin_defs');
|
const plugins = require('../../static/js/pluginfw/plugin_defs');
|
||||||
import log4js from 'log4js';
|
import log4js from 'log4js';
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
import {MapArrayType} from "../types/MapType";
|
import {MapArrayType} from "../types/MapType";
|
||||||
import {SocketModule} from "../types/SocketModule";
|
import {SocketModule} from "../types/SocketModule";
|
||||||
const log4js = require('log4js');
|
const log4js = require('log4js');
|
||||||
const settings = require('../utils/Settings');
|
import settings from '../utils/Settings';
|
||||||
const stats = require('../../node/stats')
|
const stats = require('../../node/stats')
|
||||||
|
|
||||||
const logger = log4js.getLogger('socket.io');
|
const logger = log4js.getLogger('socket.io');
|
||||||
|
|
|
@ -14,7 +14,7 @@ import fs from 'fs';
|
||||||
const hooks = require('../../static/js/pluginfw/hooks');
|
const hooks = require('../../static/js/pluginfw/hooks');
|
||||||
import log4js from 'log4js';
|
import log4js from 'log4js';
|
||||||
const SessionStore = require('../db/SessionStore');
|
const SessionStore = require('../db/SessionStore');
|
||||||
const settings = require('../utils/Settings');
|
import settings from '../utils/Settings';
|
||||||
const stats = require('../stats')
|
const stats = require('../stats')
|
||||||
import util from 'util';
|
import util from 'util';
|
||||||
const webaccess = require('./express/webaccess');
|
const webaccess = require('./express/webaccess');
|
||||||
|
@ -190,6 +190,7 @@ exports.restartServer = async () => {
|
||||||
secretRotator = new SecretRotator(
|
secretRotator = new SecretRotator(
|
||||||
'expressSessionSecrets', keyRotationInterval, sessionLifetime, settings.sessionKey);
|
'expressSessionSecrets', keyRotationInterval, sessionLifetime, settings.sessionKey);
|
||||||
await secretRotator.start();
|
await secretRotator.start();
|
||||||
|
// @ts-ignore
|
||||||
secret = secretRotator.secrets;
|
secret = secretRotator.secrets;
|
||||||
}
|
}
|
||||||
if (!secret) throw new Error('missing cookie signing secret');
|
if (!secret) throw new Error('missing cookie signing secret');
|
||||||
|
|
|
@ -5,7 +5,7 @@ import fs from "fs";
|
||||||
import * as url from "node:url";
|
import * as url from "node:url";
|
||||||
import {MapArrayType} from "../../types/MapType";
|
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 ADMIN_PATH = path.join(settings.root, 'src', 'templates');
|
||||||
const PROXY_HEADER = "x-proxy-path"
|
const PROXY_HEADER = "x-proxy-path"
|
||||||
|
|
|
@ -9,7 +9,7 @@ const eejs = require('../../eejs');
|
||||||
const fsp = require('fs').promises;
|
const fsp = require('fs').promises;
|
||||||
const hooks = require('../../../static/js/pluginfw/hooks');
|
const hooks = require('../../../static/js/pluginfw/hooks');
|
||||||
const plugins = require('../../../static/js/pluginfw/plugins');
|
const plugins = require('../../../static/js/pluginfw/plugins');
|
||||||
const settings = require('../../utils/Settings');
|
import settings from '../../utils/Settings';
|
||||||
const UpdateCheck = require('../../utils/UpdateCheck');
|
const UpdateCheck = require('../../utils/UpdateCheck');
|
||||||
const padManager = require('../../db/PadManager');
|
const padManager = require('../../db/PadManager');
|
||||||
const api = require('../../db/API');
|
const api = require('../../db/API');
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import {ArgsExpressType} from "../../types/ArgsExpressType";
|
import {ArgsExpressType} from "../../types/ArgsExpressType";
|
||||||
|
|
||||||
const hasPadAccess = require('../../padaccess');
|
const hasPadAccess = require('../../padaccess');
|
||||||
const settings = require('../../utils/Settings');
|
import settings from '../../utils/Settings';
|
||||||
const exportHandler = require('../../handler/ExportHandler');
|
const exportHandler = require('../../handler/ExportHandler');
|
||||||
const importHandler = require('../../handler/ImportHandler');
|
const importHandler = require('../../handler/ImportHandler');
|
||||||
const padManager = require('../../db/PadManager');
|
const padManager = require('../../db/PadManager');
|
||||||
|
|
|
@ -24,7 +24,7 @@ const cloneDeep = require('lodash.clonedeep');
|
||||||
const createHTTPError = require('http-errors');
|
const createHTTPError = require('http-errors');
|
||||||
|
|
||||||
const apiHandler = require('../../handler/APIHandler');
|
const apiHandler = require('../../handler/APIHandler');
|
||||||
const settings = require('../../utils/Settings');
|
import settings from '../../utils/Settings';
|
||||||
|
|
||||||
const log4js = require('log4js');
|
const log4js = require('log4js');
|
||||||
const logger = log4js.getLogger('API');
|
const logger = log4js.getLogger('API');
|
||||||
|
|
|
@ -6,7 +6,7 @@ import events from 'events';
|
||||||
const express = require('../express');
|
const express = require('../express');
|
||||||
import log4js from 'log4js';
|
import log4js from 'log4js';
|
||||||
const proxyaddr = require('proxy-addr');
|
const proxyaddr = require('proxy-addr');
|
||||||
const settings = require('../../utils/Settings');
|
import settings from '../../utils/Settings';
|
||||||
import {Server, Socket} from 'socket.io'
|
import {Server, Socket} from 'socket.io'
|
||||||
const socketIORouter = require('../../handler/SocketIORouter');
|
const socketIORouter = require('../../handler/SocketIORouter');
|
||||||
const hooks = require('../../../static/js/pluginfw/hooks');
|
const hooks = require('../../../static/js/pluginfw/hooks');
|
||||||
|
|
|
@ -6,7 +6,7 @@ import fs from 'node:fs';
|
||||||
const fsp = fs.promises;
|
const fsp = fs.promises;
|
||||||
const toolbar = require('../../utils/toolbar');
|
const toolbar = require('../../utils/toolbar');
|
||||||
const hooks = require('../../../static/js/pluginfw/hooks');
|
const hooks = require('../../../static/js/pluginfw/hooks');
|
||||||
const settings = require('../../utils/Settings');
|
import settings from '../../utils/Settings';
|
||||||
import util from 'node:util';
|
import util from 'node:util';
|
||||||
const webaccess = require('./webaccess');
|
const webaccess = require('./webaccess');
|
||||||
const plugins = require('../../../static/js/pluginfw/plugin_defs');
|
const plugins = require('../../../static/js/pluginfw/plugin_defs');
|
||||||
|
@ -40,7 +40,7 @@ exports.expressPreSession = async (hookName:string, {app}:any) => {
|
||||||
|
|
||||||
app.get('/robots.txt', (req:any, res:any) => {
|
app.get('/robots.txt', (req:any, res:any) => {
|
||||||
let filePath =
|
let filePath =
|
||||||
path.join(settings.root, 'src', 'static', 'skins', settings.skinName, 'robots.txt');
|
path.join(settings.root, 'src', 'static', 'skins', settings.skinName!, 'robots.txt');
|
||||||
res.sendFile(filePath, (err:any) => {
|
res.sendFile(filePath, (err:any) => {
|
||||||
// there is no custom robots.txt, send the default robots.txt which dissallows all
|
// there is no custom robots.txt, send the default robots.txt which dissallows all
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -64,7 +64,7 @@ exports.expressPreSession = async (hookName:string, {app}:any) => {
|
||||||
|
|
||||||
const fns = [
|
const fns = [
|
||||||
...(settings.favicon ? [path.resolve(settings.root, settings.favicon)] : []),
|
...(settings.favicon ? [path.resolve(settings.root, settings.favicon)] : []),
|
||||||
path.join(settings.root, 'src', 'static', 'skins', settings.skinName, 'favicon.ico'),
|
path.join(settings.root, 'src', 'static', 'skins', settings.skinName!, 'favicon.ico'),
|
||||||
path.join(settings.root, 'src', 'static', 'favicon.ico'),
|
path.join(settings.root, 'src', 'static', 'favicon.ico'),
|
||||||
];
|
];
|
||||||
for (const fn of fns) {
|
for (const fn of fns) {
|
||||||
|
@ -174,6 +174,7 @@ const handleLiveReload = async (args: any, padString: string, timeSliderString:
|
||||||
req,
|
req,
|
||||||
toolbar,
|
toolbar,
|
||||||
isReadOnly,
|
isReadOnly,
|
||||||
|
settings: settings,
|
||||||
entrypoint: '/watch/pad?hash=' + hash
|
entrypoint: '/watch/pad?hash=' + hash
|
||||||
})
|
})
|
||||||
res.send(content);
|
res.send(content);
|
||||||
|
@ -203,6 +204,7 @@ const handleLiveReload = async (args: any, padString: string, timeSliderString:
|
||||||
req,
|
req,
|
||||||
toolbar,
|
toolbar,
|
||||||
isReadOnly,
|
isReadOnly,
|
||||||
|
settings: settings,
|
||||||
entrypoint: '/watch/timeslider?hash=' + hash
|
entrypoint: '/watch/timeslider?hash=' + hash
|
||||||
})
|
})
|
||||||
res.send(content);
|
res.send(content);
|
||||||
|
|
|
@ -7,7 +7,7 @@ const fs = require('fs').promises;
|
||||||
import {minify} from '../../utils/Minify';
|
import {minify} from '../../utils/Minify';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
const plugins = require('../../../static/js/pluginfw/plugin_defs');
|
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.
|
// Rewrite tar to include modules with no extensions and proper rooted paths.
|
||||||
const getTar = async () => {
|
const getTar = async () => {
|
||||||
|
|
|
@ -7,7 +7,7 @@ const path = require('path');
|
||||||
const fsp = require('fs').promises;
|
const fsp = require('fs').promises;
|
||||||
const plugins = require('../../../static/js/pluginfw/plugin_defs');
|
const plugins = require('../../../static/js/pluginfw/plugin_defs');
|
||||||
const sanitizePathname = require('../../utils/sanitizePathname');
|
const sanitizePathname = require('../../utils/sanitizePathname');
|
||||||
const settings = require('../../utils/Settings');
|
import settings from '../../utils/Settings';
|
||||||
|
|
||||||
// Returns all *.js files under specDir (recursively) as relative paths to specDir, using '/'
|
// Returns all *.js files under specDir (recursively) as relative paths to specDir, using '/'
|
||||||
// instead of path.sep to separate pathname components.
|
// instead of path.sep to separate pathname components.
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {SocketClientRequest} from "../../types/SocketClientRequest";
|
||||||
import {WebAccessTypes} from "../../types/WebAccessTypes";
|
import {WebAccessTypes} from "../../types/WebAccessTypes";
|
||||||
import {SettingsUser} from "../../types/SettingsUser";
|
import {SettingsUser} from "../../types/SettingsUser";
|
||||||
const httpLogger = log4js.getLogger('http');
|
const httpLogger = log4js.getLogger('http');
|
||||||
const settings = require('../../utils/Settings');
|
import settings from '../../utils/Settings';
|
||||||
const hooks = require('../../../static/js/pluginfw/hooks');
|
const hooks = require('../../../static/js/pluginfw/hooks');
|
||||||
const readOnlyManager = require('../../db/ReadOnlyManager');
|
const readOnlyManager = require('../../db/ReadOnlyManager');
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ const path = require('path');
|
||||||
const _ = require('underscore');
|
const _ = require('underscore');
|
||||||
const pluginDefs = require('../../static/js/pluginfw/plugin_defs');
|
const pluginDefs = require('../../static/js/pluginfw/plugin_defs');
|
||||||
const existsSync = require('../utils/path_exists');
|
const existsSync = require('../utils/path_exists');
|
||||||
const settings = require('../utils/Settings');
|
import settings from '../utils/Settings';
|
||||||
|
|
||||||
// returns all existing messages merged together and grouped by langcode
|
// returns all existing messages merged together and grouped by langcode
|
||||||
// {es: {"foo": "string"}, en:...}
|
// {es: {"foo": "string"}, en:...}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import Provider, {Account, Configuration} from 'oidc-provider';
|
||||||
import {generateKeyPair, exportJWK, KeyLike} from 'jose'
|
import {generateKeyPair, exportJWK, KeyLike} from 'jose'
|
||||||
import MemoryAdapter from "./OIDCAdapter";
|
import MemoryAdapter from "./OIDCAdapter";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
const settings = require('../utils/Settings');
|
import settings from '../utils/Settings';
|
||||||
import {IncomingForm} from 'formidable'
|
import {IncomingForm} from 'formidable'
|
||||||
import express, {Request, Response} from 'express';
|
import express, {Request, Response} from 'express';
|
||||||
import {format} from 'url'
|
import {format} from 'url'
|
||||||
|
@ -137,7 +137,7 @@ export const expressCreateServer = async (hookName: string, args: ArgsExpressTyp
|
||||||
} else if (token.kind === "ClientCredentials") {
|
} else if (token.kind === "ClientCredentials") {
|
||||||
let extraParams: MapArrayType<string> = {}
|
let extraParams: MapArrayType<string> = {}
|
||||||
|
|
||||||
settings.sso.clients
|
settings.sso.clients!
|
||||||
.filter((client:any) => client.client_id === token.clientId)
|
.filter((client:any) => client.client_id === token.clientId)
|
||||||
.forEach((client:any) => {
|
.forEach((client:any) => {
|
||||||
if(client.extraParams !== undefined) {
|
if(client.extraParams !== undefined) {
|
||||||
|
|
|
@ -29,7 +29,7 @@ import pkg from '../package.json';
|
||||||
import {checkForMigration} from "../static/js/pluginfw/installer";
|
import {checkForMigration} from "../static/js/pluginfw/installer";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
|
||||||
const settings = require('./utils/Settings');
|
import settings from './utils/Settings';
|
||||||
|
|
||||||
let wtfnode: any;
|
let wtfnode: any;
|
||||||
if (settings.dumpOnUncleanExit) {
|
if (settings.dumpOnUncleanExit) {
|
||||||
|
|
|
@ -24,7 +24,7 @@ import {AsyncQueueTask} from "../types/AsyncQueueTask";
|
||||||
|
|
||||||
const spawn = require('child_process').spawn;
|
const spawn = require('child_process').spawn;
|
||||||
const async = require('async');
|
const async = require('async');
|
||||||
const settings = require('./Settings');
|
import settings from './Settings';
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
|
|
||||||
// on windows we have to spawn a process for each convertion,
|
// on windows we have to spawn a process for each convertion,
|
||||||
|
|
|
@ -18,9 +18,9 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
const log4js = require('log4js');
|
import log4js from 'log4js';
|
||||||
const path = require('path');
|
import path from 'path';
|
||||||
const _ = require('underscore');
|
import _ from 'underscore';
|
||||||
|
|
||||||
const absPathLogger = log4js.getLogger('AbsolutePaths');
|
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
|
* @return {string} The identified absolute base path. If such path cannot be
|
||||||
* identified, prints a log and exits the application.
|
* identified, prints a log and exits the application.
|
||||||
*/
|
*/
|
||||||
exports.findEtherpadRoot = () => {
|
export const findEtherpadRoot = () => {
|
||||||
if (etherpadRoot != null) {
|
if (etherpadRoot != null) {
|
||||||
return etherpadRoot;
|
return etherpadRoot;
|
||||||
}
|
}
|
||||||
|
@ -130,12 +130,12 @@ exports.findEtherpadRoot = () => {
|
||||||
* it is returned unchanged. Otherwise it is interpreted
|
* it is returned unchanged. Otherwise it is interpreted
|
||||||
* relative to exports.root.
|
* relative to exports.root.
|
||||||
*/
|
*/
|
||||||
exports.makeAbsolute = (somePath: string) => {
|
export const makeAbsolute = (somePath: string) => {
|
||||||
if (path.isAbsolute(somePath)) {
|
if (path.isAbsolute(somePath)) {
|
||||||
return 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}"`);
|
absPathLogger.debug(`Relative path "${somePath}" can be rewritten to "${rewrittenPath}"`);
|
||||||
return rewrittenPath;
|
return rewrittenPath;
|
||||||
|
@ -149,7 +149,7 @@ exports.makeAbsolute = (somePath: string) => {
|
||||||
* a subdirectory of the base one
|
* a subdirectory of the base one
|
||||||
* @return {boolean}
|
* @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
|
// 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);
|
const relative = path.relative(parent, arbitraryDir);
|
||||||
return !!relative && !relative.startsWith('..') && !path.isAbsolute(relative);
|
return !!relative && !relative.startsWith('..') && !path.isAbsolute(relative);
|
||||||
|
|
|
@ -21,7 +21,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// An object containing the parsed command-line options
|
// An object containing the parsed command-line options
|
||||||
exports.argv = {};
|
import {MapArrayType} from "../types/MapType";
|
||||||
|
|
||||||
|
export const argvP: MapArrayType<any> = {};
|
||||||
|
|
||||||
const argv = process.argv.slice(2);
|
const argv = process.argv.slice(2);
|
||||||
let arg, prevArg;
|
let arg, prevArg;
|
||||||
|
@ -32,22 +34,22 @@ for (let i = 0; i < argv.length; i++) {
|
||||||
|
|
||||||
// Override location of settings.json file
|
// Override location of settings.json file
|
||||||
if (prevArg === '--settings' || prevArg === '-s') {
|
if (prevArg === '--settings' || prevArg === '-s') {
|
||||||
exports.argv.settings = arg;
|
argvP.settings = arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Override location of credentials.json file
|
// Override location of credentials.json file
|
||||||
if (prevArg === '--credentials') {
|
if (prevArg === '--credentials') {
|
||||||
exports.argv.credentials = arg;
|
argvP.credentials = arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Override location of settings.json file
|
// Override location of settings.json file
|
||||||
if (prevArg === '--sessionkey') {
|
if (prevArg === '--sessionkey') {
|
||||||
exports.argv.sessionkey = arg;
|
argvP.sessionkey = arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Override location of APIKEY.txt file
|
// Override location of APIKEY.txt file
|
||||||
if (prevArg === '--apikey') {
|
if (prevArg === '--apikey') {
|
||||||
exports.argv.apikey = arg;
|
argvP.apikey = arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
prevArg = arg;
|
prevArg = arg;
|
||||||
|
|
|
@ -23,7 +23,7 @@ const log4js = require('log4js');
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const runCmd = require('./run_cmd');
|
const runCmd = require('./run_cmd');
|
||||||
const settings = require('./Settings');
|
import settings from './Settings';
|
||||||
|
|
||||||
const logger = log4js.getLogger('LibreOffice');
|
const logger = log4js.getLogger('LibreOffice');
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ import mime from 'mime-types';
|
||||||
import log4js from 'log4js';
|
import log4js from 'log4js';
|
||||||
import {compressCSS, compressJS} from './MinifyWorker'
|
import {compressCSS, compressJS} from './MinifyWorker'
|
||||||
|
|
||||||
const settings = require('./Settings');
|
import settings from './Settings';
|
||||||
import {promises as fs} from 'fs';
|
import {promises as fs} from 'fs';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
const plugins = require('../../static/js/pluginfw/plugin_defs');
|
const plugins = require('../../static/js/pluginfw/plugin_defs');
|
||||||
|
|
|
@ -28,124 +28,111 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {MapArrayType} from "../types/MapType";
|
import {MapArrayType} from "../types/MapType";
|
||||||
import {SettingsNode, SettingsTree} from "./SettingsTree";
|
import {SettingsNode} from "./SettingsTree";
|
||||||
import {coerce} from "semver";
|
import {version} from '../../package.json'
|
||||||
|
import {findEtherpadRoot, isSubdir, makeAbsolute} from './AbsolutePaths';
|
||||||
|
import fs from 'fs';
|
||||||
|
import os from 'os';
|
||||||
|
import path from 'path';
|
||||||
|
import {argvP} from "./Cli";
|
||||||
|
import jsonminify from 'jsonminify';
|
||||||
|
import log4js from 'log4js';
|
||||||
|
import randomString from './randomstring';
|
||||||
|
|
||||||
const absolutePaths = require('./AbsolutePaths');
|
import _ from 'underscore';
|
||||||
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');
|
|
||||||
|
|
||||||
// Exported values that settings.json and credentials.json cannot override.
|
|
||||||
const nonSettings = [
|
|
||||||
'credentialsFilename',
|
|
||||||
'settingsFilename',
|
|
||||||
];
|
|
||||||
|
|
||||||
// This is a function to make it easy to create a new instance. It is important to not reuse a
|
class Settings {
|
||||||
// config object after passing it to log4js.configure() because that method mutates the object. :(
|
|
||||||
const defaultLogConfig = (level: string, layoutType: string) => ({
|
|
||||||
appenders: {console: {type: 'console', layout: {type: layoutType}}},
|
|
||||||
categories: {
|
|
||||||
default: {appenders: ['console'], level},
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const defaultLogLevel = 'INFO';
|
|
||||||
const defaultLogLayoutType = 'colored';
|
|
||||||
|
|
||||||
const initLogging = (config: any) => {
|
|
||||||
// log4js.configure() modifies exports.logconfig so check for equality first.
|
|
||||||
log4js.configure(config);
|
|
||||||
log4js.getLogger('console');
|
|
||||||
|
|
||||||
// Overwrites for console output methods
|
|
||||||
console.debug = logger.debug.bind(logger);
|
|
||||||
console.log = logger.info.bind(logger);
|
|
||||||
console.warn = logger.warn.bind(logger);
|
|
||||||
console.error = logger.error.bind(logger);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
constructor() {
|
||||||
// Initialize logging as early as possible with reasonable defaults. Logging will be re-initialized
|
// 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.
|
// with the user's chosen log level and logger config after the settings have been loaded.
|
||||||
initLogging(defaultLogConfig(defaultLogLevel, defaultLogLayoutType));
|
this.initLogging(this.defaultLogConfig(this.defaultLogLevel));
|
||||||
|
this.logger.info('All relative paths will be interpreted relative to the identified ' +
|
||||||
/* Root path of the installation */
|
`Etherpad base dir: ${this.root}`);
|
||||||
exports.root = absolutePaths.findEtherpadRoot();
|
// initially load settings
|
||||||
logger.info('All relative paths will be interpreted relative to the identified ' +
|
this.reloadSettings();
|
||||||
`Etherpad base dir: ${exports.root}`);
|
}
|
||||||
exports.settingsFilename = absolutePaths.makeAbsolute(argv.settings || 'settings.json');
|
|
||||||
exports.credentialsFilename = absolutePaths.makeAbsolute(argv.credentials || 'credentials.json');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The app title, visible e.g. in the browser window
|
* The app title, visible e.g. in the browser window
|
||||||
*/
|
*/
|
||||||
exports.title = 'Etherpad';
|
title = 'Etherpad';
|
||||||
|
settingsFilename = makeAbsolute(argvP.settings || 'settings.json');
|
||||||
|
credentialsFilename = makeAbsolute(argvP.credentials || 'credentials.json');
|
||||||
|
|
||||||
|
suppressDisableMsg = ' -- To suppress these warning messages change ' +
|
||||||
|
'suppressErrorsInPadText to true in your settings.json\n';
|
||||||
|
defaultLogLevel = 'INFO';
|
||||||
|
private logger = log4js.getLogger('settings');
|
||||||
|
/* Root path of the installation */
|
||||||
|
root = findEtherpadRoot();
|
||||||
/**
|
/**
|
||||||
* Pathname of the favicon you want to use. If null, the skin's favicon is
|
* Pathname of the favicon you want to use. If null, the skin's favicon is
|
||||||
* used if one is provided by the skin, otherwise the default Etherpad favicon
|
* used if one is provided by the skin, otherwise the default Etherpad favicon
|
||||||
* is used. If this is a relative path it is interpreted as relative to the
|
* is used. If this is a relative path it is interpreted as relative to the
|
||||||
* Etherpad root directory.
|
* Etherpad root directory.
|
||||||
*/
|
*/
|
||||||
exports.favicon = null;
|
favicon: string|null = null;
|
||||||
|
// Exported values that settings.json and credentials.json cannot override.
|
||||||
exports.ttl = {
|
nonSettings = [
|
||||||
AccessToken: 1 * 60 * 60, // 1 hour in seconds
|
'credentialsFilename',
|
||||||
AuthorizationCode: 10 * 60, // 10 minutes in seconds
|
'settingsFilename',
|
||||||
ClientCredentials: 1 * 60 * 60, // 1 hour in seconds
|
]
|
||||||
IdToken: 1 * 60 * 60, // 1 hour in seconds
|
|
||||||
RefreshToken: 1 * 24 * 60 * 60, // 1 day in seconds
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Skin name.
|
* Skin name.
|
||||||
*
|
*
|
||||||
* Initialized to null, so we can spot an old configuration file and invite the
|
* Initialized to null, so we can spot an old configuration file and invite the
|
||||||
* user to update it before falling back to the default.
|
* user to update it before falling back to the default.
|
||||||
*/
|
*/
|
||||||
exports.skinName = null;
|
skinName: string | null = null;
|
||||||
|
skinVariants = 'super-light-toolbar super-light-editor light-background';
|
||||||
exports.skinVariants = 'super-light-toolbar super-light-editor light-background';
|
ttl = {
|
||||||
|
AccessToken: 1 * 60 * 60, // 1 hour in seconds
|
||||||
|
AuthorizationCode: 10 * 60, // 10 minutes in seconds
|
||||||
|
ClientCredentials: 1 * 60 * 60, // 1 hour in seconds
|
||||||
|
IdToken: 1 * 60 * 60, // 1 hour in seconds
|
||||||
|
RefreshToken: 1 * 24 * 60 * 60, // 1 day in seconds
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* The IP ep-lite should listen to
|
* Should we suppress Error messages from being in Pad Contents
|
||||||
*/
|
*/
|
||||||
exports.ip = '0.0.0.0';
|
suppressErrorsInPadText = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Port ep-lite should listen to
|
* The Port ep-lite should listen to
|
||||||
*/
|
*/
|
||||||
exports.port = process.env.PORT || 9001;
|
port = process.env.PORT as unknown as number || 9001;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should we suppress Error messages from being in Pad Contents
|
* The IP ep-lite should listen to
|
||||||
*/
|
*/
|
||||||
exports.suppressErrorsInPadText = false;
|
ip: string = '0.0.0.0';
|
||||||
|
|
||||||
|
// 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. :(
|
||||||
|
private defaultLogConfig = (level: string) => ({
|
||||||
|
appenders: {console: {type: 'console'}},
|
||||||
|
categories: {
|
||||||
|
default: {appenders: ['console'], level},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SSL signed server key and the Certificate Authority's own certificate
|
* 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.
|
* default case: ep-lite does *not* use SSL. A signed server key is not required in this case.
|
||||||
*/
|
*/
|
||||||
exports.ssl = false;
|
ssl:{
|
||||||
|
key:string,
|
||||||
|
cert:string
|
||||||
|
ca?: string[]
|
||||||
|
}|false = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* socket.io transport methods
|
* socket.io transport methods
|
||||||
**/
|
**/
|
||||||
exports.socketTransportProtocols = ['websocket', 'polling'];
|
socketTransportProtocols: any[] = ['websocket', 'polling'];
|
||||||
|
socketIo = {
|
||||||
exports.socketIo = {
|
|
||||||
/**
|
/**
|
||||||
* Maximum permitted client message size (in bytes).
|
* Maximum permitted client message size (in bytes).
|
||||||
*
|
*
|
||||||
|
@ -157,28 +144,25 @@ exports.socketIo = {
|
||||||
maxHttpBufferSize: 50000,
|
maxHttpBufferSize: 50000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The authentication method used by the server.
|
The authentication method used by the server.
|
||||||
The default value is sso
|
The default value is sso
|
||||||
If you want to use the old authentication system, change this to apikey
|
If you want to use the old authentication system, change this to apikey
|
||||||
*/
|
*/
|
||||||
exports.authenticationMethod = 'sso'
|
authenticationMethod = 'sso'
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The Type of the database
|
* The Type of the database
|
||||||
*/
|
*/
|
||||||
exports.dbType = 'dirty';
|
dbType = 'dirty';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This setting is passed with dbType to ueberDB to set up the database
|
* This setting is passed with dbType to ueberDB to set up the database
|
||||||
*/
|
*/
|
||||||
exports.dbSettings = {filename: path.join(exports.root, 'var/dirty.db')};
|
dbSettings = {filename: path.join(this.root, 'var/dirty.db')};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default Text of a new pad
|
* The default Text of a new pad
|
||||||
*/
|
*/
|
||||||
exports.defaultPadText = [
|
defaultPadText = [
|
||||||
'Welcome to Etherpad!',
|
'Welcome to Etherpad!',
|
||||||
'',
|
'',
|
||||||
'This pad text is synchronized as you type, so that everyone viewing this page sees the same ' +
|
'This pad text is synchronized as you type, so that everyone viewing this page sees the same ' +
|
||||||
|
@ -187,10 +171,11 @@ exports.defaultPadText = [
|
||||||
'Etherpad on Github: https://github.com/ether/etherpad-lite',
|
'Etherpad on Github: https://github.com/ether/etherpad-lite',
|
||||||
].join('\n');
|
].join('\n');
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default Pad Settings for a user (Can be overridden by changing the setting
|
* The default Pad Settings for a user (Can be overridden by changing the setting
|
||||||
*/
|
*/
|
||||||
exports.padOptions = {
|
padOptions = {
|
||||||
noColors: false,
|
noColors: false,
|
||||||
showControls: true,
|
showControls: true,
|
||||||
showChat: true,
|
showChat: true,
|
||||||
|
@ -207,7 +192,7 @@ exports.padOptions = {
|
||||||
/**
|
/**
|
||||||
* Whether certain shortcut keys are enabled for a user in the pad
|
* Whether certain shortcut keys are enabled for a user in the pad
|
||||||
*/
|
*/
|
||||||
exports.padShortcutEnabled = {
|
padShortcutEnabled = {
|
||||||
altF9: true,
|
altF9: true,
|
||||||
altC: true,
|
altC: true,
|
||||||
delete: true,
|
delete: true,
|
||||||
|
@ -235,7 +220,7 @@ exports.padShortcutEnabled = {
|
||||||
/**
|
/**
|
||||||
* The toolbar buttons and order.
|
* The toolbar buttons and order.
|
||||||
*/
|
*/
|
||||||
exports.toolbar = {
|
public toolbar = {
|
||||||
left: [
|
left: [
|
||||||
['bold', 'italic', 'underline', 'strikethrough'],
|
['bold', 'italic', 'underline', 'strikethrough'],
|
||||||
['orderedlist', 'unorderedlist', 'indent', 'outdent'],
|
['orderedlist', 'unorderedlist', 'indent', 'outdent'],
|
||||||
|
@ -255,92 +240,89 @@ exports.toolbar = {
|
||||||
/**
|
/**
|
||||||
* A flag that requires any user to have a valid session (via the api) before accessing a pad
|
* A flag that requires any user to have a valid session (via the api) before accessing a pad
|
||||||
*/
|
*/
|
||||||
exports.requireSession = false;
|
requireSession = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A flag that prevents users from creating new pads
|
* A flag that prevents users from creating new pads
|
||||||
*/
|
*/
|
||||||
exports.editOnly = false;
|
editOnly = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Max age that responses will have (affects caching layer).
|
* Max age that responses will have (affects caching layer).
|
||||||
*/
|
*/
|
||||||
exports.maxAge = 1000 * 60 * 60 * 6; // 6 hours
|
maxAge = 1000 * 60 * 60 * 6; // 6 hours
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A flag that shows if minification is enabled or not
|
* A flag that shows if minification is enabled or not
|
||||||
*/
|
*/
|
||||||
exports.minify = true;
|
minify = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The path of the abiword executable
|
* The path of the abiword executable
|
||||||
*/
|
*/
|
||||||
exports.abiword = null;
|
abiword = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The path of the libreoffice executable
|
* The path of the libreoffice executable
|
||||||
*/
|
*/
|
||||||
exports.soffice = null;
|
soffice = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should we support none natively supported file types on import?
|
* Should we support none natively supported file types on import?
|
||||||
*/
|
*/
|
||||||
exports.allowUnknownFileEnds = true;
|
allowUnknownFileEnds = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The log level of log4js
|
* The log level of log4js
|
||||||
*/
|
*/
|
||||||
exports.loglevel = defaultLogLevel;
|
loglevel: any = this.defaultLogLevel;
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The log layout type of log4js
|
|
||||||
*/
|
|
||||||
exports.logLayoutType = defaultLogLayoutType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disable IP logging
|
* Disable IP logging
|
||||||
*/
|
*/
|
||||||
exports.disableIPlogging = false;
|
disableIPlogging = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of seconds to automatically reconnect pad
|
* Number of seconds to automatically reconnect pad
|
||||||
*/
|
*/
|
||||||
exports.automaticReconnectionTimeout = 0;
|
automaticReconnectionTimeout = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disable Load Testing
|
* Disable Load Testing
|
||||||
*/
|
*/
|
||||||
exports.loadTest = false;
|
loadTest = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disable dump of objects preventing a clean exit
|
* Disable dump of objects preventing a clean exit
|
||||||
*/
|
*/
|
||||||
exports.dumpOnUncleanExit = false;
|
dumpOnUncleanExit = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable indentation on new lines
|
* Enable indentation on new lines
|
||||||
*/
|
*/
|
||||||
exports.indentationOnNewLine = true;
|
indentationOnNewLine = true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* log4js appender configuration
|
* log4js appender configuration
|
||||||
*/
|
*/
|
||||||
exports.logconfig = null;
|
private logconfig: { categories: { default: { level: string, appenders: string[] } }, appenders: { console: { type: string } } } | null = null;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Deprecated cookie signing key.
|
* Deprecated cookie signing key.
|
||||||
*/
|
*/
|
||||||
exports.sessionKey = null;
|
sessionKey: string|null = null;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Trust Proxy, whether or not trust the x-forwarded-for header.
|
* Trust Proxy, whether or not trust the x-forwarded-for header.
|
||||||
*/
|
*/
|
||||||
exports.trustProxy = false;
|
trustProxy = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Settings controlling the session cookie issued by Etherpad.
|
* Settings controlling the session cookie issued by Etherpad.
|
||||||
*/
|
*/
|
||||||
exports.cookie = {
|
cookie = {
|
||||||
keyRotationInterval: 1 * 24 * 60 * 60 * 1000,
|
keyRotationInterval: 1 * 24 * 60 * 60 * 1000,
|
||||||
/*
|
/*
|
||||||
* Value of the SameSite cookie property. "Lax" is recommended unless
|
* Value of the SameSite cookie property. "Lax" is recommended unless
|
||||||
|
@ -363,27 +345,31 @@ exports.cookie = {
|
||||||
* authorization. Note: /admin always requires authentication, and
|
* authorization. Note: /admin always requires authentication, and
|
||||||
* either authorization by a module, or a user with is_admin set
|
* either authorization by a module, or a user with is_admin set
|
||||||
*/
|
*/
|
||||||
exports.requireAuthentication = false;
|
requireAuthentication = false;
|
||||||
exports.requireAuthorization = false;
|
requireAuthorization = false;
|
||||||
exports.users = {};
|
users = {};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This setting is used for configuring sso
|
* This setting is used for configuring sso
|
||||||
*/
|
*/
|
||||||
exports.sso = {
|
sso:{
|
||||||
|
issuer: string,
|
||||||
|
clients?: any[],
|
||||||
|
|
||||||
|
} = {
|
||||||
issuer: "http://localhost:9001"
|
issuer: "http://localhost:9001"
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Show settings in admin page, by default it is true
|
* Show settings in admin page, by default it is true
|
||||||
*/
|
*/
|
||||||
exports.showSettingsInAdminPage = true;
|
public showSettingsInAdminPage = true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* By default, when caret is moved out of viewport, it scrolls the minimum
|
* By default, when caret is moved out of viewport, it scrolls the minimum
|
||||||
* height needed to make this line visible.
|
* height needed to make this line visible.
|
||||||
*/
|
*/
|
||||||
exports.scrollWhenFocusLineIsOutOfViewport = {
|
scrollWhenFocusLineIsOutOfViewport = {
|
||||||
/*
|
/*
|
||||||
* Percentage of viewport height to be additionally scrolled.
|
* Percentage of viewport height to be additionally scrolled.
|
||||||
*/
|
*/
|
||||||
|
@ -416,12 +402,12 @@ exports.scrollWhenFocusLineIsOutOfViewport = {
|
||||||
*
|
*
|
||||||
* Do not enable on production machines.
|
* Do not enable on production machines.
|
||||||
*/
|
*/
|
||||||
exports.exposeVersion = false;
|
exposeVersion = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Override any strings found in locale directories
|
* Override any strings found in locale directories
|
||||||
*/
|
*/
|
||||||
exports.customLocaleStrings = {};
|
customLocaleStrings = {};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* From Etherpad 1.8.3 onwards, import and export of pads is always rate
|
* From Etherpad 1.8.3 onwards, import and export of pads is always rate
|
||||||
|
@ -432,7 +418,7 @@ exports.customLocaleStrings = {};
|
||||||
*
|
*
|
||||||
* See https://github.com/nfriedly/express-rate-limit for more options
|
* See https://github.com/nfriedly/express-rate-limit for more options
|
||||||
*/
|
*/
|
||||||
exports.importExportRateLimiting = {
|
importExportRateLimiting: { max: number, windowMs?: number } = {
|
||||||
// duration of the rate limit window (milliseconds)
|
// duration of the rate limit window (milliseconds)
|
||||||
windowMs: 90000,
|
windowMs: 90000,
|
||||||
|
|
||||||
|
@ -448,7 +434,7 @@ exports.importExportRateLimiting = {
|
||||||
*
|
*
|
||||||
* See https://github.com/animir/node-rate-limiter-flexible/wiki/Overall-example#websocket-single-connection-prevent-flooding for more options
|
* See https://github.com/animir/node-rate-limiter-flexible/wiki/Overall-example#websocket-single-connection-prevent-flooding for more options
|
||||||
*/
|
*/
|
||||||
exports.commitRateLimiting = {
|
commitRateLimiting = {
|
||||||
// duration of the rate limit window (seconds)
|
// duration of the rate limit window (seconds)
|
||||||
duration: 1,
|
duration: 1,
|
||||||
|
|
||||||
|
@ -462,39 +448,53 @@ exports.commitRateLimiting = {
|
||||||
*
|
*
|
||||||
* File size is specified in bytes. Default is 50 MB.
|
* File size is specified in bytes. Default is 50 MB.
|
||||||
*/
|
*/
|
||||||
exports.importMaxFileSize = 50 * 1024 * 1024;
|
importMaxFileSize = 50 * 1024 * 1024;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disable Admin UI tests
|
* Disable Admin UI tests
|
||||||
*/
|
*/
|
||||||
exports.enableAdminUITests = false;
|
enableAdminUITests = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enable auto conversion of pad Ids to lowercase.
|
* Enable auto conversion of pad Ids to lowercase.
|
||||||
* e.g. /p/EtHeRpAd to /p/etherpad
|
* e.g. /p/EtHeRpAd to /p/etherpad
|
||||||
*/
|
*/
|
||||||
exports.lowerCasePadIds = false;
|
lowerCasePadIds = false;
|
||||||
|
|
||||||
|
randomVersionString: string|null = null;
|
||||||
|
|
||||||
|
private initLogging = (config: any) => {
|
||||||
|
// log4js.configure() modifies logconfig so check for equality first.
|
||||||
|
log4js.configure(config);
|
||||||
|
log4js.getLogger('console');
|
||||||
|
|
||||||
|
// Overwrites for console output methods
|
||||||
|
console.debug = this.logger.debug.bind(this.logger);
|
||||||
|
console.log = this.logger.info.bind(this.logger);
|
||||||
|
console.warn = this.logger.warn.bind(this.logger);
|
||||||
|
console.error = this.logger.error.bind(this.logger);
|
||||||
|
}
|
||||||
|
|
||||||
// checks if abiword is avaiable
|
// checks if abiword is avaiable
|
||||||
exports.abiwordAvailable = () => {
|
abiwordAvailable = () => {
|
||||||
if (exports.abiword != null) {
|
if (this.abiword != null) {
|
||||||
return os.type().indexOf('Windows') !== -1 ? 'withoutPDF' : 'yes';
|
return os.type().indexOf('Windows') !== -1 ? 'withoutPDF' : 'yes';
|
||||||
} else {
|
} else {
|
||||||
return 'no';
|
return 'no';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.sofficeAvailable = () => {
|
sofficeAvailable = () => {
|
||||||
if (exports.soffice != null) {
|
if (this.soffice != null) {
|
||||||
return os.type().indexOf('Windows') !== -1 ? 'withoutPDF' : 'yes';
|
return os.type().indexOf('Windows') !== -1 ? 'withoutPDF' : 'yes';
|
||||||
} else {
|
} else {
|
||||||
return 'no';
|
return 'no';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.exportAvailable = () => {
|
exportAvailable = () => {
|
||||||
const abiword = exports.abiwordAvailable();
|
const abiword = this.abiwordAvailable();
|
||||||
const soffice = exports.sofficeAvailable();
|
const soffice = this.sofficeAvailable();
|
||||||
|
|
||||||
if (abiword === 'no' && soffice === 'no') {
|
if (abiword === 'no' && soffice === 'no') {
|
||||||
return 'no';
|
return 'no';
|
||||||
|
@ -507,13 +507,13 @@ exports.exportAvailable = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Provide git version if available
|
// Provide git version if available
|
||||||
exports.getGitCommit = () => {
|
getGitCommit = () => {
|
||||||
let version = '';
|
let version = '';
|
||||||
try {
|
try {
|
||||||
let rootPath = exports.root;
|
let rootPath = this.root;
|
||||||
if (fs.lstatSync(`${rootPath}/.git`).isFile()) {
|
if (fs.lstatSync(`${rootPath}/.git`).isFile()) {
|
||||||
rootPath = fs.readFileSync(`${rootPath}/.git`, 'utf8');
|
rootPath = fs.readFileSync(`${rootPath}/.git`, 'utf8');
|
||||||
rootPath = rootPath.split(' ').pop().trim();
|
rootPath = rootPath.split(' ').pop()!.trim();
|
||||||
} else {
|
} else {
|
||||||
rootPath += '/.git';
|
rootPath += '/.git';
|
||||||
}
|
}
|
||||||
|
@ -526,15 +526,13 @@ exports.getGitCommit = () => {
|
||||||
}
|
}
|
||||||
version = version.substring(0, 7);
|
version = version.substring(0, 7);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
logger.warn(`Can't get git version for server header\n${e.message}`);
|
this.logger.warn(`Can't get git version for server header\n${e.message}`);
|
||||||
}
|
}
|
||||||
return version;
|
return version;
|
||||||
};
|
}
|
||||||
|
|
||||||
// Return etherpad version from package.json
|
// Return etherpad version from package.json
|
||||||
exports.getEpVersion = () => require('../../package.json').version;
|
getEpVersion = () => version;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receives a settingsObj and, if the property name is a valid configuration
|
* Receives a settingsObj and, if the property name is a valid configuration
|
||||||
|
@ -543,32 +541,37 @@ exports.getEpVersion = () => require('../../package.json').version;
|
||||||
* This code refactors a previous version that copied & pasted the same code for
|
* This code refactors a previous version that copied & pasted the same code for
|
||||||
* both "settings.json" and "credentials.json".
|
* both "settings.json" and "credentials.json".
|
||||||
*/
|
*/
|
||||||
const storeSettings = (settingsObj: any) => {
|
private storeSettings = (settingsObj: any) => {
|
||||||
for (const i of Object.keys(settingsObj || {})) {
|
for (const i of Object.keys(settingsObj || {})) {
|
||||||
if (nonSettings.includes(i)) {
|
if (this.nonSettings.includes(i)) {
|
||||||
logger.warn(`Ignoring setting: '${i}'`);
|
this.logger.warn(`Ignoring setting: '${i}'`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// test if the setting starts with a lowercase character
|
// test if the setting starts with a lowercase character
|
||||||
if (i.charAt(0).search('[a-z]') !== 0) {
|
if (i.charAt(0).search('[a-z]') !== 0) {
|
||||||
logger.warn(`Settings should start with a lowercase character: '${i}'`);
|
this.logger.warn(`Settings should start with a lowercase character: '${i}'`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we know this setting, so we overwrite it
|
// we know this setting, so we overwrite it
|
||||||
// or it's a settings hash, specific to a plugin
|
// or it's a settings hash, specific to a plugin
|
||||||
if (exports[i] !== undefined || i.indexOf('ep_') === 0) {
|
// @ts-ignore
|
||||||
|
if (this[i] !== undefined || i.indexOf('ep_') === 0) {
|
||||||
if (_.isObject(settingsObj[i]) && !Array.isArray(settingsObj[i])) {
|
if (_.isObject(settingsObj[i]) && !Array.isArray(settingsObj[i])) {
|
||||||
exports[i] = _.defaults(settingsObj[i], exports[i]);
|
// @ts-ignore
|
||||||
|
this[i] = _.defaults(settingsObj[i], exports[i]);
|
||||||
} else {
|
} else {
|
||||||
exports[i] = settingsObj[i];
|
// @ts-ignore
|
||||||
|
this[i] = settingsObj[i];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// this setting is unknown, output a warning and throw it away
|
// this setting is unknown, output a warning and throw it away
|
||||||
logger.warn(`Unknown Setting: '${i}'. This setting doesn't exist or it was removed`);
|
this.logger.warn(`Unknown Setting: '${i}'. This setting doesn't exist or it was removed`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If stringValue is a numeric string, or its value is "true" or "false", coerce
|
* If stringValue is a numeric string, or its value is "true" or "false", coerce
|
||||||
|
@ -582,7 +585,7 @@ const storeSettings = (settingsObj: any) => {
|
||||||
* short syntax "${ABIWORD}", and not "${ABIWORD:null}": the latter would result
|
* short syntax "${ABIWORD}", and not "${ABIWORD:null}": the latter would result
|
||||||
* in the literal string "null", instead.
|
* in the literal string "null", instead.
|
||||||
*/
|
*/
|
||||||
const coerceValue = (stringValue: string) => {
|
private coerceValue = (stringValue: string) => {
|
||||||
// cooked from https://stackoverflow.com/questions/175739/built-in-way-in-javascript-to-check-if-a-string-is-a-valid-number
|
// cooked from https://stackoverflow.com/questions/175739/built-in-way-in-javascript-to-check-if-a-string-is-a-valid-number
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const isNumeric = !isNaN(stringValue) && !isNaN(parseFloat(stringValue) && isFinite(stringValue));
|
const isNumeric = !isNaN(stringValue) && !isNaN(parseFloat(stringValue) && isFinite(stringValue));
|
||||||
|
@ -643,7 +646,7 @@ const coerceValue = (stringValue: string) => {
|
||||||
*
|
*
|
||||||
* see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_replacer_parameter
|
* see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_replacer_parameter
|
||||||
*/
|
*/
|
||||||
const lookupEnvironmentVariables = (obj: MapArrayType<any>) => {
|
private lookupEnvironmentVariables = (obj: MapArrayType<any>) => {
|
||||||
const replaceEnvs = (obj: MapArrayType<any>) => {
|
const replaceEnvs = (obj: MapArrayType<any>) => {
|
||||||
for (let [key, value] of Object.entries(obj)) {
|
for (let [key, value] of Object.entries(obj)) {
|
||||||
/*
|
/*
|
||||||
|
@ -702,7 +705,7 @@ const lookupEnvironmentVariables = (obj: MapArrayType<any>) => {
|
||||||
const defaultValue = match[3];
|
const defaultValue = match[3];
|
||||||
|
|
||||||
if ((envVarValue === undefined) && (defaultValue === undefined)) {
|
if ((envVarValue === undefined) && (defaultValue === undefined)) {
|
||||||
logger.warn(`Environment variable "${envVarName}" does not contain any value for ` +
|
this.logger.warn(`Environment variable "${envVarName}" does not contain any value for ` +
|
||||||
`configuration key "${key}", and no default was given. Using null. ` +
|
`configuration key "${key}", and no default was given. Using null. ` +
|
||||||
'THIS BEHAVIOR MAY CHANGE IN A FUTURE VERSION OF ETHERPAD; you should ' +
|
'THIS BEHAVIOR MAY CHANGE IN A FUTURE VERSION OF ETHERPAD; you should ' +
|
||||||
'explicitly use "null" as the default if you want to continue to use null.');
|
'explicitly use "null" as the default if you want to continue to use null.');
|
||||||
|
@ -716,10 +719,10 @@ const lookupEnvironmentVariables = (obj: MapArrayType<any>) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((envVarValue === undefined) && (defaultValue !== undefined)) {
|
if ((envVarValue === undefined) && (defaultValue !== undefined)) {
|
||||||
logger.debug(`Environment variable "${envVarName}" not found for ` +
|
this.logger.debug(`Environment variable "${envVarName}" not found for ` +
|
||||||
`configuration key "${key}". Falling back to default value.`);
|
`configuration key "${key}". Falling back to default value.`);
|
||||||
|
|
||||||
obj[key] = coerceValue(defaultValue);
|
obj[key] = this.coerceValue(defaultValue);
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -729,10 +732,10 @@ const lookupEnvironmentVariables = (obj: MapArrayType<any>) => {
|
||||||
* For numeric and boolean strings let's convert it to proper types before
|
* For numeric and boolean strings let's convert it to proper types before
|
||||||
* returning it, in order to maintain backward compatibility.
|
* returning it, in order to maintain backward compatibility.
|
||||||
*/
|
*/
|
||||||
logger.debug(
|
this.logger.debug(
|
||||||
`Configuration key "${key}" will be read from environment variable "${envVarName}"`);
|
`Configuration key "${key}" will be read from environment variable "${envVarName}"`);
|
||||||
|
|
||||||
obj[key] = coerceValue(envVarValue!);
|
obj[key] = this.coerceValue(envVarValue!);
|
||||||
}
|
}
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
|
@ -764,7 +767,8 @@ const lookupEnvironmentVariables = (obj: MapArrayType<any>) => {
|
||||||
const rooting = root.collectFromLeafsUpwards()
|
const rooting = root.collectFromLeafsUpwards()
|
||||||
obj = Object.assign(obj, rooting)
|
obj = Object.assign(obj, rooting)
|
||||||
return obj;
|
return obj;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -775,7 +779,7 @@ const lookupEnvironmentVariables = (obj: MapArrayType<any>) => {
|
||||||
*
|
*
|
||||||
* The isSettings variable only controls the error logging.
|
* The isSettings variable only controls the error logging.
|
||||||
*/
|
*/
|
||||||
const parseSettings = (settingsFilename: string, isSettings: boolean) => {
|
private parseSettings = (settingsFilename: string, isSettings: boolean) => {
|
||||||
let settingsStr = '';
|
let settingsStr = '';
|
||||||
|
|
||||||
let settingsType, notFoundMessage, notFoundFunction;
|
let settingsType, notFoundMessage, notFoundFunction;
|
||||||
|
@ -783,11 +787,11 @@ const parseSettings = (settingsFilename: string, isSettings: boolean) => {
|
||||||
if (isSettings) {
|
if (isSettings) {
|
||||||
settingsType = 'settings';
|
settingsType = 'settings';
|
||||||
notFoundMessage = 'Continuing using defaults!';
|
notFoundMessage = 'Continuing using defaults!';
|
||||||
notFoundFunction = logger.warn.bind(logger);
|
notFoundFunction = this.logger.warn.bind(this.logger);
|
||||||
} else {
|
} else {
|
||||||
settingsType = 'credentials';
|
settingsType = 'credentials';
|
||||||
notFoundMessage = 'Ignoring.';
|
notFoundMessage = 'Ignoring.';
|
||||||
notFoundFunction = logger.info.bind(logger);
|
notFoundFunction = this.logger.info.bind(this.logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -805,145 +809,137 @@ const parseSettings = (settingsFilename: string, isSettings: boolean) => {
|
||||||
|
|
||||||
const settings = JSON.parse(settingsStr);
|
const settings = JSON.parse(settingsStr);
|
||||||
|
|
||||||
logger.info(`${settingsType} loaded from: ${settingsFilename}`);
|
this.logger.info(`${settingsType} loaded from: ${settingsFilename}`);
|
||||||
|
|
||||||
return lookupEnvironmentVariables(settings);
|
return this.lookupEnvironmentVariables(settings);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
logger.error(`There was an error processing your ${settingsType} ` +
|
this.logger.error(`There was an error processing your ${settingsType} ` +
|
||||||
`file from ${settingsFilename}: ${e.message}`);
|
`file from ${settingsFilename}: ${e.message}`);
|
||||||
|
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
exports.reloadSettings = () => {
|
|
||||||
const settings = parseSettings(exports.settingsFilename, true);
|
|
||||||
const credentials = parseSettings(exports.credentialsFilename, false);
|
|
||||||
storeSettings(settings);
|
|
||||||
storeSettings(credentials);
|
|
||||||
|
|
||||||
// Init logging config
|
|
||||||
exports.logconfig = defaultLogConfig(
|
|
||||||
exports.loglevel ? exports.loglevel : defaultLogLevel,
|
|
||||||
exports.logLayoutType ? exports.logLayoutType : defaultLogLayoutType
|
|
||||||
);
|
|
||||||
logger.warn("loglevel: " + exports.loglevel);
|
|
||||||
logger.warn("logLayoutType: " + exports.logLayoutType);
|
|
||||||
initLogging(exports.logconfig);
|
|
||||||
|
|
||||||
if (!exports.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';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!exports.socketTransportProtocols.includes("websocket") || !exports.socketTransportProtocols.includes("polling")) {
|
reloadSettings = () => {
|
||||||
logger.warn("Invalid socketTransportProtocols setting. Please check out settings.json.template and update your settings.json. Falling back to the default ['websocket', 'polling'].");
|
const settings = this.parseSettings(this.settingsFilename, true);
|
||||||
exports.socketTransportProtocols = ['websocket', 'polling'];
|
const credentials = this.parseSettings(this.credentialsFilename, false);
|
||||||
|
this.storeSettings(settings);
|
||||||
|
this.storeSettings(credentials);
|
||||||
|
|
||||||
|
// Init logging config
|
||||||
|
this.logconfig = this.defaultLogConfig(this.loglevel ? this.loglevel : this.defaultLogLevel);
|
||||||
|
this.initLogging(this.logconfig);
|
||||||
|
|
||||||
|
if (!this.skinName) {
|
||||||
|
this.logger.warn('No "skinName" parameter found. Please check out settings.json.template and ' +
|
||||||
|
'update your settings.json. Falling back to the default "colibris".');
|
||||||
|
this.skinName = 'colibris';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.socketTransportProtocols.includes("websocket") || this.socketTransportProtocols.includes("polling")) {
|
||||||
|
this.logger.warn("Invalid socketTransportProtocols setting. Please check out settings.json.template and update your settings.json. Falling back to the default ['websocket', 'polling'].");
|
||||||
|
this.socketTransportProtocols = ['websocket', 'polling'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// checks if skinName has an acceptable value, otherwise falls back to "colibris"
|
// checks if skinName has an acceptable value, otherwise falls back to "colibris"
|
||||||
if (exports.skinName) {
|
if (this.skinName) {
|
||||||
const skinBasePath = path.join(exports.root, 'src', 'static', 'skins');
|
const skinBasePath = path.join(this.root, 'src', 'static', 'skins');
|
||||||
const countPieces = exports.skinName.split(path.sep).length;
|
const countPieces = this.skinName.split(path.sep).length;
|
||||||
|
|
||||||
if (countPieces !== 1) {
|
if (countPieces !== 1) {
|
||||||
logger.error(`skinName must be the name of a directory under "${skinBasePath}". This is ` +
|
this.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: "${this.skinName}". Falling back to the default "colibris".`);
|
||||||
|
this.skinName = 'colibris';
|
||||||
exports.skinName = 'colibris';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// informative variable, just for the log messages
|
// informative variable, just for the log messages
|
||||||
let skinPath = path.join(skinBasePath, exports.skinName);
|
let skinPath = path.join(skinBasePath, this.skinName);
|
||||||
|
|
||||||
// what if someone sets skinName == ".." or "."? We catch him!
|
// what if someone sets skinName == ".." or "."? We catch him!
|
||||||
if (absolutePaths.isSubdir(skinBasePath, skinPath) === false) {
|
if (isSubdir(skinBasePath, skinPath) === false) {
|
||||||
logger.error(`Skin path ${skinPath} must be a subdirectory of ${skinBasePath}. ` +
|
this.logger.error(`Skin path ${skinPath} must be a subdirectory of ${skinBasePath}. ` +
|
||||||
'Falling back to the default "colibris".');
|
'Falling back to the default "colibris".');
|
||||||
|
|
||||||
exports.skinName = 'colibris';
|
this.skinName = 'colibris';
|
||||||
skinPath = path.join(skinBasePath, exports.skinName);
|
skinPath = path.join(skinBasePath, this.skinName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fs.existsSync(skinPath) === false) {
|
if (fs.existsSync(skinPath) === false) {
|
||||||
logger.error(`Skin path ${skinPath} does not exist. Falling back to the default "colibris".`);
|
this.logger.error(`Skin path ${skinPath} does not exist. Falling back to the default "colibris".`);
|
||||||
exports.skinName = 'colibris';
|
this.skinName = 'colibris';
|
||||||
skinPath = path.join(skinBasePath, exports.skinName);
|
skinPath = path.join(skinBasePath,this.skinName);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info(`Using skin "${exports.skinName}" in dir: ${skinPath}`);
|
this.logger.info(`Using skin "${this.skinName}" in dir: ${skinPath}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exports.abiword) {
|
if (this.abiword) {
|
||||||
// Check abiword actually exists
|
// Check abiword actually exists
|
||||||
if (exports.abiword != null) {
|
if (this.abiword != null) {
|
||||||
fs.exists(exports.abiword, (exists: boolean) => {
|
let exists = fs.existsSync(this.abiword)
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
const abiwordError = 'Abiword does not exist at this path, check your settings file.';
|
const abiwordError = 'Abiword does not exist at this path, check your settings file.';
|
||||||
if (!exports.suppressErrorsInPadText) {
|
if (!this.suppressErrorsInPadText) {
|
||||||
exports.defaultPadText += `\nError: ${abiwordError}${suppressDisableMsg}`;
|
this.defaultPadText += `\nError: ${abiwordError}${this.suppressDisableMsg}`;
|
||||||
}
|
}
|
||||||
logger.error(`${abiwordError} File location: ${exports.abiword}`);
|
this.logger.error(`${abiwordError} File location: ${this.abiword}`);
|
||||||
exports.abiword = null;
|
this.abiword = null;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exports.soffice) {
|
if (this.soffice) {
|
||||||
fs.exists(exports.soffice, (exists: boolean) => {
|
let exists = fs.existsSync(this.soffice)
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
const sofficeError =
|
const sofficeError =
|
||||||
'soffice (libreoffice) does not exist at this path, check your settings file.';
|
'soffice (libreoffice) does not exist at this path, check your settings file.';
|
||||||
|
|
||||||
if (!exports.suppressErrorsInPadText) {
|
if (!this.suppressErrorsInPadText) {
|
||||||
exports.defaultPadText += `\nError: ${sofficeError}${suppressDisableMsg}`;
|
this.defaultPadText += `\nError: ${sofficeError}${this.suppressDisableMsg}`;
|
||||||
}
|
}
|
||||||
logger.error(`${sofficeError} File location: ${exports.soffice}`);
|
this.logger.error(`${sofficeError} File location: ${this.soffice}`);
|
||||||
exports.soffice = null;
|
this.soffice = null;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const sessionkeyFilename = absolutePaths.makeAbsolute(argv.sessionkey || './SESSIONKEY.txt');
|
const sessionkeyFilename = makeAbsolute(argvP.sessionkey || './SESSIONKEY.txt');
|
||||||
if (!exports.sessionKey) {
|
if (!this.sessionKey) {
|
||||||
try {
|
try {
|
||||||
exports.sessionKey = fs.readFileSync(sessionkeyFilename, 'utf8');
|
this.sessionKey = fs.readFileSync(sessionkeyFilename, 'utf8');
|
||||||
logger.info(`Session key loaded from: ${sessionkeyFilename}`);
|
this.logger.info(`Session key loaded from: ${sessionkeyFilename}`);
|
||||||
} catch (err) { /* ignored */
|
} catch (err) { /* ignored */
|
||||||
}
|
}
|
||||||
const keyRotationEnabled = exports.cookie.keyRotationInterval && exports.cookie.sessionLifetime;
|
const keyRotationEnabled = this.cookie.keyRotationInterval && this.cookie.sessionLifetime;
|
||||||
if (!exports.sessionKey && !keyRotationEnabled) {
|
if (!this.sessionKey && !keyRotationEnabled) {
|
||||||
logger.info(
|
this.logger.info(
|
||||||
`Session key file "${sessionkeyFilename}" not found. Creating with random contents.`);
|
`Session key file "${sessionkeyFilename}" not found. Creating with random contents.`);
|
||||||
exports.sessionKey = randomString(32);
|
this.sessionKey = randomString(32);
|
||||||
fs.writeFileSync(sessionkeyFilename, exports.sessionKey, 'utf8');
|
fs.writeFileSync(sessionkeyFilename, this.sessionKey, 'utf8');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.warn('Declaring the sessionKey in the settings.json is deprecated. ' +
|
this.logger.warn('Declaring the sessionKey in the settings.json is deprecated. ' +
|
||||||
'This value is auto-generated now. Please remove the setting from the file. -- ' +
|
'This value is auto-generated now. Please remove the setting from the file. -- ' +
|
||||||
'If you are seeing this error after restarting using the Admin User ' +
|
'If you are seeing this error after restarting using the Admin User ' +
|
||||||
'Interface then you can ignore this message.');
|
'Interface then you can ignore this message.');
|
||||||
}
|
}
|
||||||
if (exports.sessionKey) {
|
if (this.sessionKey) {
|
||||||
logger.warn(`The sessionKey setting and ${sessionkeyFilename} file are deprecated; ` +
|
this.logger.warn(`The sessionKey setting and ${sessionkeyFilename} file are deprecated; ` +
|
||||||
'use automatic key rotation instead (see the cookie.keyRotationInterval setting).');
|
'use automatic key rotation instead (see the cookie.keyRotationInterval setting).');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exports.dbType === 'dirty') {
|
if (this.dbType === 'dirty') {
|
||||||
const dirtyWarning = 'DirtyDB is used. This is not recommended for production.';
|
const dirtyWarning = 'DirtyDB is used. This is not recommended for production.';
|
||||||
if (!exports.suppressErrorsInPadText) {
|
if (!this.suppressErrorsInPadText) {
|
||||||
exports.defaultPadText += `\nWarning: ${dirtyWarning}${suppressDisableMsg}`;
|
this.defaultPadText += `\nWarning: ${dirtyWarning}${this.suppressDisableMsg}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.dbSettings.filename = absolutePaths.makeAbsolute(exports.dbSettings.filename);
|
this.dbSettings.filename = makeAbsolute(this.dbSettings.filename);
|
||||||
logger.warn(`${dirtyWarning} File location: ${exports.dbSettings.filename}`);
|
this.logger.warn(`${dirtyWarning} File location: ${this.dbSettings.filename}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exports.ip === '') {
|
if (this.ip === '') {
|
||||||
// using Unix socket for connectivity
|
// using Unix socket for connectivity
|
||||||
logger.warn('The settings file contains an empty string ("") for the "ip" parameter. The ' +
|
this.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.');
|
'"port" parameter will be interpreted as the path to a Unix socket to bind at.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -958,13 +954,13 @@ exports.reloadSettings = () => {
|
||||||
* ACHTUNG: this may prevent caching HTTP proxies to work
|
* ACHTUNG: this may prevent caching HTTP proxies to work
|
||||||
* TODO: remove the "?v=randomstring" parameter, and replace with hashed filenames instead
|
* TODO: remove the "?v=randomstring" parameter, and replace with hashed filenames instead
|
||||||
*/
|
*/
|
||||||
exports.randomVersionString = randomString(4);
|
this.randomVersionString = randomString(4);
|
||||||
logger.info(`Random string used for versioning assets: ${exports.randomVersionString}`);
|
this.logger.info(`Random string used for versioning assets: ${this.randomVersionString}`);
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
const settings = new Settings()
|
||||||
|
|
||||||
|
export default settings
|
||||||
|
|
||||||
|
|
||||||
exports.exportedForTestingOnly = {
|
|
||||||
parseSettings,
|
|
||||||
};
|
|
||||||
|
|
||||||
// initially load settings
|
|
||||||
exports.reloadSettings();
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
const semver = require('semver');
|
const semver = require('semver');
|
||||||
const settings = require('./Settings');
|
import settings from './Settings';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
const headers = {
|
const headers = {
|
||||||
'User-Agent': 'Etherpad/' + settings.getEpVersion(),
|
'User-Agent': 'Etherpad/' + settings.getEpVersion(),
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
* Generates a random String with the given length. Is needed to generate the
|
* Generates a random String with the given length. Is needed to generate the
|
||||||
* Author, Group, readonly, session Ids
|
* Author, Group, readonly, session Ids
|
||||||
*/
|
*/
|
||||||
const cryptoMod = require('crypto');
|
import cryptoMod from 'crypto';
|
||||||
|
|
||||||
const randomString = (len: number) => cryptoMod.randomBytes(len).toString('hex');
|
const randomString = (len: number) => cryptoMod.randomBytes(len).toString('hex');
|
||||||
|
|
||||||
module.exports = randomString;
|
export default randomString
|
||||||
|
|
|
@ -8,7 +8,7 @@ import {Readable} from "node:stream";
|
||||||
const spawn = require('cross-spawn');
|
const spawn = require('cross-spawn');
|
||||||
const log4js = require('log4js');
|
const log4js = require('log4js');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const settings = require('./Settings');
|
import settings from './Settings';
|
||||||
|
|
||||||
const logger = log4js.getLogger('runCmd');
|
const logger = log4js.getLogger('runCmd');
|
||||||
|
|
||||||
|
|
|
@ -88,6 +88,7 @@
|
||||||
"@types/jquery": "^3.5.30",
|
"@types/jquery": "^3.5.30",
|
||||||
"@types/js-cookie": "^3.0.6",
|
"@types/js-cookie": "^3.0.6",
|
||||||
"@types/jsdom": "^21.1.7",
|
"@types/jsdom": "^21.1.7",
|
||||||
|
"@types/jsonminify": "^0.4.3",
|
||||||
"@types/jsonwebtoken": "^9.0.6",
|
"@types/jsonwebtoken": "^9.0.6",
|
||||||
"@types/mime-types": "^2.1.4",
|
"@types/mime-types": "^2.1.4",
|
||||||
"@types/mocha": "^10.0.7",
|
"@types/mocha": "^10.0.7",
|
||||||
|
|
|
@ -4,7 +4,7 @@ import {node_modules, pluginInstallPath} from "./installer";
|
||||||
import {accessSync, constants, rmSync, symlinkSync, unlinkSync} from "node:fs";
|
import {accessSync, constants, rmSync, symlinkSync, unlinkSync} from "node:fs";
|
||||||
import {dependencies, name} from '../../../package.json'
|
import {dependencies, name} from '../../../package.json'
|
||||||
import {pathToFileURL} from 'node:url';
|
import {pathToFileURL} from 'node:url';
|
||||||
const settings = require('../../../node/utils/Settings');
|
import settings from '../../../node/utils/Settings';
|
||||||
import {readFileSync} from "fs";
|
import {readFileSync} from "fs";
|
||||||
|
|
||||||
export class LinkInstaller {
|
export class LinkInstaller {
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {promises as fs} from "fs";
|
||||||
const plugins = require('./plugins');
|
const plugins = require('./plugins');
|
||||||
const hooks = require('./hooks');
|
const hooks = require('./hooks');
|
||||||
const runCmd = require('../../../node/utils/run_cmd');
|
const runCmd = require('../../../node/utils/run_cmd');
|
||||||
const settings = require('../../../node/utils/Settings');
|
import settings from '../../../node/utils/Settings';
|
||||||
import {LinkInstaller} from "./LinkInstaller";
|
import {LinkInstaller} from "./LinkInstaller";
|
||||||
|
|
||||||
const {findEtherpadRoot} = require('../../../node/utils/AbsolutePaths');
|
const {findEtherpadRoot} = require('../../../node/utils/AbsolutePaths');
|
||||||
|
|
|
@ -9,7 +9,7 @@ const runCmd = require('../../../node/utils/run_cmd');
|
||||||
const tsort = require('./tsort');
|
const tsort = require('./tsort');
|
||||||
const pluginUtils = require('./shared');
|
const pluginUtils = require('./shared');
|
||||||
const defs = require('./plugin_defs');
|
const defs = require('./plugin_defs');
|
||||||
const settings = require('../../../node/utils/Settings');
|
import settings from '../../../node/utils/Settings'
|
||||||
|
|
||||||
const logger = log4js.getLogger('plugins');
|
const logger = log4js.getLogger('plugins');
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<%
|
<%
|
||||||
var settings = require("ep_etherpad-lite/node/utils/Settings")
|
var langs = require("ep_etherpad-lite/node/hooks/i18n").availableLangs
|
||||||
, langs = require("ep_etherpad-lite/node/hooks/i18n").availableLangs
|
|
||||||
, pluginUtils = require('ep_etherpad-lite/static/js/pluginfw/shared')
|
, pluginUtils = require('ep_etherpad-lite/static/js/pluginfw/shared')
|
||||||
;
|
;
|
||||||
%>
|
%>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<%
|
<%
|
||||||
var settings = require("ep_etherpad-lite/node/utils/Settings")
|
var langs = require("ep_etherpad-lite/node/hooks/i18n").availableLangs
|
||||||
, langs = require("ep_etherpad-lite/node/hooks/i18n").availableLangs
|
|
||||||
%>
|
%>
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html translate="no" class="pad <%=settings.skinVariants%>">
|
<html translate="no" class="pad <%=settings.skinVariants%>">
|
||||||
|
|
|
@ -10,7 +10,7 @@ import padutils from '../../static/js/pad_utils';
|
||||||
const process = require('process');
|
const process = require('process');
|
||||||
const server = require('../../node/server');
|
const server = require('../../node/server');
|
||||||
const setCookieParser = require('set-cookie-parser');
|
const setCookieParser = require('set-cookie-parser');
|
||||||
const settings = require('../../node/utils/Settings');
|
import settings from '../../node/utils/Settings';
|
||||||
import supertest from 'supertest';
|
import supertest from 'supertest';
|
||||||
import TestAgent from "supertest/lib/agent";
|
import TestAgent from "supertest/lib/agent";
|
||||||
import {Http2Server} from "node:http2";
|
import {Http2Server} from "node:http2";
|
||||||
|
@ -26,7 +26,7 @@ export let baseUrl:string|null = null;
|
||||||
export let httpServer: Http2Server|null = null;
|
export let httpServer: Http2Server|null = null;
|
||||||
export const logger = log4js.getLogger('test');
|
export const logger = log4js.getLogger('test');
|
||||||
|
|
||||||
const logLevel = logger.level;
|
const logLevel = logger.level as log4js.Level;
|
||||||
|
|
||||||
// Mocha doesn't monitor unhandled Promise rejections, so convert them to uncaught exceptions.
|
// Mocha doesn't monitor unhandled Promise rejections, so convert them to uncaught exceptions.
|
||||||
// https://github.com/mochajs/mocha/issues/2640
|
// https://github.com/mochajs/mocha/issues/2640
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue