< 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: 86
Coverable lines: 86
Total lines: 165
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            .FirstOrDefaultAsync(r => r.Nombre == RolAdministrador);
 68
 069        if (rol == null)
 70        {
 071            Console.Error.WriteLine($"[ERROR] El rol '{RolAdministrador}' no existe en la base de datos.");
 072            Console.Error.WriteLine("        Ejecuta primero: psql -f scripts/setup-admin.sql");
 073            return 1;
 74        }
 75
 076        if (usuarioExistente != null)
 77        {
 78            // Reset: actualizar hash y desbloquear
 079            usuarioExistente.PasswordHash = passwordHash;
 080            usuarioExistente.Estado = "activo";
 081            usuarioExistente.IntentosFallidos = 0;
 082            usuarioExistente.BloqueadoHasta = null;
 083            usuarioExistente.FechaActualizacion = DateTime.Now;
 84
 085            if (!usuarioExistente.Roles.Any(r => r.Nombre == RolAdministrador))
 086                usuarioExistente.Roles.Add(rol);
 87
 088            await context.SaveChangesAsync();
 89
 090            Console.WriteLine($"[OK] Contraseña de '{username}' actualizada. Rol '{RolAdministrador}' confirmado.");
 091            Console.WriteLine($"     ID: {usuarioExistente.Id}");
 92        }
 93        else
 94        {
 95            // Crear nuevo usuario
 096            var usuario = new Usuario
 097            {
 098                Username = username,
 099                PasswordHash = passwordHash,
 0100                Estado = "activo",
 0101                FechaActualizacion = DateTime.Now,
 0102                Roles = new List<Rol> { rol }
 0103            };
 104
 0105            context.Usuarios.Add(usuario);
 0106            await context.SaveChangesAsync();
 107
 0108            Console.WriteLine($"[OK] Usuario '{username}' creado con rol '{RolAdministrador}'.");
 0109            Console.WriteLine($"     ID: {usuario.Id}");
 0110        }
 111
 0112        Console.WriteLine();
 0113        return 0;
 0114    }
 115
 116    private static string LeerInput(string prompt, string defaultValue = "")
 117    {
 0118        Console.Write(prompt);
 0119        var input = Console.ReadLine()?.Trim();
 0120        return string.IsNullOrWhiteSpace(input) ? defaultValue : input;
 121    }
 122
 123    private static string LeerPasswordSeguro(string prompt)
 124    {
 0125        Console.Write(prompt);
 0126        var password = new System.Text.StringBuilder();
 127
 128        ConsoleKeyInfo key;
 129        do
 130        {
 0131            key = Console.ReadKey(intercept: true);
 132
 0133            if (key.Key == ConsoleKey.Backspace && password.Length > 0)
 134            {
 0135                password.Remove(password.Length - 1, 1);
 0136                Console.Write("\b \b");
 137            }
 0138            else if (key.Key != ConsoleKey.Enter && key.Key != ConsoleKey.Backspace)
 139            {
 0140                password.Append(key.KeyChar);
 0141                Console.Write("*");
 142            }
 0143        } while (key.Key != ConsoleKey.Enter);
 144
 0145        Console.WriteLine();
 0146        return password.ToString();
 147    }
 148
 149    private static (bool esValido, string mensaje) ValidarPassword(string password)
 150    {
 0151        if (password.Length < 8)
 0152            return (false, "Debe tener al menos 8 caracteres.");
 153
 0154        if (!password.Any(char.IsUpper))
 0155            return (false, "Debe contener al menos una letra mayúscula.");
 156
 0157        if (!password.Any(char.IsLower))
 0158            return (false, "Debe contener al menos una letra minúscula.");
 159
 0160        if (!password.Any(char.IsDigit))
 0161            return (false, "Debe contener al menos un número.");
 162
 0163        return (true, string.Empty);
 164    }
 165}