Merge commit 'bf4e257c83988f5231721473acdb3c919d651d1c' into v3.x

This commit is contained in:
Misty Release Bot
2024-03-27 14:15:04 +00:00
9 changed files with 106 additions and 24 deletions

View File

@@ -1,3 +1,61 @@
#### v3.7.1 (2024-03-14)
##### Chores
* up harmony (1b24b337)
* up harmony (b6c3a9d2)
* up harmony (f107a7ff)
* incrementing version number - v3.7.0 (9a6153d7)
* update changelog for v3.7.0 (f1f81b17)
* incrementing version number - v3.6.7 (86a17e38)
* incrementing version number - v3.6.6 (6604bf37)
* incrementing version number - v3.6.5 (6c653625)
* incrementing version number - v3.6.4 (83d131b4)
* incrementing version number - v3.6.3 (fc7d2bfd)
* incrementing version number - v3.6.2 (0f577a57)
* incrementing version number - v3.6.1 (f1a69468)
* incrementing version number - v3.6.0 (4cdf85f8)
* incrementing version number - v3.5.3 (ed0e8783)
* incrementing version number - v3.5.2 (52fbb2da)
* incrementing version number - v3.5.1 (4c543488)
* incrementing version number - v3.5.0 (d06fb4f0)
* incrementing version number - v3.4.3 (5c984250)
* incrementing version number - v3.4.2 (3f0dac38)
* incrementing version number - v3.4.1 (01e69574)
* incrementing version number - v3.4.0 (fd9247c5)
* incrementing version number - v3.3.9 (5805e770)
* incrementing version number - v3.3.8 (a5603565)
* incrementing version number - v3.3.7 (b26f1744)
* incrementing version number - v3.3.6 (7fb38792)
* incrementing version number - v3.3.4 (a67f84ea)
* incrementing version number - v3.3.3 (f94d239b)
* incrementing version number - v3.3.2 (ec9dac97)
* incrementing version number - v3.3.1 (151cc68f)
* incrementing version number - v3.3.0 (fc1ad70f)
* incrementing version number - v3.2.3 (b06d3e63)
* incrementing version number - v3.2.2 (758ecfcd)
* incrementing version number - v3.2.1 (20145074)
* incrementing version number - v3.2.0 (9ecac38e)
* incrementing version number - v3.1.7 (0b4e81ab)
* incrementing version number - v3.1.6 (b3a3b130)
* incrementing version number - v3.1.5 (ec19343a)
* incrementing version number - v3.1.4 (2452783c)
* incrementing version number - v3.1.3 (3b4e9d3f)
* incrementing version number - v3.1.2 (40fa3489)
* incrementing version number - v3.1.1 (40250733)
* incrementing version number - v3.1.0 (0cb386bd)
* incrementing version number - v3.0.1 (26f6ea49)
* incrementing version number - v3.0.0 (224e08cd)
##### New Features
* allow setting max-old-space-size in config (d1ce594c)
##### Bug Fixes
* #12408, fix mem leak due to mongodb 6.4.0 (285293c4)
* tids:create on topic post (3b48695b)
#### v3.7.0 (2024-03-06)
##### Chores

View File

@@ -103,8 +103,8 @@
"nodebb-plugin-ntfy": "1.7.3",
"nodebb-plugin-spam-be-gone": "2.2.1",
"nodebb-rewards-essentials": "1.0.0",
"nodebb-theme-harmony": "1.2.40",
"nodebb-theme-lavender": "7.1.7",
"nodebb-theme-harmony": "1.2.44",
"nodebb-theme-lavender": "7.1.8",
"nodebb-theme-peace": "2.2.4",
"nodebb-theme-persona": "13.3.11",
"nodebb-widget-essentials": "7.0.15",

View File

