< Summary

Information
Class: FAU.Logica.Services.UsuarioService
Assembly: FAU.Logica
File(s): /home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.Logica/Services/UsuarioService.cs
Line coverage
86%
Covered lines: 93
Uncovered lines: 14
Coverable lines: 107
Total lines: 232
Line coverage: 86.9%
Branch coverage
92%
Covered branches: 24
Total branches: 26
Branch coverage: 92.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
GetByIdAsync()100%11100%
GetByUsernameAsync()100%11100%
GetAllAsync()100%11100%
CreateAsync()75%4485.71%
UpdateAsync()83.33%6678.57%
CambiarEstadoAsync()100%4486.66%
CambiarPasswordAsync()100%4485.71%
AsignarRolAsync()100%6685.71%
RemoverRolAsync()100%4483.33%
DeleteAsync()100%11100%

File(s)

/home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.Logica/Services/UsuarioService.cs

#LineLine coverage
 1using FAU.DataAccess.Repositories;
 2using FAU.Entidades;
 3using FAU.Logica.Validadores;
 4
 5namespace FAU.Logica.Services;
 6
 7public class UsuarioService : IUsuarioService
 8{
 9    private readonly IUsuarioRepository _usuarioRepository;
 10    private readonly IRolRepository _rolRepository;
 11    private readonly IAuditoriaService _auditoriaService;
 12    private readonly ICurrentUserContext _currentUser;
 13
 2414    public UsuarioService(IUsuarioRepository usuarioRepository, IRolRepository rolRepository, IAuditoriaService auditori
 15    {
 2416        _usuarioRepository = usuarioRepository;
 2417        _rolRepository = rolRepository;
 2418        _auditoriaService = auditoriaService;
 2419        _currentUser = currentUser;
 2420    }
 21
 22    public async Task<Usuario?> GetByIdAsync(long id)
 23    {
 224        return await _usuarioRepository.GetByIdAsync(id);
 225    }
 26
 27    public async Task<Usuario?> GetByUsernameAsync(string username)
 28    {
 129        return await _usuarioRepository.GetByUsernameAsync(username);
 130    }
 31
 32    public async Task<IEnumerable<Usuario>> GetAllAsync()
 33    {
 134        return await _usuarioRepository.GetAllAsync();
 135    }
 36
 37    public async Task<(bool Success, Usuario? Usuario, string? Error)> CreateAsync(string username, string password, lon
 38    {
 39        try
 40        {
 241            if (await _usuarioRepository.ExistsAsync(username))
 42            {
 143                return (false, null, "El nombre de usuario ya está en uso");
 44            }
 45
 146            var (isValid, error) = PasswordPolicy.Validate(password);
 147            if (!isValid)
 48            {
 049                return (false, null, error);
 50            }
 51
 152            var passwordHash = BCrypt.Net.BCrypt.HashPassword(password);
 53
 154            var nuevoUsuario = new Usuario
 155            {
 156                Username = username,
 157                PasswordHash = passwordHash,
 158                Estado = "activo",
 159                IntentosFallidos = 0,
 160                PersonaId = personaId,
 161                FechaActualizacion = DateTime.UtcNow
 162            };
 63
 164            var usuarioCreado = await _usuarioRepository.CreateAsync(nuevoUsuario);
 165            await _auditoriaService.LogAuditoriaAsync(_currentUser.UserId ?? 0, AccionEnum.CrearUsuario, ContextoEnum.Us
 166            return (true, usuarioCreado, null);
 67        }
 068        catch (Exception ex)
 69        {
 070            return (false, null, $"Error al crear usuario: {ex.Message}");
 71        }
 272    }
 73
 74    public async Task<(bool Success, Usuario? Usuario, string? Error)> UpdateAsync(long id, string? newPassword = null)
 75    {
 76        try
 77        {
 378            var usuario = await _usuarioRepository.GetByIdAsync(id);
 379            if (usuario == null)
 80            {
 181                return (false, null, "Usuario no encontrado");
 82            }
 83
 284            if (!string.IsNullOrWhiteSpace(newPassword))
 85            {
 186                var (isValid, error) = PasswordPolicy.Validate(newPassword);
 187                if (!isValid)
 88                {
 089                    return (false, null, error);
 90                }
 91
 192                usuario.PasswordHash = BCrypt.Net.BCrypt.HashPassword(newPassword);
 93            }
 94
 295            var usuarioActualizado = await _usuarioRepository.UpdateAsync(usuario);
 296            await _auditoriaService.LogAuditoriaAsync(_currentUser.UserId ?? 0, AccionEnum.ActualizarUsuario, ContextoEn
 297            return (true, usuarioActualizado, null);
 98        }
 099        catch (Exception ex)
 100        {
 0101            return (false, null, $"Error al actualizar usuario: {ex.Message}");
 102        }
 3103    }
 104
 105    public async Task<(bool Success, string? Error)> CambiarEstadoAsync(long id, string nuevoEstado)
 106    {
 107        try
 108        {
 3109            var usuario = await _usuarioRepository.GetByIdAsync(id);
 3110            if (usuario == null)
 111            {
 1112                return (false, "Usuario no encontrado");
 113            }
 114
 115            // Validar estados permitidos
 2116            var estadosPermitidos = new[] { "Activo", "Bloqueado", "Inactivo" };
 2117            if (!estadosPermitidos.Contains(nuevoEstado, StringComparer.OrdinalIgnoreCase))
 118            {
 1119                return (false, "Estado inválido. Valores permitidos: Activo, Bloqueado, Inactivo");
 120            }
 121
 1122            var estadoAnterior = usuario.Estado;
 1123            usuario.Estado = nuevoEstado;
 1124            usuario.FechaActualizacion = DateTime.UtcNow;
 125
 1126            await _usuarioRepository.UpdateAsync(usuario);
 1127            await _auditoriaService.LogAuditoriaAsync(_currentUser.UserId ?? 0, AccionEnum.ActualizarUsuario, ContextoEn
 1128            return (true, null);
 129        }
 0130        catch (Exception ex)
 131        {
 0132            return (false, $"Error al cambiar estado del usuario: {ex.Message}");
 133        }
 3134    }
 135
 136    public async Task<(bool Success, string? Error)> CambiarPasswordAsync(long id, string nuevaPassword)
 137    {
 138        try
 139        {
 4140            var usuario = await _usuarioRepository.GetByIdAsync(id);
 4141            if (usuario == null)
 142            {
 1143                return (false, "Usuario no encontrado");
 144            }
 145
 3146            var (isValid, error) = PasswordPolicy.Validate(nuevaPassword);
 3147            if (!isValid)
 148            {
 2149                return (false, error);
 150            }
 151
 1152            usuario.PasswordHash = BCrypt.Net.BCrypt.HashPassword(nuevaPassword);
 1153            usuario.FechaActualizacion = DateTime.UtcNow;
 154
 1155            await _usuarioRepository.UpdateAsync(usuario);
 1156            await _auditoriaService.LogAuditoriaAsync(_currentUser.UserId ?? 0, AccionEnum.ActualizarUsuario, ContextoEn
 1157            return (true, null);
 158        }
 0159        catch (Exception ex)
 160        {
 0161            return (false, $"Error al cambiar contraseña: {ex.Message}");
 162        }
 4163    }
 164
 165    public async Task<(bool Success, string? Error)> AsignarRolAsync(long usuarioId, long rolId)
 166    {
 167        try
 168        {
 4169            var usuario = await _usuarioRepository.GetByIdAsync(usuarioId);
 4170            if (usuario == null)
 171            {
 1172                return (false, "Usuario no encontrado");
 173            }
 174
 3175            var rol = await _rolRepository.GetByIdAsync(rolId);
 3176            if (rol == null)
 177            {
 1178                return (false, "Rol no encontrado");
 179            }
 180
 3181            if (usuario.Roles.Any(r => r.Id == rolId))
 182            {
 1183                return (false, "El usuario ya tiene este rol asignado");
 184            }
 185
 1186            usuario.Roles.Add(rol);
 1187            await _usuarioRepository.UpdateAsync(usuario);
 1188            await _auditoriaService.LogAuditoriaAsync(_currentUser.UserId ?? 0, AccionEnum.ActualizarUsuario, ContextoEn
 189
 1190            return (true, null);
 191        }
 0192        catch (Exception ex)
 193        {
 0194            return (false, $"Error al asignar rol: {ex.Message}");
 195        }
 4196    }
 197
 198    public async Task<(bool Success, string? Error)> RemoverRolAsync(long usuarioId, long rolId)
 199    {
 200        try
 201        {
 3202            var usuario = await _usuarioRepository.GetByIdAsync(usuarioId);
 3203            if (usuario == null)
 204            {
 1205                return (false, "Usuario no encontrado");
 206            }
 207
 3208            var rol = usuario.Roles.FirstOrDefault(r => r.Id == rolId);
 2209            if (rol == null)
 210            {
 1211                return (false, "El usuario no tiene este rol asignado");
 212            }
 213
 1214            usuario.Roles.Remove(rol);
 1215            await _usuarioRepository.UpdateAsync(usuario);
 1216            await _auditoriaService.LogAuditoriaAsync(_currentUser.UserId ?? 0, AccionEnum.ActualizarUsuario, ContextoEn
 217
 1218            return (true, null);
 219        }
 0220        catch (Exception ex)
 221        {
 0222            return (false, $"Error al remover rol: {ex.Message}");
 223        }
 3224    }
 225
 226    public async Task DeleteAsync(long id)
 227    {
 1228        await _auditoriaService.LogAuditoriaAsync(_currentUser.UserId ?? 0, AccionEnum.ActualizarUsuario, ContextoEnum.U
 1229        await _usuarioRepository.DeleteAsync(id);
 1230    }
 231}
 232