diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 353217598..eaf004e54 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -35,10 +35,10 @@ jobs: if: ${{ github.event_name == 'pull_request' }} - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 3971cec1d..8dbd03339 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -47,7 +47,7 @@ jobs: run: src/bin/buildForWindows.sh - name: Archive production artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: etherpad-win.zip path: etherpad-win.zip @@ -65,7 +65,7 @@ jobs: uses: actions/checkout@v4 - name: Download .zip - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: etherpad-win.zip path: .. @@ -80,7 +80,7 @@ jobs: script-file: 'src/bin/nsis/etherpad.nsi' - name: Archive production artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: etherpad-win.exe path: etherpad-win.exe @@ -99,7 +99,7 @@ jobs: steps: - name: Download zip - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: etherpad-win.zip - diff --git a/CHANGELOG.md b/CHANGELOG.md index 15a526784..ce90415c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# 1.9.6 + +### Notable enhancements and fixes + +* Prevent etherpad crash when update server is not reachable +* Use npm@6 in Docker build +* Fix setting the log level in settings.json + + # 1.9.5 ### Compability changes diff --git a/README.md b/README.md index 04ae0623d..41da517af 100644 --- a/README.md +++ b/README.md @@ -52,9 +52,8 @@ We're looking for maintainers and have some funding available. Please contact J #### Quick install on Debian/Ubuntu +Install the latest Node.js LTS per [official install instructions](https://github.com/nodesource/distributions#installation-instructions), then: ```sh -curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash - -sudo apt install -y nodejs git clone --branch master https://github.com/ether/etherpad-lite.git && cd etherpad-lite && src/bin/run.sh diff --git a/src/bin/doc/package-lock.json b/src/bin/doc/package-lock.json index f4bf5c4e7..786aa1e21 100644 --- a/src/bin/doc/package-lock.json +++ b/src/bin/doc/package-lock.json @@ -5,9 +5,9 @@ "requires": true, "dependencies": { "marked": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-11.0.1.tgz", - "integrity": "sha512-P4kDhFEMlvLePBPRwOcMOv6+lYUbhfbSxJFs3Jb4Qx7v6K7l+k8Dxh9CEGfRvK71tL+qIFz5y7Pe4uzt4+/A3A==" + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-11.1.0.tgz", + "integrity": "sha512-fvKJWAPEafVj1dwGwcPI5mBB/0pvViL6NlCbNDG1HOIRwwAU/jeMoFxfbRLuirO1wRH7m4yPvBqD/O1wyWvayw==" } } } diff --git a/src/bin/doc/package.json b/src/bin/doc/package.json index eed10e225..1ca0fa87c 100644 --- a/src/bin/doc/package.json +++ b/src/bin/doc/package.json @@ -7,7 +7,7 @@ "node": ">=12.17.0" }, "dependencies": { - "marked": "^11.0.1" + "marked": "^11.1.0" }, "devDependencies": {}, "optionalDependencies": {}, diff --git a/src/node/utils/Settings.js b/src/node/utils/Settings.js index 9646c1f89..7125607ea 100644 --- a/src/node/utils/Settings.js +++ b/src/node/utils/Settings.js @@ -50,15 +50,14 @@ const nonSettings = [ // This is a function to make it easy to create a new instance. It is important to not reuse a // config object after passing it to log4js.configure() because that method mutates the object. :( -const defaultLogConfig = () => ({appenders: {console: {type: 'console'}}, +const defaultLogConfig = (level) => ({appenders: {console: {type: 'console'}}, categories: { - default: {appenders: ['console'], level: 'info'}, + default: {appenders: ['console'], level}, }}); const defaultLogLevel = 'INFO'; const initLogging = (logLevel, config) => { // log4js.configure() modifies exports.logconfig so check for equality first. - const logConfigIsDefault = deepEqual(config, defaultLogConfig()); log4js.configure(config); log4js.getLogger('console'); @@ -67,19 +66,16 @@ const initLogging = (logLevel, config) => { console.log = logger.info.bind(logger); console.warn = logger.warn.bind(logger); console.error = logger.error.bind(logger); - - // Log the warning after configuring log4js to increase the chances the user will see it. - if (!logConfigIsDefault) logger.warn('The logconfig setting is deprecated.'); }; // Initialize logging as early as possible with reasonable defaults. Logging will be re-initialized // with the user's chosen log level and logger config after the settings have been loaded. -initLogging(defaultLogLevel, defaultLogConfig()); +initLogging(defaultLogLevel, defaultLogConfig(defaultLogLevel)); /* Root path of the installation */ exports.root = absolutePaths.findEtherpadRoot(); logger.info('All relative paths will be interpreted relative to the identified ' + - `Etherpad base dir: ${exports.root}`); + `Etherpad base dir: ${exports.root}`); exports.settingsFilename = absolutePaths.makeAbsolute(argv.settings || 'settings.json'); exports.credentialsFilename = absolutePaths.makeAbsolute(argv.credentials || 'credentials.json'); @@ -160,7 +156,7 @@ exports.defaultPadText = [ 'Welcome to Etherpad!', '', 'This pad text is synchronized as you type, so that everyone viewing this page sees the same ' + - 'text. This allows you to collaborate seamlessly on documents!', + 'text. This allows you to collaborate seamlessly on documents!', '', 'Etherpad on Github: https://github.com/ether/etherpad-lite', ].join('\n'); @@ -298,7 +294,7 @@ exports.indentationOnNewLine = true; /* * log4js appender configuration */ -exports.logconfig = defaultLogConfig(); +exports.logconfig = null; /* * Deprecated cookie signing key. @@ -646,9 +642,9 @@ const lookupEnvironmentVariables = (obj) => { if ((envVarValue === undefined) && (defaultValue === undefined)) { logger.warn(`Environment variable "${envVarName}" does not contain any value for ` + - `configuration key "${key}", and no default was given. Using null. ` + - '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.'); + `configuration key "${key}", and no default was given. Using null. ` + + '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.'); /* * We have to return null, because if we just returned undefined, the @@ -659,7 +655,7 @@ const lookupEnvironmentVariables = (obj) => { if ((envVarValue === undefined) && (defaultValue !== undefined)) { logger.debug(`Environment variable "${envVarName}" not found for ` + - `configuration key "${key}". Falling back to default value.`); + `configuration key "${key}". Falling back to default value.`); return coerceValue(defaultValue); } @@ -726,7 +722,7 @@ const parseSettings = (settingsFilename, isSettings) => { return replacedSettings; } catch (e) { logger.error(`There was an error processing your ${settingsType} ` + - `file from ${settingsFilename}: ${e.message}`); + `file from ${settingsFilename}: ${e.message}`); process.exit(1); } @@ -738,11 +734,13 @@ exports.reloadSettings = () => { storeSettings(settings); storeSettings(credentials); + // Init logging config + exports.logconfig = defaultLogConfig(exports.loglevel ? exports.loglevel : defaultLogLevel); initLogging(exports.loglevel, 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".'); + 'update your settings.json. Falling back to the default "colibris".'); exports.skinName = 'colibris'; } @@ -753,7 +751,7 @@ exports.reloadSettings = () => { if (countPieces !== 1) { logger.error(`skinName must be the name of a directory under "${skinBasePath}". This is ` + - `not valid: "${exports.skinName}". Falling back to the default "colibris".`); + `not valid: "${exports.skinName}". Falling back to the default "colibris".`); exports.skinName = 'colibris'; } @@ -764,7 +762,7 @@ exports.reloadSettings = () => { // what if someone sets skinName == ".." or "."? We catch him! if (absolutePaths.isSubdir(skinBasePath, skinPath) === false) { logger.error(`Skin path ${skinPath} must be a subdirectory of ${skinBasePath}. ` + - 'Falling back to the default "colibris".'); + 'Falling back to the default "colibris".'); exports.skinName = 'colibris'; skinPath = path.join(skinBasePath, exports.skinName); @@ -825,9 +823,9 @@ exports.reloadSettings = () => { } } else { logger.warn('Declaring the sessionKey in the settings.json is deprecated. ' + - '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 ' + - 'Interface then you can ignore this message.'); + '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 ' + + 'Interface then you can ignore this message.'); } if (exports.sessionKey) { logger.warn(`The sessionKey setting and ${sessionkeyFilename} file are deprecated; ` + @@ -847,7 +845,7 @@ exports.reloadSettings = () => { if (exports.ip === '') { // using Unix socket for connectivity logger.warn('The settings file contains an empty string ("") for the "ip" parameter. The ' + - '"port" parameter will be interpreted as the path to a Unix socket to bind at.'); + '"port" parameter will be interpreted as the path to a Unix socket to bind at.'); } /* @@ -871,3 +869,4 @@ exports.exportedForTestingOnly = { // initially load settings exports.reloadSettings(); + diff --git a/src/package-lock.json b/src/package-lock.json index 54474c1cd..346177459 100644 --- a/src/package-lock.json +++ b/src/package-lock.json @@ -1,6 +1,6 @@ { "name": "ep_etherpad-lite", - "version": "1.9.5", + "version": "1.9.6", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -90,9 +90,9 @@ } }, "@eslint/js": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.55.0.tgz", - "integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", "dev": true }, "@humanwhocodes/config-array": { @@ -1374,15 +1374,15 @@ "dev": true }, "eslint": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.55.0.tgz", - "integrity": "sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.55.0", + "@eslint/js": "8.56.0", "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -7038,9 +7038,9 @@ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "rate-limiter-flexible": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/rate-limiter-flexible/-/rate-limiter-flexible-3.0.6.tgz", - "integrity": "sha512-tlvbee6lyse/XTWmsuBDS4MT8N65FyM151bPmQlFyfhv9+RIHs7d3rSTXoz0j35H910dM01mH0yTIeWYo8+aAw==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rate-limiter-flexible/-/rate-limiter-flexible-4.0.0.tgz", + "integrity": "sha512-SkA18LEPqJJKHixi6E7tzBKTXbj9gu5wPyfTykPVRZR5JGSw0dMCjtZsjlfuabVY940pu28Wu87NZN4FhztnyQ==" }, "raw-body": { "version": "2.5.1", diff --git a/src/package.json b/src/package.json index 34b9e5954..a3aa49de1 100644 --- a/src/package.json +++ b/src/package.json @@ -56,7 +56,7 @@ "npm": "^6.14.18", "openapi-backend": "^5.10.5", "proxy-addr": "^2.0.7", - "rate-limiter-flexible": "^3.0.6", + "rate-limiter-flexible": "^4.0.0", "rehype": "^13.0.1", "rehype-minify-whitespace": "^6.0.0", "resolve": "1.22.8", @@ -78,7 +78,7 @@ "etherpad-lite": "node/server.js" }, "devDependencies": { - "eslint": "^8.55.0", + "eslint": "^8.56.0", "eslint-config-etherpad": "^3.0.22", "etherpad-cli-client": "^2.0.2", "mocha": "^10.0.0", @@ -105,6 +105,6 @@ "test": "mocha --timeout 120000 --recursive tests/backend/specs ../node_modules/ep_*/static/tests/backend/specs", "test-container": "mocha --timeout 5000 tests/container/specs/api" }, - "version": "1.9.5", + "version": "1.9.6", "license": "Apache-2.0" } diff --git a/src/static/js/pluginfw/installer.js b/src/static/js/pluginfw/installer.js index 6c5784b00..d0e9dab6c 100644 --- a/src/static/js/pluginfw/installer.js +++ b/src/static/js/pluginfw/installer.js @@ -15,6 +15,10 @@ const onAllTasksFinished = async () => { await hooks.aCallAll('restartServer'); }; +const headers = { + 'User-Agent': 'Etherpad/' + settings.getEpVersion(), +} + let tasks = 0; const wrapTaskCb = (cb) => { @@ -77,12 +81,15 @@ exports.getAvailablePlugins = (maxCacheAge) => { return resolve(exports.availablePlugins); } - await axios.get('https://static.etherpad.org/plugins.json') - .then(pluginsLoaded => { - exports.availablePlugins = pluginsLoaded.data; - cacheTimestamp = nowTimestamp; - resolve(exports.availablePlugins); - }) + await axios.get('https://static.etherpad.org/plugins.json', {headers: headers}) + .then(pluginsLoaded => { + exports.availablePlugins = pluginsLoaded.data; + cacheTimestamp = nowTimestamp; + resolve(exports.availablePlugins); + }) + .catch(async err => { + return reject(err); + }); }) }