diff --git a/docs/references/api.md b/docs/references/api.md index b16ba3d13..193b7ee3a 100644 --- a/docs/references/api.md +++ b/docs/references/api.md @@ -860,6 +860,19 @@ Response (200): } ``` +### Set members + +PUT `/api/v1/groups/:groupId` admin + +Sets the members of an existing group with id `groupId`. + +Request: +``` +{ + userIds: [ , ... ] // list of users to be part of this group +} +``` + ### List groups GET `/api/v1/groups` admin diff --git a/src/groupdb.js b/src/groupdb.js index 0d63b9403..840c6537f 100644 --- a/src/groupdb.js +++ b/src/groupdb.js @@ -12,6 +12,7 @@ exports = module.exports = { getMembers: getMembers, addMember: addMember, removeMember: removeMember, + setMembers: setMembers, isMember: isMember, getGroups: getGroups, @@ -147,6 +148,25 @@ function getMembers(groupId, callback) { }); } +function setMembers(groupId, userIds, callback) { + assert.strictEqual(typeof groupId, 'string'); + assert(Array.isArray(userIds)); + assert.strictEqual(typeof callback, 'function'); + + var queries = []; + queries.push({ query: 'DELETE FROM groupMembers WHERE groupId = ?', args: [ groupId ] }); + for (var i = 0; i < userIds.length; i++) { + queries.push({ query: 'INSERT INTO groupMembers (groupId, userId) VALUES (?, ?)', args: [ groupId, userIds[i] ] }); + } + + database.transaction(queries, function (error) { + if (error && error.code === 'ER_NO_REFERENCED_ROW_2') return callback(new DatabaseError(DatabaseError.NOT_FOUND)); + if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error)); + + callback(error); + }); +} + function getGroups(userId, callback) { assert.strictEqual(typeof userId, 'string'); assert.strictEqual(typeof callback, 'function'); diff --git a/src/groups.js b/src/groups.js index dd481d20c..3c79dc2b1 100644 --- a/src/groups.js +++ b/src/groups.js @@ -12,6 +12,7 @@ exports = module.exports = { getMembers: getMembers, addMember: addMember, + setMembers: setMembers, removeMember: removeMember, isMember: isMember, @@ -203,6 +204,19 @@ function addMember(groupId, userId, callback) { }); } +function setMembers(groupId, userIds, callback) { + assert.strictEqual(typeof groupId, 'string'); + assert(Array.isArray(userIds)); + assert.strictEqual(typeof callback, 'function'); + + groupdb.setMembers(groupId, userIds, function (error) { + if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new GroupError(GroupError.NOT_FOUND, 'Invalid group or user id')); + if (error) return callback(new GroupError(GroupError.INTERNAL_ERROR, error)); + + return callback(null); + }); +} + function removeMember(groupId, userId, callback) { assert.strictEqual(typeof groupId, 'string'); assert.strictEqual(typeof userId, 'string'); diff --git a/src/routes/groups.js b/src/routes/groups.js index 2edfb992e..e968e28c7 100644 --- a/src/routes/groups.js +++ b/src/routes/groups.js @@ -4,7 +4,8 @@ exports = module.exports = { get: get, list: list, create: create, - remove: remove + remove: remove, + update: update }; var assert = require('assert'), @@ -44,6 +45,20 @@ function get(req, res, next) { }); } +function update(req, res, next) { + assert.strictEqual(typeof req.params.groupId, 'string'); + + if (!req.body.userIds) return next(new HttpError(404, 'missing or invalid userIds fields')); + if (!Array.isArray(req.body.userIds)) return next(new HttpError(404, 'userIds must be an array')); + + groups.setMembers(req.params.groupId, req.body.userIds, function (error) { + if (error && error.reason === GroupError.NOT_FOUND) return next(new HttpError(404, 'Invalid group or user id')); + if (error) return next(new HttpError(500, error)); + + next(new HttpSuccess(200)); + }); +} + function list(req, res, next) { groups.getAllWithMembers(function (error, result) { if (error) return next(new HttpError(500, error)); diff --git a/src/server.js b/src/server.js index 01edb3ca9..a41c5a364 100644 --- a/src/server.js +++ b/src/server.js @@ -123,6 +123,7 @@ function initializeExpressSync() { router.get ('/api/v1/groups', usersScope, routes.user.requireAdmin, routes.groups.list); router.post('/api/v1/groups', usersScope, routes.user.requireAdmin, routes.groups.create); router.get ('/api/v1/groups/:groupId', usersScope, routes.user.requireAdmin, routes.groups.get); + router.put ('/api/v1/groups/:groupId', usersScope, routes.user.requireAdmin, routes.groups.update); router.del ('/api/v1/groups/:groupId', usersScope, routes.user.requireAdmin, routes.user.verifyPassword, routes.groups.remove); // form based login routes used by oauth2 frame