From e5d3059ffbf5ff784807c6c2259a9cbc123263d3 Mon Sep 17 00:00:00 2001 From: William Belle Date: Thu, 19 Oct 2023 18:35:26 +0200 Subject: [PATCH 1/4] Add people (Unit API) --- src/services/people.service.js | 7 ++- src/services/unit.service.js | 6 ++- src/utils/ldap.util.js | 50 ++++++++++++++++++++- tests/resources/unit/unit-mandalore-en.json | 3 +- tests/resources/unit/unit-mandalore-fr.json | 3 +- 5 files changed, 63 insertions(+), 6 deletions(-) diff --git a/src/services/people.service.js b/src/services/people.service.js index ecbe8d8..5b74598 100644 --- a/src/services/people.service.js +++ b/src/services/people.service.js @@ -33,9 +33,14 @@ function getPersonByName (name) { return getPerson(ldapQuery); } +function getPersonByUnit (unit) { + return getPerson(`(ou=${unit})`); +} + module.exports = { getPersonByEmail, getPersonByName, getPersonByPhone, - getPersonBySciper + getPersonBySciper, + getPersonByUnit }; diff --git a/src/services/unit.service.js b/src/services/unit.service.js index e0259fe..16cbf76 100644 --- a/src/services/unit.service.js +++ b/src/services/unit.service.js @@ -1,4 +1,6 @@ +const ldapUtil = require('../utils/ldap.util'); const cadidbService = require('./cadidb.service'); +const peopleService = require('./people.service'); async function get (params) { const lang = params.hl || 'fr'; @@ -104,8 +106,8 @@ async function getUnit (acro, lang) { unitFullDetails.url = dict.url; } if (dict.has_accreds) { - // TODO: Get people from ldap - + const ldapUnitPersons = await peopleService.getPersonByUnit(dict.sigle); + unitFullDetails.people = ldapUtil.ldap2unit(ldapUnitPersons, lang); } else { unitFullDetails.subunits = await getSubunits(dict.id_unite, lang); } diff --git a/src/utils/ldap.util.js b/src/utils/ldap.util.js index 8e3b653..91d5758 100644 --- a/src/utils/ldap.util.js +++ b/src/utils/ldap.util.js @@ -37,6 +37,23 @@ function newLdapAddressMapper () { return ldapAddressMapper; } +function newLdapUnitMapper (lang) { + const ldapUnitMapper = { + mail: ['email', (val) => val[0]], + sn: ['name', (val) => val], + givenName: ['firstname', (val) => val], + displayName: ['displayName', (val) => val[0]], + roomNumber: ['officeList', (val) => val], + telephoneNumber: ['phoneList', (val) => val] + }; + if (lang === 'fr') { + ldapUnitMapper.description = ['position', (val) => val[0]]; + } else { + ldapUnitMapper['description;lang-en'] = ['position', (val) => val[0]]; + } + return ldapUnitMapper; +} + function sortAccreds (obj) { return obj.sort((a, b) => a.rank - b.rank); } @@ -281,6 +298,36 @@ function ldapAddress2api (ldapResults) { return person; } +function ldap2unit (ldapResults, hl) { + const list = []; + const ldapUnitMapper = newLdapUnitMapper(hl); + + for (const [sciper, entry] of Object.entries(ldapResults)) { + const person = { sciper, rank: 0 }; + for (let acc = 0; acc < entry.length; acc++) { + for (let att = 0; att < entry[acc].attributes.length; att++) { + if (entry[acc].attributes[att].type in ldapUnitMapper) { + person[ldapUnitMapper[entry[acc].attributes[att].type][0]] = + ldapUnitMapper[ + entry[acc].attributes[att].type + ][1](entry[acc].attributes[att].values); + } + } + } + const correctName = getCorrectName( + person.firstname, + person.name, + person.displayName + ); + person.firstname = correctName[0]; + person.name = correctName[1]; + delete person.displayName; + person.profile = getProfile(person.email, sciper); + list.push(person); + } + return sortPersons(list, ''); +} + module.exports = { buildLdapQueryForPerson, dn2acronym, @@ -288,5 +335,6 @@ module.exports = { getCorrectName, getProfile, ldap2api, - ldapAddress2api + ldapAddress2api, + ldap2unit }; diff --git a/tests/resources/unit/unit-mandalore-en.json b/tests/resources/unit/unit-mandalore-en.json index 0b93cf9..66badd1 100644 --- a/tests/resources/unit/unit-mandalore-en.json +++ b/tests/resources/unit/unit-mandalore-en.json @@ -35,5 +35,6 @@ "firstname": "Din", "email": "", "profile": "" - } + }, + "people": [] } diff --git a/tests/resources/unit/unit-mandalore-fr.json b/tests/resources/unit/unit-mandalore-fr.json index ac0ae90..940d407 100644 --- a/tests/resources/unit/unit-mandalore-fr.json +++ b/tests/resources/unit/unit-mandalore-fr.json @@ -35,5 +35,6 @@ "firstname": "Din", "email": "", "profile": "" - } + }, + "people": [] } From beee598becba50dec87ccaa311425052332cdb62 Mon Sep 17 00:00:00 2001 From: William Belle Date: Mon, 30 Oct 2023 13:47:29 +0100 Subject: [PATCH 2/4] Tests with correct ldap --- src/services/unit.service.js | 5 ++- tests/resources/cadidb/getUnit-mandalore.json | 4 +-- tests/resources/unit/unit-mandalore-en.json | 33 ++++++++++++++++--- tests/resources/unit/unit-mandalore-fr.json | 33 ++++++++++++++++--- 4 files changed, 62 insertions(+), 13 deletions(-) diff --git a/src/services/unit.service.js b/src/services/unit.service.js index 05f370e..f081ff5 100644 --- a/src/services/unit.service.js +++ b/src/services/unit.service.js @@ -111,7 +111,10 @@ async function getUnit (acro, lang) { } if (dict.has_accreds) { const ldapUnitPersons = await peopleService.getPersonByUnit(dict.sigle); - unitFullDetails.people = ldapUtil.ldap2unit(ldapUnitPersons, lang); + const UnitPersons = ldapUtil.ldap2unit(ldapUnitPersons, lang); + if (UnitPersons.length > 0) { + unitFullDetails.people = UnitPersons; + } } else { unitFullDetails.subunits = await getSubunits(dict.id_unite, lang); } diff --git a/tests/resources/cadidb/getUnit-mandalore.json b/tests/resources/cadidb/getUnit-mandalore.json index 89d5fb0..1991f99 100644 --- a/tests/resources/cadidb/getUnit-mandalore.json +++ b/tests/resources/cadidb/getUnit-mandalore.json @@ -5,8 +5,8 @@ "libelle": "Mandalore est une planète située dans les territoires de la bordure extérieure de la galaxie.", "libelle_en": "", "hierarchie": "EPFL SO TV-3 MANDALORE", - "resp_sciper": "670005", - "resp_nom": "Grogu", + "resp_sciper": "670003", + "resp_nom": "Djarin", "resp_nom_usuel": null, "resp_prenom": "Din", "resp_prenom_usuel": null, diff --git a/tests/resources/unit/unit-mandalore-en.json b/tests/resources/unit/unit-mandalore-en.json index a34015a..ae918c4 100644 --- a/tests/resources/unit/unit-mandalore-en.json +++ b/tests/resources/unit/unit-mandalore-en.json @@ -30,11 +30,34 @@ "CH-1015 Lausanne" ], "head": { - "sciper": "670005", - "name": "Grogu", + "sciper": "670003", + "name": "Djarin", "firstname": "Din", - "email": "din.grogu@epfl.ch", - "profile": "din.grogu" + "email": "din.djarin@epfl.ch", + "profile": "din.djarin" }, - "people": [] + "people": [ + { + "email": "din.djarin@epfl.ch", + "firstname": "Din", + "name": "Djarin", + "officeList": ["Sundari 231"], + "phoneList": ["+41 21 0054321"], + "position": "Bounty hunter", + "profile": "din.djarin", + "rank": 0, + "sciper": "670003" + }, + { + "email": "paz.vizsla@epfl.ch", + "firstname": "Paz", + "name": "Vizsla", + "officeList": ["Ronion 001"], + "phoneList": ["+41 21 0654321"], + "position": "Heavy infantry", + "profile": "paz.vizsla", + "rank": 0, + "sciper": "670004" + } + ] } diff --git a/tests/resources/unit/unit-mandalore-fr.json b/tests/resources/unit/unit-mandalore-fr.json index f4e535b..1077256 100644 --- a/tests/resources/unit/unit-mandalore-fr.json +++ b/tests/resources/unit/unit-mandalore-fr.json @@ -30,11 +30,34 @@ "CH-1015 Lausanne" ], "head": { - "sciper": "670005", - "name": "Grogu", + "sciper": "670003", + "name": "Djarin", "firstname": "Din", - "email": "din.grogu@epfl.ch", - "profile": "din.grogu" + "email": "din.djarin@epfl.ch", + "profile": "din.djarin" }, - "people": [] + "people": [ + { + "email": "din.djarin@epfl.ch", + "firstname": "Din", + "name": "Djarin", + "officeList": ["Sundari 231"], + "phoneList": ["+41 21 0054321"], + "position": "Chasseur de prime", + "profile": "din.djarin", + "rank": 0, + "sciper": "670003" + }, + { + "email": "paz.vizsla@epfl.ch", + "firstname": "Paz", + "name": "Vizsla", + "officeList": ["Ronion 001"], + "phoneList": ["+41 21 0654321"], + "position": "Infanterie lourde", + "profile": "paz.vizsla", + "rank": 0, + "sciper": "670004" + } + ] } From 011d999f14921373f2502acda469bb52a4f1b474 Mon Sep 17 00:00:00 2001 From: William Belle Date: Mon, 30 Oct 2023 14:06:06 +0100 Subject: [PATCH 3/4] Add unit without accreds --- tests/resources/cadidb/getUnit-nevarro.json | 20 ++++++++++ .../resources/cadidb/getUnitPath-nevarro.json | 22 +++++++++++ .../resources/cadidb/searchUnits-nevarro.json | 8 ++++ tests/resources/unit/unit-nevarro-fr.json | 39 +++++++++++++++++++ tests/unit.test.js | 26 +++++++++++++ 5 files changed, 115 insertions(+) create mode 100644 tests/resources/cadidb/getUnit-nevarro.json create mode 100644 tests/resources/cadidb/getUnitPath-nevarro.json create mode 100644 tests/resources/cadidb/searchUnits-nevarro.json create mode 100644 tests/resources/unit/unit-nevarro-fr.json diff --git a/tests/resources/cadidb/getUnit-nevarro.json b/tests/resources/cadidb/getUnit-nevarro.json new file mode 100644 index 0000000..6b25a99 --- /dev/null +++ b/tests/resources/cadidb/getUnit-nevarro.json @@ -0,0 +1,20 @@ +[ + { + "sigle": "NEVARRO", + "id_unite": 10111, + "libelle": "Nevarro est une planète volcanique située dans les territoires de la bordure extérieure de la galaxie.", + "libelle_en": "", + "hierarchie": "EPFL SO TV-3 NEVARRO", + "resp_sciper": "670003", + "resp_nom": "Djarin", + "resp_nom_usuel": null, + "resp_prenom": "Din", + "resp_prenom_usuel": null, + "url": "", + "faxes": "", + "adresse": "EPFL SO TV-3 NEVARRO $ Outer Rim $ Station 12 $ CH-1015 Lausanne $ $ ", + "cmpl_type": "F", + "ghost": null, + "has_accreds": "1" + } +] diff --git a/tests/resources/cadidb/getUnitPath-nevarro.json b/tests/resources/cadidb/getUnitPath-nevarro.json new file mode 100644 index 0000000..8a7338c --- /dev/null +++ b/tests/resources/cadidb/getUnitPath-nevarro.json @@ -0,0 +1,22 @@ +[ + { + "sigle": "SO", + "libelle": "", + "libelle_en": "Spin-off" + }, + { + "sigle": "EPFL", + "libelle": "Ecole polytechnique fédérale de Lausanne", + "libelle_en": "Ecole polytechnique fédérale de Lausanne" + }, + { + "sigle": "TV-3", + "libelle": "Série TV 3", + "libelle_en": "TV Series 3" + }, + { + "sigle": "NEVARRO", + "libelle": "Nevarro est une planète volcanique située dans les territoires de la bordure extérieure de la galaxie.", + "libelle_en": "" + } +] diff --git a/tests/resources/cadidb/searchUnits-nevarro.json b/tests/resources/cadidb/searchUnits-nevarro.json new file mode 100644 index 0000000..8868d34 --- /dev/null +++ b/tests/resources/cadidb/searchUnits-nevarro.json @@ -0,0 +1,8 @@ +[ + { + "sigle": "NEVARRO", + "libelle": "Nevarro est une planète volcanique située dans les territoires de la bordure extérieure de la galaxie.", + "libelle_en": "Nevarro is a volcanic planet located in the Outer Rim territories of the galaxy.", + "hierarchie": "EPFL SO TV-3 NEVARRO" + } +] diff --git a/tests/resources/unit/unit-nevarro-fr.json b/tests/resources/unit/unit-nevarro-fr.json new file mode 100644 index 0000000..3e76b58 --- /dev/null +++ b/tests/resources/unit/unit-nevarro-fr.json @@ -0,0 +1,39 @@ +{ + "code": 10111, + "acronym": "NEVARRO", + "name": "Nevarro est une planète volcanique située dans les territoires de la bordure extérieure de la galaxie.", + "unitPath": "EPFL SO TV-3 NEVARRO", + "path": [ + { + "acronym": "EPFL", + "name": "Ecole polytechnique fédérale de Lausanne" + }, + { + "acronym": "SO", + "name": "Spin-off" + }, + { + "acronym": "TV-3", + "name": "Série TV 3" + }, + { + "acronym": "NEVARRO", + "name": "Nevarro est une planète volcanique située dans les territoires de la bordure extérieure de la galaxie." + } + ], + "terminal": "1", + "ghost": null, + "address": [ + "EPFL SO TV-3 NEVARRO", + "Outer Rim", + "Station 12", + "CH-1015 Lausanne" + ], + "head": { + "sciper": "670003", + "name": "Djarin", + "firstname": "Din", + "email": "din.djarin@epfl.ch", + "profile": "din.djarin" + } +} diff --git a/tests/unit.test.js b/tests/unit.test.js index a89345e..5ba6e7c 100644 --- a/tests/unit.test.js +++ b/tests/unit.test.js @@ -133,6 +133,32 @@ describe('Test API Unit ("/api/unit")', () => { expect(JSON.parse(response.text)).toStrictEqual(jsonResult); }); + test('It should return a unit without people', async () => { + const mockConnection = { + query: jest.fn().mockImplementation((query, values, referrer) => { + let jsonData; + switch (referrer) { + case 'searchUnits': + jsonData = require('./resources/cadidb/searchUnits-nevarro.json'); + break; + case 'getUnit': + jsonData = require('./resources/cadidb/getUnit-nevarro.json'); + break; + case 'getUnitPath': + jsonData = require('./resources/cadidb/getUnitPath-nevarro.json'); + } + return Promise.resolve([jsonData]); + }), + release: jest.fn() + }; + mysql.createPool().getConnection.mockResolvedValue(mockConnection); + + const jsonResult = require('./resources/unit/unit-nevarro-fr.json'); + const response = await request(app).get('/api/unit?q=nevarro&hl=fr'); + expect(response.statusCode).toBe(200); + expect(JSON.parse(response.text)).toStrictEqual(jsonResult); + }); + test('It should return a unit with subunits', async () => { const mockConnection = { query: jest.fn().mockImplementation((query, values, referrer) => { From 5cf37484cd6aaaac58b5fbc278c2b1c40766d51f Mon Sep 17 00:00:00 2001 From: William Belle Date: Mon, 30 Oct 2023 14:13:10 +0100 Subject: [PATCH 4/4] Docs --- src/services/unit.service.js | 2 +- src/utils/ldap.util.js | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/services/unit.service.js b/src/services/unit.service.js index f081ff5..e728475 100644 --- a/src/services/unit.service.js +++ b/src/services/unit.service.js @@ -111,7 +111,7 @@ async function getUnit (acro, lang) { } if (dict.has_accreds) { const ldapUnitPersons = await peopleService.getPersonByUnit(dict.sigle); - const UnitPersons = ldapUtil.ldap2unit(ldapUnitPersons, lang); + const UnitPersons = ldapUtil.ldapUnit2api(ldapUnitPersons, lang); if (UnitPersons.length > 0) { unitFullDetails.people = UnitPersons; } diff --git a/src/utils/ldap.util.js b/src/utils/ldap.util.js index 91d5758..fdb80df 100644 --- a/src/utils/ldap.util.js +++ b/src/utils/ldap.util.js @@ -298,7 +298,18 @@ function ldapAddress2api (ldapResults) { return person; } -function ldap2unit (ldapResults, hl) { +/** + * Convert LDAP Unit result into API result. + * + * @example + * const ldapUtil = require('../utils/ldap.util'); + * const persons = ldapUtil.ldapUnit2api(ldapResults, 'en'); + * + * @param {object} ldapResults The result from the LDAP Unit search. + * @param {string} hl The user interface language. + * @returns {object} Return the result for the API. + */ +function ldapUnit2api (ldapResults, hl) { const list = []; const ldapUnitMapper = newLdapUnitMapper(hl); @@ -336,5 +347,5 @@ module.exports = { getProfile, ldap2api, ldapAddress2api, - ldap2unit + ldapUnit2api };