From d3f9eb173d4b56a9d3f663e8f8b0b003e31d0b57 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Thu, 25 Jan 2024 09:50:08 +0100 Subject: [PATCH] refs #5770 feat approach2 --- modules/account/back/models/samba-config.js | 113 ++++++++- .../back/models/specs/samba-config.spec.js | 220 ++++++++++++++---- 2 files changed, 288 insertions(+), 45 deletions(-) diff --git a/modules/account/back/models/samba-config.js b/modules/account/back/models/samba-config.js index 911b429c9..7f7ad8ca5 100644 --- a/modules/account/back/models/samba-config.js +++ b/modules/account/back/models/samba-config.js @@ -170,7 +170,82 @@ module.exports = Self => { o => usersToSync.add(o.sAMAccountName)); }, - async syncRoles(role) { + async syncRoles() { + let $ = app.models; + let { + client, + accountConfig + } = this; + + // Prepare data + + let roles = await $.VnRole.find({ + fields: ['id', 'name', 'description'] + }); + let roleRoles = await $.RoleRole.find({ + fields: ['role', 'inheritsFrom'] + }); + let roleMap = toMap(roleRoles, e => { + return {key: e.inheritsFrom, val: e.role}; + }); + + let accounts = await $.Account.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}; + }); + + // Delete roles + + let opts = { + scope: 'sub', + attributes: ['dn'], + filter: 'objectClass=posixGroup' + }; + let reqs = []; + await client.searchForeach(this.groupDn, opts, object => { + if (shouldSync) + reqs.push(client.del(object.dn)); + }); + await Promise.all(reqs); + + // Recreate roles + + reqs = []; + for (let role of roles) { + let newEntry = { + objectClass: ['top', 'posixGroup'], + cn: role.name, + description: role.description, + gidNumber: accountConfig.idBase + role.id + }; + + let memberUid = []; + for (let 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},${this.groupDn}`; + if (shouldSync) + reqs.push(client.add(dn, newEntry)); + } + await Promise.all(reqs); + }, + async syncRole(role) { let $ = app.models; let { client, @@ -247,6 +322,42 @@ module.exports = Self => { reqs.push(client.add(dn, newEntry)); } await Promise.all(reqs); + }, + async syncRoleX(roleName, info) { + let vnRoleArgs = { + fields: ['id', 'name', 'description'], + + }; + let role = null; + let roles = []; + if (roleName) { + vnRoleArgs.where = { + name: roleName + }; + role = await $.VnRole.find(vnRoleArgs); + } else roles = await $.VnRole.find(vnRoleArgs); + let roleRoleArgs = { + fields: ['role', 'inheritsFrom'], + + }; + if (role) roleRoleArgs.where = {'role.id': roles[0].id}; + let roleRoles = await $.RoleRole.find(roleRoleArgs); + let roleMap = toMap(roleRoles, e => { + return {key: e.inheritsFrom, val: e.role}; + }); + + let currentGroupList = await this.sambaTool('group', ['list']); + if (info.disableGroup || info.enableGroup) { + if (currentGroupList.includes(roleName)) + await this.sambaTool('group', ['modify', roleName, `--is-visible=${info.enableGroup ? 'yes' : 'no'}`]); + } else if (info.removeGroup) + await this.sambaTool('group', ['delete']); + + else if (info.recreateGroups) { + for (const role of roleMap) + await this.sambaTool('group', ['add', roleName, `--description=${role.description}`]); + } } + }); }; diff --git a/modules/account/back/models/specs/samba-config.spec.js b/modules/account/back/models/specs/samba-config.spec.js index 39eb0a878..b0588e9a3 100644 --- a/modules/account/back/models/specs/samba-config.spec.js +++ b/modules/account/back/models/specs/samba-config.spec.js @@ -1,8 +1,9 @@ +// const execFile = require('child_process').execFile; const app = require('vn-loopback/server/server'); -const RoleControlFlags = { - ACCOUNTDISABLE: 0x2 -}; -describe('Samba config', () => { +// const RoleControlFlags = { +// ACCOUNTDISABLE: 0x2 +// }; +fdescribe('Samba config', () => { // const employeeId = 1; // const developerId = 9; // const sysadminId = 66; @@ -10,52 +11,183 @@ describe('Samba config', () => { // const rootId = 100; // const clarkKent = 1103; - const roles = { + // const roles = { - itBoss: {id: 104, value: 'itBoss'} - }; + // itBoss: {id: 104, value: 'itBoss'} + // }; - it('With role as argument', async() => { - syncRole(roles.itBoss.value); + it('SyncRoles', async() => { + await syncRoles(); }); - it('No role as argument', async() => { + // it('With role as argument', async() => { + // syncRole(roles.itBoss.value); + // }); - }); + // it('No role as argument', async() => { + + // }); }); +async function sambaTool(command, args = []) { + // const allArgs = [command].concat( + // args + // ); + switch (command) { + case 'user': + if (args[0] === 'list') + return ['user1', 'user2']; + break; + case 'group': + if (args[0] === 'list') + return ['employee', 'customer', 'agency', 'group1']; + else if (args[0] === 'add') { + return new Promise(resolve => { + resolve(`samba-tool add ${args[1]}`); + }); + } else if (args[0] === 'delete') { + return new Promise(resolve => { + resolve(`samba-tool ${args[0]} ${args[1]}`); + }); + } else if (args[0] === 'listmembers') { + return new Promise(resolve => { + resolve(`samba-tool ${args[0]} ${args[1]}`); + }); + } else if (args[0] === 'addmembers') { + return new Promise(resolve => { + resolve(`samba-tool ${args[0]} ${args[1]} ${args[2]}`); + }); + } else if (args[0] === 'removemembers') { + return new Promise(resolve => { + resolve(`samba-tool ${args[0]} ${args[1]} ${args[2]}`); + }); + // return `samba-tool ${args[0]} ${args[1]} ${args[2]}`; + } + break; -async function syncRole(roleName, info) { - let vnRoleArgs = { - fields: ['id', 'name', 'description'], - - }; - let role = null; - let roles = []; - if (roleName) { - vnRoleArgs.where = { - name: roleName - }; - role = await $.VnRole.find(vnRoleArgs); - } else roles = await $.VnRole.find(vnRoleArgs); - let roleRoleArgs = { - fields: ['role', 'inheritsFrom'], - - }; - if (role) roleRoleArgs.where = {'role.id': roles[0].id}; - let roleRoles = await $.RoleRole.find(roleRoleArgs); - let roleMap = toMap(roleRoles, e => { - return {key: e.inheritsFrom, val: e.role}; - }); - - let currentGroupList = await this.sambaTool('group', ['list']); - if (info.disableGroup || info.enableGroup) { - if (currentGroupList.includes(roleName)) - await this.sambaTool('group', ['modify', roleName, `--is-visible=${info.enableGroup ? 'yes' : 'no'}`]); - } else if (info.removeGroup) - await this.sambaTool('group', ['delete']); - - else if (info.recreateGroups) { - for (const role of roleMap) - await this.sambaTool('group', ['add', roleName, `--description=${role.description}`]); + default: + break; } } +async function syncRoles() { + let $ = app.models; + // let { + // client, + // accountConfig + // } = this; + + // Prepare data + try { + // OBTENER ROLES + let roles = (await $.VnRole.find({ + fields: ['id', 'name', 'description'], + limit: 5 + })); + let rolesMap = roles.map(role => role.name); + expect(rolesMap.length).toEqual(5); + // OBTENER SAMBA ROLES + let sambaCurrentRoles = await sambaTool('group', ['list']); + expect(sambaCurrentRoles.length).toEqual(4); + // Encontrar elementos para eliminados + const rolesToDelete = sambaCurrentRoles.filter(item => !rolesMap.includes(item)); + expect(rolesToDelete.length).toEqual(1); + // Encontrar elementos insertar + const rolesToInsert = rolesMap.filter(item => !sambaCurrentRoles.includes(item)); + expect(rolesToInsert.length).toEqual(2); + // OBTENER USUARIOS Y SUS ROLES + if (rolesToDelete.length > 0 || rolesToInsert.length > 0) { + let accounts = await $.Account.find({ + fields: ['id'], + include: { + relation: 'user', + scope: { + include: { + relation: 'role', + scope: {fields: ['name'], + where: {'name': {inq: rolesToInsert}} + } + }, + fields: ['name', 'roleFk'], + where: {'active': true} + } + } + }); + let accountMap = toMap(accounts, e => { + let user = e.user(); + if (!user) return; + let role = user.role(); + if (!role) return; + return {key: role.name, val: user.name}; + }); + // for (const [key, value] of accountMap) { + // value.forEach(v => { + // console.log(v); + // }); + // console.log(`${key} = ${value}`); + // } + + if (rolesToDelete.length > 0) { + // PROCEDIMIENTO PARA ELIMINAR USUARIOS ASOCIADOS AL ROL + let usersToDelete = rolesToDelete.flatMap(role => { + const exist = accountMap.get(role); + + if (exist) { + return accountMap.get(role)?.map( + a => sambaTool('group', ['removemembers', role, a]) + ); + } else return []; + } + ); + const resultsUserDelete = await Promise.all(usersToDelete); + expect(resultsUserDelete.length).toEqual(0); + // PROCEDIMIENTO PARA ELIMINAR ROLES + const resultsRoleDelete = await Promise.all( + rolesToDelete.map(role => sambaTool('group', ['delete', role])) + ); + expect(resultsRoleDelete.length).toEqual(1); + expect(resultsRoleDelete[0]).toEqual('samba-tool delete group1'); + } + + if (rolesToInsert.length > 0) { + // PROCEDIMIENTO PARA INSERTAR USUARIOS ASOCIADOS AL ROL + let usersToInsert = rolesToInsert.flatMap(role => accountMap.get(role).map( + a => sambaTool('group', ['addmembers', role, a]) + ) + ); + const resultsUserInsert = await Promise.all(usersToInsert); + expect(resultsUserInsert.length).toEqual(2); + expect(resultsUserInsert[0]).toEqual('samba-tool addmembers administrative administrative'); + expect(resultsUserInsert[1]).toEqual('samba-tool addmembers guest guest'); + // PROCEDIMIENTO PARA INSERTAR ROLES + const resultsRoleInsert = await Promise.all( + rolesToInsert.map(role => sambaTool('group', ['add', role])) + ); + expect(resultsRoleInsert.length).toEqual(2); + expect(resultsRoleInsert[0]).toEqual('samba-tool add administrative'); + expect(resultsRoleInsert[1]).toEqual('samba-tool add guest'); + } + } + // let roleRoles = await $.RoleRole.find({ + // fields: ['role', 'inheritsFrom'] + // }); + // let roleMap = toMap(roleRoles, e => { + // return {key: e.inheritsFrom, val: e.role}; + // }); + + console.log('Elementos eliminados:', rolesToDelete); + console.log('Elementos para insertar:', rolesToInsert); + } catch (error) { + console.error(error); + } +} + +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; +}