make upload permissions global

give upload image permission to registered users on install
add global privileges to app.user.privileges for client side use
v1.18.x
Barış Soner Uşaklı 7 years ago
parent bf1e2cfe46
commit ff6c6a54c1

@ -59,7 +59,7 @@
"morgan": "^1.9.0",
"mousetrap": "^1.6.1",
"nconf": "^0.9.1",
"nodebb-plugin-composer-default": "6.0.7",
"nodebb-plugin-composer-default": "6.0.8",
"nodebb-plugin-dbsearch": "2.0.9",
"nodebb-plugin-emoji": "2.0.9",
"nodebb-plugin-emoji-android": "2.0.0",

@ -62,7 +62,6 @@ module.exports = function (Categories) {
'posts:edit',
'posts:delete',
'topics:delete',
'upload:post:image',
];
async.series([

@ -20,12 +20,6 @@ chatsController.get = function (req, res, callback) {
async.waterfall([
function (next) {
privileges.global.can('chat', req.uid, next);
},
function (canChat, next) {
if (!canChat) {
return next(new Error('[[error:no-privileges]]'));
}
user.getUidByUserslug(req.params.userslug, next);
},
function (_uid, next) {
@ -33,6 +27,13 @@ chatsController.get = function (req, res, callback) {
if (!uid) {
return callback();
}
privileges.global.can('chat', req.uid, next);
},
function (canChat, next) {
if (!canChat) {
return next(new Error('[[error:no-privileges]]'));
}
messaging.getRecentChats(req.uid, uid, 0, 19, next);
},
function (_recentChats, next) {

@ -37,9 +37,6 @@ uploadsController.upload = function (req, res, filesIterator) {
uploadsController.uploadPost = function (req, res, next) {
uploadsController.upload(req, res, function (uploadedFile, next) {
if (!parseInt(req.body.cid, 10)) {
return next(new Error('[[error:category-not-selected]]'));
}
var isImage = uploadedFile.type.match(/image./);
if (isImage) {
uploadAsImage(req, uploadedFile, next);
@ -52,7 +49,7 @@ uploadsController.uploadPost = function (req, res, next) {
function uploadAsImage(req, uploadedFile, callback) {
async.waterfall([
function (next) {
privileges.categories.can('upload:post:image', req.body.cid, req.uid, next);
privileges.global.can('upload:post:image', req.uid, next);
},
function (canUpload, next) {
if (!canUpload) {
@ -82,7 +79,7 @@ function uploadAsImage(req, uploadedFile, callback) {
function uploadAsFile(req, uploadedFile, callback) {
async.waterfall([
function (next) {
privileges.categories.can('upload:post:file', req.body.cid, req.uid, next);
privileges.global.can('upload:post:file', req.uid, next);
},
function (canUpload, next) {
if (!canUpload) {

@ -354,8 +354,8 @@ function createGlobalModeratorsGroup(next) {
}
function giveGlobalPrivileges(next) {
var groups = require('./groups');
groups.join('cid:0:privileges:groups:chat', 'registered-users', next);
var privileges = require('./privileges');
privileges.global.give(['chat', 'upload:post:image'], 'registered-users', next);
}
function createCategories(next) {

@ -78,8 +78,8 @@ module.exports = function (middleware) {
isModerator: function (next) {
user.isModeratorOfAnyCategory(req.uid, next);
},
canChat: function (next) {
privileges.global.can('chat', req.uid, next);
privileges: function (next) {
privileges.global.get(req.uid, next);
},
user: function (next) {
var userData = {
@ -136,6 +136,7 @@ module.exports = function (middleware) {
results.user.isAdmin = results.isAdmin;
results.user.isGlobalMod = results.isGlobalMod;
results.user.isMod = !!results.isModerator;
results.user.privileges = results.privileges;
results.user.uid = parseInt(results.user.uid, 10);
results.user.email = String(results.user.email);

@ -12,8 +12,6 @@ privileges.privilegeLabels = [
{ name: 'Edit Posts' },
{ name: 'Delete Posts' },
{ name: 'Delete Topics' },
{ name: 'Upload Images' },
{ name: 'Upload Files' },
{ name: 'Purge' },
{ name: 'Moderate' },
];
@ -28,8 +26,6 @@ privileges.userPrivilegeList = [
'posts:edit',
'posts:delete',
'topics:delete',
'upload:post:image',
'upload:post:file',
'purge',
'moderate',
];

@ -198,19 +198,13 @@ module.exports = function (privileges) {
};
privileges.categories.give = function (privileges, cid, groupName, callback) {
giveOrRescind(groups.join, privileges, cid, groupName, callback);
helpers.giveOrRescind(groups.join, privileges, cid, groupName, callback);
};
privileges.categories.rescind = function (privileges, cid, groupName, callback) {
giveOrRescind(groups.leave, privileges, cid, groupName, callback);
helpers.giveOrRescind(groups.leave, privileges, cid, groupName, callback);
};
function giveOrRescind(method, privileges, cid, groupName, callback) {
async.eachSeries(privileges, function (privilege, next) {
method('cid:' + cid + ':privileges:groups:' + privilege, groupName, next);
}, callback);
}
privileges.categories.canMoveAllTopics = function (currentCid, targetCid, uid, callback) {
async.waterfall([
function (next) {

@ -2,8 +2,10 @@
'use strict';
var async = require('async');
var _ = require('lodash');
var user = require('../user');
var groups = require('../groups');
var helpers = require('./helpers');
var plugins = require('../plugins');
@ -12,10 +14,14 @@ module.exports = function (privileges) {
privileges.global.privilegeLabels = [
{ name: 'Chat' },
{ name: 'Upload Images' },
{ name: 'Upload Files' },
];
privileges.global.userPrivilegeList = [
'chat',
'upload:post:image',
'upload:post:file',
];
privileges.global.groupPrivilegeList = privileges.global.userPrivilegeList.map(function (privilege) {
@ -48,6 +54,34 @@ module.exports = function (privileges) {
], callback);
};
privileges.global.get = function (uid, callback) {
async.waterfall([
function (next) {
async.parallel({
privileges: function (next) {
helpers.isUserAllowedTo(privileges.global.userPrivilegeList, uid, 0, next);
},
isAdministrator: function (next) {
user.isAdministrator(uid, next);
},
isGlobalModerator: function (next) {
user.isGlobalModerator(uid, next);
},
}, next);
},
function (results, next) {
var privData = _.zipObject(privileges.global.userPrivilegeList, results.privileges);
var isAdminOrMod = results.isAdministrator || results.isGlobalModerator;
plugins.fireHook('filter:privileges.global.get', {
chat: privData.chat || isAdminOrMod,
'upload:post:image': privData['upload:post:image'] || isAdminOrMod,
'upload:post:file': privData['upload:post:file'] || isAdminOrMod,
}, next);
},
], callback);
};
privileges.global.can = function (privilege, uid, callback) {
helpers.some([
function (next) {
@ -63,4 +97,32 @@ module.exports = function (privileges) {
},
], callback);
};
privileges.global.give = function (privileges, groupName, callback) {
helpers.giveOrRescind(groups.join, privileges, 0, groupName, callback);
};
privileges.global.rescind = function (privileges, groupName, callback) {
helpers.giveOrRescind(groups.leave, privileges, 0, groupName, callback);
};
privileges.global.userPrivileges = function (uid, callback) {
var tasks = {};
privileges.global.userPrivilegeList.forEach(function (privilege) {
tasks[privilege] = async.apply(groups.isMember, uid, 'cid:0:privileges:' + privilege);
});
async.parallel(tasks, callback);
};
privileges.global.groupPrivileges = function (groupName, callback) {
var tasks = {};
privileges.global.groupPrivilegeList.forEach(function (privilege) {
tasks[privilege] = async.apply(groups.isMember, groupName, 'cid:0:privileges:' + privilege);
});
async.parallel(tasks, callback);
};
};

@ -221,3 +221,9 @@ helpers.getGroupPrivileges = function (cid, hookName, groupPrivilegeList, callba
},
], callback);
};
helpers.giveOrRescind = function (method, privileges, cid, groupName, callback) {
async.eachSeries(privileges, function (privilege, next) {
method('cid:' + cid + ':privileges:groups:' + privilege, groupName, next);
}, callback);
};

@ -0,0 +1,45 @@
'use strict';
var async = require('async');
var groups = require('../../groups');
var privileges = require('../../privileges');
var db = require('../../database');
module.exports = {
name: 'Give upload privilege to registered-users globally if it is given on a category',
timestamp: Date.UTC(2018, 0, 3),
method: function (callback) {
db.getSortedSetRange('categories:cid', 0, -1, function (err, cids) {
if (err) {
return callback(err);
}
async.eachSeries(cids, function (cid, next) {
getGroupPrivileges(cid, function (err, groupPrivileges) {
if (err) {
return next(err);
}
var privs = [];
if (groupPrivileges['groups:upload:post:image']) {
privs.push('upload:post:image');
}
if (groupPrivileges['groups:upload:post:file']) {
privs.push('upload:post:file');
}
privileges.global.give(privs, 'registered-users', next);
});
}, callback);
});
},
};
function getGroupPrivileges(cid, callback) {
var tasks = {};
['groups:upload:post:image', 'groups:upload:post:file'].forEach(function (privilege) {
tasks[privilege] = async.apply(groups.isMember, 'registered-users', 'cid:' + cid + ':privileges:' + privilege);
});
async.parallel(tasks, callback);
}

@ -5,7 +5,7 @@
<th class="arrowed" colspan="3">
[[admin/manage/categories:privileges.section-viewing]]
</th>
<th class="arrowed" colspan="8">
<th class="arrowed" colspan="6">
[[admin/manage/categories:privileges.section-posting]]
</th>
<th class="arrowed" colspan="2">
@ -61,7 +61,7 @@
<th class="arrowed" colspan="3">
[[admin/manage/categories:privileges.section-viewing]]
</th>
<th class="arrowed" colspan="8">
<th class="arrowed" colspan="6">
[[admin/manage/categories:privileges.section-posting]]
</th>
<th class="arrowed" colspan="2">

@ -638,7 +638,7 @@ describe('Categories', function () {
});
});
it('should load user privileges', function (done) {
it('should load category user privileges', function (done) {
privileges.categories.userPrivileges(categoryObj.cid, 1, function (err, data) {
assert.ifError(err);
assert.deepEqual(data, {
@ -651,8 +651,6 @@ describe('Categories', function () {
'topics:tag': false,
'topics:delete': false,
'posts:edit': false,
'upload:post:file': false,
'upload:post:image': false,
purge: false,
moderate: false,
});
@ -661,7 +659,20 @@ describe('Categories', function () {
});
});
it('should load group privileges', function (done) {
it('should load global user privileges', function (done) {
privileges.global.userPrivileges(1, function (err, data) {
assert.ifError(err);
assert.deepEqual(data, {
chat: false,
'upload:post:image': false,
'upload:post:file': false,
});
done();
});
});
it('should load category group privileges', function (done) {
privileges.categories.groupPrivileges(categoryObj.cid, 'registered-users', function (err, data) {
assert.ifError(err);
assert.deepEqual(data, {
@ -674,8 +685,6 @@ describe('Categories', function () {
'groups:posts:delete': true,
'groups:read': true,
'groups:topics:read': true,
'groups:upload:post:file': false,
'groups:upload:post:image': true,
'groups:purge': false,
'groups:moderate': false,
});
@ -684,6 +693,19 @@ describe('Categories', function () {
});
});
it('should load global group privileges', function (done) {
privileges.global.groupPrivileges('registered-users', function (err, data) {
assert.ifError(err);
assert.deepEqual(data, {
'groups:chat': true,
'groups:upload:post:image': true,
'groups:upload:post:file': false,
});
done();
});
});
it('should return false if cid is falsy', function (done) {
privileges.categories.isUserAllowedTo('find', null, adminUid, function (err, isAllowed) {
assert.ifError(err);

@ -71,9 +71,9 @@ describe('Groups', function () {
describe('.list()', function () {
it('should list the groups present', function (done) {
Groups.getGroupsFromSet('groups:createtime', 0, 0, -1, function (err, groups) {
Groups.getGroupsFromSet('groups:visible:createtime', 0, 0, -1, function (err, groups) {
assert.ifError(err);
assert.equal(groups.length, 7);
assert.equal(groups.length, 4);
done();
});
});

@ -414,7 +414,7 @@ describe('Messaging Library', function () {
it('should fail to load room if user is not in', function (done) {
socketModules.chats.loadRoom({ uid: 0 }, { roomId: roomId }, function (err) {
assert.equal(err.message, '[[error:not-allowed]]');
assert.equal(err.message, '[[error:no-privileges]]');
done();
});
});
@ -579,11 +579,12 @@ describe('Messaging Library', function () {
});
});
it('should 404 for guest', function (done) {
it('should 500 for guest with no privilege error', function (done) {
meta.config.disableChat = 0;
request(nconf.get('url') + '/user/baz/chats', function (err, response) {
request(nconf.get('url') + '/api/user/baz/chats', { json: true }, function (err, response, body) {
assert.ifError(err);
assert.equal(response.statusCode, 404);
assert.equal(response.statusCode, 500);
assert.equal(body.error, '[[error:no-privileges]]');
done();
});
});

@ -154,6 +154,9 @@ function setupMockDefaults(callback) {
winston.info('test_database flushed');
setupDefaultConfigs(meta, next);
},
function (next) {
giveDefaultGlobalPrivileges(next);
},
function (next) {
meta.configs.init(next);
},
@ -182,6 +185,11 @@ function setupDefaultConfigs(meta, next) {
meta.configs.setOnEmpty(defaults, next);
}
function giveDefaultGlobalPrivileges(next) {
var privileges = require('../../src/privileges');
privileges.global.give(['chat', 'upload:post:image'], 'registered-users', next);
}
function enableDefaultPlugins(callback) {
winston.info('Enabling default plugins\n');

@ -62,7 +62,7 @@ describe('Upload Controllers', function () {
assert.ifError(err);
jar = _jar;
csrf_token = _csrf_token;
privileges.categories.give(['upload:post:file'], cid, 'registered-users', done);
privileges.global.give(['upload:post:file'], 'registered-users', done);
});
});
@ -77,17 +77,8 @@ describe('Upload Controllers', function () {
});
});
it('should fail to upload an image to a post with invalid cid', function (done) {
helpers.uploadFile(nconf.get('url') + '/api/post/upload', path.join(__dirname, '../test/files/test.png'), { cid: '0' }, jar, csrf_token, function (err, res, body) {
assert.ifError(err);
assert.equal(res.statusCode, 500);
assert.equal(body.error, '[[error:category-not-selected]]');
done();
});
});
it('should upload an image to a post', function (done) {
helpers.uploadFile(nconf.get('url') + '/api/post/upload', path.join(__dirname, '../test/files/test.png'), { cid: cid }, jar, csrf_token, function (err, res, body) {
helpers.uploadFile(nconf.get('url') + '/api/post/upload', path.join(__dirname, '../test/files/test.png'), {}, jar, csrf_token, function (err, res, body) {
assert.ifError(err);
assert.equal(res.statusCode, 200);
assert(Array.isArray(body));
@ -100,7 +91,7 @@ describe('Upload Controllers', function () {
it('should resize and upload an image to a post', function (done) {
var oldValue = meta.config.maximumImageWidth;
meta.config.maximumImageWidth = 10;
helpers.uploadFile(nconf.get('url') + '/api/post/upload', path.join(__dirname, '../test/files/test.png'), { cid: cid }, jar, csrf_token, function (err, res, body) {
helpers.uploadFile(nconf.get('url') + '/api/post/upload', path.join(__dirname, '../test/files/test.png'), {}, jar, csrf_token, function (err, res, body) {
assert.ifError(err);
assert.equal(res.statusCode, 200);
assert(Array.isArray(body));
@ -116,7 +107,7 @@ describe('Upload Controllers', function () {
meta.config.allowFileUploads = 1;
var oldValue = meta.config.allowedFileExtensions;
meta.config.allowedFileExtensions = 'png,jpg,bmp,html';
helpers.uploadFile(nconf.get('url') + '/api/post/upload', path.join(__dirname, '../test/files/503.html'), { cid: cid }, jar, csrf_token, function (err, res, body) {
helpers.uploadFile(nconf.get('url') + '/api/post/upload', path.join(__dirname, '../test/files/503.html'), {}, jar, csrf_token, function (err, res, body) {
meta.config.allowedFileExtensions = oldValue;
assert.ifError(err);
assert.equal(res.statusCode, 200);

Loading…
Cancel
Save