Merge remote-tracking branch 'refs/remotes/origin/master' into develop

v1.18.x
Baris Usakli 8 years ago
commit bc0645dc26

@ -309,4 +309,4 @@ function versionCheck() {
winston.warn('Your version of Node.js is too outdated for NodeBB. Please update your version of Node.js.');
winston.warn('Recommended ' + range.green + ', '.reset + version.yellow + ' provided\n'.reset);
}
}
}

@ -59,15 +59,15 @@
"nodebb-plugin-dbsearch": "2.0.6",
"nodebb-plugin-emoji-extended": "1.1.1",
"nodebb-plugin-emoji-one": "1.2.1",
"nodebb-plugin-markdown": "8.0.3",
"nodebb-plugin-mentions": "2.1.5",
"nodebb-plugin-markdown": "8.1.0",
"nodebb-plugin-mentions": "2.1.6",
"nodebb-plugin-soundpack-default": "1.0.0",
"nodebb-plugin-spam-be-gone": "0.5.1",
"nodebb-rewards-essentials": "0.0.9",
"nodebb-theme-lavender": "4.0.5",
"nodebb-theme-persona": "5.0.21",
"nodebb-theme-persona": "5.0.22",
"nodebb-theme-slick": "1.1.0",
"nodebb-theme-vanilla": "6.0.16",
"nodebb-theme-vanilla": "6.0.17",
"nodebb-widget-essentials": "3.0.1",
"nodemailer": "2.6.4",
"nodemailer-sendmail-transport": "1.0.0",

@ -11,6 +11,7 @@
"only-admins": "Only display to Admins",
"only-global-mods-and-admins": "Only display to Global Moderators and Admins",
"only-logged-in": "Only display to logged in users",
"only-guest": "Only display to guests",
"open-new-window": "Open in a new window",
"installed-plugins-required": "Installed Plugins Required:",

@ -2,7 +2,9 @@
"post-queue": "Post Queue",
"description": "There are no posts in the post queue. <br> To enable this feature, go to <a href=\"%1\">Settings &rarr; Post &rarr; Posting Restrictions</a> and enable <strong>Post Queue</strong>.",
"user": "User",
"category": "Category",
"title": "Title",
"content": "Content",
"posted": "Posted"
"posted": "Posted",
"reply-to": "Reply to \"%1\""
}

@ -45,6 +45,7 @@
"new_register": "<strong>%1</strong> sent a registration request.",
"new_register_multiple": "There are <strong>%1</strong> registration requests awaiting review.",
"flag_assigned_to_you": "<strong>Flag %1</strong> has been assigned to you",
"post_awaiting_review": "Post awaiting review",
"email-confirmed": "Email Confirmed",
"email-confirmed-message": "Thank you for validating your email. Your account is now fully activated.",

@ -9,6 +9,7 @@
"moderator-tools": "Moderator Tools",
"flagged-content": "Flagged Content",
"ip-blacklist": "IP Blacklist",
"post-queue": "Post Queue",
"users/online": "Online Users",
"users/latest": "Latest Users",

@ -16,7 +16,7 @@
"mongo.index-size": "Index Size",
"mongo.file-size": "File Size",
"mongo.resident-memory": "Resident Memory",
"mongo.virtual-memory": "Virtual Memory",
"mongo.virtual-memory": "حافظۀ مجازی",
"mongo.mapped-memory": "Mapped Memory",
"mongo.raw-info": "MongoDB Raw Info",

