mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-08-07 17:10:51 +02:00
Merge branch 'develop' into bootstrap5
This commit is contained in:
@@ -3,8 +3,9 @@
|
||||
const cacheController = module.exports;
|
||||
|
||||
const utils = require('../../utils');
|
||||
const plugins = require('../../plugins');
|
||||
|
||||
cacheController.get = function (req, res) {
|
||||
cacheController.get = async function (req, res) {
|
||||
const postCache = require('../../posts/cache');
|
||||
const groupCache = require('../../groups').cache;
|
||||
const { objectCache } = require('../../database');
|
||||
@@ -23,29 +24,33 @@ cacheController.get = function (req, res) {
|
||||
misses: utils.addCommas(String(cache.misses)),
|
||||
hitRatio: ((cache.hits / (cache.hits + cache.misses) || 0)).toFixed(4),
|
||||
enabled: cache.enabled,
|
||||
ttl: cache.ttl,
|
||||
};
|
||||
}
|
||||
|
||||
const data = {
|
||||
postCache: getInfo(postCache),
|
||||
groupCache: getInfo(groupCache),
|
||||
localCache: getInfo(localCache),
|
||||
let caches = {
|
||||
post: postCache,
|
||||
group: groupCache,
|
||||
local: localCache,
|
||||
};
|
||||
|
||||
if (objectCache) {
|
||||
data.objectCache = getInfo(objectCache);
|
||||
caches.object = objectCache;
|
||||
}
|
||||
caches = await plugins.hooks.fire('filter:admin.cache.get', caches);
|
||||
for (const [key, value] of Object.entries(caches)) {
|
||||
caches[key] = getInfo(value);
|
||||
}
|
||||
|
||||
res.render('admin/advanced/cache', data);
|
||||
res.render('admin/advanced/cache', { caches });
|
||||
};
|
||||
|
||||
cacheController.dump = function (req, res, next) {
|
||||
const caches = {
|
||||
cacheController.dump = async function (req, res, next) {
|
||||
let caches = {
|
||||
post: require('../../posts/cache'),
|
||||
object: require('../../database').objectCache,
|
||||
group: require('../../groups').cache,
|
||||
local: require('../../cache'),
|
||||
};
|
||||
caches = await plugins.hooks.fire('filter:admin.cache.get', caches);
|
||||
if (!caches[req.query.name]) {
|
||||
return next();
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ const groups = require('../../groups');
|
||||
const meta = require('../../meta');
|
||||
const pagination = require('../../pagination');
|
||||
const events = require('../../events');
|
||||
const slugify = require('../../slugify');
|
||||
|
||||
const groupsController = module.exports;
|
||||
|
||||
@@ -31,7 +32,8 @@ groupsController.list = async function (req, res) {
|
||||
};
|
||||
|
||||
groupsController.get = async function (req, res, next) {
|
||||
const groupName = req.params.name;
|
||||
const slug = slugify(req.params.name);
|
||||
const groupName = await groups.getGroupNameByGroupSlug(slug);
|
||||
const [groupNames, group] = await Promise.all([
|
||||
getGroupNames(),
|
||||
groups.get(groupName, { uid: req.uid, truncateUserList: true, userListCount: 20 }),
|
||||
|
||||
@@ -339,19 +339,7 @@ authenticationController.doLogin = async function (req, uid) {
|
||||
return;
|
||||
}
|
||||
const loginAsync = util.promisify(req.login).bind(req);
|
||||
|
||||
const { reroll } = req.res.locals;
|
||||
if (reroll !== false) {
|
||||
const regenerateSession = util.promisify(req.session.regenerate).bind(req.session);
|
||||
|
||||
const sessionData = { ...req.session };
|
||||
await regenerateSession();
|
||||
for (const [prop, value] of Object.entries(sessionData)) {
|
||||
req.session[prop] = value;
|
||||
}
|
||||
}
|
||||
|
||||
await loginAsync({ uid: uid }, { keepSessionInfo: true });
|
||||
await loginAsync({ uid: uid }, { keepSessionInfo: req.res.locals !== false });
|
||||
await authenticationController.onSuccessfulLogin(req, uid);
|
||||
};
|
||||
|
||||
|
||||
@@ -434,11 +434,22 @@ helpers.formatApiResponse = async (statusCode, res, payload) => {
|
||||
res.set('cache-control', 'private');
|
||||
}
|
||||
|
||||
let code = 'ok';
|
||||
let message = 'OK';
|
||||
switch (statusCode) {
|
||||
case 202:
|
||||
code = 'accepted';
|
||||
message = 'Accepted';
|
||||
break;
|
||||
|
||||
case 204:
|
||||
code = 'no-content';
|
||||
message = 'No Content';
|
||||
break;
|
||||
}
|
||||
|
||||
res.status(statusCode).json({
|
||||
status: {
|
||||
code: 'ok',
|
||||
message: 'OK',
|
||||
},
|
||||
status: { code, message },
|
||||
response: payload || {},
|
||||
});
|
||||
} else if (payload instanceof Error) {
|
||||
|
||||
@@ -88,6 +88,7 @@ topicsController.get = async function getTopic(req, res, next) {
|
||||
topicData['reputation:disabled'] = meta.config['reputation:disabled'];
|
||||
topicData['downvote:disabled'] = meta.config['downvote:disabled'];
|
||||
topicData['feeds:disableRSS'] = meta.config['feeds:disableRSS'] || 0;
|
||||
topicData['signatures:hideDuplicates'] = meta.config['signatures:hideDuplicates'];
|
||||
topicData.bookmarkThreshold = meta.config.bookmarkThreshold;
|
||||
topicData.necroThreshold = meta.config.necroThreshold;
|
||||
topicData.postEditDuration = meta.config.postEditDuration;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const winston = require('winston');
|
||||
|
||||
const user = require('../user');
|
||||
const privileges = require('../privileges');
|
||||
@@ -90,7 +91,10 @@ userController.exportProfile = async function (req, res, next) {
|
||||
sendExport(`${res.locals.uid}_profile.json`, 'application/json', res, next);
|
||||
};
|
||||
|
||||
// DEPRECATED; Remove in NodeBB v3.0.0
|
||||
function sendExport(filename, type, res, next) {
|
||||
winston.warn(`[users/export] Access via page API is deprecated, use GET /api/v3/users/:uid/exports/:type instead.`);
|
||||
|
||||
res.sendFile(filename, {
|
||||
root: path.join(__dirname, '../../build/export'),
|
||||
headers: {
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
const util = require('util');
|
||||
const nconf = require('nconf');
|
||||
const path = require('path');
|
||||
const crypto = require('crypto');
|
||||
const fs = require('fs').promises;
|
||||
|
||||
const db = require('../../database');
|
||||
const api = require('../../api');
|
||||
@@ -15,6 +18,12 @@ const helpers = require('../helpers');
|
||||
|
||||
const Users = module.exports;
|
||||
|
||||
const exportMetadata = new Map([
|
||||
['posts', ['csv', 'text/csv']],
|
||||
['uploads', ['zip', 'application/zip']],
|
||||
['profile', ['json', 'application/json']],
|
||||
]);
|
||||
|
||||
const hasAdminPrivilege = async (uid, privilege) => {
|
||||
const ok = await privileges.admin.can(`admin:${privilege}`, uid);
|
||||
if (!ok) {
|
||||
@@ -296,3 +305,52 @@ Users.confirmEmail = async (req, res) => {
|
||||
helpers.formatApiResponse(404, res);
|
||||
}
|
||||
};
|
||||
|
||||
const prepareExport = async (req, res) => {
|
||||
const [extension] = exportMetadata.get(req.params.type);
|
||||
const filename = `${req.params.uid}_${req.params.type}.${extension}`;
|
||||
try {
|
||||
const stat = await fs.stat(path.join(__dirname, '../../../build/export', filename));
|
||||
const modified = new Date(stat.mtimeMs);
|
||||
res.set('Last-Modified', modified.toUTCString());
|
||||
res.set('ETag', `"${crypto.createHash('md5').update(String(stat.mtimeMs)).digest('hex')}"`);
|
||||
res.status(204);
|
||||
return true;
|
||||
} catch (e) {
|
||||
res.status(404);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
Users.checkExportByType = async (req, res) => {
|
||||
await prepareExport(req, res);
|
||||
res.end();
|
||||
};
|
||||
|
||||
Users.getExportByType = async (req, res) => {
|
||||
const [extension, mime] = exportMetadata.get(req.params.type);
|
||||
const filename = `${req.params.uid}_${req.params.type}.${extension}`;
|
||||
|
||||
const exists = await prepareExport(req, res);
|
||||
if (!exists) {
|
||||
return res.end();
|
||||
}
|
||||
|
||||
res.status(200);
|
||||
res.sendFile(filename, {
|
||||
root: path.join(__dirname, '../../../build/export'),
|
||||
headers: {
|
||||
'Content-Type': mime,
|
||||
'Content-Disposition': `attachment; filename=${filename}`,
|
||||
},
|
||||
}, (err) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Users.generateExportsByType = async (req, res) => {
|
||||
await api.users.generateExport(req, req.params);
|
||||
helpers.formatApiResponse(202, res);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user