< Summary

Information
Class: FAU.API.Seeds.SuperAdminSeeder
Assembly: FAU.API
File(s): /home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.API/Seeds/SuperAdminSeeder.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 87
Coverable lines: 87
Total lines: 166
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 46
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
RunAsync()0%420200%
LeerInput(...)0%2040%
LeerPasswordSeguro(...)0%110100%
ValidarPassword(...)0%210140%

File(s)

/home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.API/Seeds/SuperAdminSeeder.cs

#LineLine coverage
 1using FAU.DataAccess;
 2using FAU.Entidades;
 3using Microsoft.EntityFrameworkCore;
 4
 5namespace FAU.API.Seeds;
 6
 7/// <summary>
 8/// Crea o resetea el usuario Administrador del sistema.
 9/// Solo se ejecuta desde la aplicación con el comando --seed-admin.
 10/// El hash de la contraseña se genera con el mismo BCrypt que usa el login.
 11///
 12/// Uso:
 13///   dotnet run --project FAU.API -- --seed-admin           (crear)
 14///   dotnet run --project FAU.API -- --seed-admin --reset   (resetear password de usuario existente)
 15/// </summary>
 16public static class SuperAdminSeeder
 17{
 18    private const string RolAdministrador = "Administrador";
 19
 20    public static async Task<int> RunAsync(string[] args, IServiceProvider services)
 21    {
 022        var context = services.GetRequiredService<ApplicationDbContext>();
 023        var reset = args.Contains("--reset");
 24
 025        Console.WriteLine();
 026        Console.WriteLine("========================================");
 027        Console.WriteLine("  FAU Liquidacion - Crear Super Admin  ");
 028        Console.WriteLine("========================================");
 029        if (reset)
 030            Console.WriteLine("  Modo: RESET (actualiza usuario existente)");
 031        Console.WriteLine();
 32
 033        var username = Environment.GetEnvironmentVariable("SEED_ADMIN_USERNAME")
 034                       ?? LeerInput("Usuario (default: admin): ", defaultValue: "admin");
 35
 036        var password = Environment.GetEnvironmentVariable("SEED_ADMIN_PASSWORD")
 037                       ?? LeerPasswordSeguro("Contraseña: ");
 38
 039        if (string.IsNullOrWhiteSpace(password))
 40        {
 041            Console.Error.WriteLine("[ERROR] La contraseña no puede estar vacía.");
 042            return 1;
 43        }
 44
 045        var validacion = ValidarPassword(password);
 046        if (!validacion.esValido)
 47        {
 048            Console.Error.WriteLine($"[ERROR] Contraseña inválida: {validacion.mensaje}");
 049            return 1;
 50        }
 51
 052        var passwordHash = BCrypt.Net.BCrypt.HashPassword(password);
 53
 054        var usuarioExistente = await context.Usuarios
 055            .Include(u => u.Roles)
 056            .FirstOrDefaultAsync(u => u.Username == username);
 57
 058        if (usuarioExistente != null && !reset)
 59        {
 060            Console.Error.WriteLine($"[ERROR] Ya existe un usuario con el nombre '{username}'.");
 061            Console.Error.WriteLine($"        Para resetear su contraseña ejecuta:");
 062            Console.Error.WriteLine($"        dotnet run --project FAU.API -- --seed-admin --reset");
 063            return 1;
 64        }
 65
 066        var rol = await context.Roles
 067            .Include(r => r.Permisos)
 068            .FirstOrDefaultAsync(r => r.Nombre == RolAdministrador);
 69
 070        if (rol == null)
 71        {
 072            Console.Error.WriteLine($"[ERROR] El rol '{RolAdministrador}' no existe en la base de datos.");
 073            Console.Error.WriteLine("        Ejecuta primero: psql -f scripts/setup-admin.sql");
 074            return 1;
 75        }
 76
 077        if (usuarioExistente != null)
 78        {
 79            // Reset: actualizar hash y desbloquear
 080            usuarioExistente.PasswordHash = passwordHash;
 081            usuarioExistente.Estado = "activo";
 082            usuarioExistente.IntentosFallidos = 0;
 083            usuarioExistente.BloqueadoHasta = null;
 084            usuarioExistente.FechaActualizacion = DateTime.UtcNow;
 85
 086            if (!usuarioExistente.Roles.Any(r => r.Nombre == RolAdministrador))
 087                usuarioExistente.Roles.Add(rol);
 88
 089            await context.SaveChangesAsync();
 90
 091            Console.WriteLine($"[OK] Contraseña de '{username}' actualizada. Rol '{RolAdministrador}' confirmado.");
 092            Console.WriteLine($"     ID: {usuarioExistente.Id}");
 93        }
 94        else
 95        {
 96            // Crear nuevo usuario
 097            var usuario = new Usuario
 098            {
 099                Username = username,
 0100                PasswordHash = passwordHash,
 0101                Estado = "activo",
 0102                FechaActualizacion = DateTime.UtcNow,
 0103                Roles = new List<Rol> { rol }
 0104            };
 105
 0106            context.Usuarios.Add(usuario);
 0107            await context.SaveChangesAsync();
 108
 0109            Console.WriteLine($"[OK] Usuario '{username}' creado con rol '{RolAdministrador}'.");
 0110            Console.WriteLine($"     ID: {usuario.Id}");
 0111        }
 112
 0113        Console.WriteLine();
 0114        return 0;
 0115    }
 116
 117    private static string LeerInput(string prompt, string defaultValue = "")
 118    {
 0119        Console.Write(prompt);
 0120        var input = Console.ReadLine()?.Trim();
 0121        return string.IsNullOrWhiteSpace(input) ? defaultValue : input;
 122    }
 123
 124    private static string LeerPasswordSeguro(string prompt)
 125    {
 0126        Console.Write(prompt);
 0127        var password = new System.Text.StringBuilder();
 128
 129        ConsoleKeyInfo key;
 130        do
 131        {
 0132            key = Console.ReadKey(intercept: true);
 133
 0134            if (key.Key == ConsoleKey.Backspace && password.Length > 0)
 135            {
 0136                password.Remove(password.Length - 1, 1);
 0137                Console.Write("\b \b");
 138            }
 0139            else if (key.Key != ConsoleKey.Enter && key.Key != ConsoleKey.Backspace)
 140            {
 0141                password.Append(key.KeyChar);
 0142                Console.Write("*");
 143            }
 0144        } while (key.Key != ConsoleKey.Enter);
 145
 0146        Console.WriteLine();
 0147        return password.ToString();
 148    }
 149
 150    private static (bool esValido, string mensaje) ValidarPassword(string password)
 151    {
 0152        if (password.Length < 8)
 0153            return (false, "Debe tener al menos 8 caracteres.");
 154
 0155        if (!password.Any(char.IsUpper))
 0156            return (false, "Debe contener al menos una letra mayúscula.");
 157
 0158        if (!password.Any(char.IsLower))
 0159            return (false, "Debe contener al menos una letra minúscula.");
 160
 0161        if (!password.Any(char.IsDigit))
 0162            return (false, "Debe contener al menos un número.");
 163
 0164        return (true, string.Empty);
 165    }
 166}