mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-09-02 01:57:38 +02:00
Merge remote-tracking branch 'refs/remotes/origin/master' into develop
This commit is contained in:
@@ -62,6 +62,9 @@ helpers.getUserDataByUserSlug = function (userslug, callerUID, callback) {
|
||||
sso: function (next) {
|
||||
plugins.fireHook('filter:auth.list', { uid: uid, associations: [] }, next);
|
||||
},
|
||||
canEdit: function (next) {
|
||||
privileges.users.canEdit(callerUID, uid, next);
|
||||
},
|
||||
canBanUser: function (next) {
|
||||
privileges.users.canBanUser(callerUID, uid, next);
|
||||
},
|
||||
@@ -113,7 +116,7 @@ helpers.getUserDataByUserSlug = function (userslug, callerUID, callback) {
|
||||
userData.isAdminOrGlobalModerator = isAdmin || isGlobalModerator;
|
||||
userData.isAdminOrGlobalModeratorOrModerator = isAdmin || isGlobalModerator || isModerator;
|
||||
userData.isSelfOrAdminOrGlobalModerator = isSelf || isAdmin || isGlobalModerator;
|
||||
userData.canEdit = isAdmin || (isGlobalModerator && !results.isTargetAdmin);
|
||||
userData.canEdit = results.canEdit;
|
||||
userData.canBan = results.canBanUser;
|
||||
userData.canChangePassword = isAdmin || (isSelf && parseInt(meta.config['password:disableEdit'], 10) !== 1);
|
||||
userData.isSelf = isSelf;
|
||||
|
||||
@@ -48,6 +48,7 @@ dashboardController.get = function (req, res, next) {
|
||||
version: nconf.get('version'),
|
||||
notices: results.notices,
|
||||
stats: results.stats,
|
||||
canRestart: !!process.send,
|
||||
});
|
||||
},
|
||||
], next);
|
||||
|
||||
@@ -129,7 +129,7 @@ helpers.buildCategoryBreadcrumbs = function (cid, callback) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
if (!meta.config.homePageRoute && meta.config.homePageCustom) {
|
||||
if (meta.config.homePageRoute && meta.config.homePageRoute !== 'categories') {
|
||||
breadcrumbs.unshift({
|
||||
text: '[[global:header.categories]]',
|
||||
url: nconf.get('relative_path') + '/categories',
|
||||
|
||||
@@ -387,7 +387,7 @@ Flags.create = function (type, id, uid, reason, timestamp, callback) {
|
||||
tasks.push(async.apply(Flags.update, flagId, uid, { state: 'open' }));
|
||||
}
|
||||
|
||||
async.parallel(tasks, function (err) {
|
||||
async.series(tasks, function (err) {
|
||||
next(err, flagId);
|
||||
});
|
||||
},
|
||||
|
||||
@@ -143,6 +143,11 @@ function build(targets, callback) {
|
||||
target = target.toLowerCase().replace(/-/g, '');
|
||||
if (!aliases[target]) {
|
||||
winston.warn('[build] Unknown target: ' + target);
|
||||
if (target.indexOf(',') !== -1) {
|
||||
winston.warn('[build] Are you specifying multiple targets? Separate them with spaces:');
|
||||
winston.warn('[build] e.g. `./nodebb build adminjs tpl`');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ var plugins = require('../plugins');
|
||||
var cache = require('./cache');
|
||||
var pubsub = require('../pubsub');
|
||||
var utils = require('../utils');
|
||||
var translator = require('../translator');
|
||||
|
||||
module.exports = function (Posts) {
|
||||
pubsub.on('post:edit', function (pid) {
|
||||
@@ -149,6 +150,7 @@ module.exports = function (Posts) {
|
||||
topicData.tags = data.tags;
|
||||
topicData.oldTitle = results.topic.title;
|
||||
topicData.timestamp = results.topic.timestamp;
|
||||
var renamed = translator.escape(validator.escape(String(title))) !== results.topic.title;
|
||||
plugins.fireHook('action:topic.edit', { topic: topicData, uid: data.uid });
|
||||
next(null, {
|
||||
tid: tid,
|
||||
@@ -158,7 +160,7 @@ module.exports = function (Posts) {
|
||||
oldTitle: results.topic.title,
|
||||
slug: topicData.slug,
|
||||
isMainPost: true,
|
||||
renamed: title !== results.topic.title,
|
||||
renamed: renamed,
|
||||
tags: tags,
|
||||
});
|
||||
},
|
||||
|
||||
@@ -141,9 +141,13 @@ module.exports = function (privileges) {
|
||||
}, next);
|
||||
},
|
||||
function (results, next) {
|
||||
var canEdit = results.isAdmin || (results.isGlobalMod && !results.isTargetAdmin);
|
||||
|
||||
next(null, canEdit);
|
||||
results.canEdit = results.isAdmin || (results.isGlobalMod && !results.isTargetAdmin);
|
||||
results.callerUid = callerUid;
|
||||
results.uid = uid;
|
||||
plugins.fireHook('filter:user.canEdit', results, next);
|
||||
},
|
||||
function (data, next) {
|
||||
next(null, data.canEdit);
|
||||
},
|
||||
], callback);
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@ module.exports = function (SocketUser) {
|
||||
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
isAdminOrSelfAndPasswordMatch(socket.uid, data, next);
|
||||
isPrivilegedOrSelfAndPasswordMatch(socket.uid, data, next);
|
||||
},
|
||||
function (next) {
|
||||
SocketUser.updateProfile(socket, data, next);
|
||||
@@ -29,7 +29,7 @@ module.exports = function (SocketUser) {
|
||||
}
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
user.isAdminOrSelf(socket.uid, data.uid, next);
|
||||
user.isAdminOrGlobalModOrSelf(socket.uid, data.uid, next);
|
||||
},
|
||||
function (next) {
|
||||
user.updateCoverPicture(data, next);
|
||||
@@ -43,7 +43,7 @@ module.exports = function (SocketUser) {
|
||||
}
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
user.isAdminOrSelf(socket.uid, data.uid, next);
|
||||
user.isAdminOrGlobalModOrSelf(socket.uid, data.uid, next);
|
||||
},
|
||||
function (next) {
|
||||
user.uploadCroppedPicture(data, next);
|
||||
@@ -58,7 +58,7 @@ module.exports = function (SocketUser) {
|
||||
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
user.isAdminOrSelf(socket.uid, data.uid, next);
|
||||
user.isAdminOrGlobalModOrSelf(socket.uid, data.uid, next);
|
||||
},
|
||||
function (next) {
|
||||
user.removeCoverPicture(data, next);
|
||||
@@ -66,11 +66,13 @@ module.exports = function (SocketUser) {
|
||||
], callback);
|
||||
};
|
||||
|
||||
function isAdminOrSelfAndPasswordMatch(uid, data, callback) {
|
||||
function isPrivilegedOrSelfAndPasswordMatch(uid, data, callback) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
async.parallel({
|
||||
isAdmin: async.apply(user.isAdministrator, uid),
|
||||
isTargetAdmin: async.apply(user.isAdministrator, data.uid),
|
||||
isGlobalMod: async.apply(user.isGlobalModerator, uid),
|
||||
hasPassword: async.apply(user.hasPassword, data.uid),
|
||||
passwordMatch: function (next) {
|
||||
if (data.password) {
|
||||
@@ -84,7 +86,11 @@ module.exports = function (SocketUser) {
|
||||
function (results, next) {
|
||||
var isSelf = parseInt(uid, 10) === parseInt(data.uid, 10);
|
||||
|
||||
if (!results.isAdmin && !isSelf) {
|
||||
if (results.isTargetAdmin && !results.isAdmin) {
|
||||
return next(new Error('[[error:no-privileges]]'));
|
||||
}
|
||||
|
||||
if ((!results.isAdmin || !results.isGlobalMod) && !isSelf) {
|
||||
return next(new Error('[[error:no-privileges]]'));
|
||||
}
|
||||
|
||||
|
||||
@@ -253,16 +253,13 @@ module.exports = function (Topics) {
|
||||
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
Topics.exists(tid, next);
|
||||
},
|
||||
function (exists, next) {
|
||||
if (!exists) {
|
||||
return next(new Error('[[error:no-topic]]'));
|
||||
}
|
||||
Topics.getTopicFields(tid, ['cid', 'lastposttime', 'pinned', 'deleted', 'postcount', 'upvotes', 'downvotes'], next);
|
||||
Topics.getTopicData(tid, next);
|
||||
},
|
||||
function (topicData, next) {
|
||||
topic = topicData;
|
||||
if (!topic) {
|
||||
return next(new Error('[[error:no-topic]]'));
|
||||
}
|
||||
if (parseInt(cid, 10) === parseInt(topic.cid, 10)) {
|
||||
return next(new Error('[[error:cant-move-topic-to-same-category]]'));
|
||||
}
|
||||
@@ -273,11 +270,15 @@ module.exports = function (Topics) {
|
||||
'cid:' + topicData.cid + ':tids:votes',
|
||||
'cid:' + topicData.cid + ':tids:lastposttime',
|
||||
'cid:' + topicData.cid + ':recent_tids',
|
||||
'cid:' + topicData.cid + ':uid:' + topicData.uid + ':tids',
|
||||
], tid, next);
|
||||
},
|
||||
function (next) {
|
||||
db.sortedSetAdd('cid:' + cid + ':tids:lastposttime', topic.lastposttime, tid, next);
|
||||
},
|
||||
function (next) {
|
||||
db.sortedSetAdd('cid:' + cid + ':uid:' + topic.uid + ':tids', topic.timestamp, tid, next);
|
||||
},
|
||||
function (next) {
|
||||
if (parseInt(topic.pinned, 10)) {
|
||||
db.sortedSetAdd('cid:' + cid + ':tids:pinned', Date.now(), tid, next);
|
||||
|
||||
@@ -1,37 +1,43 @@
|
||||
'use strict';
|
||||
|
||||
var db = require('../../database');
|
||||
var meta = require('../../meta');
|
||||
|
||||
module.exports = {
|
||||
name: 'Generate customHTML block from old customJS setting',
|
||||
timestamp: Date.UTC(2017, 9, 12),
|
||||
method: function (callback) {
|
||||
var newHTML = meta.config.customJS;
|
||||
var newJS = [];
|
||||
|
||||
// Forgive me for parsing HTML with regex...
|
||||
var scriptMatch = /^<script\s?(?!async|deferred)?>([\s\S]+?)<\/script>/m;
|
||||
var match = scriptMatch.exec(newHTML);
|
||||
|
||||
while (match) {
|
||||
if (match[1]) {
|
||||
// Append to newJS array
|
||||
newJS.push(match[1].trim());
|
||||
|
||||
// Remove the match from the existing value
|
||||
newHTML = ((match.index > 0 ? newHTML.slice(0, match.index) : '') + newHTML.slice(match.index + match[0].length)).trim();
|
||||
db.getObjectField('config', 'customJS', function (err, newHTML) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
match = scriptMatch.exec(newHTML);
|
||||
}
|
||||
var newJS = [];
|
||||
|
||||
// Combine newJS array
|
||||
newJS = newJS.join('\n\n');
|
||||
// Forgive me for parsing HTML with regex...
|
||||
var scriptMatch = /^<script\s?(?!async|deferred)?>([\s\S]+?)<\/script>/m;
|
||||
var match = scriptMatch.exec(newHTML);
|
||||
|
||||
// Write both values to config
|
||||
meta.configs.setMultiple({
|
||||
customHTML: newHTML,
|
||||
customJS: newJS,
|
||||
}, callback);
|
||||
while (match) {
|
||||
if (match[1]) {
|
||||
// Append to newJS array
|
||||
newJS.push(match[1].trim());
|
||||
|
||||
// Remove the match from the existing value
|
||||
newHTML = ((match.index > 0 ? newHTML.slice(0, match.index) : '') + newHTML.slice(match.index + match[0].length)).trim();
|
||||
}
|
||||
|
||||
match = scriptMatch.exec(newHTML);
|
||||
}
|
||||
|
||||
// Combine newJS array
|
||||
newJS = newJS.join('\n\n');
|
||||
|
||||
// Write both values to config
|
||||
meta.configs.setMultiple({
|
||||
customHTML: newHTML,
|
||||
customJS: newJS,
|
||||
}, callback);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
52
src/upgrades/1.7.4/fix_user_topics_per_category.js
Normal file
52
src/upgrades/1.7.4/fix_user_topics_per_category.js
Normal file
@@ -0,0 +1,52 @@
|
||||
'use strict';
|
||||
|
||||
var async = require('async');
|
||||
var batch = require('../../batch');
|
||||
var db = require('../../database');
|
||||
|
||||
module.exports = {
|
||||
name: 'Fix topics in categories per user if they were moved',
|
||||
timestamp: Date.UTC(2018, 0, 22),
|
||||
method: function (callback) {
|
||||
var progress = this.progress;
|
||||
|
||||
batch.processSortedSet('topics:tid', function (tids, next) {
|
||||
async.eachLimit(tids, 500, function (tid, _next) {
|
||||
progress.incr();
|
||||
var topicData;
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
db.getObjectFields('topic:' + tid, ['cid', 'tid', 'uid', 'oldCid', 'timestamp'], next);
|
||||
},
|
||||
function (_topicData, next) {
|
||||
topicData = _topicData;
|
||||
if (!topicData.cid || !topicData.oldCid) {
|
||||
return _next();
|
||||
}
|
||||
|
||||
db.isSortedSetMember('cid:' + topicData.oldCid + ':uid:' + topicData.uid, topicData.tid, next);
|
||||
},
|
||||
function (isMember, next) {
|
||||
if (isMember) {
|
||||
async.series([
|
||||
function (next) {
|
||||
db.sortedSetRemove('cid:' + topicData.oldCid + ':uid:' + topicData.uid + ':tids', tid, next);
|
||||
},
|
||||
function (next) {
|
||||
db.sortedSetAdd('cid:' + topicData.cid + ':uid:' + topicData.uid + ':tids', topicData.timestamp, tid, next);
|
||||
},
|
||||
], function (err) {
|
||||
next(err);
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
},
|
||||
], _next);
|
||||
}, next);
|
||||
}, {
|
||||
progress: progress,
|
||||
batch: 500,
|
||||
}, callback);
|
||||
},
|
||||
};
|
||||
@@ -119,7 +119,7 @@ UserReset.commit = function (code, password, callback) {
|
||||
user.hashPassword(password, next);
|
||||
},
|
||||
function (hash, next) {
|
||||
async.parallel([
|
||||
async.series([
|
||||
async.apply(user.setUserFields, uid, { password: hash, 'email:confirmed': 1 }),
|
||||
async.apply(db.deleteObjectField, 'reset:uid', code),
|
||||
async.apply(db.sortedSetRemove, 'reset:issueDate', code),
|
||||
@@ -128,7 +128,10 @@ UserReset.commit = function (code, password, callback) {
|
||||
async.apply(user.auth.resetLockout, uid),
|
||||
async.apply(db.delete, 'uid:' + uid + ':confirm:email:sent'),
|
||||
async.apply(db.sortedSetRemove, 'users:notvalidated', uid),
|
||||
], next);
|
||||
async.apply(UserReset.cleanByUid, uid),
|
||||
], function (err) {
|
||||
next(err);
|
||||
});
|
||||
},
|
||||
], callback);
|
||||
};
|
||||
|
||||
@@ -101,13 +101,15 @@
|
||||
<div class="panel-heading">[[admin/general/dashboard:control-panel]]</div>
|
||||
<div class="panel-body text-center">
|
||||
<p>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-warning reload">[[admin/general/dashboard:reload]]</button>
|
||||
<button class="btn btn-danger restart">[[admin/general/dashboard:restart]]</button>
|
||||
</div>
|
||||
<button class="btn btn-block btn-warning reload"<!-- IF !canRestart --> disabled<!-- END -->>[[admin/general/dashboard:reload]]</button>
|
||||
<button class="btn btn-block btn-danger restart"<!-- IF !canRestart --> disabled<!-- END -->>[[admin/general/dashboard:restart]]</button>
|
||||
</p>
|
||||
<p class="help-block">
|
||||
<p class="<!-- IF canRestart -->help-block<!-- ELSE -->alert alert-warning<!-- END -->">
|
||||
<!-- IF canRestart -->
|
||||
[[admin/general/dashboard:restart-warning]]
|
||||
<!-- ELSE -->
|
||||
[[admin/general/dashboard:restart-disabled]]
|
||||
<!-- END -->
|
||||
</p>
|
||||
<p>
|
||||
<a href="{config.relative_path}/admin/settings/advanced" class="btn btn-info btn-block" data-placement="bottom" data-toggle="tooltip" title="[[admin/general/dashboard:maintenance-mode-title]]">[[admin/general/dashboard:maintenance-mode]]</a>
|
||||
|
||||
Reference in New Issue
Block a user