ci: docker_tag=ext - Fix: use sub instead of profile_idn and correct URL base v1.0.9
All checks were successful
build-and-push-ext / build_push (push) Successful in 23s

This commit is contained in:
dev4 2025-09-19 12:20:52 +00:00
parent 0c74cccc04
commit c4d8676b55
3 changed files with 34 additions and 39 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "lecoffre-back-mini", "name": "lecoffre-back-mini",
"version": "1.0.8", "version": "1.0.9",
"description": "Mini serveur avec une route /api/ping", "description": "Mini serveur avec une route /api/ping",
"main": "dist/server.js", "main": "dist/server.js",
"scripts": { "scripts": {

View File

@ -109,21 +109,16 @@ export class IdNotController {
profile_idn: payload?.profile_idn profile_idn: payload?.profile_idn
}); });
// Try standard flow with profile_idn; otherwise fallback via rattachements using sub // Always use sub for rattachements API as it's more reliable than profile_idn
let userData: any; Logger.info('IdNot using rattachements API with sub', { sub: payload.sub });
if (payload?.profile_idn && typeof payload.profile_idn === 'string') { const rattachementsJson = await IdNotService.getUserRattachements(payload.sub);
userData = await IdNotService.getUserData(payload.profile_idn); const results: any[] = Array.isArray(rattachementsJson?.result) ? rattachementsJson.result : [];
} else { // pick first office rattachement with a defined entite
Logger.info('IdNot fallback via rattachements using sub'); const candidate = results.find((r: any) => r?.entite?.typeEntite?.name === 'office') || results[0];
const rattachementsJson = await IdNotService.getUserRattachements(payload.sub); if (!candidate) {
const results: any[] = Array.isArray(rattachementsJson?.result) ? rattachementsJson.result : []; throw new ForbiddenError('User not attached to an office');
// pick first office rattachement with a defined entite
const candidate = results.find((r: any) => r?.entite?.typeEntite?.name === 'office') || results[0];
if (!candidate) {
throw new ForbiddenError('User not attached to an office');
}
userData = candidate;
} }
const userData = candidate;
// Log d'analyse (non sensible) pour diagnostiquer les cas de rattachement // Log d'analyse (non sensible) pour diagnostiquer les cas de rattachement
Logger.info('IdNot userData summary', { Logger.info('IdNot userData summary', {

View File

@ -79,18 +79,18 @@ export class IdNotService {
const baseUrl = endpoints[i]; const baseUrl = endpoints[i];
const searchParams = searchParamsVariants[i]; const searchParams = searchParamsVariants[i];
const url = `${baseUrl}?${searchParams}`; const url = `${baseUrl}?${searchParams}`;
try { try {
Logger.info(`IdNot getUserRattachements attempt ${i + 1}`, { url, idNot }); Logger.info(`IdNot getUserRattachements attempt ${i + 1}`, { url, idNot });
const response = await fetch(url, { method: 'GET' }); const response = await fetch(url, { method: 'GET' });
if (response.ok) { if (response.ok) {
const data = await response.json(); const data = await response.json();
Logger.info(`IdNot getUserRattachements success`, { url, idNot }); Logger.info(`IdNot getUserRattachements success`, { url, idNot });
return data; return data;
} }
// Log détaillé pour les erreurs // Log détaillé pour les erreurs
const text = await response.text().catch(() => ''); const text = await response.text().catch(() => '');
Logger.error(`IdNot getUserRattachements attempt ${i + 1} failed`, { Logger.error(`IdNot getUserRattachements attempt ${i + 1} failed`, {
@ -100,31 +100,31 @@ export class IdNotService {
statusText: response.statusText, statusText: response.statusText,
bodySnippet: text?.substring(0, 500) bodySnippet: text?.substring(0, 500)
}); });
// Si c'est une erreur 4xx (sauf 404), ne pas réessayer // Si c'est une erreur 4xx (sauf 404), ne pas réessayer
if (response.status >= 400 && response.status < 500 && response.status !== 404) { if (response.status >= 400 && response.status < 500 && response.status !== 404) {
throw new ExternalServiceError('IdNot', `Failed to fetch rattachements: ${response.status} ${response.statusText}`); throw new ExternalServiceError('IdNot', `Failed to fetch rattachements: ${response.status} ${response.statusText}`);
} }
} catch (error) { } catch (error) {
Logger.error(`IdNot getUserRattachements attempt ${i + 1} error`, { Logger.error(`IdNot getUserRattachements attempt ${i + 1} error`, {
url, url,
idNot, idNot,
error: error instanceof Error ? error.message : String(error) error: error instanceof Error ? error.message : String(error)
}); });
// Si c'est la dernière tentative, relancer l'erreur // Si c'est la dernière tentative, relancer l'erreur
if (i === endpoints.length - 1) { if (i === endpoints.length - 1) {
throw error; throw error;
} }
} }
// Attendre un peu avant la prochaine tentative // Attendre un peu avant la prochaine tentative
if (i < endpoints.length - 1) { if (i < endpoints.length - 1) {
await new Promise(resolve => setTimeout(resolve, 300 * (i + 1))); await new Promise(resolve => setTimeout(resolve, 300 * (i + 1)));
} }
} }
throw new ExternalServiceError('IdNot', 'Failed to fetch rattachements after all attempts'); throw new ExternalServiceError('IdNot', 'Failed to fetch rattachements after all attempts');
} }
@ -159,20 +159,20 @@ export class IdNotService {
} }
static async getUserData(profileIdn: string) { static async getUserData(profileIdn: string) {
const { IDNOT_API_KEY, IDNOT_API_BASE_URL } = process.env; const { IDNOT_API_KEY, IDNOT_ANNUARY_BASE_URL } = process.env;
if (!IDNOT_API_KEY || !IDNOT_API_BASE_URL) { if (!IDNOT_API_KEY || !IDNOT_ANNUARY_BASE_URL) {
throw new Error('Missing IDnot API key or base URL'); throw new Error('Missing IDnot API key or annuary base URL');
} }
// Essayer plusieurs variantes d'endpoints selon la documentation API Annuaire V2 // Essayer plusieurs variantes d'endpoints selon la documentation API Annuaire V2
const endpoints = [ const endpoints = [
// Format correct selon doc: /api/pp/v2/personnes/{id}/rattachements // Format correct selon doc: /api/pp/v2/personnes/{id}/rattachements
`${IDNOT_API_BASE_URL}/api/pp/v2/personnes/${profileIdn}/rattachements`, `${IDNOT_ANNUARY_BASE_URL}/api/pp/v2/personnes/${profileIdn}/rattachements`,
// Variante sans /annuaire dans l'URL de base // Variante sans /annuaire dans l'URL de base
`${IDNOT_API_BASE_URL.replace('/annuaire', '')}/api/pp/v2/personnes/${profileIdn}/rattachements`, `${IDNOT_ANNUARY_BASE_URL.replace('/annuaire', '')}/api/pp/v2/personnes/${profileIdn}/rattachements`,
// Ancien format (fallback) // Ancien format (fallback)
`${IDNOT_API_BASE_URL}/api/pp/v2/rattachements/${profileIdn}` `${IDNOT_ANNUARY_BASE_URL}/api/pp/v2/rattachements/${profileIdn}`
]; ];
const searchParams = new URLSearchParams({ const searchParams = new URLSearchParams({
@ -182,18 +182,18 @@ export class IdNotService {
for (let i = 0; i < endpoints.length; i++) { for (let i = 0; i < endpoints.length; i++) {
const baseUrl = endpoints[i]; const baseUrl = endpoints[i];
const userUrl = `${baseUrl}?${searchParams}`; const userUrl = `${baseUrl}?${searchParams}`;
try { try {
Logger.info(`IdNot getUserData attempt ${i + 1}`, { url: userUrl, profileIdn }); Logger.info(`IdNot getUserData attempt ${i + 1}`, { url: userUrl, profileIdn });
const userResp = await fetch(userUrl, { method: 'GET' }); const userResp = await fetch(userUrl, { method: 'GET' });
if (userResp.ok) { if (userResp.ok) {
const userData = await userResp.json(); const userData = await userResp.json();
Logger.info(`IdNot getUserData success`, { url: userUrl, profileIdn }); Logger.info(`IdNot getUserData success`, { url: userUrl, profileIdn });
return userData; return userData;
} }
// Log détaillé pour les erreurs // Log détaillé pour les erreurs
const text = await userResp.text().catch(() => ''); const text = await userResp.text().catch(() => '');
Logger.error(`IdNot getUserData attempt ${i + 1} failed`, { Logger.error(`IdNot getUserData attempt ${i + 1} failed`, {
@ -203,31 +203,31 @@ export class IdNotService {
statusText: userResp.statusText, statusText: userResp.statusText,
bodySnippet: text?.substring(0, 500) bodySnippet: text?.substring(0, 500)
}); });
// Si c'est une erreur 4xx (sauf 404), ne pas réessayer // Si c'est une erreur 4xx (sauf 404), ne pas réessayer
if (userResp.status >= 400 && userResp.status < 500 && userResp.status !== 404) { if (userResp.status >= 400 && userResp.status < 500 && userResp.status !== 404) {
throw new ExternalServiceError('IdNot', `Failed to fetch user data: ${userResp.status} ${userResp.statusText}`); throw new ExternalServiceError('IdNot', `Failed to fetch user data: ${userResp.status} ${userResp.statusText}`);
} }
} catch (error) { } catch (error) {
Logger.error(`IdNot getUserData attempt ${i + 1} error`, { Logger.error(`IdNot getUserData attempt ${i + 1} error`, {
url: userUrl, url: userUrl,
profileIdn, profileIdn,
error: error instanceof Error ? error.message : String(error) error: error instanceof Error ? error.message : String(error)
}); });
// Si c'est la dernière tentative, relancer l'erreur // Si c'est la dernière tentative, relancer l'erreur
if (i === endpoints.length - 1) { if (i === endpoints.length - 1) {
throw error; throw error;
} }
} }
// Attendre un peu avant la prochaine tentative // Attendre un peu avant la prochaine tentative
if (i < endpoints.length - 1) { if (i < endpoints.length - 1) {
await new Promise(resolve => setTimeout(resolve, 200 * (i + 1))); await new Promise(resolve => setTimeout(resolve, 200 * (i + 1)));
} }
} }
throw new ExternalServiceError('IdNot', 'Failed to fetch user data after all attempts'); throw new ExternalServiceError('IdNot', 'Failed to fetch user data after all attempts');
} }