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 accounts = await $.UserAccount.find({ fields: ['id'], include: { relation: 'user', scope: { fields: ['name'], include: { relation: 'roles', scope: { fields: ['inheritsFrom'] } } } } }); let map = new Map(); for (let account of accounts) { let user = account.user(); for (let inherit of user.roles()) { let roleId = inherit.inheritsFrom; if (!map.has(roleId)) map.set(roleId, []); map.get(roleId).push(user.name); } } reqs = []; for (let role of roles) { let newEntry = { objectClass: ['top', 'posixGroup'], cn: role.name, gidNumber: accountConfig.idBase + role.id }; let memberUid = map.get(role.id); if (memberUid) 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; }; };