From a30b10ebff3503451f98b6836cf0e60b0fcadd55 Mon Sep 17 00:00:00 2001 From: dmolinari Date: Thu, 16 Apr 2026 10:06:43 -0300 Subject: [PATCH] fix(web): UsuarioPermisos shape nested para matchear backend [UDT-009] El backend devuelve { rolPermisos, overrides: {grant, deny}, effective } (nested) segun spec, pero el frontend lo lee como {grant, deny} planos. Causaba TypeError: permisoData.grant is not iterable al abrir tab Permisos. Tests del frontend actualizados con el shape correcto. --- .../features/users/components/PermisosEditor.tsx | 8 ++++---- src/web/src/features/users/types.ts | 8 ++++---- .../tests/features/users/PermisosEditor.test.tsx | 8 ++++---- .../tests/features/users/getUserPermisos.test.ts | 14 ++++++-------- 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/web/src/features/users/components/PermisosEditor.tsx b/src/web/src/features/users/components/PermisosEditor.tsx index db5781b..10c339b 100644 --- a/src/web/src/features/users/components/PermisosEditor.tsx +++ b/src/web/src/features/users/components/PermisosEditor.tsx @@ -55,9 +55,9 @@ export function PermisosEditor({ userId }: PermisosEditorProps) { // Start all known codes as 'heredado' for (const c of permisoData.rolPermisos) map.set(c, 'heredado') // Apply grant overrides - for (const c of permisoData.grant) map.set(c, 'concedido') + for (const c of permisoData.overrides.grant) map.set(c, 'concedido') // Apply deny overrides - for (const c of permisoData.deny) map.set(c, 'denegado') + for (const c of permisoData.overrides.deny) map.set(c, 'denegado') setStates(map) setSaveError(null) }, [permisoData]) @@ -79,8 +79,8 @@ export function PermisosEditor({ userId }: PermisosEditorProps) { // Filter catalog to only show permisos that appear in rolPermisos, grant, deny, or all catalog const allCodes = new Set([ ...permisoData.rolPermisos, - ...permisoData.grant, - ...permisoData.deny, + ...permisoData.overrides.grant, + ...permisoData.overrides.deny, ]) // Use catalog for grouping and names, showing all permisos known plus any from overrides diff --git a/src/web/src/features/users/types.ts b/src/web/src/features/users/types.ts index 62b38e4..80c44b2 100644 --- a/src/web/src/features/users/types.ts +++ b/src/web/src/features/users/types.ts @@ -50,11 +50,11 @@ export interface UpdateUserPayload { // UDT-009 — Permisos overrides per-user types export interface UsuarioPermisos { - usuarioId: number - rol: string rolPermisos: string[] - grant: string[] - deny: string[] + overrides: { + grant: string[] + deny: string[] + } effective: string[] } diff --git a/src/web/src/tests/features/users/PermisosEditor.test.tsx b/src/web/src/tests/features/users/PermisosEditor.test.tsx index 2c77cac..067e4e6 100644 --- a/src/web/src/tests/features/users/PermisosEditor.test.tsx +++ b/src/web/src/tests/features/users/PermisosEditor.test.tsx @@ -18,11 +18,11 @@ const catalogoPermisos = [ // User permisos — from /api/v1/users/42/permisos const mockUsuarioPermisos = { - usuarioId: 42, - rol: 'cajero', rolPermisos: ['ventas:contado:crear', 'ventas:contado:cobrar'], - grant: ['textos:editar'], - deny: ['ventas:contado:cobrar'], + overrides: { + grant: ['textos:editar'], + deny: ['ventas:contado:cobrar'], + }, effective: ['ventas:contado:crear', 'textos:editar'], } diff --git a/src/web/src/tests/features/users/getUserPermisos.test.ts b/src/web/src/tests/features/users/getUserPermisos.test.ts index 4e80a01..2533c6e 100644 --- a/src/web/src/tests/features/users/getUserPermisos.test.ts +++ b/src/web/src/tests/features/users/getUserPermisos.test.ts @@ -6,11 +6,11 @@ import { getUserPermisos } from '../../../features/users/api/getUserPermisos' const API_URL = 'http://localhost:5000' const mockUsuarioPermisos = { - usuarioId: 42, - rol: 'cajero', rolPermisos: ['ventas:contado:crear', 'ventas:contado:cobrar'], - grant: ['textos:editar'], - deny: ['ventas:contado:cobrar'], + overrides: { + grant: ['textos:editar'], + deny: ['ventas:contado:cobrar'], + }, effective: ['ventas:contado:crear', 'textos:editar'], } @@ -30,11 +30,9 @@ describe('getUserPermisos api client', () => { const result = await getUserPermisos(42) - expect(result.usuarioId).toBe(42) - expect(result.rol).toBe('cajero') expect(result.rolPermisos).toEqual(['ventas:contado:crear', 'ventas:contado:cobrar']) - expect(result.grant).toEqual(['textos:editar']) - expect(result.deny).toEqual(['ventas:contado:cobrar']) + expect(result.overrides.grant).toEqual(['textos:editar']) + expect(result.overrides.deny).toEqual(['ventas:contado:cobrar']) expect(result.effective).toEqual(['ventas:contado:crear', 'textos:editar']) })