5ddc5ddf02
chore(udt-008): bootstrap rama feature/UDT-008 [UDT-008]
2026-04-15 17:34:12 -03:00
c0d1ea4ac2
Merge pull request 'UDT-006: Middleware de Autorización (RBAC enforcement)' ( #10 ) from feature/UDT-006 into main
2026-04-15 20:15:18 +00:00
8513e99554
test(api): assert count 21 permisos admin post-V007 [UDT-006]
2026-04-15 16:49:54 -03:00
96e7290fb7
refactor(web): eliminar guards inline rol admin en páginas de roles/permisos [UDT-006]
2026-04-15 16:49:21 -03:00
f6cdd7650b
feat(web): ProtectedRoute extraído + router migrado + CreateUserPage cleanup [UDT-006]
2026-04-15 16:41:39 -03:00
8935115da9
feat(web): usePermission + CanPerform [UDT-006]
2026-04-15 16:40:23 -03:00
2efd5e2fdb
feat(web): authStore + useLogin persisten permisos [UDT-006]
2026-04-15 16:39:18 -03:00
0218d8d371
feat(api): migrar controllers admin a RequirePermission [UDT-006]
2026-04-15 16:34:32 -03:00
4866c4f21f
feat(api): ForbiddenProblemDetailsHandler 403 shape [UDT-006]
2026-04-15 16:27:36 -03:00
58d0df601f
feat(api): RequirePermissionAttribute + PermissionAuthorizationHandler [UDT-006]
2026-04-15 16:26:30 -03:00
cdb8dcd03c
feat(api): login response permisos desde RolPermiso [UDT-006]
2026-04-15 16:24:21 -03:00
2afac53fca
Merge pull request 'UDT-005: Gestión de Permisos (RBAC) — catálogo + asignación rol↔permisos' ( #9 ) from feature/UDT-005 into main
2026-04-15 19:02:02 +00:00
1a864e9f8b
fix(app): validar formato codigo rol en GetRolPermisos [UDT-005]
...
Agrega GetRolPermisosQueryValidator con regex ^[a-z][a-z0-9_]*$ para
rechazar codigos invalidos con 400 en GET /api/v1/roles/{codigo}/permisos.
2026-04-15 15:56:49 -03:00
885a8cef17
feat(web): BATCH 6 - feature permisos con grid por modulo [UDT-005]
...
- api/types.ts: PermisoDto, AssignPermisosRequest
- api/listPermisos, getRolPermisos, assignPermisos
- hooks: usePermisos, useRolPermisos, useAssignPermisos (TanStack Query)
- components/RolPermisosEditor: checkbox-grid agrupado por modulo (codigo.split(':')[0])
- pages/RolPermisosPage: selector rol activo + guard admin + RolPermisosEditor
- router.tsx: ruta /admin/permisos
- AppSidebar.tsx: link Permisos (KeyRound icon) en seccion admin
- tests: 5 smoke tests RolPermisosEditor (render, prefill, toggle, save, 400)
2026-04-15 15:46:49 -03:00
4913a35d06
feat(api): BATCH 5 - PermisosController + tests HTTP [UDT-005]
2026-04-15 15:42:03 -03:00
be2257a9bf
feat(infra): BATCH 4 - Permiso/RolPermiso repos Dapper + tests integracion [UDT-005]
2026-04-15 15:39:25 -03:00
704794a2e2
feat(app): BATCH 3 - handlers permisos con TDD [UDT-005]
2026-04-15 15:31:26 -03:00
7ddb71c24c
feat(domain): BATCH 2 - Permiso entity + catalogo const [UDT-005]
2026-04-15 15:31:20 -03:00
7d2190c37e
feat(db): BATCH 1 - V005/V006 Permiso y RolPermiso + seed [UDT-005]
2026-04-15 15:26:22 -03:00
f6ad371de4
chore(tests): BATCH 0 - agregar Permiso y RolPermiso a TablesToIgnore [UDT-005]
2026-04-15 15:26:19 -03:00
4d3e55c422
Actualizar README.md
2026-04-15 17:36:36 +00:00
e5ee8e673b
Merge pull request 'UDT-004: Gestión de Roles (tabla maestra + CRUD admin + validator dinámico + UI)' ( #8 ) from feature/UDT-004 into main
2026-04-15 16:19:58 +00:00
57e4cdac01
chore(tests): limpia warning xUnit2012 en CreateUsuario_WithInactiveRol_Returns400
...
Reemplaza Assert.True(enumerable.Any(...)) por Assert.Contains idiomatico.
2026-04-15 13:03:18 -03:00
fae06fb8b8
feat(web): UDT-004 gestion de roles + UserForm dinamico
...
- features/roles: API clients (list/get/create/update/deactivate), TanStack Query hooks, RolForm (create + edit variants), RolesList con acciones y guard 409, paginas RolesPage/NewRolPage/EditRolPage
- router.tsx: rutas /admin/roles, /admin/roles/nuevo, /admin/roles/:codigo/editar
- AppSidebar: nav Roles (admin-only)
- features/users: useRolesForSelect wrapper (filtra activo=true), UserForm fetchea roles async con loading/error states; elimina ROL_OPTIONS hardcoded
- tests: 47 vitest verdes (10 authStore + 5 auth api + 7 axios + 3 useCreateUser + 3 RolesList + 5 LoginPage + 7 UserForm + 7 RolForm). Typecheck limpio
2026-04-15 12:58:08 -03:00
6f999b8fcd
feat(api): UDT-004 controller de roles + refactor validator UDT-003 a lookup dinamico
...
- RolesController /api/v1/roles CRUD admin-only: GET list, GET {codigo}, POST, PUT, DELETE (soft-delete con guard 409)
- ExceptionFilter: mapea RolNotFound (404), RolAlreadyExists (409), RolInUse (409)
- DI: registra 5 handlers de Roles (Application) y IRolRepository/RolRepository (Infrastructure)
- CreateUsuarioCommandValidator: reemplaza whitelist hardcoded por IRolRepository.ExistsActiveByCodigoAsync via MustAsync; constructor recibe (AuthOptions, IRolRepository)
- Tests: 202 verdes (173 application + 29 api). Nuevas: RolesEndpointTests (13 integration), CreateUsuarioCommandValidatorTests reescrito con NSubstitute mock, CreateUsuario_WithInactiveRol_Returns400 en Api.Tests
- Fix: ApiIntegration pasa de IClassFixture (N factories) a ICollectionFixture (1 factory shared) — evitaba ObjectDisposedException sobre RSABCrypt al compartir coleccion con multiples test classes
- tests/tests.runsettings: MaxCpuCount=1 para evitar race entre assemblies sobre SIGCM2_Test
2026-04-15 12:50:24 -03:00
34b714750a
feat(api): UDT-004 dominio + repositorio + application roles (tdd)
...
- Migraciones V003 (tabla Rol + 8 seeds canonicos) y V004 (drop CK + FK Usuario.Rol)
- Dominio: Rol entity + 3 excepciones (RolNotFound/AlreadyExists/InUse)
- Infraestructura: RolRepository (Dapper) con List/Get/ExistsActive/Add/Update/HasActiveUsuarios
- Application: CRUD queries y commands (List, Get, Create, Update, Deactivate) + validators (codigo regex ^[a-z][a-z0-9_]*$)
- Validator UDT-003: whitelist alineada a codigos canonicos (full IRolRepository lookup diferido a Phase 5.1)
- Tests: 169 application + 15 api (todos verdes). Respawn configurado para re-seedear Rol canonical post-reset.
- Estricto TDD: RED/GREEN/TRIANGULATE en todos los handlers nuevos.
2026-04-15 12:31:29 -03:00
e0e9ec3b88
Actualizar README.md
2026-04-15 14:28:52 +00:00
c6352e1e39
Merge pull request 'docs: add minimal README' ( #7 ) from chore/readme into main
2026-04-15 14:27:49 +00:00
ddc7c8d53d
docs: add minimal README with stack, structure, run instructions
2026-04-15 11:27:20 -03:00
890da06f71
Merge pull request 'UDT-003: Registro de Usuarios (admin-only) + fix JWT claim mapping' ( #4 ) from feature/UDT-003 into main
2026-04-15 14:23:53 +00:00
bce591e63c
fix(auth): preserve JWT claim names in bearer middleware
...
JwtBearerOptions.MapInboundClaims defaulted to true, which mapped the
'sub' claim to ClaimTypes.NameIdentifier in HttpContext.User. Logout
endpoint read User.FindFirst("sub") and got null, returning 401 for
any authenticated caller.
Fix: set MapInboundClaims=false and pin NameClaimType="name" so the
JWT claims land in the principal with their original names, aligning
with how JwtService.GetPrincipalFromExpiredToken (used by refresh)
already consumes them.
Unblocks Login_Refresh_Logout_FullFlow integration test (15/15 green).
2026-04-15 11:03:15 -03:00
dd99e5cc69
feat(web): UDT-003 formulario de alta de usuarios (admin)
...
Agrega CreateUserPage con UserForm (react-hook-form + Zod), hook useCreateUser
(TanStack Query mutation), ruta /users/new protegida y entrada en AppSidebar.
Incluye tests Vitest: UserForm (9 casos) y useCreateUser (3 casos).
2026-04-15 10:57:11 -03:00
3d598faffc
feat(api): UDT-003 registro de usuarios — backend completo (Phases 1-6)
...
- Domain: Usuario.ForCreation factory, UsernameAlreadyExistsException, IUsuarioRepository extendido
- Application: CreateUsuarioCommand/Validator/Handler, UsuarioCreatedDto, AuthOptions password policy
- Infrastructure: UsuarioRepository.ExistsByUsernameAsync + AddAsync (INSERT OUTPUT INSERTED.Id), RoleClaimType="rol" en TokenValidationParameters
- Api: UsuariosController POST api/v1/users [Authorize(Roles="admin")], ExceptionFilter mapea UsernameAlreadyExistsException + SqlException 2627 → 409
- Tests (unit): 43 tests — 33 validator + 10 handler (107 total, green)
- Tests (integration): 7 tests CreateUsuarioEndpoint — 401/403/400/201/409/race/e2e (green)
- Fix: TestWebAppFactory.ConfigureTestServices reemplaza SqlConnectionFactory singleton con CS de test correcto
2026-04-15 10:47:48 -03:00
023d30fce4
chore(repo): gitignore .claude/ local state and autogen src/src.sln
2026-04-14 14:39:38 -03:00
5b3797a81c
Merge pull request 'UDT-002: Logout + Refresh Token con rotación y chain revocation' ( #3 ) from feature/UDT-002 into main
2026-04-14 17:37:47 +00:00
96dbeecc0f
fix(web): use endsWith for /auth path exclusion in refresh interceptor
...
Avoids substring-match false positives on future endpoints whose URL could
contain /auth/refresh or /auth/login as infix (W-01 from verify report).
2026-04-14 13:59:37 -03:00
7fadb88da0
docs(web): smoke test checklist UDT-002 — login, refresh, logout, reuse detection
2026-04-14 13:52:59 -03:00
dd4f4dbd5e
test(web): LoginPage — verify setAuth receives expiresIn and calculates expiresAt
2026-04-14 13:51:41 -03:00
bdaaaffaf6
feat(web): axiosClient — request/response interceptors with singleton refresh queue
2026-04-14 13:50:49 -03:00
d40b7247fc
feat(web): authApi — add refresh() and logout() with types and tests
2026-04-14 13:49:39 -03:00
f806e0a483
test(web): authStore TDD — refreshToken, expiresAt, clearAuth, updateAccess, logout async
2026-04-14 13:48:50 -03:00
f1d4ea0047
fix(test): RefreshTokenRepository tests use Respawn pattern instead of transaction isolation
...
Transaction-scoped tests conflicted with the repository opening its own connection,
blocking on FK locks for the uncommitted seeded user and causing timeouts.
Switched to the Respawn pattern used by UsuarioRepositoryTests ([Collection("Database")])
which commits seed data and resets between test classes.
2026-04-14 13:45:53 -03:00
fd2ff8a802
feat(api): map InvalidRefreshTokenException and TokenReuseDetectedException to generic 401
2026-04-14 13:28:45 -03:00
8768067fdd
feat(api): add /refresh [AllowAnonymous] and /logout [Authorize] endpoints to AuthController
2026-04-14 13:28:45 -03:00
4e7b2690bd
test(api): add Refresh and Logout endpoint integration tests RED
2026-04-14 13:28:44 -03:00
aed26e3de9
feat(infra): register RefreshTokenRepository, RefreshTokenGenerator, ClientContext and handlers in DI
2026-04-14 13:28:36 -03:00
cb4250f7b3
feat(infra): implement ClientContext for IP and UserAgent from IHttpContextAccessor
2026-04-14 13:28:35 -03:00
19ac807500
feat(infra): add RefreshTokenDays to JwtOptions and AuthOptions config
2026-04-14 13:28:35 -03:00
0c809da633
feat(infra): implement RefreshTokenRepository with Dapper and add GetByIdAsync to UsuarioRepository
2026-04-14 13:28:29 -03:00
e405c0453b
test(infra): add RefreshTokenRepository integration tests RED
2026-04-14 13:28:28 -03:00