From 5353960ae7820d38e386592682e3991e1401d8d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Tue, 29 Jan 2019 13:11:45 -0500 Subject: [PATCH] fix: #7316 --- public/src/admin/manage/registration.js | 4 +- src/controllers/globalmods.js | 16 ++++++ src/routes/index.js | 1 + src/socket.io/admin/user.js | 38 -------------- src/socket.io/user.js | 1 + src/socket.io/user/registration.js | 70 +++++++++++++++++++++++++ test/controllers-admin.js | 18 +++++++ test/user.js | 22 ++++---- 8 files changed, 120 insertions(+), 50 deletions(-) create mode 100644 src/socket.io/user/registration.js diff --git a/public/src/admin/manage/registration.js b/public/src/admin/manage/registration.js index 048aafbf96..08f8b6722b 100644 --- a/public/src/admin/manage/registration.js +++ b/public/src/admin/manage/registration.js @@ -9,7 +9,7 @@ define('admin/manage/registration', function () { var parent = $(this).parents('[data-username]'); var action = $(this).attr('data-action'); var username = parent.attr('data-username'); - var method = action === 'accept' ? 'admin.user.acceptRegistration' : 'admin.user.rejectRegistration'; + var method = action === 'accept' ? 'user.acceptRegistration' : 'user.rejectRegistration'; socket.emit(method, { username: username }, function (err) { if (err) { @@ -25,7 +25,7 @@ define('admin/manage/registration', function () { var email = parent.attr('data-invitation-mail'); var invitedBy = parent.attr('data-invited-by'); var action = $(this).attr('data-action'); - var method = 'admin.user.deleteInvitation'; + var method = 'user.deleteInvitation'; var removeRow = function () { var nextRow = parent.next(); diff --git a/src/controllers/globalmods.js b/src/controllers/globalmods.js index 1cae97a4e2..ed564c9093 100644 --- a/src/controllers/globalmods.js +++ b/src/controllers/globalmods.js @@ -4,6 +4,7 @@ var async = require('async'); var user = require('../user'); var adminBlacklistController = require('./admin/blacklist'); +var usersController = require('./admin/users'); var globalModsController = module.exports; @@ -20,3 +21,18 @@ globalModsController.ipBlacklist = function (req, res, next) { }, ], next); }; + + +globalModsController.registrationQueue = function (req, res, next) { + async.waterfall([ + function (next) { + user.isAdminOrGlobalMod(req.uid, next); + }, + function (isAdminOrGlobalMod, next) { + if (!isAdminOrGlobalMod) { + return next(); + } + usersController.registrationQueue(req, res, next); + }, + ], next); +}; diff --git a/src/routes/index.js b/src/routes/index.js index 40abf06e42..e62b115059 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -46,6 +46,7 @@ function modRoutes(app, middleware, controllers) { function globalModRoutes(app, middleware, controllers) { setupPageRoute(app, '/ip-blacklist', middleware, [], controllers.globalMods.ipBlacklist); + setupPageRoute(app, '/registration-queue', middleware, [], controllers.globalMods.registrationQueue); } function topicRoutes(app, middleware, controllers) { diff --git a/src/socket.io/admin/user.js b/src/socket.io/admin/user.js index de27e1f07d..6bbf7d57ae 100644 --- a/src/socket.io/admin/user.js +++ b/src/socket.io/admin/user.js @@ -221,44 +221,6 @@ User.search = function (socket, data, callback) { ], callback); }; -User.deleteInvitation = function (socket, data, callback) { - user.deleteInvitation(data.invitedBy, data.email, callback); -}; - -User.acceptRegistration = function (socket, data, callback) { - async.waterfall([ - function (next) { - user.acceptRegistration(data.username, next); - }, - function (uid, next) { - events.log({ - type: 'registration-approved', - uid: socket.uid, - ip: socket.ip, - targetUid: uid, - }); - next(null, uid); - }, - ], callback); -}; - -User.rejectRegistration = function (socket, data, callback) { - async.waterfall([ - function (next) { - user.rejectRegistration(data.username, next); - }, - function (next) { - events.log({ - type: 'registration-rejected', - uid: socket.uid, - ip: socket.ip, - username: data.username, - }); - next(); - }, - ], callback); -}; - User.restartJobs = function (socket, data, callback) { user.startJobs(callback); }; diff --git a/src/socket.io/user.js b/src/socket.io/user.js index db1c49d48f..3db21d34d8 100644 --- a/src/socket.io/user.js +++ b/src/socket.io/user.js @@ -22,6 +22,7 @@ require('./user/search')(SocketUser); require('./user/status')(SocketUser); require('./user/picture')(SocketUser); require('./user/ban')(SocketUser); +require('./user/registration')(SocketUser); SocketUser.exists = function (socket, data, callback) { if (!data || !data.username) { diff --git a/src/socket.io/user/registration.js b/src/socket.io/user/registration.js new file mode 100644 index 0000000000..aee1382eb2 --- /dev/null +++ b/src/socket.io/user/registration.js @@ -0,0 +1,70 @@ +'use strict'; + +var async = require('async'); +var user = require('../../user'); +var events = require('../../events'); + +module.exports = function (SocketUser) { + SocketUser.acceptRegistration = function (socket, data, callback) { + async.waterfall([ + function (next) { + user.isAdminOrGlobalMod(socket.uid, next); + }, + function (isAdminOrGlobalMod, next) { + if (!isAdminOrGlobalMod) { + return next(new Error('[[error:no-privileges]]')); + } + + user.acceptRegistration(data.username, next); + }, + function (uid, next) { + events.log({ + type: 'registration-approved', + uid: socket.uid, + ip: socket.ip, + targetUid: uid, + }); + next(null, uid); + }, + ], callback); + }; + + SocketUser.rejectRegistration = function (socket, data, callback) { + async.waterfall([ + function (next) { + user.isAdminOrGlobalMod(socket.uid, next); + }, + function (isAdminOrGlobalMod, next) { + if (!isAdminOrGlobalMod) { + return next(new Error('[[error:no-privileges]]')); + } + + user.rejectRegistration(data.username, next); + }, + function (next) { + events.log({ + type: 'registration-rejected', + uid: socket.uid, + ip: socket.ip, + username: data.username, + }); + next(); + }, + ], callback); + }; + + SocketUser.deleteInvitation = function (socket, data, callback) { + async.waterfall([ + function (next) { + user.isAdminOrGlobalMod(socket.uid, next); + }, + function (isAdminOrGlobalMod, next) { + if (!isAdminOrGlobalMod) { + return next(new Error('[[error:no-privileges]]')); + } + + user.deleteInvitation(data.invitedBy, data.email, next); + }, + ], callback); + }; +}; diff --git a/test/controllers-admin.js b/test/controllers-admin.js index 7f72de3c05..9672f6ad4a 100644 --- a/test/controllers-admin.js +++ b/test/controllers-admin.js @@ -300,6 +300,24 @@ describe('Admin Controllers', function () { }); }); + it('should 404 if users is not privileged', function (done) { + request(nconf.get('url') + '/api/registration-queue', { json: true }, function (err, res, body) { + assert.ifError(err); + assert.equal(res.statusCode, 404); + assert(body); + done(); + }); + }); + + it('should load /api/registration-queue', function (done) { + request(nconf.get('url') + '/api/registration-queue', { jar: jar, json: true }, function (err, res, body) { + assert.ifError(err); + assert.equal(res.statusCode, 200); + assert(body); + done(); + }); + }); + it('should load /admin/manage/admins-mods', function (done) { request(nconf.get('url') + '/api/admin/manage/admins-mods', { jar: jar, json: true }, function (err, res, body) { assert.ifError(err); diff --git a/test/user.js b/test/user.js index c59021cbde..2d5505a6a8 100644 --- a/test/user.js +++ b/test/user.js @@ -1638,7 +1638,7 @@ describe('User', function () { }); it('should reject user registration', function (done) { - socketAdmin.user.rejectRegistration({ uid: adminUid }, { username: 'rejectme' }, function (err) { + socketUser.rejectRegistration({ uid: adminUid }, { username: 'rejectme' }, function (err) { assert.ifError(err); User.getRegistrationQueue(0, -1, function (err, users) { assert.ifError(err); @@ -1657,7 +1657,7 @@ describe('User', function () { gdpr_consent: true, }, function (err) { assert.ifError(err); - socketAdmin.user.acceptRegistration({ uid: adminUid }, { username: 'acceptme' }, function (err, uid) { + socketUser.acceptRegistration({ uid: adminUid }, { username: 'acceptme' }, function (err, uid) { assert.ifError(err); User.exists(uid, function (err, exists) { assert.ifError(err); @@ -1676,15 +1676,17 @@ describe('User', function () { describe('invites', function () { var socketUser = require('../src/socket.io/user'); var inviterUid; + var adminUid; before(function (done) { - User.create({ - username: 'inviter', - email: 'inviter@nodebb.org', - }, function (err, uid) { + async.parallel({ + inviter: async.apply(User.create, { username: 'inviter', email: 'inviter@nodebb.org' }), + admin: async.apply(User.create, { username: 'adminInvite' }), + }, function (err, results) { assert.ifError(err); - inviterUid = uid; - done(); + inviterUid = results.inviter; + adminUid = results.admin; + groups.join('administrators', adminUid, done); }); }); @@ -1793,8 +1795,8 @@ describe('User', function () { }); it('should delete invitation', function (done) { - var socketAdmin = require('../src/socket.io/admin'); - socketAdmin.user.deleteInvitation({ uid: inviterUid }, { invitedBy: 'inviter', email: 'invite1@test.com' }, function (err) { + var socketUser = require('../src/socket.io/user'); + socketUser.deleteInvitation({ uid: adminUid }, { invitedBy: 'inviter', email: 'invite1@test.com' }, function (err) { assert.ifError(err); db.isSetMember('invitation:uid:' + inviterUid, 'invite1@test.com', function (err, isMember) { assert.ifError(err);