Apigateway/Microservicios/MsUsuarios/Controllers/AuthController.cs

317 lines
11 KiB
C#

using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using MSAdminUsuarios.Context;
using Security;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
namespace MSAdminUsuarios.Controllers
{
[ApiController]
[Route("[controller]")]
public class AuthController : ControllerBase
{
private readonly ModelContext _context;
private readonly Encripter _encript = new();
public AuthController(ModelContext context)
{
_context = context;
}
[HttpPost("Login")]
public IActionResult Login([FromBody] LoginModel login)
{
try
{
if (!_encript.IsValid) return BadRequest("Lectura inválida");
if (login.TX_LOGINNAME_USUMS == null) return BadRequest("Es necesario ingresar un correo");
if (login.TX_PASSWORD_USUMS == null) return BadRequest("Es necesario ingresar una contraseña");
USUARIO? user = _context.USUARIOSMs.FirstOrDefault(u => u.TX_LOGINNAME_USUMS == login.TX_LOGINNAME_USUMS && u.TX_PASSWORD_USUMS == _encript.EncryptPwd(login.TX_PASSWORD_USUMS));
if (user == null) return BadRequest("Usuario o contraseña incorrectos");
string token = Token(user);
return Ok(new {
token = token,
user = user.TX_PKDOC_USUMS
});
} catch (Exception e)
{
return BadRequest(e.Message);
}
}
[HttpPost("CambiarClave")]
public IActionResult CambiarClave([FromBody] USUARIO us)
{
try
{
USUARIO? user = _context.USUARIOSMs.FirstOrDefault(u => us.NU_PK_USUMS == u.NU_PK_USUMS);
if (user == null) return BadRequest("Usuario no encontrado.");
string newPass = _encript.EncryptPwd(us.TX_PASSWORD_USUMS!);
user.TX_PASSWORD_USUMS = newPass;
_context.USUARIOSMs.Update(user);
_context.SaveChanges();
return Ok("Contraseña actualizada correctamente");
} catch (Exception e)
{
return Conflict(e.Message);
}
}
[HttpPost("Proveedor")]
public IActionResult LoginProveedores([FromBody] LoginModel login)
{
try
{
if (!_encript.IsValid) return BadRequest(new ResLoginExt("Lectura inválida"));
if (login.TX_LOGINNAME_USUMS == null) return BadRequest(new ResLoginExt("Es necesario ingresar un usuario"));
if (login.TX_PASSWORD_USUMS == null) return BadRequest(new ResLoginExt("Es necesario ingresar una contraseña"));
USUARIO? userExist = _context.USUARIOSMs.FirstOrDefault(u => u.TX_LOGINNAME_USUMS == login.TX_LOGINNAME_USUMS);
if (userExist == null) return BadRequest(new ResLoginExt("Usuario o contraseña incorrectos"));
USUARIO? user = _context.USUARIOSMs.FirstOrDefault(u => u.TX_LOGINNAME_USUMS == login.TX_LOGINNAME_USUMS && u.TX_PASSWORD_USUMS == _encript.EncryptPwd(login.TX_PASSWORD_USUMS));
if (user == null) return BadRequest(new ResLoginExt("Usuario o contraseña incorrectos", true, userExist.NU_ESTADO_USUMS));
if (user.NU_ESTADO_USUMS != 1) return BadRequest(new ResLoginExt("Usuario inactivo o eliminado.", true, user.NU_ESTADO_USUMS));
string token = Token(user);
return Ok(new ResLoginExt("Bienvenido al sistema.", true, user.NU_ESTADO_USUMS, token));
}
catch (Exception e)
{
return BadRequest(e.Message);
}
}
[HttpPatch("RenovarToken")]
public IActionResult RefreshToken([FromBody] string token)
{
try
{
#warning este metodo se debe revisar, des-encriptado no se debe permitir!
JwtSecurityTokenHandler handler = new();
JwtSecurityToken tkn = handler.ReadJwtToken(Encripter.Descypher(token));
int pk = Int32.Parse(tkn.Claims.FirstOrDefault(c => c.Type == "pk").Value);
USUARIO? user = _context.USUARIOSMs.FirstOrDefault(u => u.NU_PK_USUMS == pk);
if (user == null) return BadRequest("No se encuentra usuario");
string newToken = Token(user);
return Ok(newToken);
} catch(Exception ex)
{
return BadRequest(ex.Message);
}
}
[HttpGet("Encriptar")]
public IActionResult Encriptar(string text, int tipo)
{
if (!_encript.IsValid) return BadRequest("Lectura inválida");
if (tipo == 0) return Ok(_encript.EncryptPwd(text));
return Ok(_encript.EncryptHashTkn(text));
}
[HttpGet("Desencriptar")]
public IActionResult Desencriptar(string text, int tipo)
{
if (!_encript.IsValid) return BadRequest("Lectura inválida");
if (tipo == 0) return Ok(_encript.DecryptPwd(text));
return Ok(_encript.DecryptHashTkn(text));
}
[HttpGet("TknCambioClave")]
public IActionResult ObtenerTokenCambioClave(int pkUs)
{
try
{
return Ok(TokenCambioClave(pkUs));
} catch (Exception e)
{
return BadRequest(e.Message);
}
}
[AcceptVerbs("GET")]
string Token(USUARIO user)
{
List<PERFILPORUSUARIO> perfilesPorUsuario = (from perf in _context.PERFILESPORUSUARIOs
where perf.TX_FKDOC_USUMS == user.TX_PKDOC_USUMS && perf.NU_FK_PFL != null && perf.BL_ESTADO_PFLXUSU == 1
select perf).ToList();
List<int?> perfiles = perfilesPorUsuario.Select(p => p.NU_FK_PFL).ToList();
List<PERMISO> permisos = (from perfXUs in perfilesPorUsuario
join perm in _context.PERMISOSMs on perfXUs.NU_FK_PFL equals perm.NU_FK_PFL
where perm.BL_ESTADO_PMS == 1
select perm).ToList();
Dictionary<string, string> perfilesPorPermiso = new();
foreach (PERMISO p in permisos)
{
string key = p.NU_FK_MS.ToString();
string val = p.NU_FK_PFL.ToString();
if (perfilesPorPermiso.ContainsKey(key))
{
string antVal = perfilesPorPermiso[key];
perfilesPorPermiso.Remove(key);
perfilesPorPermiso.Add(key, antVal + "," + val);
}
else
{
perfilesPorPermiso.Add(key, val);
}
}
perfiles.Add(-1);
//Security key debe ser un environment variable seguro
var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Encripter.HashKey));
var signingCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256);
string nombres = "";
string apellidos = "";
if (user.TX_PRIMERNOM_USUMS != null) nombres += user.TX_PRIMERNOM_USUMS;
if (user.TX_SEGUNDONOM_USUMS != null) nombres += " " + user.TX_SEGUNDONOM_USUMS;
if (user.TX_PRIMERAPELL_USUMS != null) apellidos += user.TX_PRIMERAPELL_USUMS;
if (user.TX_SEGUNDOAPELL_USUMS != null) apellidos += " " + user.TX_SEGUNDOAPELL_USUMS;
nombres = nombres.Trim();
apellidos = apellidos.Trim();
if (nombres == "") nombres = "N";
if (apellidos == "") apellidos = "A";
int tipo_doc = user.NU_TIPODOC_USUMS == null ? -1 : (int)user.NU_TIPODOC_USUMS;
ClaimsIdentity claims = new ClaimsIdentity(new List<Claim>
{
new Claim("user", user.TX_PKDOC_USUMS),
new Claim("nombres", nombres),
new Claim("apellidos", apellidos),
new Claim("tipo_doc", tipo_doc.ToString()),
new Claim("pk", user.NU_PK_USUMS.ToString())
});
foreach (int p in perfiles)
{
claims.AddClaim(new Claim("perfiles", p.ToString(), ClaimValueTypes.String));
}
//foreach (PERMISO p in permisos)
//{
// claims.AddClaim(new Claim("permisos", Encripter.Encrypt(p.NU_FK_MS.ToString())));
//}
foreach (KeyValuePair<string, string> p in perfilesPorPermiso)
{
string key = p.Key;
string val = p.Value;
claims.AddClaim(new Claim("permisos", _encript.EncryptHashTkn(key) + "::" + val));
}
var securityTokenDescriptor = new SecurityTokenDescriptor
{
Subject = claims,
Expires = DateTime.Now.AddDays(20),
SigningCredentials = signingCredentials
};
var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
var securityToken = jwtSecurityTokenHandler.CreateToken(securityTokenDescriptor);
var token = jwtSecurityTokenHandler.WriteToken(securityToken);
return Encripter.Cypher(token);
}
string TokenCambioClave(int pkUser)
{
USUARIO? user = _context.USUARIOSMs.FirstOrDefault(u => pkUser == u.NU_PK_USUMS);
if (user == null) throw new Exception("Usuario no encontrado");
//Security key debe ser un environment variable seguro
var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Encripter.HashKey));
var signingCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256);
ClaimsIdentity claims = new ClaimsIdentity(new List<Claim>
{
new Claim("user", user.TX_PKDOC_USUMS),
new Claim("loginName", user.TX_LOGINNAME_USUMS),
new Claim("pk", user.NU_PK_USUMS.ToString())
});
var securityTokenDescriptor = new SecurityTokenDescriptor
{
Subject = claims,
Expires = DateTime.Now.AddMinutes(20),
SigningCredentials = signingCredentials
};
var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
var securityToken = jwtSecurityTokenHandler.CreateToken(securityTokenDescriptor);
var token = jwtSecurityTokenHandler.WriteToken(securityToken);
return Encripter.Cypher(token);
}
}
public class LoginModel
{
public string? TX_LOGINNAME_USUMS { get; set; }
public string? TX_PASSWORD_USUMS { get; set; }
}
public class ResLoginExt
{
public ResLoginExt(string _message, bool _exist = false, int? _estado = null, string? _token = "")
{
Message = _message;
Token = _token;
Existe = _exist;
Estado = _estado;
}
public bool Existe { get; set; }
public int? Estado { get; set; }
public string? Token { get; set; }
public string Message { get; set; } = null!;
}
static class Options
{
}
}