Files
cloudron-box/src/groupdb.js
T

301 lines
12 KiB
JavaScript
Raw Normal View History

2016-02-07 20:25:08 -08:00
'use strict';
exports = module.exports = {
get: get,
2016-02-09 15:26:34 -08:00
getWithMembers: getWithMembers,
2016-02-09 13:33:30 -08:00
getAll: getAll,
getAllWithMembers: getAllWithMembers,
2016-02-07 20:25:08 -08:00
add: add,
2018-06-14 21:12:52 -07:00
update: update,
2016-02-07 20:25:08 -08:00
del: del,
count: count,
2016-02-08 09:41:21 -08:00
getMembers: getMembers,
addMember: addMember,
removeMember: removeMember,
2016-09-29 14:44:12 -07:00
setMembers: setMembers,
2016-02-08 10:53:01 -08:00
isMember: isMember,
2016-02-08 09:41:21 -08:00
2016-02-08 20:38:50 -08:00
getGroups: getGroups,
2016-02-09 15:47:02 -08:00
setGroups: setGroups,
2016-02-08 20:38:50 -08:00
2018-06-16 00:29:56 -07:00
getRoles: getRoles,
2018-06-14 21:56:18 -07:00
_clear: clear
2016-02-07 20:25:08 -08:00
};
var assert = require('assert'),
database = require('./database.js'),
2018-06-14 21:12:52 -07:00
DatabaseError = require('./databaseerror'),
2018-06-16 00:29:56 -07:00
safe = require('safetydance'),
_ = require('underscore');
2016-02-07 20:25:08 -08:00
2018-06-14 21:12:52 -07:00
var GROUPS_FIELDS = [ 'id', 'name', 'rolesJson' ].join(',');
function postProcess(result) {
assert.strictEqual(typeof result, 'object');
assert(result.rolesJson === null || typeof result.rolesJson === 'string');
result.roles = safe.JSON.parse(result.rolesJson) || [ ];
delete result.rolesJson;
}
2016-02-07 20:25:08 -08:00
function get(groupId, callback) {
assert.strictEqual(typeof groupId, 'string');
assert.strictEqual(typeof callback, 'function');
2016-09-30 09:18:41 -07:00
database.query('SELECT ' + GROUPS_FIELDS + ' FROM groups WHERE id = ? ORDER BY name', [ groupId ], function (error, result) {
2016-02-07 20:25:08 -08:00
if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error));
if (result.length === 0) return callback(new DatabaseError(DatabaseError.NOT_FOUND));
2018-06-14 21:12:52 -07:00
postProcess(result[0]);
2016-02-07 20:25:08 -08:00
callback(null, result[0]);
});
}
2016-02-09 15:26:34 -08:00
function getWithMembers(groupId, callback) {
assert.strictEqual(typeof groupId, 'string');
assert.strictEqual(typeof callback, 'function');
database.query('SELECT ' + GROUPS_FIELDS + ',GROUP_CONCAT(groupMembers.userId) AS userIds ' +
' FROM groups LEFT OUTER JOIN groupMembers ON groups.id = groupMembers.groupId ' +
' WHERE groups.id = ? ' +
' GROUP BY groups.id', [ groupId ], function (error, results) {
if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error));
if (results.length === 0) return callback(new DatabaseError(DatabaseError.NOT_FOUND));
var result = results[0];
result.userIds = result.userIds ? result.userIds.split(',') : [ ];
2018-06-14 21:12:52 -07:00
postProcess(result);
2016-02-09 15:26:34 -08:00
callback(null, result);
});
}
2016-02-09 13:33:30 -08:00
function getAll(callback) {
assert.strictEqual(typeof callback, 'function');
2018-06-14 21:12:52 -07:00
database.query('SELECT ' + GROUPS_FIELDS + ' FROM groups', function (error, results) {
2016-02-09 13:33:30 -08:00
if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error));
2018-06-14 21:12:52 -07:00
results.forEach(postProcess);
callback(null, results);
2016-02-09 13:33:30 -08:00
});
}
function getAllWithMembers(callback) {
database.query('SELECT ' + GROUPS_FIELDS + ',GROUP_CONCAT(groupMembers.userId) AS userIds ' +
' FROM groups LEFT OUTER JOIN groupMembers ON groups.id = groupMembers.groupId ' +
' GROUP BY groups.id', function (error, results) {
if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error));
if (results.length === 0) return callback(new DatabaseError(DatabaseError.NOT_FOUND));
results.forEach(function (result) { result.userIds = result.userIds ? result.userIds.split(',') : [ ]; });
2018-06-14 21:12:52 -07:00
results.forEach(postProcess);
callback(null, results);
});
}
2018-06-14 21:12:52 -07:00
function add(id, name, roles, callback) {
2016-02-07 20:25:08 -08:00
assert.strictEqual(typeof id, 'string');
assert.strictEqual(typeof name, 'string');
2018-06-14 21:12:52 -07:00
assert(Array.isArray(roles));
2016-02-07 20:25:08 -08:00
assert.strictEqual(typeof callback, 'function');
2018-06-14 21:12:52 -07:00
database.query('INSERT INTO groups (id, name, rolesJson) VALUES (?, ?, ?)', [ id, name, JSON.stringify(roles) ], function (error, result) {
2016-02-07 20:25:08 -08:00
if (error && error.code === 'ER_DUP_ENTRY') return callback(new DatabaseError(DatabaseError.ALREADY_EXISTS, error));
if (error || result.affectedRows !== 1) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error));
2016-02-07 20:25:08 -08:00
callback(null);
});
}
2018-06-14 21:12:52 -07:00
function update(id, data, callback) {
assert.strictEqual(typeof id, 'string');
assert(data && typeof data === 'object');
assert.strictEqual(typeof callback, 'function');
var args = [ ];
var fields = [ ];
for (var k in data) {
if (k === 'roles') {
assert(Array.isArray(data.roles));
2018-06-14 22:42:40 -07:00
fields.push('rolesJson = ?');
2018-06-14 21:12:52 -07:00
args.push(data.roles.length === 0 ? null : JSON.stringify(data.roles));
} else if (k === 'name') {
assert.strictEqual(typeof data.name, 'string');
2018-06-14 22:42:40 -07:00
fields.push(k + ' = ?');
2018-06-14 21:12:52 -07:00
args.push(data.name);
}
}
args.push(id);
2018-06-14 22:42:40 -07:00
database.query('UPDATE groups SET ' + fields.join(', ') + ' WHERE id = ?', args, function (error, result) {
2018-06-14 21:12:52 -07:00
if (error && error.code === 'ER_DUP_ENTRY' && error.sqlMessage.indexOf('groups_name') !== -1) return callback(new DatabaseError(DatabaseError.ALREADY_EXISTS, 'name already exists'));
if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error));
2018-06-14 22:42:40 -07:00
if (result.affectedRows !== 1) return callback(new DatabaseError(DatabaseError.NOT_FOUND));
2018-06-14 21:12:52 -07:00
return callback(null);
});
}
2016-02-07 20:25:08 -08:00
function del(id, callback) {
assert.strictEqual(typeof id, 'string');
assert.strictEqual(typeof callback, 'function');
2016-02-13 11:55:30 +01:00
// also cleanup the groupMembers table
var queries = [];
queries.push({ query: 'DELETE FROM groupMembers WHERE groupId = ?', args: [ id ] });
queries.push({ query: 'DELETE FROM groups WHERE id = ?', args: [ id ] });
database.transaction(queries, function (error, result) {
2016-02-07 20:25:08 -08:00
if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error));
2016-02-13 11:55:30 +01:00
if (result[1].affectedRows !== 1) return callback(new DatabaseError(DatabaseError.NOT_FOUND));
2016-02-07 20:25:08 -08:00
callback(error);
});
}
function count(callback) {
assert.strictEqual(typeof callback, 'function');
database.query('SELECT COUNT(*) AS total FROM groups', function (error, result) {
if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error));
return callback(null, result[0].total);
});
}
function clear(callback) {
2016-02-08 09:41:21 -08:00
database.query('DELETE FROM groupMembers', function (error) {
2016-02-07 20:25:08 -08:00
if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error));
2016-02-09 12:23:48 -08:00
database.query('DELETE FROM groups WHERE id != ?', [ 'admin' ], function (error) {
2016-02-08 09:41:21 -08:00
if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error));
callback(error);
});
});
}
function getMembers(groupId, callback) {
2016-02-09 15:47:02 -08:00
assert.strictEqual(typeof groupId, 'string');
assert.strictEqual(typeof callback, 'function');
2016-02-08 09:41:21 -08:00
database.query('SELECT userId FROM groupMembers WHERE groupId=?', [ groupId ], function (error, result) {
if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error));
// if (result.length === 0) return callback(new DatabaseError(DatabaseError.NOT_FOUND)); // need to differentiate group with no members and invalid groupId
callback(error, result.map(function (r) { return r.userId; }));
2016-02-07 20:25:08 -08:00
});
}
2016-09-29 14:44:12 -07:00
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);
});
}
2016-02-08 20:38:50 -08:00
function getGroups(userId, callback) {
2016-02-09 15:47:02 -08:00
assert.strictEqual(typeof userId, 'string');
assert.strictEqual(typeof callback, 'function');
database.query('SELECT groupId FROM groupMembers WHERE userId=? ORDER BY groupId', [ userId ], function (error, result) {
2016-02-08 20:38:50 -08:00
if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error));
// if (result.length === 0) return callback(new DatabaseError(DatabaseError.NOT_FOUND)); // need to differentiate group with no members and invalid groupId
callback(error, result.map(function (r) { return r.groupId; }));
});
}
2016-02-09 15:47:02 -08:00
function setGroups(userId, groupIds, callback) {
assert.strictEqual(typeof userId, 'string');
assert(Array.isArray(groupIds));
assert.strictEqual(typeof callback, 'function');
var queries = [ ];
queries.push({ query: 'DELETE from groupMembers WHERE userId = ?', args: [ userId ] });
groupIds.forEach(function (gid) {
queries.push({ query: 'INSERT INTO groupMembers (groupId, userId) VALUES (? , ?)', args: [ gid, userId ] });
});
database.transaction(queries, function (error) {
if (error && error.code === 'ER_NO_REFERENCED_ROW_2') return callback(new DatabaseError(DatabaseError.NOT_FOUND, error.message));
if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error));
callback(null);
});
}
2016-02-08 09:41:21 -08:00
function addMember(groupId, userId, callback) {
assert.strictEqual(typeof groupId, 'string');
assert.strictEqual(typeof userId, 'string');
assert.strictEqual(typeof callback, 'function');
database.query('INSERT INTO groupMembers (groupId, userId) VALUES (?, ?)', [ groupId, userId ], function (error, result) {
if (error && error.code === 'ER_DUP_ENTRY') return callback(new DatabaseError(DatabaseError.ALREADY_EXISTS, error));
if (error && error.code === 'ER_NO_REFERENCED_ROW_2') return callback(new DatabaseError(DatabaseError.NOT_FOUND));
if (error || result.affectedRows !== 1) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error));
callback(null);
});
}
function removeMember(groupId, userId, callback) {
assert.strictEqual(typeof groupId, 'string');
assert.strictEqual(typeof userId, 'string');
assert.strictEqual(typeof callback, 'function');
database.query('DELETE FROM groupMembers WHERE groupId = ? AND userId = ?', [ groupId, userId ], function (error, result) {
if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error));
if (result.affectedRows !== 1) return callback(new DatabaseError(DatabaseError.NOT_FOUND));
callback(null);
});
}
2016-02-08 10:53:01 -08:00
function isMember(groupId, userId, callback) {
assert.strictEqual(typeof groupId, 'string');
assert.strictEqual(typeof userId, 'string');
assert.strictEqual(typeof callback, 'function');
database.query('SELECT 1 FROM groupMembers WHERE groupId=? AND userId=?', [ groupId, userId ], function (error, result) {
if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error));
callback(null, result.length !== 0);
});
}
2018-06-16 00:29:56 -07:00
function getRoles(userId, callback) {
assert.strictEqual(typeof userId, 'string');
assert.strictEqual(typeof callback, 'function');
database.query('SELECT ' + GROUPS_FIELDS + ' ' +
' FROM groups INNER JOIN groupMembers ON groups.id = groupMembers.groupId AND groupMembers.userId = ?', [ userId ], function (error, results) {
if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error));
if (results.length === 0) return callback(new DatabaseError(DatabaseError.NOT_FOUND));
results.forEach(postProcess);
2018-06-16 13:03:52 -07:00
callback(null, _.uniq(_.flatten(results.map(function (r) { return r.roles; }))));
2018-06-16 00:29:56 -07:00
});
}