@@ -28,8 +28,10 @@ module.exports = function (Groups) {
Groups.ownership.rescind = async function (toUid, groupName) {
// If the owners set only contains one member (and toUid is that member), error out!
const numOwners = await db.setCount(`group:${groupName}:owners`);
const isOwner = await db.isSortedSetMember(`group:${groupName}:owners`);
const [numOwners, isOwner] = await Promise.all([
db.setCount(`group:${groupName}:owners`),
db.isSetMember(`group:${groupName}:owners`, toUid),
]);
if (numOwners <= 1 && isOwner) {
throw new Error('[[error:group-needs-owner]]');
}

View File

@@ -22,7 +22,7 @@ let sanitizeConfig = {
a: ['href', 'name', 'hreflang', 'media', 'rel', 'target', 'type'],
img: ['alt', 'height', 'ismap', 'src', 'usemap', 'width', 'srcset'],
iframe: ['height', 'name', 'src', 'width'],
video: ['autoplay', 'controls', 'height', 'loop', 'muted', 'poster', 'preload', 'src', 'width'],
video: ['autoplay', 'playsinline', 'controls', 'height', 'loop', 'muted', 'poster', 'preload', 'src', 'width'],
audio: ['autoplay', 'controls', 'loop', 'muted', 'preload', 'src'],
source: ['type', 'src', 'srcset', 'sizes', 'media', 'height', 'width'],
embed: ['height', 'src', 'type', 'width'],

View File

@@ -11,6 +11,7 @@ const topics = require('../topics');
const notifications = require('../notifications');
const utils = require('../utils');
const events = require('../events');
const translator = require('../translator');
const api = require('../api');
const sockets = require('.');
@@ -159,10 +160,13 @@ async function canEditQueue(socket, data, action) {
}
async function sendQueueNotification(type, targetUid, path, notificationText) {
const bodyShort = notificationText ?
translator.compile(`notifications:${type}`, notificationText) :
translator.compile(`notifications:${type}`);
const notifData = {
type: type,
nid: `${type}-${targetUid}-${path}`,
bodyShort: notificationText ? `[[notifications:${type}, ${notificationText}]]` : `[[notifications:${type}]]`,
bodyShort: bodyShort,
path: path,
};
if (parseInt(meta.config.postQueueNotificationUid, 10) > 0) {

View File

@@ -159,18 +159,24 @@ module.exports = function (Topics) {
return tids;
}
const topicData = await Topics.getTopicsFields(tids, [
'tid', 'timestamp', 'lastposttime', 'upvotes', 'downvotes', 'postcount', 'pinned',
]);
const sortMap = {
recent: sortRecent,
old: sortOld,
create: sortCreate,
posts: sortPopular,
votes: sortVotes,
views: sortViews,
};
const sortFn = sortMap[params.sort] || sortRecent;
const { sortMap, fields } = await plugins.hooks.fire('filter:topics.sortOptions', {
params,
fields: [
'tid', 'timestamp', 'lastposttime', 'upvotes', 'downvotes', 'postcount', 'pinned',
],
sortMap: {
recent: sortRecent,
old: sortOld,
create: sortCreate,
posts: sortPopular,
votes: sortVotes,
views: sortViews,
},
});
const topicData = await Topics.getTopicsFields(tids, fields);
const sortFn = sortMap.hasOwnProperty(params.sort) && sortMap[params.sort] ?
sortMap[params.sort] : sortRecent;
if (params.floatPinned) {
floatPinned(topicData, sortFn);

View File

@@ -1,9 +1,8 @@
<div>
<label for="agree-terms">[[register:terms-of-use]]</label>
<div class="tos">{termsOfUse}</div>
<div class="checkbox">
<label>
<input type="checkbox" name="agree-terms" id="agree-terms"> [[register:agree-to-terms-of-use]]
</label>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="agree-terms" id="agree-terms">
<label class="form-check-label">[[register:agree-to-terms-of-use]]</label>
</div>
</div>

View File

@@ -2,7 +2,7 @@
<p class="lead">[[user:consent.lead]]</p>
<p>[[user:consent.intro]]</p>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" name="gdpr_agree_data" id="gdpr_agree_data">
<input class="form-check-input" type="checkbox" name="gdpr_agree_data" id="gdpr_agree_data" role="switch">
<label class="form-check-label" for="gdpr_agree_data">[[register:gdpr-agree-data]]</label>
</div>
@@ -16,7 +16,7 @@
</p>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="gdpr_agree_email" id="gdpr_agree_email">
<input class="form-check-input" type="checkbox" name="gdpr_agree_email" id="gdpr_agree_email" role="switch">
<label class="form-check-label" for="gdpr_agree_email">[[register:gdpr-agree-email]]</label>
</div>
</div>

View File

@@ -914,6 +914,19 @@ describe('Groups', () => {
assert(!isInvited);
});
it('should fail to rescind last owner', async () => {
const uid = await User.create({ username: 'lastgroupowner' });
await Groups.create({
name: 'last owner',
description: 'Foobar!',
ownerUid: uid,
});
await assert.rejects(
apiGroups.rescind({ uid: adminUid }, { slug: 'last-owner', uid: uid }),
{ message: '[[error:group-needs-owner]]' },
);
});
it('should error if user is not invited', async () => {
await assert.rejects(
apiGroups.acceptInvite({ uid: adminUid }, { slug: 'privatecanjoin', uid: adminUid }),