@ -41,6 +41,7 @@
var loggedIn = data.config ? data.config.loggedIn : false;
if (properties) {
if ((properties.loggedIn && !loggedIn) ||
(properties.guestOnly && loggedIn) ||
(properties.globalMod && !data.isGlobalMod && !data.isAdmin) ||
(properties.adminOnly && !data.isAdmin) ||
(properties.searchInstalled && !data.searchEnabled)) {

@ -4,6 +4,8 @@ var async = require('async');
var db = require('../../database');
var user = require('../../user');
var topics = require('../../topics');
var categories = require('../../categories');
var pagination = require('../../pagination');
var utils = require('../../utils');
@ -51,11 +53,34 @@ postQueueController.get = function (req, res, next) {
});
user.getUsersFields(uids, ['username', 'userslug', 'picture'], next);
},
function (userData) {
function (userData, next) {
postData.forEach(function (postData, index) {
postData.user = userData[index];
});
async.map(postData, function (postData, next) {
async.waterfall([
function (next) {
if (postData.data.cid) {
next(null, { cid: postData.data.cid });
} else if (postData.data.tid) {
topics.getTopicFields(postData.data.tid, ['title', 'cid'], next);
} else {
next(null, { cid: 0 });
}
},
function (topicData, next) {
postData.topic = topicData;
categories.getCategoryData(topicData.cid, next);
},
function (categoryData, next) {
postData.category = categoryData;
next(null, postData);
},
], next);
}, next);
},
function (postData) {
res.render('admin/manage/post-queue', {
title: '[[pages:post-queue]]',
posts: postData,

@ -3,6 +3,7 @@
var async = require('async');
var S = require('string');
var validator = require('validator');
var db = require('./database');
var user = require('./user');
@ -211,6 +212,7 @@ Messaging.getTeaser = function (uid, roomId, callback) {
}
if (teaser.content) {
teaser.content = S(teaser.content).stripTags().decodeHTMLEntities().s;
teaser.content = validator.escape(String(teaser.content));
}
teaser.timestampISO = utils.toISOString(teaser.timestamp);

@ -181,3 +181,8 @@ middleware.processTimeagoLocales = function (req, res, next) {
},
], next);
};
middleware.delayLoading = function (req, res, next) {
// Introduces an artificial delay during load so that brute force attacks are effectively mitigated
setTimeout(next, 1000);
};

@ -6,6 +6,7 @@ var db = require('../database');
var user = require('../user');
var meta = require('../meta');
var topics = require('../topics');
var notifications = require('../notifications');
var privileges = require('../privileges');
var socketHelpers = require('../socket.io/helpers');
@ -43,6 +44,22 @@ module.exports = function (Posts) {
function (next) {
user.setUserField(data.uid, 'lastposttime', Date.now(), next);
},
function (next) {
notifications.create({
nid: 'post-queued-' + id,
mergeId: 'post-queue',
bodyShort: '[[notifications:post_awaiting_review]]',
bodyLong: data.content,
path: '/post-queue',
}, next);
},
function (notification, next) {
if (notification) {
notifications.pushGroups(notification, ['administrators', 'Global Moderators'], next);
} else {
next();
}
},
function (next) {
next(null, {
queued: true,
@ -92,6 +109,9 @@ module.exports = function (Posts) {
function (next) {
db.delete('post:queue:' + id, next);
},
function (next) {
notifications.rescind('post-queued-' + id, next);
},
], callback);
};

@ -32,7 +32,7 @@ function mainRoutes(app, middleware, controllers) {
setupPageRoute(app, '/confirm/:code', middleware, [], controllers.confirmEmail);
setupPageRoute(app, '/outgoing', middleware, [], controllers.outgoing);
setupPageRoute(app, '/search', middleware, [], controllers.search.search);
setupPageRoute(app, '/reset/:code?', middleware, [], controllers.reset);
setupPageRoute(app, '/reset/:code?', middleware, [middleware.delayLoading], controllers.reset);
setupPageRoute(app, '/tos', middleware, [], controllers.termsOfUse);
app.post('/compose', middleware.applyCSRF, controllers.composePost);

@ -185,6 +185,7 @@ module.exports = function (User) {
function (next) {
db.sortedSetAdd('users:notvalidated', Date.now(), uid, next);
},
async.apply(User.reset.cleanByUid, uid),
], function (err) {
next(err);
});

@ -7,6 +7,7 @@ var winston = require('winston');
var user = require('../user');
var utils = require('../utils');
var translator = require('../translator');
var batch = require('../batch');
var db = require('../database');
var meta = require('../meta');
@ -167,3 +168,42 @@ UserReset.clean = function (callback) {
},
], callback);
};
UserReset.cleanByUid = function (uid, callback) {
if (typeof callback !== 'function') {
callback = function () {};
}
var toClean = [];
uid = parseInt(uid, 10);
async.waterfall([
async.apply(db.getSortedSetRange.bind(db), 'reset:issueDate', 0, -1),
function (tokens, next) {
batch.processArray(tokens, function (tokens, next) {
db.getObjectFields('reset:uid', tokens, function (err, results) {
for (var code in results) {
if (results.hasOwnProperty(code) && parseInt(results[code], 10) === uid) {
toClean.push(code);
}
}
next(err);
});
}, next);
},
function (next) {
if (!toClean.length) {
winston.verbose('[UserReset.cleanByUid] No tokens found for uid (' + uid + ').');
return setImmediate(next);
}
winston.verbose('[UserReset.cleanByUid] Found ' + toClean.length + ' token(s), removing...');
async.parallel([
async.apply(db.deleteObjectFields, 'reset:uid', toClean),
async.apply(db.sortedSetRemove, 'reset:issueDate', toClean),
async.apply(db.sortedSetRemove, 'reset:issueDate:uid', uid),
], next);
},
], callback);
};

