130 lines
3.8 KiB
JavaScript
130 lines
3.8 KiB
JavaScript
const ldap = require('../../util/ldapjs-extra');
|
|
|
|
module.exports = Self => {
|
|
Self.remoteMethod('sync', {
|
|
description: 'Synchronizes the user with the other user databases',
|
|
http: {
|
|
path: `/sync`,
|
|
verb: 'PATCH'
|
|
}
|
|
});
|
|
|
|
Self.sync = async function() {
|
|
let $ = Self.app.models;
|
|
|
|
let ldapConfig = await $.LdapConfig.findOne({
|
|
fields: ['host', 'rdn', 'password', 'groupDn']
|
|
});
|
|
let accountConfig = await $.AccountConfig.findOne({
|
|
fields: ['idBase']
|
|
});
|
|
|
|
if (!ldapConfig) return;
|
|
|
|
// Connect
|
|
|
|
let client = ldap.createClient({
|
|
url: `ldap://${ldapConfig.host}:389`
|
|
});
|
|
|
|
let ldapPassword = Buffer
|
|
.from(ldapConfig.password, 'base64')
|
|
.toString('ascii');
|
|
await client.bind(ldapConfig.rdn, ldapPassword);
|
|
|
|
let err;
|
|
try {
|
|
// Delete roles
|
|
|
|
let opts = {
|
|
scope: 'sub',
|
|
attributes: ['dn'],
|
|
filter: 'objectClass=posixGroup'
|
|
};
|
|
res = await client.search(ldapConfig.groupDn, opts);
|
|
|
|
let reqs = [];
|
|
await new Promise((resolve, reject) => {
|
|
res.on('error', err => {
|
|
if (err.name === 'NoSuchObjectError')
|
|
err = new Error(`Object '${ldapConfig.groupDn}' does not exist`);
|
|
reject(err);
|
|
});
|
|
res.on('searchEntry', e => {
|
|
reqs.push(client.del(e.object.dn));
|
|
});
|
|
res.on('end', resolve);
|
|
});
|
|
await Promise.all(reqs);
|
|
|
|
// Recreate roles
|
|
|
|
let roles = await $.Role.find({
|
|
fields: ['id', 'name']
|
|
});
|
|
let roleRoles = await $.RoleRole.find({
|
|
fields: ['role', 'inheritsFrom']
|
|
});
|
|
let roleMap = toMap(roleRoles, e => {
|
|
return {key: e.inheritsFrom, val: e.role};
|
|
});
|
|
|
|
let accounts = await $.UserAccount.find({
|
|
fields: ['id'],
|
|
include: {
|
|
relation: 'user',
|
|
scope: {
|
|
fields: ['name', 'roleFk'],
|
|
where: {active: true}
|
|
}
|
|
}
|
|
});
|
|
let accountMap = toMap(accounts, e => {
|
|
let user = e.user();
|
|
if (!user) return;
|
|
return {key: user.roleFk, val: user.name};
|
|
});
|
|
|
|
reqs = [];
|
|
for (let role of roles) {
|
|
let newEntry = {
|
|
objectClass: ['top', 'posixGroup'],
|
|
cn: role.name,
|
|
gidNumber: accountConfig.idBase + role.id
|
|
};
|
|
|
|
let memberUid = [];
|
|
for (subrole of roleMap.get(role.id) || [])
|
|
memberUid = memberUid.concat(accountMap.get(subrole) || []);
|
|
|
|
if (memberUid.length) {
|
|
memberUid.sort((a, b) => a.localeCompare(b));
|
|
newEntry.memberUid = memberUid;
|
|
}
|
|
|
|
let dn = `cn=${role.name},${ldapConfig.groupDn}`;
|
|
reqs.push(client.add(dn, newEntry));
|
|
}
|
|
await Promise.all(reqs);
|
|
} catch (e) {
|
|
err = e;
|
|
}
|
|
|
|
// FIXME: Cannot disconnect, hangs on undind() call
|
|
// await client.unbind();
|
|
if (err) throw err;
|
|
};
|
|
};
|
|
|
|
function toMap(array, fn) {
|
|
let map = new Map();
|
|
for (let item of array) {
|
|
let keyVal = fn(item);
|
|
if (!keyVal) continue;
|
|
let key = keyVal.key;
|
|
if (!map.has(key)) map.set(key, []);
|
|
map.get(key).push(keyVal.val);
|
|
}
|
|
return map;
|
|
}
|