mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-03-12 23:50:47 +01:00
Merge branch 'master' into webpack5
This commit is contained in:
@@ -22,4 +22,4 @@ ENV NODE_ENV=production \
|
||||
|
||||
EXPOSE 4567
|
||||
|
||||
CMD node ./nodebb build ; node ./nodebb start
|
||||
CMD test -n "${SETUP}" && ./nodebb setup || node ./nodebb build; node ./nodebb start
|
||||
|
||||
@@ -89,10 +89,10 @@
|
||||
"nodebb-plugin-2factor": "3.0.4",
|
||||
"nodebb-plugin-composer-default": "7.0.20",
|
||||
"nodebb-plugin-dbsearch": "5.1.1",
|
||||
"nodebb-plugin-emoji": "3.5.12",
|
||||
"nodebb-plugin-emoji": "3.5.16",
|
||||
"nodebb-plugin-emoji-android": "2.0.5",
|
||||
"nodebb-plugin-markdown": "9.0.6",
|
||||
"nodebb-plugin-mentions": "3.0.4",
|
||||
"nodebb-plugin-markdown": "9.0.7",
|
||||
"nodebb-plugin-mentions": "3.0.5",
|
||||
"nodebb-plugin-spam-be-gone": "0.7.13",
|
||||
"nodebb-rewards-essentials": "0.2.1",
|
||||
"nodebb-theme-lavender": "5.3.2",
|
||||
|
||||
@@ -436,7 +436,7 @@ ajaxify.widgets = { render: render };
|
||||
|
||||
ajaxify.loadTemplate = function (template, callback) {
|
||||
$.ajax({
|
||||
url: `${config.assetBaseUrl}/templates/${template}.js`,
|
||||
url: `${config.asset_base_url}/templates/${template}.js`,
|
||||
dataType: 'text',
|
||||
success: function (script) {
|
||||
var context = {
|
||||
|
||||
@@ -5,7 +5,7 @@ const factory = require('./translator.common');
|
||||
define('translator', ['jquery', 'utils'], function (jQuery, utils) {
|
||||
function loadClient(language, namespace) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
jQuery.getJSON([config.assetBaseUrl, 'language', language, namespace].join('/') + '.json?' + config['cache-buster'], function (data) {
|
||||
jQuery.getJSON([config.asset_base_url, 'language', language, namespace].join('/') + '.json?' + config['cache-buster'], function (data) {
|
||||
const payload = {
|
||||
language: language,
|
||||
namespace: namespace,
|
||||
|
||||
@@ -14,6 +14,7 @@ const apiController = module.exports;
|
||||
|
||||
const relative_path = nconf.get('relative_path');
|
||||
const upload_url = nconf.get('upload_url');
|
||||
const asset_base_url = nconf.get('asset_base_url');
|
||||
const socketioTransports = nconf.get('socket.io:transports') || ['polling', 'websocket'];
|
||||
const socketioOrigins = nconf.get('socket.io:origins');
|
||||
const websocketAddress = nconf.get('socket.io:address') || '';
|
||||
@@ -22,7 +23,8 @@ apiController.loadConfig = async function (req) {
|
||||
const config = {
|
||||
relative_path,
|
||||
upload_url,
|
||||
assetBaseUrl: `${relative_path}/assets`,
|
||||
asset_base_url,
|
||||
assetBaseUrl: asset_base_url, // deprecate in 1.20.x
|
||||
siteTitle: validator.escape(String(meta.config.title || meta.config.browserTitle || 'NodeBB')),
|
||||
browserTitle: validator.escape(String(meta.config.browserTitle || meta.config.title || 'NodeBB')),
|
||||
titleLayout: (meta.config.titleLayout || '{pageTitle} | {browserTitle}').replace(/{/g, '{').replace(/}/g, '}'),
|
||||
|
||||
@@ -46,22 +46,54 @@ questions.optional = [
|
||||
},
|
||||
];
|
||||
|
||||
function checkSetupFlag() {
|
||||
let setupVal = install.values;
|
||||
function checkSetupFlagEnv() {
|
||||
let setupVal = install.values || {};
|
||||
|
||||
const envConfMap = {
|
||||
NODEBB_URL: 'url',
|
||||
NODEBB_PORT: 'port',
|
||||
NODEBB_ADMIN_USERNAME: 'admin:username',
|
||||
NODEBB_ADMIN_PASSWORD: 'admin:password',
|
||||
NODEBB_ADMIN_EMAIL: 'admin:email',
|
||||
NODEBB_DB: 'database',
|
||||
NODEBB_DB_HOST: 'host',
|
||||
NODEBB_DB_PORT: 'port',
|
||||
NODEBB_DB_USER: 'username',
|
||||
NODEBB_DB_PASSWORD: 'password',
|
||||
NODEBB_DB_NAME: 'database',
|
||||
NODEBB_DB_SSL: 'ssl',
|
||||
};
|
||||
|
||||
// Set setup values from env vars (if set)
|
||||
winston.info('[install/checkSetupFlagEnv] checking env vars for setup info...');
|
||||
|
||||
Object.entries(process.env).forEach(([evName, evValue]) => { // get setup values from env
|
||||
if (evName.startsWith('NODEBB_DB_')) {
|
||||
setupVal[`${process.env.NODEBB_DB}:${envConfMap[evName]}`] = evValue;
|
||||
} else if (evName.startsWith('NODEBB_')) {
|
||||
setupVal[envConfMap[evName]] = evValue;
|
||||
}
|
||||
});
|
||||
|
||||
setupVal['admin:password:confirm'] = setupVal['admin:password'];
|
||||
|
||||
// try to get setup values from json, if successful this overwrites all values set by env
|
||||
// TODO: better behaviour would be to support overrides per value, i.e. in order of priority (generic pattern):
|
||||
// flag, env, config file, default
|
||||
try {
|
||||
if (nconf.get('setup')) {
|
||||
setupVal = JSON.parse(nconf.get('setup'));
|
||||
const setupJSON = JSON.parse(nconf.get('setup'));
|
||||
setupVal = { ...setupVal, ...setupJSON };
|
||||
}
|
||||
} catch (err) {
|
||||
winston.error('Invalid json in nconf.get(\'setup\'), ignoring setup values');
|
||||
winston.error('[install/checkSetupFlagEnv] invalid json in nconf.get(\'setup\'), ignoring setup values from json');
|
||||
}
|
||||
|
||||
if (setupVal && typeof setupVal === 'object') {
|
||||
if (setupVal['admin:username'] && setupVal['admin:password'] && setupVal['admin:password:confirm'] && setupVal['admin:email']) {
|
||||
install.values = setupVal;
|
||||
} else {
|
||||
winston.error('Required values are missing for automated setup:');
|
||||
winston.error('[install/checkSetupFlagEnv] required values are missing for automated setup:');
|
||||
if (!setupVal['admin:username']) {
|
||||
winston.error(' admin:username');
|
||||
}
|
||||
@@ -95,7 +127,7 @@ function checkCIFlag() {
|
||||
if (ciVals.hasOwnProperty('host') && ciVals.hasOwnProperty('port') && ciVals.hasOwnProperty('database')) {
|
||||
install.ciVals = ciVals;
|
||||
} else {
|
||||
winston.error('Required values are missing for automated CI integration:');
|
||||
winston.error('[install/checkCIFlag] required values are missing for automated CI integration:');
|
||||
if (!ciVals.hasOwnProperty('host')) {
|
||||
winston.error(' host');
|
||||
}
|
||||
@@ -521,7 +553,7 @@ async function checkUpgrade() {
|
||||
|
||||
install.setup = async function () {
|
||||
try {
|
||||
checkSetupFlag();
|
||||
checkSetupFlagEnv();
|
||||
checkCIFlag();
|
||||
await setupConfig();
|
||||
await setupDefaultConfigs();
|
||||
|
||||
@@ -95,6 +95,7 @@ function loadConfig(configFile) {
|
||||
nconf.set('secure', urlObject.protocol === 'https:');
|
||||
nconf.set('use_port', !!urlObject.port);
|
||||
nconf.set('relative_path', relativePath);
|
||||
nconf.set('asset_base_url', `${relativePath}/assets`);
|
||||
nconf.set('port', nconf.get('PORT') || nconf.get('port') || urlObject.port || (nconf.get('PORT_ENV_VAR') ? nconf.get(nconf.get('PORT_ENV_VAR')) : false) || 4567);
|
||||
|
||||
// cookies don't provide isolation by port: http://stackoverflow.com/a/16328399/122353
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/* eslint-disable no-await-in-loop */
|
||||
|
||||
'use strict';
|
||||
|
||||
const crypto = require('crypto');
|
||||
@@ -14,13 +16,11 @@ module.exports = {
|
||||
const { progress } = this;
|
||||
|
||||
await batch.processSortedSet('users:joindate', async (uids) => {
|
||||
let keys = uids.map(uid => `uid:${uid}:uploads`);
|
||||
const exists = await db.exists(keys);
|
||||
keys = keys.filter((key, idx) => exists[idx]);
|
||||
const keys = uids.map(uid => `uid:${uid}:uploads`);
|
||||
progress.incr(uids.length);
|
||||
|
||||
progress.incr(uids.length - keys.length);
|
||||
|
||||
await Promise.all(keys.map(async (key, idx) => {
|
||||
for (let idx = 0; idx < uids.length; idx++) {
|
||||
const key = keys[idx];
|
||||
// Rename the paths within
|
||||
let uploads = await db.getSortedSetRangeWithScores(key, 0, -1);
|
||||
|
||||
@@ -37,9 +37,7 @@ module.exports = {
|
||||
// Add uid to the upload's hash object
|
||||
uploads = await db.getSortedSetMembers(key);
|
||||
await db.setObjectBulk(uploads.map(relativePath => [`upload:${md5(relativePath)}`, { uid: uids[idx] }]));
|
||||
|
||||
progress.incr();
|
||||
}));
|
||||
}
|
||||
}, {
|
||||
batch: 100,
|
||||
progress: progress,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/* eslint-disable no-await-in-loop */
|
||||
|
||||
'use strict';
|
||||
|
||||
const crypto = require('crypto');
|
||||
@@ -18,14 +20,14 @@ module.exports = {
|
||||
const exists = await db.exists(keys);
|
||||
keys = keys.filter((key, idx) => exists[idx]);
|
||||
|
||||
progress.incr(pids.length - keys.length);
|
||||
progress.incr(pids.length);
|
||||
|
||||
await Promise.all(keys.map(async (key) => {
|
||||
for (const key of keys) {
|
||||
// Rename the paths within
|
||||
let uploads = await db.getSortedSetRangeWithScores(key, 0, -1);
|
||||
|
||||
// Don't process those that have already the right format
|
||||
uploads = uploads.filter(upload => !upload.value.startsWith('files/'));
|
||||
uploads = uploads.filter(upload => upload && upload.value && !upload.value.startsWith('files/'));
|
||||
|
||||
// Rename the zset members
|
||||
await db.sortedSetRemove(key, uploads.map(upload => upload.value));
|
||||
@@ -38,12 +40,21 @@ module.exports = {
|
||||
// Rename the object and pids zsets
|
||||
const hashes = uploads.map(upload => md5(upload.value));
|
||||
const newHashes = uploads.map(upload => md5(`files/${upload.value}`));
|
||||
const promises = hashes.map((hash, idx) => db.rename(`upload:${hash}`, `upload:${newHashes[idx]}`));
|
||||
promises.concat(hashes.map((hash, idx) => db.rename(`upload:${hash}:pids`, `upload:${newHashes[idx]}:pids`)));
|
||||
|
||||
await Promise.all(promises);
|
||||
progress.incr();
|
||||
}));
|
||||
// cant use db.rename since `fix_user_uploads_zset.js` upgrade script already creates
|
||||
// `upload:md5(upload.value) hash, trying to rename to existing key results in dupe error
|
||||
const oldData = await db.getObjects(hashes.map(hash => `upload:${hash}`));
|
||||
const bulkSet = [];
|
||||
oldData.forEach((data, idx) => {
|
||||
if (data) {
|
||||
bulkSet.push([`upload:${newHashes[idx]}`, data]);
|
||||
}
|
||||
});
|
||||
await db.setObjectBulk(bulkSet);
|
||||
await db.deleteAll(hashes.map(hash => `upload:${hash}`));
|
||||
|
||||
await Promise.all(hashes.map((hash, idx) => db.rename(`upload:${hash}:pids`, `upload:${newHashes[idx]}:pids`)));
|
||||
}
|
||||
}, {
|
||||
batch: 100,
|
||||
progress: progress,
|
||||
|
||||
@@ -108,8 +108,11 @@ module.exports = function (User) {
|
||||
`uid:${uid}:notifications:read`,
|
||||
`uid:${uid}:notifications:unread`,
|
||||
`uid:${uid}:bookmarks`,
|
||||
`uid:${uid}:tids_read`,
|
||||
`uid:${uid}:tids_unread`,
|
||||
`uid:${uid}:followed_tids`,
|
||||
`uid:${uid}:ignored_tids`,
|
||||
`uid:${uid}:blocked_uids`,
|
||||
`user:${uid}:settings`,
|
||||
`user:${uid}:usernames`,
|
||||
`user:${uid}:emails`,
|
||||
|
||||
@@ -38,6 +38,7 @@ nconf.defaults({
|
||||
const urlObject = url.parse(nconf.get('url'));
|
||||
const relativePath = urlObject.pathname !== '/' ? urlObject.pathname : '';
|
||||
nconf.set('relative_path', relativePath);
|
||||
nconf.set('asset_base_url', `${relativePath}/assets`);
|
||||
nconf.set('upload_path', path.join(nconf.get('base_dir'), nconf.get('upload_path')));
|
||||
nconf.set('upload_url', '/assets/uploads');
|
||||
nconf.set('url_parsed', urlObject);
|
||||
|
||||
Reference in New Issue
Block a user