diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b43ddb762..edb20fc334 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,42 @@ +#### v2.7.0 (2022-12-14) + +##### Chores + +* added stub file in hy (9ee8502d) +* **deps:** + * update dependency lint-staged to v13.1.0 (#11082) (693d4783) + * update dependency eslint to v8.29.0 (#11074) (eab5b754) + * update dependency lint-staged to v13.0.4 (#11064) (f947ac6d) +* **i18n:** + * fallback strings for new resources: nodebb.admin-settings-email (0e319a58) + * fallback strings for new resources: nodebb.admin-settings-email (9676b192) + +##### New Features + +* update transifex config (for use with new cli) (f11094cb) +* integrating basic client-side form validity checking in settings v1 and v2 (dadbcd73) +* add ./nodebb install (4efc19d5) + +##### Bug Fixes + +* **deps:** + * update dependency nodebb-theme-lavender to v6.0.1 (#11081) (df3f1c5e) + * update dependency esbuild to v0.16.3 (#11083) (85d38158) + * update dependency html-to-text to v9 (#11075) (d8e9738d) + * update dependency ace-builds to v1.13.2 (#11080) (35be4594) + * update dependency fs-extra to v11 (#11072) (aafb7f6e) + * update dependency esbuild to v0.15.16 (#11069) (7bc4b836) + * update dependency mongodb to v4.12.1 (#11062) (e14d4abc) +* relax selectors for client-side form validation so that all form elements are checked (43e7c988) +* change hsts-maxage back to numeric input type, change API token uid input to numeric text type (db8d3a94) +* replace input type number with text/pattern (45ae31f8) +* categories.js not showing custom privileges (#10856) (8c4d6bbe) +* #11077, add admin uploads paths to priv mapping (07a02125) + +##### Tests + +* dont try to load admin upload routes (c2bb2b30) + #### v2.6.1 (2022-11-28) ##### Chores diff --git a/install/package.json b/install/package.json index d20d494edd..ad81347ca3 100644 --- a/install/package.json +++ b/install/package.json @@ -30,7 +30,7 @@ "dependencies": { "@adactive/bootstrap-tagsinput": "0.8.2", "@isaacs/ttlcache": "1.2.1", - "ace-builds": "1.13.2", + "ace-builds": "1.14.0", "archiver": "5.3.1", "async": "3.2.4", "autoprefixer": "10.4.13", @@ -45,7 +45,7 @@ "clipboard": "2.0.11", "colors": "1.4.0", "commander": "9.4.1", - "compare-versions": "5.0.1", + "compare-versions": "5.0.3", "compression": "1.7.4", "connect-flash": "0.1.1", "connect-mongo": "4.6.0", @@ -58,7 +58,7 @@ "csurf": "1.11.0", "daemon": "1.1.0", "diff": "5.1.0", - "esbuild": "0.16.3", + "esbuild": "0.16.10", "express": "4.18.2", "express-session": "1.17.3", "express-useragent": "1.0.15", @@ -66,9 +66,9 @@ "fs-extra": "11.1.0", "graceful-fs": "4.2.10", "helmet": "5.1.1", - "html-to-text": "9.0.2", + "html-to-text": "9.0.3", "ipaddr.js": "2.0.1", - "jquery": "3.6.1", + "jquery": "3.6.3", "jquery-deserialize": "2.0.0", "jquery-form": "4.3.0", "jquery-serializeobject": "1.0.0", @@ -83,13 +83,13 @@ "material-design-lite": "1.3.0", "mime": "3.0.0", "mkdirp": "1.0.4", - "mongodb": "4.12.1", + "mongodb": "4.13.0", "morgan": "1.10.0", "mousetrap": "1.6.5", "multiparty": "4.2.3", "@nodebb/bootswatch": "3.4.2", "nconf": "0.12.0", - "nodebb-plugin-2factor": "5.1.1", + "nodebb-plugin-2factor": "5.1.2", "nodebb-plugin-composer-default": "9.2.4", "nodebb-plugin-dbsearch": "5.1.5", "nodebb-plugin-emoji": "4.0.6", @@ -102,7 +102,7 @@ "nodebb-theme-persona": "12.1.12", "nodebb-theme-slick": "2.0.2", "nodebb-theme-vanilla": "12.1.19", - "nodebb-widget-essentials": "6.0.0", + "nodebb-widget-essentials": "6.0.1", "nodemailer": "6.8.0", "nprogress": "0.2.0", "passport": "0.6.0", @@ -110,7 +110,7 @@ "passport-local": "1.0.0", "pg": "8.8.0", "pg-cursor": "2.7.4", - "postcss": "8.4.19", + "postcss": "8.4.20", "postcss-clean": "1.2.0", "progress-webpack-plugin": "1.0.16", "prompt": "1.3.0", @@ -119,15 +119,15 @@ "request-promise-native": "1.0.9", "rimraf": "3.0.2", "rss": "1.2.2", - "sanitize-html": "2.7.3", + "sanitize-html": "2.8.1", "semver": "7.3.8", "serve-favicon": "2.5.0", - "sharp": "0.31.2", + "sharp": "0.31.3", "sitemap": "7.1.1", "slideout": "1.0.1", "socket.io": "4.5.4", "socket.io-client": "4.5.4", - "@socket.io/redis-adapter": "7.2.0", + "@socket.io/redis-adapter": "8.0.0", "sortablejs": "1.15.0", "spdx-license-list": "6.6.0", "spider-detector": "2.0.0", @@ -152,7 +152,7 @@ "@commitlint/cli": "17.3.0", "@commitlint/config-angular": "17.3.0", "coveralls": "3.1.1", - "eslint": "8.29.0", + "eslint": "8.30.0", "eslint-config-nodebb": "0.2.1", "eslint-plugin-import": "2.26.0", "grunt": "1.5.3", @@ -160,14 +160,14 @@ "husky": "8.0.2", "jsdom": "20.0.3", "lint-staged": "13.1.0", - "mocha": "10.1.0", + "mocha": "10.2.0", "mocha-lcov-reporter": "1.3.0", "mockdate": "3.0.5", "nyc": "15.1.0", "smtp-server": "3.11.0" }, "resolutions": { - "*/jquery": "3.6.1" + "*/jquery": "3.6.3" }, "bugs": { "url": "https://github.com/NodeBB/NodeBB/issues" diff --git a/public/src/modules/settings.js b/public/src/modules/settings.js index 50e05853f3..8e43fc1d3c 100644 --- a/public/src/modules/settings.js +++ b/public/src/modules/settings.js @@ -518,7 +518,6 @@ define('settings', ['hooks', 'alerts'], function (hooks, alerts) { formEl = $(formEl); const controls = formEl.get(0).elements; - console.log(controls); const ok = Settings.check(controls); if (!ok) { return; diff --git a/src/cli/index.js b/src/cli/index.js index cad46b4609..938f588701 100644 --- a/src/cli/index.js +++ b/src/cli/index.js @@ -175,9 +175,10 @@ program program .command('install [plugin]') .description('Launch the NodeBB web installer for configuration setup or install a plugin') - .action((plugin) => { + .option('-f, --force', 'Force plugin installation even if it may be incompatible with currently installed NodeBB version') + .action((plugin, options) => { if (plugin) { - require('./manage').install(plugin); + require('./manage').install(plugin, options); } else { require('./setup').webInstall(); } diff --git a/src/cli/manage.js b/src/cli/manage.js index 45480e735f..d67126270c 100644 --- a/src/cli/manage.js +++ b/src/cli/manage.js @@ -14,7 +14,10 @@ const analytics = require('../analytics'); const reset = require('./reset'); const { pluginNamePattern, themeNamePattern, paths } = require('../constants'); -async function install(plugin) { +async function install(plugin, options) { + if (!options) { + options = {}; + } try { await db.init(); if (!pluginNamePattern.test(plugin)) { @@ -31,7 +34,11 @@ async function install(plugin) { const nbbVersion = require(paths.currentPackage).version; const suggested = await plugins.suggest(plugin, nbbVersion); if (!suggested.version) { - throw new Error(suggested.message); + if (!options.force) { + throw new Error(suggested.message); + } + winston.warn(`${suggested.message} Proceeding with installation anyway due to force option being provided`); + suggested.version = 'latest'; } winston.info('Installing Plugin `%s@%s`', plugin, suggested.version); await plugins.toggleInstall(plugin, suggested.version); diff --git a/src/controllers/mods.js b/src/controllers/mods.js index f80e9230f3..48a3bd8ff3 100644 --- a/src/controllers/mods.js +++ b/src/controllers/mods.js @@ -141,6 +141,7 @@ modsController.flags.detail = async function (req, res, next) { return memo; }, {}), + states: Object.fromEntries(flags._states), title: `[[pages:flag-details, ${req.params.flagId}]]`, privileges: results.privileges, breadcrumbs: helpers.buildBreadcrumbs([ diff --git a/src/flags.js b/src/flags.js index 7d8b5e43aa..8a400c9d88 100644 --- a/src/flags.js +++ b/src/flags.js @@ -20,15 +20,24 @@ const batch = require('./batch'); const Flags = module.exports; -Flags._constants = { - states: ['open', 'wip', 'resolved', 'rejected'], - state_class: { - open: 'info', - wip: 'warning', - resolved: 'success', - rejected: 'danger', - }, -}; +Flags._states = new Map([ + ['open', { + label: '[[flags:state-open]]', + class: 'danger', + }], + ['wip', { + label: '[[flags:state-wip]]', + class: 'warning', + }], + ['resolved', { + label: '[[flags:state-resolved]]', + class: 'success', + }], + ['rejected', { + label: '[[flags:state-rejected]]', + class: 'secondary', + }], +]); Flags.init = async function () { // Query plugins for custom filter strategies and merge into core filter strategies @@ -78,14 +87,15 @@ Flags.init = async function () { } }, }, + states: Flags._states, helpers: { prepareSets: prepareSets, }, }; try { - const data = await plugins.hooks.fire('filter:flags.getFilters', hookData); - Flags._filters = data.filters; + ({ filters: Flags._filters } = await plugins.hooks.fire('filter:flags.getFilters', hookData)); + ({ filters: Flags._filters, states: Flags._states } = await plugins.hooks.fire('filter:flags.init', hookData)); } catch (err) { winston.error(`[flags/init] Could not retrieve filters\n${err.stack}`); Flags._filters = {}; @@ -197,7 +207,7 @@ Flags.list = async function (data) { heat: reportCounts[idx], ...flagObj, }; - flagObj.labelClass = Flags._constants.state_class[flagObj.state]; + flagObj.labelClass = Flags._states.get(flagObj.state).class; return Object.assign(flagObj, { target_readable: `${flagObj.type.charAt(0).toUpperCase() + flagObj.type.slice(1)} ${flagObj.targetId}`, @@ -674,7 +684,7 @@ Flags.update = async function (flagId, uid, changeset) { if (current[prop] === changeset[prop]) { delete changeset[prop]; } else if (prop === 'state') { - if (!Flags._constants.states.includes(changeset[prop])) { + if (!Flags._states.has(changeset[prop])) { delete changeset[prop]; } else { tasks.push(db.sortedSetAdd(`flags:byState:${changeset[prop]}`, now, flagId)); diff --git a/src/plugins/hooks.js b/src/plugins/hooks.js index 4174723a70..58f8c85f96 100644 --- a/src/plugins/hooks.js +++ b/src/plugins/hooks.js @@ -33,6 +33,11 @@ Hooks._deprecated = new Map([ since: 'v2.2.0', until: 'v3.0.0', }], + ['filter:flags.getFilters', { + new: 'filter:flags.init', + since: 'v2.7.0', + until: 'v3.0.0', + }], ]); Hooks.internals = {