mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-03-11 15:10:45 +01:00
Merge branch 'develop' into bootstrap5
This commit is contained in:
@@ -21,7 +21,7 @@
|
||||
"headers.coop": "Cross-Origin-Opener-Policy",
|
||||
"headers.corp": "Cross-Origin-Resource-Policy",
|
||||
"headers.permissions-policy": "Permissions-Policy",
|
||||
"headers.permissions-policy-help": "Allows setting permissions policy header, for example \"geolocation=*, camera=()\", see <a href=\"https://github.com/w3c/webappsec-permissions-policy/blob/main/permissions-policy-explainer.md\">this</a> for more info.",
|
||||
"headers.permissions-policy-help": "Позволява задаването на стойност в заглавката „permissions-policy“ (политика за разрешенията), като например „geolocation=*, camera=()“. Вижте <a href=\"https://github.com/w3c/webappsec-permissions-policy/blob/main/permissions-policy-explainer.md\">тук</a> за повече информация.",
|
||||
"hsts": "Стриктна транспортна сигурност",
|
||||
"hsts.enabled": "Включване на HSTS (препоръчително)",
|
||||
"hsts.maxAge": "Максимална възраст на HSTS",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
define('admin/settings', ['uploader', 'mousetrap', 'hooks', 'alerts'], function (uploader, mousetrap, hooks, alerts) {
|
||||
define('admin/settings', ['uploader', 'mousetrap', 'hooks', 'alerts', 'settings'], function (uploader, mousetrap, hooks, alerts, settings) {
|
||||
const Settings = {};
|
||||
|
||||
Settings.populateTOC = function () {
|
||||
@@ -65,6 +65,11 @@ define('admin/settings', ['uploader', 'mousetrap', 'hooks', 'alerts'], function
|
||||
saveBtn.off('click').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
const ok = settings.check(document.querySelectorAll('#content [data-field]'));
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
saveFields(fields, function onFieldsSaved(err) {
|
||||
if (err) {
|
||||
return alerts.alert({
|
||||
|
||||
@@ -514,6 +514,13 @@ define('settings', ['hooks', 'alerts'], function (hooks, alerts) {
|
||||
save: function (hash, formEl, callback) {
|
||||
formEl = $(formEl);
|
||||
|
||||
const controls = formEl.get(0).elements;
|
||||
console.log(controls);
|
||||
const ok = Settings.check(controls);
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (formEl.length) {
|
||||
const values = helper.serializeForm(formEl);
|
||||
|
||||
@@ -556,6 +563,26 @@ define('settings', ['hooks', 'alerts'], function (hooks, alerts) {
|
||||
});
|
||||
}
|
||||
},
|
||||
check: function (controls) {
|
||||
const onTrigger = (e) => {
|
||||
const wrapper = e.target.closest('.form-group');
|
||||
if (wrapper) {
|
||||
wrapper.classList.add('has-error');
|
||||
}
|
||||
|
||||
e.target.removeEventListener('invalid', onTrigger);
|
||||
};
|
||||
|
||||
return Array.prototype.map.call(controls, (controlEl) => {
|
||||
const wrapper = controlEl.closest('.form-group');
|
||||
if (wrapper) {
|
||||
wrapper.classList.remove('has-error');
|
||||
}
|
||||
|
||||
controlEl.addEventListener('invalid', onTrigger);
|
||||
return controlEl.reportValidity();
|
||||
}).every(Boolean);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -176,11 +176,16 @@ program
|
||||
});
|
||||
|
||||
program
|
||||
.command('install')
|
||||
.description('Launch the NodeBB web installer for configuration setup')
|
||||
.action(() => {
|
||||
require('./setup').webInstall();
|
||||
.command('install [plugin]')
|
||||
.description('Launch the NodeBB web installer for configuration setup or install a plugin')
|
||||
.action((plugin) => {
|
||||
if (plugin) {
|
||||
require('./manage').install(plugin);
|
||||
} else {
|
||||
require('./setup').webInstall();
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('build [targets...]')
|
||||
.description(`Compile static assets ${chalk.red('(JS, CSS, templates, languages)')}`)
|
||||
|
||||
@@ -12,7 +12,36 @@ const plugins = require('../plugins');
|
||||
const events = require('../events');
|
||||
const analytics = require('../analytics');
|
||||
const reset = require('./reset');
|
||||
const { pluginNamePattern, themeNamePattern } = require('../constants');
|
||||
const { pluginNamePattern, themeNamePattern, paths } = require('../constants');
|
||||
|
||||
async function install(plugin) {
|
||||
try {
|
||||
await db.init();
|
||||
if (!pluginNamePattern.test(plugin)) {
|
||||
// Allow omission of `nodebb-plugin-`
|
||||
plugin = `nodebb-plugin-${plugin}`;
|
||||
}
|
||||
|
||||
plugin = await plugins.autocomplete(plugin);
|
||||
|
||||
const isInstalled = await plugins.isInstalled(plugin);
|
||||
if (isInstalled) {
|
||||
throw new Error('plugin already installed');
|
||||
}
|
||||
const nbbVersion = require(paths.currentPackage).version;
|
||||
const suggested = await plugins.suggest(plugin, nbbVersion);
|
||||
if (!suggested.version) {
|
||||
throw new Error(suggested.message);
|
||||
}
|
||||
winston.info('Installing Plugin `%s@%s`', plugin, suggested.version);
|
||||
await plugins.toggleInstall(plugin, suggested.version);
|
||||
|
||||
process.exit(0);
|
||||
} catch (err) {
|
||||
winston.error(`An error occurred during plugin installation\n${err.stack}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
async function activate(plugin) {
|
||||
if (themeNamePattern.test(plugin)) {
|
||||
@@ -166,6 +195,7 @@ async function buildWrapper(targets, options) {
|
||||
}
|
||||
|
||||
exports.build = buildWrapper;
|
||||
exports.install = install;
|
||||
exports.activate = activate;
|
||||
exports.listPlugins = listPlugins;
|
||||
exports.listEvents = listEvents;
|
||||
|
||||
@@ -87,6 +87,15 @@ module.exports = function (Plugins) {
|
||||
throw new Error('[[error:plugin-not-whitelisted]]');
|
||||
};
|
||||
|
||||
Plugins.suggest = async function (pluginId, nbbVersion) {
|
||||
const body = await request({
|
||||
method: 'GET',
|
||||
url: `https://packages.nodebb.org/api/v1/suggest?package=${encodeURIComponent(pluginId)}&version=${encodeURIComponent(nbbVersion)}`,
|
||||
json: true,
|
||||
});
|
||||
return body;
|
||||
};
|
||||
|
||||
Plugins.toggleInstall = async function (id, version) {
|
||||
pubsub.publish('plugins:toggleInstall', { hostname: os.hostname(), id: id, version: version });
|
||||
return await toggleInstall(id, version);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<input type="hidden" name="timestamp" />
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="uid">[[admin/settings/api:uid]]</label>
|
||||
<input type="number" name="uid" class="form-control" placeholder="1" min="0" />
|
||||
<input type="text" inputmode="numeric" pattern="\d+" name="uid" class="form-control" placeholder="1" />
|
||||
<p class="form-text">
|
||||
[[admin/settings/api:uid-help-text]]
|
||||
</p>
|
||||
|
||||
Reference in New Issue
Block a user