@ -78,6 +78,12 @@
<span class="mdl-switch__label"><strong>[[admin/general/navigation:only-logged-in]]</strong></span>
</label>
</div>
<div class="checkbox">
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
<input class="mdl-switch__input" type="checkbox" name="property:guestOnly" <!-- IF enabled.properties.guestOnly -->checked<!-- ENDIF enabled.properties.guestOnly -->/>
<span class="mdl-switch__label"><strong>[[admin/general/navigation:only-guest]]</strong></span>
</label>
</div>
<div class="checkbox">
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
<input class="mdl-switch__input" type="checkbox" name="property:targetBlank" <!-- IF enabled.properties.targetBlank -->checked<!-- ENDIF enabled.properties.targetBlank -->/>

@ -16,6 +16,7 @@
<thead>
<tr>
<th>[[admin/manage/post-queue:user]]</th>
<th>[[admin/manage/post-queue:category]]</th>
<th>[[admin/manage/post-queue:title]]</th>
<th>[[admin/manage/post-queue:content]]</th>
<th>[[admin/manage/post-queue:posted]]</th>
@ -33,9 +34,15 @@
<!-- ENDIF posts.user.userslug -->
</td>
<td class="col-md-2">
<a href="{config.relative_path}/category/{posts.category.slug}"><!-- IF posts.categiry.icon --><span class="fa-stack"><i style="color: {posts.category.bgColor};" class="fa fa-circle fa-stack-2x"></i><i style="color: {posts.category.color};" class="fa fa-stack-1x fa-fw {posts.category.icon}"></i></span><!-- ENDIF posts.category.icon --> {posts.category.name}</a>
</td>
<td class="col-md-2">
<!-- IF posts.data.tid -->
<a href="{config.relative_path}/topic/{posts.data.tid}">[[admin/manage/post-queue:reply-to, {posts.topic.title}]]</a>
<!-- ENDIF posts.data.tid -->
{posts.data.title}
</td>
<td class="col-md-7">
<td class="col-md-5">
{posts.data.content}
</td>
<td class="col-md-1">

@ -85,7 +85,7 @@
{privileges.groups.name}
</td>
<td></td>
{function.spawnPrivilegeStates, name, privileges}
{function.spawnPrivilegeStates, privileges.groups.name, privileges}
</tr>
<!-- END privileges.groups -->
<tr>

@ -437,6 +437,17 @@ describe('Messaging Library', function () {
});
});
it('should escape teaser', function (done) {
socketModules.chats.send({ uid: fooUid }, { roomId: roomId, message: '<svg/onload=alert(document.location);' }, function (err, messageData) {
assert.ifError(err);
socketModules.chats.getRecentChats({ uid: fooUid }, { after: 0, uid: fooUid }, function (err, data) {
assert.ifError(err);
assert.equal(data.rooms[0].teaser.content, '&lt;svg&#x2F;onload=alert(document.location);');
done();
});
});
});
it('should fail to check if user has private chat with invalid data', function (done) {
socketModules.chats.hasPrivateChat({ uid: null }, null, function (err) {
assert.equal(err.message, '[[error:invalid-data]]');

Loading…
Cancel
Save