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.
This commit is contained in:
@@ -63,7 +63,7 @@ public sealed class CreateUsuarioEndpointTests : IClassFixture<TestWebAppFactory
|
||||
nombre = "Test",
|
||||
apellido = "Usuario",
|
||||
email = (string?)null,
|
||||
rol = "vendedor"
|
||||
rol = "cajero"
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -76,7 +76,7 @@ public sealed class CreateUsuarioEndpointTests : IClassFixture<TestWebAppFactory
|
||||
await conn.ExecuteAsync("""
|
||||
IF NOT EXISTS (SELECT 1 FROM dbo.Usuario WHERE Username = @Username)
|
||||
INSERT INTO dbo.Usuario (Username, PasswordHash, Nombre, Apellido, Rol, PermisosJson, Activo)
|
||||
VALUES (@Username, @Hash, 'Vendedor', 'Test', 'vendedor', '[]', 1)
|
||||
VALUES (@Username, @Hash, 'Vendedor', 'Test', 'cajero', '[]', 1)
|
||||
""",
|
||||
new { Username = username, Hash = passwordHash });
|
||||
}
|
||||
@@ -126,7 +126,7 @@ public sealed class CreateUsuarioEndpointTests : IClassFixture<TestWebAppFactory
|
||||
nombre = "Vendedor",
|
||||
apellido = "Test",
|
||||
email = (string?)null,
|
||||
rol = "vendedor"
|
||||
rol = "cajero"
|
||||
}, adminToken);
|
||||
|
||||
var createResp = await _client.SendAsync(createRequest);
|
||||
@@ -190,7 +190,7 @@ public sealed class CreateUsuarioEndpointTests : IClassFixture<TestWebAppFactory
|
||||
nombre = "Integration",
|
||||
apellido = "Test",
|
||||
email = "integration@test.com",
|
||||
rol = "vendedor"
|
||||
rol = "cajero"
|
||||
}, adminToken);
|
||||
|
||||
try
|
||||
@@ -211,7 +211,7 @@ public sealed class CreateUsuarioEndpointTests : IClassFixture<TestWebAppFactory
|
||||
|
||||
Assert.True(id.GetInt32() > 0, "'id' must be positive");
|
||||
Assert.Equal(newUsername, username.GetString());
|
||||
Assert.Equal("vendedor", rol.GetString());
|
||||
Assert.Equal("cajero", rol.GetString());
|
||||
|
||||
// Must NOT contain passwordHash
|
||||
Assert.False(json.TryGetProperty("passwordHash", out _), "Response must NOT leak 'passwordHash'");
|
||||
@@ -253,7 +253,7 @@ public sealed class CreateUsuarioEndpointTests : IClassFixture<TestWebAppFactory
|
||||
nombre = "First",
|
||||
apellido = "User",
|
||||
email = (string?)null,
|
||||
rol = "vendedor"
|
||||
rol = "cajero"
|
||||
}, adminToken);
|
||||
var firstResp = await _client.SendAsync(first);
|
||||
Assert.Equal(HttpStatusCode.Created, firstResp.StatusCode);
|
||||
@@ -266,7 +266,7 @@ public sealed class CreateUsuarioEndpointTests : IClassFixture<TestWebAppFactory
|
||||
nombre = "Second",
|
||||
apellido = "User",
|
||||
email = (string?)null,
|
||||
rol = "consulta"
|
||||
rol = "reportes"
|
||||
}, adminToken);
|
||||
var secondResp = await _client.SendAsync(second);
|
||||
|
||||
@@ -299,7 +299,7 @@ public sealed class CreateUsuarioEndpointTests : IClassFixture<TestWebAppFactory
|
||||
await conn.ExecuteAsync("""
|
||||
IF NOT EXISTS (SELECT 1 FROM dbo.Usuario WHERE Username = @Username)
|
||||
INSERT INTO dbo.Usuario (Username, PasswordHash, Nombre, Apellido, Rol, PermisosJson, Activo)
|
||||
VALUES (@Username, '$2a$12$placeholder_hash_for_race_test', 'Race', 'User', 'vendedor', '[]', 1)
|
||||
VALUES (@Username, '$2a$12$placeholder_hash_for_race_test', 'Race', 'User', 'cajero', '[]', 1)
|
||||
""", new { Username = username });
|
||||
|
||||
try
|
||||
@@ -314,7 +314,7 @@ public sealed class CreateUsuarioEndpointTests : IClassFixture<TestWebAppFactory
|
||||
nombre = "Race",
|
||||
apellido = "User",
|
||||
email = (string?)null,
|
||||
rol = "vendedor"
|
||||
rol = "cajero"
|
||||
}, adminToken);
|
||||
|
||||
var response = await _client.SendAsync(request);
|
||||
@@ -357,7 +357,7 @@ public sealed class CreateUsuarioEndpointTests : IClassFixture<TestWebAppFactory
|
||||
nombre = "E2E",
|
||||
apellido = "Test",
|
||||
email = (string?)null,
|
||||
rol = "vendedor"
|
||||
rol = "cajero"
|
||||
}, adminToken);
|
||||
|
||||
var createResp = await _client.SendAsync(createReq);
|
||||
@@ -380,7 +380,7 @@ public sealed class CreateUsuarioEndpointTests : IClassFixture<TestWebAppFactory
|
||||
|
||||
// Verify usuario in response
|
||||
Assert.True(loginJson.TryGetProperty("usuario", out var usuario));
|
||||
Assert.Equal("vendedor", usuario.GetProperty("rol").GetString());
|
||||
Assert.Equal("cajero", usuario.GetProperty("rol").GetString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user