diff --git a/modules/account/back/methods/account-linker/syncRoles.js b/modules/account/back/methods/account-linker/syncRoles.js new file mode 100644 index 000000000..682664bcf --- /dev/null +++ b/modules/account/back/methods/account-linker/syncRoles.js @@ -0,0 +1,17 @@ +const NotFoundError = require('vn-loopback/util/not-found-error'); + +module.exports = Self => { + Self.remoteMethod('syncRoles', { + description: 'syncRoles', + http: { + path: `/syncRoles`, + verb: 'GET' + } + }); + + Self.syncRoles = async function() { + const connector = await Self.getLinker(); + if (!connector) throw new NotFoundError('Linker not configured'); + await connector.syncRoles(); + }; +}; diff --git a/modules/account/back/mixins/account-linker.js b/modules/account/back/mixins/account-linker.js index c882d0893..6f399a993 100644 --- a/modules/account/back/mixins/account-linker.js +++ b/modules/account/back/mixins/account-linker.js @@ -4,6 +4,7 @@ const UserError = require('vn-loopback/util/user-error'); module.exports = function(Self, options) { require('../methods/account-linker/test')(Self); + require('../methods/account-linker/syncRoles')(Self); Self.once('attached', function() { app.models.AccountConfig.addLinker(Self); @@ -54,7 +55,13 @@ module.exports = function(Self, options) { /** * Synchronizes roles. */ - async syncRoles() {}, + async syncRoles() { try { + await this.syncRoles(); + } catch (e) { + let err = new UserError(e.message); + err.name = e.name; + throw err; + }}, /** * Tests linker configuration. diff --git a/modules/account/back/models/samba-config.js b/modules/account/back/models/samba-config.js index b604b4220..c1643ae30 100644 --- a/modules/account/back/models/samba-config.js +++ b/modules/account/back/models/samba-config.js @@ -1,5 +1,6 @@ const app = require('vn-loopback/server/server'); const ldap = require('../util/ldapjs-extra'); +const { differences, handleExecResponse, toMap } = require('../util/helpers'); const execFile = require('child_process').execFile; /** @@ -171,6 +172,7 @@ module.exports = Self => { }, async syncRoles() { + await this.init(); let $ = app.models; // let { // client, @@ -182,12 +184,13 @@ module.exports = Self => { // OBTENER ROLES let roles = (await $.VnRole.find({ fields: ['id', 'name', 'description'], - order: 'modified DESC' + order: 'modified DESC', + limit: 1 })); let rolesMap = roles.map(role => role.name); // OBTENER SAMBA ROLES - let sambaCurrentRoles = await sambaTool('group', ['list']); + let sambaCurrentRoles = handleExecResponse(await this.sambaTool('group', ['list'])); // Encontrar elementos a eliminar const rolesToDelete = differences(sambaCurrentRoles, rolesMap); @@ -229,7 +232,7 @@ module.exports = Self => { if (exist) { return usersMap.get(role)?.map( - a => sambaTool('group', ['removemembers', role, a]) + a => this.sambaTool('group', ['removemembers', role, a]) ); } else return []; } @@ -237,20 +240,20 @@ module.exports = Self => { const resultsUserDelete = await Promise.all(usersToDelete); // PROCEDIMIENTO PARA ELIMINAR ROLES - const resultsRoleDelete = await Promise.all( - rolesToDelete.map(role => sambaTool('group', ['delete', role])) - ); + //const resultsRoleDelete = await Promise.all( + // rolesToDelete.map(role => this.sambaTool('group', ['delete', role])) + // ); } if (rolesToInsert.length > 0) { // PROCEDIMIENTO PARA INSERTAR ROLES const resultsRoleInsert = await Promise.all( - rolesToInsert.map(role => sambaTool('group', ['add', role])) + rolesToInsert.map(role => this.sambaTool('group', ['add', role])) ); // PROCEDIMIENTO PARA INSERTAR USUARIOS ASOCIADOS AL ROL let usersToInsert = rolesToInsert.flatMap(role => usersMap.get(role).map( - a => sambaTool('group', ['addmembers', role, a]) + a => this.sambaTool('group', ['addmembers', role, a]) ) ); const resultsUserInsert = await Promise.all(usersToInsert); @@ -259,11 +262,11 @@ module.exports = Self => { if (rolesToUpdate.length > 0) { let promises = []; for await (const role of rolesToUpdate) { - const users = await sambaTool('group', ['listmembers', role]); + const users = await this.sambaTool('group', ['listmembers', role]); const usersToDelete = differences(users, usersMap.get(role)); - promises.push(usersToDelete.map(user => sambaTool('group', ['removemembers', user.name]))); + promises.push(usersToDelete.map(user => this.sambaTool('group', ['removemembers', user.name]))); const usersToInsert = differences(usersMap.get(role), users); - promises.push(usersToInsert.map(user => sambaTool('group', ['addmembers', user.name]))); + promises.push(usersToInsert.map(user => this.sambaTool('group', ['addmembers', user.name]))); await Promise.all(promises); } diff --git a/modules/account/back/util/helpers.js b/modules/account/back/util/helpers.js new file mode 100644 index 000000000..8ed67b87d --- /dev/null +++ b/modules/account/back/util/helpers.js @@ -0,0 +1,65 @@ +module.exports ={ + toMap, + binarySearch, + differences, + handleExecResponse +}; + +function handleExecResponse({stdin, stdout}) { + return stdout.split("\n"); +} + +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; +} +function binarySearch(array, value) { + let first = 0; + + let last = array.length - 1; + + while (first <= last) { + const index = Math.floor((first + last) / 2); + + const middle = array[index]; + + if (middle === value) + return index; // Elemento encontrado, devuelve la posición. + + if (middle < value) + first = index + 1; + else + last = index - 1; + } + + return -1; // Elemento no encontrado. +} + +function differences(array1, array2) { + const differences = []; + + // Ordena ambos arrays + + const sortedArray1 = array1.slice().sort(); + const sortedArray2 = array2.slice().sort(); + + for (const value of sortedArray1) { + // Busca el elemento en el array ordenado utilizando búsqueda binaria + + const result = binarySearch(sortedArray2, value); + + // Si el elemento no se encuentra, agrégalo a la lista de diferencias + + if (result === -1) + differences.push(value); + } + + return differences; +}