mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-05-07 01:05:36 +02:00
Merge branch 'master' into bootstrap5
This commit is contained in:
18
CHANGELOG.md
18
CHANGELOG.md
@@ -1,3 +1,21 @@
|
||||
#### v2.4.5 (2022-08-22)
|
||||
|
||||
##### Chores
|
||||
|
||||
* incrementing version number - v2.4.4 (d5525c87)
|
||||
* update changelog for v2.4.4 (77e492b8)
|
||||
* incrementing version number - v2.4.3 (9c647c6c)
|
||||
* incrementing version number - v2.4.2 (3aa7b855)
|
||||
* incrementing version number - v2.4.1 (60cbd148)
|
||||
* incrementing version number - v2.4.0 (4834cde3)
|
||||
* incrementing version number - v2.3.1 (d2425942)
|
||||
* incrementing version number - v2.3.0 (046ea120)
|
||||
|
||||
##### Bug Fixes
|
||||
|
||||
* wrap passport.authenticate to pass in keepSessionInfo if not already set (9b96c33d)
|
||||
* parseInt caller.uid closes #10849 (bc37a5c5)
|
||||
|
||||
#### v2.4.4 (2022-08-18)
|
||||
|
||||
##### Chores
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "nodebb",
|
||||
"license": "GPL-3.0",
|
||||
"description": "NodeBB Forum",
|
||||
"version": "2.4.4",
|
||||
"version": "2.4.5",
|
||||
"homepage": "http://www.nodebb.org",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -177,6 +177,12 @@ define('forum/topic', [
|
||||
Topic.applyDropup.call(this);
|
||||
}
|
||||
});
|
||||
hooks.onPage('action:topic.tools.load', ({ element }) => {
|
||||
Topic.applyDropup.call(element.get(0).parentNode);
|
||||
});
|
||||
hooks.onPage('action:post.tools.load', ({ element }) => {
|
||||
Topic.applyDropup.call(element.get(0).parentNode);
|
||||
});
|
||||
}
|
||||
|
||||
function addRepliesHandler() {
|
||||
|
||||
@@ -32,7 +32,6 @@ define('forum/topic/postTools', [
|
||||
|
||||
function renderMenu() {
|
||||
$('[component="topic"]').on('show.bs.dropdown', '.moderator-tools', function () {
|
||||
const self = this;
|
||||
const $this = $(this);
|
||||
const dropdownMenu = $this.find('.dropdown-menu');
|
||||
if (dropdownMenu.html()) {
|
||||
@@ -50,14 +49,14 @@ define('forum/topic/postTools', [
|
||||
|
||||
const html = await app.parseAndTranslate('partials/topic/post-menu-list', data);
|
||||
const clipboard = require('clipboard');
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
const topic = require('forum/topic');
|
||||
|
||||
dropdownMenu.html(html);
|
||||
topic.applyDropup.call(self);
|
||||
// dropdownMenu.get(0).classList.toggle('hidden', false);
|
||||
new clipboard('[data-clipboard-text]');
|
||||
|
||||
hooks.fire('action:post.tools.load');
|
||||
hooks.fire('action:post.tools.load', {
|
||||
element: dropdownMenu,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -180,12 +180,15 @@ define('forum/topic/threadTools', [
|
||||
return;
|
||||
}
|
||||
|
||||
dropdownMenu.toggleClass('hidden', true);
|
||||
socket.emit('topics.loadTopicTools', { tid: ajaxify.data.tid, cid: ajaxify.data.cid }, function (err, data) {
|
||||
if (err) {
|
||||
return alerts.error(err);
|
||||
}
|
||||
app.parseAndTranslate('partials/topic/topic-menu-list', data, function (html) {
|
||||
dropdownMenu.html(html);
|
||||
dropdownMenu.toggleClass('hidden', false);
|
||||
|
||||
hooks.fire('action:topic.tools.load', {
|
||||
element: dropdownMenu,
|
||||
});
|
||||
|
||||
192
test/user.js
192
test/user.js
@@ -2548,21 +2548,45 @@ describe('User', () => {
|
||||
|
||||
describe('hideEmail/hideFullname', () => {
|
||||
const COMMON_PW = '123456';
|
||||
let uid;
|
||||
let jar;
|
||||
let regularUserUid;
|
||||
const hidingUser = {
|
||||
username: 'hiddenemail',
|
||||
email: 'should@be.hidden',
|
||||
fullname: 'baris soner usakli',
|
||||
password: COMMON_PW,
|
||||
};
|
||||
const regularUser = {
|
||||
username: 'regularUser',
|
||||
email: 'regular@example.com',
|
||||
fullname: 'regular user',
|
||||
password: COMMON_PW,
|
||||
};
|
||||
let hidingUserJar;
|
||||
let adminUid;
|
||||
let adminJar;
|
||||
let globalModJar;
|
||||
let regularUserJar;
|
||||
|
||||
before(async () => {
|
||||
uid = await User.create({
|
||||
username: 'hiddenemail',
|
||||
email: 'should@be.hidden',
|
||||
fullname: 'baris soner usakli',
|
||||
});
|
||||
regularUserUid = await User.create({
|
||||
username: 'regularUser',
|
||||
adminUid = await User.create({
|
||||
username: 'adminhideemail',
|
||||
password: COMMON_PW,
|
||||
});
|
||||
({ jar } = await helpers.loginUser('regularUser', COMMON_PW));
|
||||
await groups.join('administrators', adminUid);
|
||||
({ jar: adminJar } = await helpers.loginUser('adminhideemail', COMMON_PW));
|
||||
|
||||
// Edge case: In a grepped test, this user should not be created as the first user to have its email not confirmed
|
||||
hidingUser.uid = await User.create(hidingUser);
|
||||
({ jar: hidingUserJar } = await helpers.loginUser(hidingUser.username, COMMON_PW));
|
||||
|
||||
const globalModUid = await User.create({
|
||||
username: 'globalmodhideemail',
|
||||
password: COMMON_PW,
|
||||
});
|
||||
await groups.join('Global Moderators', globalModUid);
|
||||
({ jar: globalModJar } = await helpers.loginUser('globalmodhideemail', COMMON_PW));
|
||||
|
||||
regularUser.uid = await User.create(regularUser);
|
||||
({ jar: regularUserJar } = await helpers.loginUser(regularUser.username, COMMON_PW));
|
||||
});
|
||||
|
||||
after((done) => {
|
||||
@@ -2571,22 +2595,152 @@ describe('User', () => {
|
||||
done();
|
||||
});
|
||||
|
||||
it('should hide email and fullname', async () => {
|
||||
async function assertPrivacy({ expectVisible, jar, v3Api, emailOnly }) {
|
||||
const path = v3Api ? `v3/users/${hidingUser.uid}` : `user/${hidingUser.username}`;
|
||||
const response = await requestAsync(`${nconf.get('url')}/api/${path}`, { json: true, jar });
|
||||
const { response: userData } = v3Api ? response : { response };
|
||||
|
||||
assert.strictEqual(userData.email, expectVisible ? hidingUser.email : '');
|
||||
if (!emailOnly) {
|
||||
assert.strictEqual(userData.fullname, expectVisible ? hidingUser.fullname : '');
|
||||
}
|
||||
}
|
||||
|
||||
it('should hide unconfirmed emails on profile pages', async () => {
|
||||
await assertPrivacy({ v3Api: false, emailOnly: true });
|
||||
await assertPrivacy({ v3Api: false, jar: hidingUserJar, emailOnly: true });
|
||||
await assertPrivacy({ v3Api: false, jar: adminJar, emailOnly: true });
|
||||
await assertPrivacy({ v3Api: false, jar: globalModJar, emailOnly: true });
|
||||
await assertPrivacy({ v3Api: false, jar: regularUserJar, emailOnly: true });
|
||||
|
||||
// Let's confirm for afterwards
|
||||
await User.email.confirmByUid(hidingUser.uid);
|
||||
});
|
||||
|
||||
it('should hide from guests by default', async () => {
|
||||
await assertPrivacy({ v3Api: false });
|
||||
});
|
||||
|
||||
it('should hide from unprivileged users by default', async () => {
|
||||
await assertPrivacy({ v3Api: false, jar: regularUserJar });
|
||||
await assertPrivacy({ v3Api: true, jar: regularUserJar });
|
||||
});
|
||||
|
||||
it('should be visible to self by default', async () => {
|
||||
await assertPrivacy({ v3Api: false, jar: hidingUserJar, expectVisible: true });
|
||||
await assertPrivacy({ v3Api: true, jar: hidingUserJar, expectVisible: true });
|
||||
});
|
||||
|
||||
it('should be visible to privileged users by default', async () => {
|
||||
await assertPrivacy({ v3Api: false, jar: adminJar, expectVisible: true });
|
||||
await assertPrivacy({ v3Api: true, jar: adminJar, expectVisible: true });
|
||||
await assertPrivacy({ v3Api: false, jar: globalModJar, expectVisible: true });
|
||||
await assertPrivacy({ v3Api: true, jar: globalModJar, expectVisible: true });
|
||||
});
|
||||
|
||||
it('should hide from guests (system-wide: hide, by-user: hide)', async () => {
|
||||
meta.config.hideEmail = 1;
|
||||
meta.config.hideFullname = 1;
|
||||
// Explicitly set user's privacy settings to hide its email and fullname
|
||||
const data = { uid: hidingUser.uid, settings: { showemail: 0, showfullname: 0 } };
|
||||
await apiUser.updateSettings({ uid: hidingUser.uid }, data);
|
||||
|
||||
await assertPrivacy({ v3Api: false });
|
||||
});
|
||||
|
||||
it('should hide from unprivileged users (system-wide: hide, by-user: hide)', async () => {
|
||||
await assertPrivacy({ v3Api: false, jar: regularUserJar });
|
||||
await assertPrivacy({ v3Api: true, jar: regularUserJar });
|
||||
});
|
||||
|
||||
it('should be visible to self (system-wide: hide, by-user: hide)', async () => {
|
||||
await assertPrivacy({ v3Api: false, jar: hidingUserJar, expectVisible: true });
|
||||
await assertPrivacy({ v3Api: true, jar: hidingUserJar, expectVisible: true });
|
||||
});
|
||||
|
||||
it('should be visible to privileged users (system-wide: hide, by-user: hide)', async () => {
|
||||
await assertPrivacy({ v3Api: false, jar: adminJar, expectVisible: true });
|
||||
await assertPrivacy({ v3Api: true, jar: adminJar, expectVisible: true });
|
||||
await assertPrivacy({ v3Api: false, jar: globalModJar, expectVisible: true });
|
||||
await assertPrivacy({ v3Api: true, jar: globalModJar, expectVisible: true });
|
||||
});
|
||||
|
||||
it('should hide from guests (system-wide: show, by-user: hide)', async () => {
|
||||
meta.config.hideEmail = 0;
|
||||
meta.config.hideFullname = 0;
|
||||
|
||||
await assertPrivacy({ v3Api: false });
|
||||
});
|
||||
|
||||
it('should hide from unprivileged users (system-wide: show, by-user: hide)', async () => {
|
||||
await assertPrivacy({ v3Api: false, jar: regularUserJar });
|
||||
await assertPrivacy({ v3Api: true, jar: regularUserJar });
|
||||
});
|
||||
|
||||
it('should be visible to self (system-wide: show, by-user: hide)', async () => {
|
||||
await assertPrivacy({ v3Api: false, jar: hidingUserJar, expectVisible: true });
|
||||
await assertPrivacy({ v3Api: true, jar: hidingUserJar, expectVisible: true });
|
||||
});
|
||||
|
||||
it('should be visible to privileged users (system-wide: show, by-user: hide)', async () => {
|
||||
await assertPrivacy({ v3Api: false, jar: adminJar, expectVisible: true });
|
||||
await assertPrivacy({ v3Api: true, jar: adminJar, expectVisible: true });
|
||||
await assertPrivacy({ v3Api: false, jar: globalModJar, expectVisible: true });
|
||||
await assertPrivacy({ v3Api: true, jar: globalModJar, expectVisible: true });
|
||||
});
|
||||
|
||||
it('should be visible to guests (system-wide: show, by-user: show)', async () => {
|
||||
meta.config.hideEmail = 0;
|
||||
meta.config.hideFullname = 0;
|
||||
|
||||
// Set user's individual privacy settings to show its email and fullname
|
||||
const data = { uid: hidingUser.uid, settings: { showemail: 1, showfullname: 1 } };
|
||||
await apiUser.updateSettings({ uid: hidingUser.uid }, data);
|
||||
|
||||
await assertPrivacy({ v3Api: false, expectVisible: true });
|
||||
});
|
||||
|
||||
it('should be visible to unprivileged users (system-wide: show, by-user: show)', async () => {
|
||||
await assertPrivacy({ v3Api: false, jar: regularUserJar, expectVisible: true });
|
||||
await assertPrivacy({ v3Api: true, jar: regularUserJar, expectVisible: true });
|
||||
});
|
||||
|
||||
// System-wide "hide" prioritized over individual users' settings
|
||||
it('should hide from guests (system-wide: hide, by-user: show)', async () => {
|
||||
meta.config.hideEmail = 1;
|
||||
meta.config.hideFullname = 1;
|
||||
|
||||
const userData1 = await requestAsync(`${nconf.get('url')}/api/user/hiddenemail`, { json: true });
|
||||
assert.strictEqual(userData1.fullname, '');
|
||||
assert.strictEqual(userData1.email, '');
|
||||
await assertPrivacy({ v3Api: false });
|
||||
});
|
||||
|
||||
const { response } = await requestAsync(`${nconf.get('url')}/api/v3/users/${uid}`, { json: true, jar: jar });
|
||||
assert.strictEqual(response.fullname, '');
|
||||
assert.strictEqual(response.email, '');
|
||||
it('should hide from unprivileged users (system-wide: hide, by-user: show)', async () => {
|
||||
await assertPrivacy({ v3Api: false, jar: regularUserJar });
|
||||
await assertPrivacy({ v3Api: true, jar: regularUserJar });
|
||||
});
|
||||
|
||||
it('should be visible to self (system-wide: hide, by-user: show)', async () => {
|
||||
await assertPrivacy({ v3Api: false, jar: hidingUserJar, expectVisible: true });
|
||||
await assertPrivacy({ v3Api: true, jar: hidingUserJar, expectVisible: true });
|
||||
});
|
||||
|
||||
it('should be visible to privileged users (system-wide: hide, by-user: show)', async () => {
|
||||
await assertPrivacy({ v3Api: false, jar: adminJar, expectVisible: true });
|
||||
await assertPrivacy({ v3Api: true, jar: adminJar, expectVisible: true });
|
||||
await assertPrivacy({ v3Api: false, jar: globalModJar, expectVisible: true });
|
||||
await assertPrivacy({ v3Api: true, jar: globalModJar, expectVisible: true });
|
||||
});
|
||||
|
||||
it('should handle array of user data (system-wide: hide)', async () => {
|
||||
const userData = await User.hidePrivateData([hidingUser, regularUser], hidingUser.uid);
|
||||
assert.strictEqual(userData[0].fullname, hidingUser.fullname);
|
||||
assert.strictEqual(userData[0].email, hidingUser.email);
|
||||
assert.strictEqual(userData[1].fullname, '');
|
||||
assert.strictEqual(userData[1].email, '');
|
||||
});
|
||||
|
||||
it('should hide fullname in topic list and topic', (done) => {
|
||||
Topics.post({
|
||||
uid: uid,
|
||||
uid: hidingUser.uid,
|
||||
title: 'Topic hidden',
|
||||
content: 'lorem ipsum',
|
||||
cid: testCid,
|
||||
|
||||
Reference in New Issue
Block a user