mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-12-20 15:30:39 +01:00
closes #6020
This commit is contained in:
@@ -14,31 +14,51 @@ var postQueueController = module.exports;
|
|||||||
postQueueController.get = function (req, res, next) {
|
postQueueController.get = function (req, res, next) {
|
||||||
var page = parseInt(req.query.page, 10) || 1;
|
var page = parseInt(req.query.page, 10) || 1;
|
||||||
var postsPerPage = 20;
|
var postsPerPage = 20;
|
||||||
var pageCount = 0;
|
var results;
|
||||||
|
|
||||||
var start = (page - 1) * postsPerPage;
|
|
||||||
var stop = start + postsPerPage - 1;
|
|
||||||
|
|
||||||
var postData;
|
|
||||||
|
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function (next) {
|
function (next) {
|
||||||
async.parallel({
|
async.parallel({
|
||||||
count: function (next) {
|
|
||||||
db.sortedSetCard('post:queue', next);
|
|
||||||
},
|
|
||||||
ids: function (next) {
|
ids: function (next) {
|
||||||
db.getSortedSetRange('post:queue', start, stop, next);
|
db.getSortedSetRange('post:queue', 0, -1, next);
|
||||||
|
},
|
||||||
|
isAdminOrGlobalMod: function (next) {
|
||||||
|
user.isAdminOrGlobalMod(req.uid, next);
|
||||||
|
},
|
||||||
|
moderatedCids: function (next) {
|
||||||
|
user.getModeratedCids(req.uid, next);
|
||||||
},
|
},
|
||||||
}, next);
|
}, next);
|
||||||
},
|
},
|
||||||
function (results, next) {
|
function (_results, next) {
|
||||||
pageCount = Math.ceil(results.count / postsPerPage);
|
results = _results;
|
||||||
|
getQueuedPosts(results.ids, next);
|
||||||
var keys = results.ids.map(function (id) {
|
},
|
||||||
return 'post:queue:' + id;
|
function (postData) {
|
||||||
|
postData = postData.filter(function (postData) {
|
||||||
|
return postData && (results.isAdminOrGlobalMod || results.moderatedCids.includes(String(postData.category.cid)));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var pageCount = Math.max(1, Math.ceil(postData.length / postsPerPage));
|
||||||
|
var start = (page - 1) * postsPerPage;
|
||||||
|
var stop = start + postsPerPage - 1;
|
||||||
|
postData = postData.slice(start, stop + 1);
|
||||||
|
|
||||||
|
res.render('admin/manage/post-queue', {
|
||||||
|
title: '[[pages:post-queue]]',
|
||||||
|
posts: postData,
|
||||||
|
pagination: pagination.create(page, pageCount),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
], next);
|
||||||
|
};
|
||||||
|
|
||||||
|
function getQueuedPosts(ids, callback) {
|
||||||
|
var keys = ids.map(function (id) {
|
||||||
|
return 'post:queue:' + id;
|
||||||
|
});
|
||||||
|
var postData;
|
||||||
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
db.getObjects(keys, next);
|
db.getObjects(keys, next);
|
||||||
},
|
},
|
||||||
function (data, next) {
|
function (data, next) {
|
||||||
@@ -80,12 +100,5 @@ postQueueController.get = function (req, res, next) {
|
|||||||
], next);
|
], next);
|
||||||
}, next);
|
}, next);
|
||||||
},
|
},
|
||||||
function (postData) {
|
], callback);
|
||||||
res.render('admin/manage/post-queue', {
|
}
|
||||||
title: '[[pages:post-queue]]',
|
|
||||||
posts: postData,
|
|
||||||
pagination: pagination.create(page, pageCount),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
], next);
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ var async = require('async');
|
|||||||
|
|
||||||
var user = require('../user');
|
var user = require('../user');
|
||||||
var adminBlacklistController = require('./admin/blacklist');
|
var adminBlacklistController = require('./admin/blacklist');
|
||||||
var adminPostQueueController = require('./admin/postqueue');
|
|
||||||
|
|
||||||
var globalModsController = module.exports;
|
var globalModsController = module.exports;
|
||||||
|
|
||||||
@@ -21,17 +20,3 @@ globalModsController.ipBlacklist = function (req, res, next) {
|
|||||||
},
|
},
|
||||||
], next);
|
], next);
|
||||||
};
|
};
|
||||||
|
|
||||||
globalModsController.postQueue = function (req, res, next) {
|
|
||||||
async.waterfall([
|
|
||||||
function (next) {
|
|
||||||
user.isAdminOrGlobalMod(req.uid, next);
|
|
||||||
},
|
|
||||||
function (isAdminOrGlobalMod, next) {
|
|
||||||
if (!isAdminOrGlobalMod) {
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
adminPostQueueController.get(req, res, next);
|
|
||||||
},
|
|
||||||
], next);
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ var categories = require('../categories');
|
|||||||
var flags = require('../flags');
|
var flags = require('../flags');
|
||||||
var analytics = require('../analytics');
|
var analytics = require('../analytics');
|
||||||
var plugins = require('../plugins');
|
var plugins = require('../plugins');
|
||||||
|
var adminPostQueueController = require('./admin/postqueue');
|
||||||
|
|
||||||
var modsController = module.exports;
|
var modsController = module.exports;
|
||||||
modsController.flags = {};
|
modsController.flags = {};
|
||||||
@@ -136,3 +137,18 @@ modsController.flags.detail = function (req, res, next) {
|
|||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
modsController.postQueue = function (req, res, next) {
|
||||||
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
user.isPrivileged(req.uid, next);
|
||||||
|
},
|
||||||
|
function (isPrivileged, next) {
|
||||||
|
if (!isPrivileged) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
adminPostQueueController.get(req, res, next);
|
||||||
|
},
|
||||||
|
], next);
|
||||||
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -128,18 +128,12 @@ module.exports = function (Posts) {
|
|||||||
Posts.submitFromQueue = function (id, callback) {
|
Posts.submitFromQueue = function (id, callback) {
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function (next) {
|
function (next) {
|
||||||
db.getObject('post:queue:' + id, next);
|
getParsedObject(id, next);
|
||||||
},
|
},
|
||||||
function (data, next) {
|
function (data, next) {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return callback();
|
return callback();
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
data.data = JSON.parse(data.data);
|
|
||||||
} catch (err) {
|
|
||||||
return next(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.type === 'topic') {
|
if (data.type === 'topic') {
|
||||||
createTopic(data.data, next);
|
createTopic(data.data, next);
|
||||||
} else if (data.type === 'reply') {
|
} else if (data.type === 'reply') {
|
||||||
@@ -152,6 +146,25 @@ module.exports = function (Posts) {
|
|||||||
], callback);
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getParsedObject(id, callback) {
|
||||||
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
db.getObject('post:queue:' + id, next);
|
||||||
|
},
|
||||||
|
function (data, next) {
|
||||||
|
if (!data) {
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
data.data = JSON.parse(data.data);
|
||||||
|
} catch (err) {
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
next(null, data);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
|
}
|
||||||
|
|
||||||
function createTopic(data, callback) {
|
function createTopic(data, callback) {
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function (next) {
|
function (next) {
|
||||||
@@ -184,23 +197,52 @@ module.exports = function (Posts) {
|
|||||||
Posts.editQueuedContent = function (uid, id, content, callback) {
|
Posts.editQueuedContent = function (uid, id, content, callback) {
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function (next) {
|
function (next) {
|
||||||
user.isAdminOrGlobalMod(uid, next);
|
Posts.canEditQueue(uid, id, next);
|
||||||
},
|
},
|
||||||
function (isAdminOrGlobalMod, next) {
|
function (canEditQueue, next) {
|
||||||
if (!isAdminOrGlobalMod) {
|
if (!canEditQueue) {
|
||||||
return callback(new Error('[[error:no-privileges]]'));
|
return callback(new Error('[[error:no-privileges]]'));
|
||||||
}
|
}
|
||||||
db.getObject('post:queue:' + id, next);
|
getParsedObject(id, next);
|
||||||
},
|
},
|
||||||
function (data, next) {
|
function (data, next) {
|
||||||
try {
|
if (!data) {
|
||||||
data.data = JSON.parse(data.data);
|
return callback();
|
||||||
} catch (err) {
|
|
||||||
return next(err);
|
|
||||||
}
|
}
|
||||||
data.data.content = content;
|
data.data.content = content;
|
||||||
db.setObjectField('post:queue:' + id, 'data', JSON.stringify(data.data), next);
|
db.setObjectField('post:queue:' + id, 'data', JSON.stringify(data.data), next);
|
||||||
},
|
},
|
||||||
], callback);
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Posts.canEditQueue = function (uid, id, callback) {
|
||||||
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
async.parallel({
|
||||||
|
isAdminOrGlobalMod: function (next) {
|
||||||
|
user.isAdminOrGlobalMod(uid, next);
|
||||||
|
},
|
||||||
|
data: function (next) {
|
||||||
|
getParsedObject(id, next);
|
||||||
|
},
|
||||||
|
}, next);
|
||||||
|
},
|
||||||
|
function (results, next) {
|
||||||
|
if (results.isAdminOrGlobalMod) {
|
||||||
|
return callback(null, true);
|
||||||
|
}
|
||||||
|
if (!results.data) {
|
||||||
|
return callback(null, false);
|
||||||
|
}
|
||||||
|
if (results.data.type === 'topic') {
|
||||||
|
next(null, results.data.data.cid);
|
||||||
|
} else if (results.data.type === 'reply') {
|
||||||
|
topics.getTopicField(results.data.data.tid, 'cid', next);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
function (cid, next) {
|
||||||
|
user.isModerator(uid, cid, next);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -42,10 +42,10 @@ function mainRoutes(app, middleware, controllers) {
|
|||||||
function modRoutes(app, middleware, controllers) {
|
function modRoutes(app, middleware, controllers) {
|
||||||
setupPageRoute(app, '/flags', middleware, [], controllers.mods.flags.list);
|
setupPageRoute(app, '/flags', middleware, [], controllers.mods.flags.list);
|
||||||
setupPageRoute(app, '/flags/:flagId', middleware, [], controllers.mods.flags.detail);
|
setupPageRoute(app, '/flags/:flagId', middleware, [], controllers.mods.flags.detail);
|
||||||
|
setupPageRoute(app, '/post-queue', middleware, [], controllers.mods.postQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
function globalModRoutes(app, middleware, controllers) {
|
function globalModRoutes(app, middleware, controllers) {
|
||||||
setupPageRoute(app, '/post-queue', middleware, [], controllers.globalMods.postQueue);
|
|
||||||
setupPageRoute(app, '/ip-blacklist', middleware, [], controllers.globalMods.ipBlacklist);
|
setupPageRoute(app, '/ip-blacklist', middleware, [], controllers.globalMods.ipBlacklist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -175,6 +175,7 @@ SocketPosts.accept = function (socket, data, callback) {
|
|||||||
SocketPosts.reject = function (socket, data, callback) {
|
SocketPosts.reject = function (socket, data, callback) {
|
||||||
acceptOrReject(posts.removeFromQueue, socket, data, callback);
|
acceptOrReject(posts.removeFromQueue, socket, data, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
SocketPosts.editQueuedContent = function (socket, data, callback) {
|
SocketPosts.editQueuedContent = function (socket, data, callback) {
|
||||||
if (!data || !data.id || !data.content) {
|
if (!data || !data.id || !data.content) {
|
||||||
return callback(new Error('[[error:invalid-data]]'));
|
return callback(new Error('[[error:invalid-data]]'));
|
||||||
@@ -185,10 +186,10 @@ SocketPosts.editQueuedContent = function (socket, data, callback) {
|
|||||||
function acceptOrReject(method, socket, data, callback) {
|
function acceptOrReject(method, socket, data, callback) {
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function (next) {
|
function (next) {
|
||||||
user.isAdminOrGlobalMod(socket.uid, next);
|
posts.canEditQueue(socket.uid, data.id, next);
|
||||||
},
|
},
|
||||||
function (isAdminOrGlobalMod, next) {
|
function (canEditQueue, next) {
|
||||||
if (!isAdminOrGlobalMod) {
|
if (!canEditQueue) {
|
||||||
return callback(new Error('[[error:no-privileges]]'));
|
return callback(new Error('[[error:no-privileges]]'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -831,7 +831,21 @@ describe('Post\'s', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should accept queued posts submit', function (done) {
|
it('should prevent regular users from approving posts', function (done) {
|
||||||
|
socketPosts.accept({ uid: uid }, { id: queueId }, function (err) {
|
||||||
|
assert.equal(err.message, '[[error:no-privileges]]');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should prevent regular users from approving non existing posts', function (done) {
|
||||||
|
socketPosts.accept({ uid: uid }, { id: 123123 }, function (err) {
|
||||||
|
assert.equal(err.message, '[[error:no-privileges]]');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should accept queued posts and submit', function (done) {
|
||||||
var ids;
|
var ids;
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function (next) {
|
function (next) {
|
||||||
@@ -846,12 +860,5 @@ describe('Post\'s', function () {
|
|||||||
},
|
},
|
||||||
], done);
|
], done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should prevent regular users from approving posts', function (done) {
|
|
||||||
socketPosts.accept({ uid: uid }, { id: 1 }, function (err) {
|
|
||||||
assert.equal(err.message, '[[error:no-privileges]]');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user