Update Usuarios Extended Fields
All checks were successful
CI/CD Pipeline / Build and Deploy with Docker Compose (push) Successful in 5m25s
All checks were successful
CI/CD Pipeline / Build and Deploy with Docker Compose (push) Successful in 5m25s
This commit is contained in:
parent
d179b1b74d
commit
050cf9af0f
@ -10,6 +10,7 @@ using Services.Models;
|
|||||||
using Services.Interfaces;
|
using Services.Interfaces;
|
||||||
using phronCare.API.Models.Authentication.Login;
|
using phronCare.API.Models.Authentication.Login;
|
||||||
using phronCare.API.Models.Authentication.SingUp;
|
using phronCare.API.Models.Authentication.SingUp;
|
||||||
|
using phronCare.API.Models.Security;
|
||||||
using Google.Authenticator;
|
using Google.Authenticator;
|
||||||
using QRCoder;
|
using QRCoder;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
@ -18,51 +19,52 @@ namespace phronCare.API.Controllers
|
|||||||
{
|
{
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
public class AuthenticationController(UserManager<IdentityUser> userManager, RoleManager<IdentityRole> roleManager, IEmailService emailService, IConfiguration configuration, SignInManager<IdentityUser> signInManager, TwoFactorAuthenticator twoFactorAuthenticator) : ControllerBase
|
public class AuthenticationController(
|
||||||
|
UserManager<ApplicationUser> userManager,
|
||||||
|
RoleManager<IdentityRole> roleManager,
|
||||||
|
IEmailService emailService,
|
||||||
|
IConfiguration configuration,
|
||||||
|
SignInManager<ApplicationUser> signInManager,
|
||||||
|
TwoFactorAuthenticator twoFactorAuthenticator) : ControllerBase
|
||||||
{
|
{
|
||||||
private const int JWT_TOKEN_VALIDITY_HOURS = 48;
|
private const int JWT_TOKEN_VALIDITY_HOURS = 48;
|
||||||
|
|
||||||
#region Declaration Section
|
#region Declaration Section
|
||||||
private readonly UserManager<IdentityUser> userManager = userManager;
|
private readonly UserManager<ApplicationUser> userManager = userManager;
|
||||||
private readonly RoleManager<IdentityRole> roleManager = roleManager;
|
private readonly RoleManager<IdentityRole> roleManager = roleManager;
|
||||||
private readonly SignInManager<IdentityUser> signInManager = signInManager;
|
private readonly SignInManager<ApplicationUser> signInManager = signInManager;
|
||||||
private readonly TwoFactorAuthenticator authenticator = twoFactorAuthenticator;
|
private readonly TwoFactorAuthenticator authenticator = twoFactorAuthenticator;
|
||||||
private readonly IEmailService emailService = emailService;
|
private readonly IEmailService emailService = emailService;
|
||||||
private readonly IConfiguration configuration = configuration;
|
private readonly IConfiguration configuration = configuration;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Segurity Endpoints
|
#region Security Endpoints
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Route("generate-qr-code")]
|
[Route("generate-qr-code")]
|
||||||
public async Task<IActionResult> GenerateQRCodeAsync()
|
public async Task<IActionResult> GenerateQRCodeAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var user = await signInManager.GetTwoFactorAuthenticationUserAsync(); // Obtén el nombre de usuario actual
|
var user = await signInManager.GetTwoFactorAuthenticationUserAsync();
|
||||||
|
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
return BadRequest(new Response { Status = "Error", Message = "Usuario no autenticado." });
|
return BadRequest(new Response { Status = "Error", Message = "Usuario no autenticado." });
|
||||||
}
|
}
|
||||||
var setupInfo = authenticator.GenerateSetupCode("MiApp", user.Email, user.Id, false, 10);
|
|
||||||
|
|
||||||
// Genera el código QR como una imagen
|
var setupInfo = authenticator.GenerateSetupCode("MiApp", user.Email, user.Id, false, 10);
|
||||||
var qrCodeGenerator = new QRCodeGenerator();
|
var qrCodeGenerator = new QRCodeGenerator();
|
||||||
var qrCodeData = qrCodeGenerator.CreateQrCode(setupInfo.ManualEntryKey, QRCodeGenerator.ECCLevel.Q);
|
var qrCodeData = qrCodeGenerator.CreateQrCode(setupInfo.ManualEntryKey, QRCodeGenerator.ECCLevel.Q);
|
||||||
var qrCode = new PngByteQRCode(qrCodeData);
|
var qrCode = new PngByteQRCode(qrCodeData);
|
||||||
|
var qrCodeImage = qrCode.GetGraphic(10);
|
||||||
// Convierte la imagen del código QR en bytes
|
|
||||||
var qrCodeImage = qrCode.GetGraphic(10); // Ajusta el tamaño según tus necesidades
|
|
||||||
var qrCodeImageData = Convert.ToBase64String(qrCodeImage);
|
var qrCodeImageData = Convert.ToBase64String(qrCodeImage);
|
||||||
|
|
||||||
// Devuelve el userId (clave secreta) y la imagen del código QR en la respuesta
|
|
||||||
return Ok(new AuthResponse
|
return Ok(new AuthResponse
|
||||||
{
|
{
|
||||||
Status = "Success",
|
Status = "Success",
|
||||||
Message = "Código QR generado satisfactoriamente.",
|
Message = "Código QR generado satisfactoriamente.",
|
||||||
ManualSetupKey = setupInfo.ManualEntryKey, // Proporciona esto al usuario para configuración manual en Google Authenticator
|
ManualSetupKey = setupInfo.ManualEntryKey,
|
||||||
QRCodeImage = qrCodeImageData // Devuelve la imagen del código QR
|
QRCodeImage = qrCodeImageData
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
@ -75,23 +77,25 @@ namespace phronCare.API.Controllers
|
|||||||
[Route("register")]
|
[Route("register")]
|
||||||
public async Task<IActionResult> Register([FromBody] RegisterUser registerUser)
|
public async Task<IActionResult> Register([FromBody] RegisterUser registerUser)
|
||||||
{
|
{
|
||||||
//Chequeo Correo existente
|
|
||||||
var userExist = await userManager.FindByEmailAsync(registerUser.EmailAddress);
|
var userExist = await userManager.FindByEmailAsync(registerUser.EmailAddress);
|
||||||
if (userExist != null)
|
if (userExist != null)
|
||||||
{
|
return StatusCode(StatusCodes.Status409Conflict, "El correo ingresado ya está en uso.");
|
||||||
return StatusCode(StatusCodes.Status409Conflict, "El correo ingresado ya esta en uso.");
|
|
||||||
}
|
|
||||||
userExist = await userManager.FindByNameAsync(registerUser.UserName);
|
userExist = await userManager.FindByNameAsync(registerUser.UserName);
|
||||||
if (userExist != null)
|
if (userExist != null)
|
||||||
{
|
|
||||||
return StatusCode(StatusCodes.Status409Conflict, "El usuario ingresado ya existe.");
|
return StatusCode(StatusCodes.Status409Conflict, "El usuario ingresado ya existe.");
|
||||||
}
|
|
||||||
|
|
||||||
IdentityUser user = new()
|
var user = new ApplicationUser
|
||||||
{
|
{
|
||||||
Email = registerUser.EmailAddress,
|
Email = registerUser.EmailAddress,
|
||||||
|
UserName = registerUser.UserName,
|
||||||
SecurityStamp = Guid.NewGuid().ToString(),
|
SecurityStamp = Guid.NewGuid().ToString(),
|
||||||
UserName = registerUser.UserName
|
FirstName = registerUser.FirstName,
|
||||||
|
LastName = registerUser.LastName,
|
||||||
|
Address = registerUser.Address,
|
||||||
|
Department = registerUser.Department,
|
||||||
|
CompanyName = registerUser.CompanyName,
|
||||||
|
BirthDate = registerUser.BirthDate
|
||||||
};
|
};
|
||||||
|
|
||||||
if (await roleManager.RoleExistsAsync(registerUser.Role))
|
if (await roleManager.RoleExistsAsync(registerUser.Role))
|
||||||
@ -99,22 +103,20 @@ namespace phronCare.API.Controllers
|
|||||||
var result = await userManager.CreateAsync(user, registerUser.Password);
|
var result = await userManager.CreateAsync(user, registerUser.Password);
|
||||||
if (!result.Succeeded)
|
if (!result.Succeeded)
|
||||||
{
|
{
|
||||||
return StatusCode(StatusCodes.Status500InternalServerError, $"Creacion de usuario fallida: {result}");
|
return StatusCode(StatusCodes.Status500InternalServerError, $"Creación de usuario fallida: {string.Join(", ", result.Errors.Select(e => e.Description))}");
|
||||||
}
|
}
|
||||||
|
|
||||||
await userManager.AddToRoleAsync(user, registerUser.Role);
|
await userManager.AddToRoleAsync(user, registerUser.Role);
|
||||||
|
|
||||||
//Add Token to Verify the email
|
|
||||||
var token = await userManager.GenerateEmailConfirmationTokenAsync(user);
|
var token = await userManager.GenerateEmailConfirmationTokenAsync(user);
|
||||||
var confirmationLink = Url.Action(nameof(ConfirmEmail), "Authentication", new { token, email = user.Email }, Request.Scheme);
|
var confirmationLink = Url.Action(nameof(ConfirmEmail), "Authentication", new { token, email = user.Email }, Request.Scheme);
|
||||||
var message = new Message([user.Email!], "phronCare - Link de verificacion", confirmationLink!);
|
var message = new Message(new[] { user.Email! }, "phronCare - Link de verificación", confirmationLink!);
|
||||||
emailService.SendEmail(message);
|
emailService.SendEmail(message);
|
||||||
|
|
||||||
return StatusCode(StatusCodes.Status201Created, $"Usuario creado satisfactoriamente. Debe autenticar la cuenta generada desde la direccion de correo registrada: {user.Email}");
|
return StatusCode(StatusCodes.Status201Created, $"Usuario creado satisfactoriamente. Debe autenticar la cuenta desde su correo: {user.Email}");
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return StatusCode(StatusCodes.Status500InternalServerError, "El rol no existe. Intentalo nuevamente!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return StatusCode(StatusCodes.Status500InternalServerError, "El rol no existe. ¡Inténtalo nuevamente!");
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("confirmemail")]
|
[HttpGet("confirmemail")]
|
||||||
@ -125,13 +127,9 @@ namespace phronCare.API.Controllers
|
|||||||
{
|
{
|
||||||
var result = await userManager.ConfirmEmailAsync(user, token);
|
var result = await userManager.ConfirmEmailAsync(user, token);
|
||||||
if (result.Succeeded)
|
if (result.Succeeded)
|
||||||
{
|
return Ok(new Response { Status = "Success", Message = "Email verificado satisfactoriamente." });
|
||||||
return StatusCode(StatusCodes.Status200OK,
|
|
||||||
new Response { Status = "Success", Message = "Email verificado satisfactoriamente" });
|
|
||||||
}
|
}
|
||||||
}
|
return Conflict(new Response { Status = "Error", Message = "Este usuario no existe." });
|
||||||
return StatusCode(StatusCodes.Status409Conflict,
|
|
||||||
new Response { Status = "Error", Message = "Este usuario no existe" });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
@ -141,9 +139,7 @@ namespace phronCare.API.Controllers
|
|||||||
await signInManager.SignOutAsync();
|
await signInManager.SignOutAsync();
|
||||||
var user = await userManager.FindByNameAsync(loginModel.Username);
|
var user = await userManager.FindByNameAsync(loginModel.Username);
|
||||||
if (user is null)
|
if (user is null)
|
||||||
{
|
return Unauthorized("El nombre de usuario o contraseña son incorrectos.");
|
||||||
return Unauthorized("El nombre de usuario o contraseña son incorrectos");
|
|
||||||
};
|
|
||||||
|
|
||||||
var canSignIn = await signInManager.CanSignInAsync(user);
|
var canSignIn = await signInManager.CanSignInAsync(user);
|
||||||
if (!canSignIn)
|
if (!canSignIn)
|
||||||
@ -151,26 +147,24 @@ namespace phronCare.API.Controllers
|
|||||||
string message = string.Empty;
|
string message = string.Empty;
|
||||||
if (userManager.Options.SignIn.RequireConfirmedEmail && !(await userManager.IsEmailConfirmedAsync(user)))
|
if (userManager.Options.SignIn.RequireConfirmedEmail && !(await userManager.IsEmailConfirmedAsync(user)))
|
||||||
{
|
{
|
||||||
message = "El usuario {" + user.UserName + "} no puede iniciar sesion sin tener el email confirmado.";
|
message = $"El usuario {user.UserName} no puede iniciar sesión sin tener el email confirmado.";
|
||||||
}
|
}
|
||||||
if (userManager.Options.SignIn.RequireConfirmedPhoneNumber && !(await userManager.IsPhoneNumberConfirmedAsync(user)))
|
if (userManager.Options.SignIn.RequireConfirmedPhoneNumber && !(await userManager.IsPhoneNumberConfirmedAsync(user)))
|
||||||
{
|
{
|
||||||
message = "El usuario {" + user.UserName + "} no puede iniciar sesion sin tener confirmado el numero de telefono.";
|
message = $"El usuario {user.UserName} no puede iniciar sesión sin tener confirmado el número de teléfono.";
|
||||||
}
|
}
|
||||||
return StatusCode(StatusCodes.Status401Unauthorized, message);
|
return Unauthorized(message);
|
||||||
}
|
}
|
||||||
if (user != null && await userManager.CheckPasswordAsync(user, loginModel.Password))
|
|
||||||
|
if (await userManager.CheckPasswordAsync(user, loginModel.Password))
|
||||||
{
|
{
|
||||||
if (!user.TwoFactorEnabled)
|
if (!user.TwoFactorEnabled)
|
||||||
{
|
|
||||||
return await GenerateAccess(user);
|
return await GenerateAccess(user);
|
||||||
|
|
||||||
|
return Accepted(new Response { Status = "Success", Message = $"Debe ingresar el código desde la app Google Authenticator: {user.UserName}" });
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return Unauthorized("El nombre de usuario o contraseña son incorrectos.");
|
||||||
return StatusCode(StatusCodes.Status202Accepted, new Response { Status = "Success", Message = $"Debe ingresar el codigo desde la app Google Authenticator : {user.UserName}" });
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return Unauthorized("El nombre de usuario o contraseña son incorrectos");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
@ -180,21 +174,17 @@ namespace phronCare.API.Controllers
|
|||||||
var user = await userManager.FindByNameAsync(username);
|
var user = await userManager.FindByNameAsync(username);
|
||||||
if (user is not null)
|
if (user is not null)
|
||||||
{
|
{
|
||||||
string secretKey = user.Id; // Obtén la clave secreta del usuario desde tu base de datos
|
bool validate = authenticator.ValidateTwoFactorPIN(user.Id, code);
|
||||||
bool isBase32 = false; // Define si la clave secreta está en formato Base32
|
|
||||||
bool validate = authenticator.ValidateTwoFactorPIN(secretKey, code, isBase32);
|
|
||||||
if (validate)
|
if (validate)
|
||||||
{
|
|
||||||
return await GenerateAccess(user);
|
return await GenerateAccess(user);
|
||||||
}
|
}
|
||||||
}
|
return Unauthorized(new Response { Status = "Error", Message = "Código de verificación incorrecto." });
|
||||||
return StatusCode(StatusCodes.Status401Unauthorized, new Response { Status = "Error", Message = "Código de verificación incorrecto." });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
[Route("forgot-password")]
|
[Route("forgot-password")]
|
||||||
public async Task<IActionResult> ForgotPassword([Required]string email)
|
public async Task<IActionResult> ForgotPassword([Required] string email)
|
||||||
{
|
{
|
||||||
var user = await userManager.FindByEmailAsync(email);
|
var user = await userManager.FindByEmailAsync(email);
|
||||||
if (user != null)
|
if (user != null)
|
||||||
@ -202,27 +192,21 @@ namespace phronCare.API.Controllers
|
|||||||
var token = await userManager.GeneratePasswordResetTokenAsync(user);
|
var token = await userManager.GeneratePasswordResetTokenAsync(user);
|
||||||
var forgotPasswordLink = Url.Action(nameof(ResetPassword), "Authentication", new { token, email = user.Email }, Request.Scheme);
|
var forgotPasswordLink = Url.Action(nameof(ResetPassword), "Authentication", new { token, email = user.Email }, Request.Scheme);
|
||||||
|
|
||||||
var message = new Message([user.Email!], "phronCare - Enlace de recuperacion de contraseña.", forgotPasswordLink!);
|
var message = new Message(new[] { user.Email! }, "phronCare - Enlace de recuperación de contraseña", forgotPasswordLink!);
|
||||||
emailService.SendEmail(message);
|
emailService.SendEmail(message);
|
||||||
return StatusCode(StatusCodes.Status200OK, $"La solicitud de cambio de contraseña se envio a: {user.Email} con éxito. Por favor verifique el enlace enviado a la casilla de correo.");
|
return Ok($"La solicitud de cambio de contraseña se envió a: {user.Email} exitosamente.");
|
||||||
}
|
}
|
||||||
return StatusCode(StatusCodes.Status400BadRequest, "No se pudo enviar el enlace al correo, por favor intente nuevamente.");
|
return BadRequest("No se pudo enviar el enlace al correo, por favor intente nuevamente.");
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("reset-password")]
|
[HttpGet("reset-password")]
|
||||||
public async Task<IActionResult> ResetPassword(string token, string email)
|
public IActionResult ResetPassword(string token, string email)
|
||||||
{
|
{
|
||||||
//var model =new ResetPassword {Token=token, Email = email};
|
var htmlContent = GetResetPasswordHtmlContent(email, token);
|
||||||
var htmlContent = GetResetPasswordHtmlContent(email,token);
|
|
||||||
var bytes = Encoding.UTF8.GetBytes(htmlContent);
|
var bytes = Encoding.UTF8.GetBytes(htmlContent);
|
||||||
var stream = new MemoryStream(bytes);
|
var stream = new MemoryStream(bytes);
|
||||||
return File(stream, "text/html");
|
return File(stream, "text/html");
|
||||||
}
|
}
|
||||||
private static string GetResetPasswordHtmlContent(string username, string token)
|
|
||||||
{
|
|
||||||
string htmlContent = @"<!DOCTYPE html><html><head><meta name=viewport content=""width=device-width""><meta http-equiv=Content-Type content=""text/html; charset=UTF-8""><title>phronCare - Notificación</title><style>body{background:white;font-family:'Helvetica',sans-serif;color:#fff}.container{background-image:linear-gradient(45deg,rgb(5,39,103) 0%,#3a0647 70%);border-radius:50px;color:#fff;padding:20px;margin:30px auto;width:500px;text-align:center;}h1{font-size:20px}h2{font-size:16px;color:yellow;overflow-wrap:break-word;}p{font-size:16px}.form-control{width: 90%;padding: .375rem .75rem;height: 110px;max-height: 150px;border: 1px solid #ced4da;border-radius: .25rem;font-size: 1rem;}textarea{resize: none;}</style></head><body><table class=container><tr><td><h1>phronCare XL: Notificación</h1><h2>" + username + "</h2><h2>Token</h2><textarea class='form-control' readonly style='max-height: 150px;'>" + token + "</textarea><h3>Tu solicitud de restablecimiento de contraseña ha sido confirmada</h3><p>Para restablecer tu contraseña en phronCare, ingrese las credenciales proporcionadas.</p></td></tr></table></body></html>";
|
|
||||||
return htmlContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
@ -237,20 +221,75 @@ namespace phronCare.API.Controllers
|
|||||||
{
|
{
|
||||||
return StatusCode(StatusCodes.Status500InternalServerError, resetPassResult.Errors.First().Description);
|
return StatusCode(StatusCodes.Status500InternalServerError, resetPassResult.Errors.First().Description);
|
||||||
}
|
}
|
||||||
return StatusCode(StatusCodes.Status200OK,$"La password ha sido cambiada correctamente.");
|
return Ok("La contraseña ha sido cambiada correctamente.");
|
||||||
}
|
}
|
||||||
return StatusCode(StatusCodes.Status500InternalServerError,"No se pudo encontrar el usuario, por favor intente nuevamente.");
|
return StatusCode(StatusCodes.Status500InternalServerError, "No se pudo encontrar el usuario, por favor intente nuevamente.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetResetPasswordHtmlContent(string username, string token)
|
||||||
|
{
|
||||||
|
return @$"
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head><meta charset='UTF-8'><meta name='viewport' content='width=device-width, initial-scale=1.0'>
|
||||||
|
<title>phronCare - Notificación</title></head>
|
||||||
|
<body><h2>Usuario: {username}</h2><h3>Token: {token}</h3></body>
|
||||||
|
</html>";
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region GenerateAccess
|
#region GenerateAccess
|
||||||
private async Task<IActionResult> GenerateAccess(IdentityUser? user)
|
//private async Task<IActionResult> GenerateAccess(ApplicationUser user)
|
||||||
|
//{
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// var authClaims = new List<Claim>
|
||||||
|
// {
|
||||||
|
// new(ClaimTypes.Name, user.UserName),
|
||||||
|
// new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
|
||||||
|
// };
|
||||||
|
|
||||||
|
// var userRoles = await userManager.GetRolesAsync(user);
|
||||||
|
// foreach (var role in userRoles)
|
||||||
|
// {
|
||||||
|
// authClaims.Add(new Claim(ClaimTypes.Role, role));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// var jwtToken = GetToken(authClaims);
|
||||||
|
|
||||||
|
// var userSession = new UserSession
|
||||||
|
// {
|
||||||
|
// UserName = user.UserName,
|
||||||
|
// Role = userRoles.First(),
|
||||||
|
// Token = new JwtSecurityTokenHandler().WriteToken(jwtToken),
|
||||||
|
// ExpiresIn = (int)jwtToken.ValidTo.Subtract(DateTime.Now).TotalSeconds,
|
||||||
|
// ExpiryTimeStamp = jwtToken.ValidTo
|
||||||
|
// };
|
||||||
|
|
||||||
|
// return Ok(userSession);
|
||||||
|
// }
|
||||||
|
// catch (Exception ex)
|
||||||
|
// {
|
||||||
|
// return BadRequest(ex.Message);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
private async Task<IActionResult> GenerateAccess(ApplicationUser user)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var authClaims = new List<Claim>
|
var authClaims = new List<Claim>
|
||||||
{
|
{
|
||||||
new(ClaimTypes.Name, user.UserName),
|
new(ClaimTypes.Name, user.UserName),
|
||||||
new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
|
new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
|
||||||
};
|
};
|
||||||
|
|
||||||
var userRoles = await userManager.GetRolesAsync(user);
|
var userRoles = await userManager.GetRolesAsync(user);
|
||||||
|
|
||||||
|
if (!userRoles.Any())
|
||||||
|
{
|
||||||
|
return BadRequest("El usuario no tiene ningún rol asignado. Verifica el proceso de registro.");
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var role in userRoles)
|
foreach (var role in userRoles)
|
||||||
{
|
{
|
||||||
authClaims.Add(new Claim(ClaimTypes.Role, role));
|
authClaims.Add(new Claim(ClaimTypes.Role, role));
|
||||||
@ -261,13 +300,21 @@ namespace phronCare.API.Controllers
|
|||||||
var userSession = new UserSession
|
var userSession = new UserSession
|
||||||
{
|
{
|
||||||
UserName = user.UserName,
|
UserName = user.UserName,
|
||||||
Role = userRoles.First(),
|
Role = userRoles.First(), // ya validado que hay al menos uno
|
||||||
Token = new JwtSecurityTokenHandler().WriteToken(jwtToken),
|
Token = new JwtSecurityTokenHandler().WriteToken(jwtToken),
|
||||||
ExpiresIn = (int)jwtToken.ValidTo.Subtract(DateTime.Now).TotalSeconds,
|
ExpiresIn = (int)jwtToken.ValidTo.Subtract(DateTime.Now).TotalSeconds,
|
||||||
ExpiryTimeStamp = jwtToken.ValidTo
|
ExpiryTimeStamp = jwtToken.ValidTo
|
||||||
};
|
};
|
||||||
|
|
||||||
return Ok(userSession);
|
return Ok(userSession);
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// O podés loguearlo con logger si querés
|
||||||
|
return StatusCode(StatusCodes.Status500InternalServerError, $"Error generando token: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class UserSession
|
public class UserSession
|
||||||
{
|
{
|
||||||
public string UserName { get; set; }
|
public string UserName { get; set; }
|
||||||
@ -277,30 +324,24 @@ namespace phronCare.API.Controllers
|
|||||||
public DateTime ExpiryTimeStamp { get; set; }
|
public DateTime ExpiryTimeStamp { get; set; }
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region GenerateToken
|
#region GenerateToken
|
||||||
private JwtSecurityToken GetToken(List<Claim> authClaims)
|
private JwtSecurityToken GetToken(List<Claim> authClaims)
|
||||||
{
|
{
|
||||||
var secret = configuration["JWT:Secret"];
|
var secret = configuration["JWT:Secret"];
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(secret))
|
if (string.IsNullOrWhiteSpace(secret))
|
||||||
throw new InvalidOperationException("El Secret no está configurado.");
|
throw new InvalidOperationException("El Secret no está configurado.");
|
||||||
|
|
||||||
// Convertir explícitamente a bytes
|
var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));
|
||||||
var keyBytes = Encoding.UTF8.GetBytes(secret);
|
|
||||||
|
|
||||||
var authSigningKey = new SymmetricSecurityKey(keyBytes);
|
|
||||||
|
|
||||||
var credentials = new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256);
|
var credentials = new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256);
|
||||||
|
|
||||||
var token = new JwtSecurityToken(
|
return new JwtSecurityToken(
|
||||||
issuer: configuration["JWT:ValidIssuer"],
|
issuer: configuration["JWT:ValidIssuer"],
|
||||||
audience: configuration["JWT:ValidAudience"],
|
audience: configuration["JWT:ValidAudience"],
|
||||||
expires: DateTime.UtcNow.AddHours(JWT_TOKEN_VALIDITY_HOURS),
|
expires: DateTime.UtcNow.AddHours(JWT_TOKEN_VALIDITY_HOURS),
|
||||||
claims: authClaims,
|
claims: authClaims,
|
||||||
signingCredentials: credentials
|
signingCredentials: credentials
|
||||||
);
|
);
|
||||||
|
|
||||||
return token;
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
302
phronCare.API/Migrations/20250429190347_ExtendApplicationUser.Designer.cs
generated
Normal file
302
phronCare.API/Migrations/20250429190347_ExtendApplicationUser.Designer.cs
generated
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using phronCare.API.Models;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace phronCare.API.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(phronCareDbContext))]
|
||||||
|
[Migration("20250429190347_ExtendApplicationUser")]
|
||||||
|
partial class ExtendApplicationUser
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "8.0.10")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||||
|
|
||||||
|
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("RoleNameIndex")
|
||||||
|
.HasFilter("[NormalizedName] IS NOT NULL");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoles", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoleClaims", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserClaims", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderKey")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderDisplayName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("LoginProvider", "ProviderKey");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserLogins", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "RoleId");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserRoles", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "LoginProvider", "Name");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserTokens", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("phronCare.API.Models.Security.ApplicationUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AccessFailedCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Address")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("BirthDate")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("CompanyName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Department")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<bool>("EmailConfirmed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("FirstName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("LastName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("LockoutEnabled")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||||
|
.HasColumnType("datetimeoffset");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedEmail")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedUserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("PhoneNumberConfirmed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("ProfileImageUrl")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("SecurityStamp")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("TwoFactorEnabled")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedEmail")
|
||||||
|
.HasDatabaseName("EmailIndex");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedUserName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("UserNameIndex")
|
||||||
|
.HasFilter("[NormalizedUserName] IS NOT NULL");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUsers", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("phronCare.API.Models.Security.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("phronCare.API.Models.Security.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("phronCare.API.Models.Security.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("phronCare.API.Models.Security.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
112
phronCare.API/Migrations/20250429190347_ExtendApplicationUser.cs
Normal file
112
phronCare.API/Migrations/20250429190347_ExtendApplicationUser.cs
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
|
||||||
|
|
||||||
|
namespace phronCare.API.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class ExtendApplicationUser : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: "a36da698-f5bc-4af3-bc25-81c675d52914");
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: "ee45c015-8a59-469d-b2ef-1019d9ab246b");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "Address",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "nvarchar(max)",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<DateTime>(
|
||||||
|
name: "BirthDate",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "datetime2",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "CompanyName",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "nvarchar(max)",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "Department",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "nvarchar(max)",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "FirstName",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "nvarchar(max)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "LastName",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "nvarchar(max)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "ProfileImageUrl",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "nvarchar(max)",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "Address",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "BirthDate",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "CompanyName",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "Department",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "FirstName",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "LastName",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "ProfileImageUrl",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
|
||||||
|
values: new object[,]
|
||||||
|
{
|
||||||
|
{ "a36da698-f5bc-4af3-bc25-81c675d52914", "1/7/2023 00:00:00", "Administrator", "ADMINISTRATOR" },
|
||||||
|
{ "ee45c015-8a59-469d-b2ef-1019d9ab246b", "1/7/2023 00:00:00", "User", "User" }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -17,7 +17,7 @@ namespace phronCare.API.Migrations
|
|||||||
{
|
{
|
||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.HasAnnotation("ProductVersion", "7.0.8")
|
.HasAnnotation("ProductVersion", "8.0.10")
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||||
|
|
||||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||||
@ -47,22 +47,6 @@ namespace phronCare.API.Migrations
|
|||||||
.HasFilter("[NormalizedName] IS NOT NULL");
|
.HasFilter("[NormalizedName] IS NOT NULL");
|
||||||
|
|
||||||
b.ToTable("AspNetRoles", (string)null);
|
b.ToTable("AspNetRoles", (string)null);
|
||||||
|
|
||||||
b.HasData(
|
|
||||||
new
|
|
||||||
{
|
|
||||||
Id = "a36da698-f5bc-4af3-bc25-81c675d52914",
|
|
||||||
ConcurrencyStamp = "1/7/2023 00:00:00",
|
|
||||||
Name = "Administrator",
|
|
||||||
NormalizedName = "ADMINISTRATOR"
|
|
||||||
},
|
|
||||||
new
|
|
||||||
{
|
|
||||||
Id = "ee45c015-8a59-469d-b2ef-1019d9ab246b",
|
|
||||||
ConcurrencyStamp = "1/7/2023 00:00:00",
|
|
||||||
Name = "User",
|
|
||||||
NormalizedName = "User"
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
@ -90,71 +74,6 @@ namespace phronCare.API.Migrations
|
|||||||
b.ToTable("AspNetRoleClaims", (string)null);
|
b.ToTable("AspNetRoleClaims", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b =>
|
|
||||||
{
|
|
||||||
b.Property<string>("Id")
|
|
||||||
.HasColumnType("nvarchar(450)");
|
|
||||||
|
|
||||||
b.Property<int>("AccessFailedCount")
|
|
||||||
.HasColumnType("int");
|
|
||||||
|
|
||||||
b.Property<string>("ConcurrencyStamp")
|
|
||||||
.IsConcurrencyToken()
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("nvarchar(256)");
|
|
||||||
|
|
||||||
b.Property<bool>("EmailConfirmed")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<bool>("LockoutEnabled")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
|
||||||
.HasColumnType("datetimeoffset");
|
|
||||||
|
|
||||||
b.Property<string>("NormalizedEmail")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("nvarchar(256)");
|
|
||||||
|
|
||||||
b.Property<string>("NormalizedUserName")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("nvarchar(256)");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.Property<bool>("PhoneNumberConfirmed")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<string>("SecurityStamp")
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.Property<bool>("TwoFactorEnabled")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<string>("UserName")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("nvarchar(256)");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("NormalizedEmail")
|
|
||||||
.HasDatabaseName("EmailIndex");
|
|
||||||
|
|
||||||
b.HasIndex("NormalizedUserName")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("UserNameIndex")
|
|
||||||
.HasFilter("[NormalizedUserName] IS NOT NULL");
|
|
||||||
|
|
||||||
b.ToTable("AspNetUsers", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@ -236,6 +155,94 @@ namespace phronCare.API.Migrations
|
|||||||
b.ToTable("AspNetUserTokens", (string)null);
|
b.ToTable("AspNetUserTokens", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("phronCare.API.Models.Security.ApplicationUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AccessFailedCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Address")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("BirthDate")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("CompanyName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Department")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<bool>("EmailConfirmed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("FirstName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("LastName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("LockoutEnabled")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||||
|
.HasColumnType("datetimeoffset");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedEmail")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedUserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("PhoneNumberConfirmed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("ProfileImageUrl")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("SecurityStamp")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("TwoFactorEnabled")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedEmail")
|
||||||
|
.HasDatabaseName("EmailIndex");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedUserName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("UserNameIndex")
|
||||||
|
.HasFilter("[NormalizedUserName] IS NOT NULL");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUsers", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
@ -247,7 +254,7 @@ namespace phronCare.API.Migrations
|
|||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
b.HasOne("phronCare.API.Models.Security.ApplicationUser", null)
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("UserId")
|
.HasForeignKey("UserId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
@ -256,7 +263,7 @@ namespace phronCare.API.Migrations
|
|||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
b.HasOne("phronCare.API.Models.Security.ApplicationUser", null)
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("UserId")
|
.HasForeignKey("UserId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
@ -271,7 +278,7 @@ namespace phronCare.API.Migrations
|
|||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
b.HasOne("phronCare.API.Models.Security.ApplicationUser", null)
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("UserId")
|
.HasForeignKey("UserId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
@ -280,7 +287,7 @@ namespace phronCare.API.Migrations
|
|||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
b.HasOne("phronCare.API.Models.Security.ApplicationUser", null)
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("UserId")
|
.HasForeignKey("UserId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
|||||||
@ -4,9 +4,33 @@ namespace phronCare.API.Models.Authentication.SingUp
|
|||||||
{
|
{
|
||||||
public class RegisterUser
|
public class RegisterUser
|
||||||
{
|
{
|
||||||
[Required(ErrorMessage ="El Username es un dato obligatorio")] public string UserName { get; set; } = string.Empty;
|
[Required(ErrorMessage = "El Username es un dato obligatorio")]
|
||||||
[EmailAddress,Required(ErrorMessage = "El correo electronico es un dato obligatorio")] public string EmailAddress { get; set;} = string.Empty;
|
public string UserName { get; set; } = string.Empty;
|
||||||
[Required(ErrorMessage = "La contraseña es un dato obligatorio")] public string Password { get; set; } = string.Empty;
|
|
||||||
[Required(ErrorMessage = "El rol es un dato obligatorio")] public string Role { get; set; } = string.Empty;
|
[Required(ErrorMessage = "El correo electrónico es un dato obligatorio")]
|
||||||
|
[EmailAddress]
|
||||||
|
public string EmailAddress { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Required(ErrorMessage = "La contraseña es un dato obligatorio")]
|
||||||
|
public string Password { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Required(ErrorMessage = "El rol es un dato obligatorio")]
|
||||||
|
public string Role { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Required(ErrorMessage = "El nombre es obligatorio")]
|
||||||
|
public string FirstName { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Required(ErrorMessage = "El apellido es obligatorio")]
|
||||||
|
public string LastName { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public string? Address { get; set; }
|
||||||
|
public string? Department { get; set; }
|
||||||
|
public string? CompanyName { get; set; }
|
||||||
|
|
||||||
|
[DataType(DataType.Date)]
|
||||||
|
public DateTime? BirthDate { get; set; }
|
||||||
|
|
||||||
|
// Podés dejar esto para el futuro
|
||||||
|
public string? ProfileImageUrl { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
20
phronCare.API/Models/Seurity/ApplicationUser.cs
Normal file
20
phronCare.API/Models/Seurity/ApplicationUser.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
|
||||||
|
namespace phronCare.API.Models.Security
|
||||||
|
{
|
||||||
|
public class ApplicationUser : IdentityUser
|
||||||
|
{
|
||||||
|
public string FirstName { get; set; }
|
||||||
|
public string LastName { get; set; }
|
||||||
|
public string? Address { get; set; }
|
||||||
|
public string? Department { get; set; }
|
||||||
|
public string? CompanyName { get; set; }
|
||||||
|
public DateTime? BirthDate { get; set; }
|
||||||
|
|
||||||
|
// Nuevo campo para imagen
|
||||||
|
public string? ProfileImageUrl { get; set; }
|
||||||
|
|
||||||
|
// Propiedad calculada
|
||||||
|
public string FullName => $"{FirstName} {LastName}";
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,19 +1,22 @@
|
|||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using phronCare.API.Models.Security;
|
||||||
|
|
||||||
namespace phronCare.API.Models
|
namespace phronCare.API.Models
|
||||||
{
|
{
|
||||||
public class phronCareDbContext: IdentityDbContext<IdentityUser>
|
public class phronCareDbContext : IdentityDbContext<ApplicationUser>
|
||||||
{
|
{
|
||||||
public phronCareDbContext(DbContextOptions<phronCareDbContext> options):base(options)
|
public phronCareDbContext(DbContextOptions<phronCareDbContext> options) : base(options)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder builder)
|
protected override void OnModelCreating(ModelBuilder builder)
|
||||||
{
|
{
|
||||||
base.OnModelCreating(builder);
|
base.OnModelCreating(builder);
|
||||||
//SeedRoles(builder);
|
//SeedRoles(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SeedRoles(ModelBuilder modelBuilder)
|
private static void SeedRoles(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
modelBuilder.Entity<IdentityRole>().HasData
|
modelBuilder.Entity<IdentityRole>().HasData
|
||||||
@ -24,3 +27,33 @@ namespace phronCare.API.Models
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//using Microsoft.AspNetCore.Identity;
|
||||||
|
//using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||||
|
//using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
//namespace phronCare.API.Models
|
||||||
|
//{
|
||||||
|
// public class phronCareDbContext: IdentityDbContext<IdentityUser>
|
||||||
|
// {
|
||||||
|
// public phronCareDbContext(DbContextOptions<phronCareDbContext> options):base(options)
|
||||||
|
// {
|
||||||
|
// }
|
||||||
|
// protected override void OnModelCreating(ModelBuilder builder)
|
||||||
|
// {
|
||||||
|
// base.OnModelCreating(builder);
|
||||||
|
// //SeedRoles(builder);
|
||||||
|
// }
|
||||||
|
// private static void SeedRoles(ModelBuilder modelBuilder)
|
||||||
|
// {
|
||||||
|
// modelBuilder.Entity<IdentityRole>().HasData
|
||||||
|
// (
|
||||||
|
// new IdentityRole() { Name = "Administrator", ConcurrencyStamp = DateTime.Today.ToString(), NormalizedName = "administrator" },
|
||||||
|
// new IdentityRole() { Name = "User", ConcurrencyStamp = DateTime.Today.ToString(), NormalizedName = "user" }
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|||||||
@ -1,22 +1,23 @@
|
|||||||
using Core.Interfaces;
|
|
||||||
using Core.Services;
|
|
||||||
using Google.Authenticator;
|
using Google.Authenticator;
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
|
using Models.Repositories;
|
||||||
using Models.Interfaces;
|
using Models.Interfaces;
|
||||||
using Models.Models;
|
using Models.Models;
|
||||||
using Models.Repositories;
|
|
||||||
using phronCare.API.Models;
|
|
||||||
using Services.Models;
|
|
||||||
using Services.Services;
|
|
||||||
using Services.Interfaces;
|
using Services.Interfaces;
|
||||||
|
using Services.Services;
|
||||||
|
using Services.Models;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Infrastructure.Repositories.Patients;
|
using Infrastructure.Repositories.Patients;
|
||||||
using PhronCare.Core.Services.Sales;
|
|
||||||
using PhronCare.Core.Data.Repositories.Sales;
|
using PhronCare.Core.Data.Repositories.Sales;
|
||||||
|
using PhronCare.Core.Services.Sales;
|
||||||
|
using phronCare.API.Models.Security;
|
||||||
|
using phronCare.API.Models;
|
||||||
|
using Core.Interfaces;
|
||||||
|
using Core.Services;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
@ -34,54 +35,7 @@ builder.Services.AddDbContext<PhronCareOperationsHubContext>(options =>
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Repositorios y Servicios
|
#region Repositorios y Servicios
|
||||||
builder.Services.AddScoped<ITicketDom, TicketService>();
|
RepositorysAndServices(builder);
|
||||||
builder.Services.AddScoped<ITicketRepository, TicketRepository>();
|
|
||||||
|
|
||||||
builder.Services.AddScoped<IAccountTypeDom, AccountTypeService>();
|
|
||||||
builder.Services.AddScoped<IPhSAccountTypeRepository, PhSAccountTypeRepository>();
|
|
||||||
|
|
||||||
builder.Services.AddScoped<ITaxConditionDom, TaxConditionService>();
|
|
||||||
builder.Services.AddScoped<IPhSTaxConditionRepository, PhOhTaxConditionRepository>();
|
|
||||||
|
|
||||||
builder.Services.AddScoped<IDocumentTypeDom, DocumentTypeService>();
|
|
||||||
builder.Services.AddScoped<IPhSDocumentTypeRepository, PhSDocumentTypeRepository>();
|
|
||||||
|
|
||||||
builder.Services.AddScoped<ICustomerDom, CustomerService>();
|
|
||||||
builder.Services.AddScoped<IPhSCustomerRepository, PhSCustomerRepository>();
|
|
||||||
|
|
||||||
builder.Services.AddScoped<IProductDom, ProductService>();
|
|
||||||
builder.Services.AddScoped<IPhSProductRepository, PhSProductRepository>();
|
|
||||||
|
|
||||||
builder.Services.AddScoped<ICustomerDom, CustomerService>();
|
|
||||||
builder.Services.AddScoped<IPhSCustomerRepository, PhSCustomerRepository>();
|
|
||||||
|
|
||||||
builder.Services.AddScoped<IProductCategoryDom, ProductCategoryService>();
|
|
||||||
builder.Services.AddScoped<IPhSProductCategoryRepository, PhSProductCategoryRepository>();
|
|
||||||
|
|
||||||
builder.Services.AddScoped<IBusinessUnitDom, BusinessUnitService>();
|
|
||||||
builder.Services.AddScoped<IPhSBusinessUnitRepository, PhSBusinessUnitRepository>();
|
|
||||||
|
|
||||||
builder.Services.AddScoped<IPatientDom, PatientService>();
|
|
||||||
builder.Services.AddScoped<IPhSPatientRepository, PhSPatientRepository>();
|
|
||||||
|
|
||||||
builder.Services.AddScoped<IProfessionalSpecialtyDom, ProfessionalSpecialtyService>();
|
|
||||||
builder.Services.AddScoped<IPhSProfessionalSpecialtyRepository, PhSProfessionalSpecialtyRepository>();
|
|
||||||
|
|
||||||
builder.Services.AddScoped<IProfessionalDom, ProfessionalService>();
|
|
||||||
builder.Services.AddScoped<IPhSProfessionalRepository, PhSProfessionalRepository>();
|
|
||||||
|
|
||||||
builder.Services.AddScoped<IInstitutionDom, InstitutionService>();
|
|
||||||
builder.Services.AddScoped<IPhSInstitutionRepository, PhSInstitutionRepository>();
|
|
||||||
|
|
||||||
builder.Services.AddScoped<IPeopleDom, PeopleService>();
|
|
||||||
builder.Services.AddScoped<IPhSPeopleRepository, PhSPeopleRepository>();
|
|
||||||
|
|
||||||
builder.Services.AddScoped<IQuoteDom, QuoteService>();
|
|
||||||
|
|
||||||
builder.Services.AddScoped<IPhSQuoteHeaderRepository, PhSQuoteHeaderRepository>();
|
|
||||||
builder.Services.AddScoped<IPhSQuoteDetailRepository, PhSQuoteDetailRepository>();
|
|
||||||
builder.Services.AddScoped<IPhSQuoteRoleRepository, PhSQuoteRoleRepository>();
|
|
||||||
builder.Services.AddScoped<IPhSFormSeriesRepository, PhSFormSeriesRepository>();
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -90,23 +44,34 @@ builder.Services.Configure<IdentityOptions>(opts => opts.SignIn.RequireConfirmed
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Security Identity EF Configuration
|
#region Security Identity EF Configuration
|
||||||
builder.Services.AddIdentity<IdentityUser, IdentityRole>()
|
builder.Services.AddIdentity<ApplicationUser, IdentityRole>()
|
||||||
.AddEntityFrameworkStores<phronCareDbContext>()
|
.AddEntityFrameworkStores<phronCareDbContext>()
|
||||||
.AddDefaultTokenProviders();
|
.AddDefaultTokenProviders();
|
||||||
builder.Services.Configure<DataProtectionTokenProviderOptions>( opts => opts.TokenLifespan=TimeSpan.FromHours(10));
|
|
||||||
|
builder.Services.Configure<DataProtectionTokenProviderOptions>(opts =>
|
||||||
|
opts.TokenLifespan = TimeSpan.FromHours(10));
|
||||||
|
|
||||||
builder.Services.AddSingleton<TwoFactorAuthenticator>();
|
builder.Services.AddSingleton<TwoFactorAuthenticator>();
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
//#region Security Identity EF Configuration
|
||||||
|
//builder.Services.AddIdentity<IdentityUser, IdentityRole>()
|
||||||
|
// .AddEntityFrameworkStores<phronCareDbContext>()
|
||||||
|
// .AddDefaultTokenProviders();
|
||||||
|
//builder.Services.Configure<DataProtectionTokenProviderOptions>( opts => opts.TokenLifespan=TimeSpan.FromHours(10));
|
||||||
|
//builder.Services.AddSingleton<TwoFactorAuthenticator>();
|
||||||
|
//#endregion
|
||||||
|
|
||||||
#region Authentication Service
|
#region Authentication Service
|
||||||
|
|
||||||
builder.Services.AddAuthentication(options =>
|
builder.Services.AddAuthentication(options =>
|
||||||
{
|
{
|
||||||
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme;
|
options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
|
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
}).AddJwtBearer(options =>
|
}).AddJwtBearer(options =>
|
||||||
{
|
{
|
||||||
options.Audience = configuration["JWT:ValidAudience"];
|
options.Audience = configuration["JWT:ValidAudience"];
|
||||||
options.RequireHttpsMetadata = false;
|
options.RequireHttpsMetadata = false;
|
||||||
options.SaveToken = true;
|
options.SaveToken = true;
|
||||||
@ -132,7 +97,7 @@ builder.Services.AddAuthentication(options =>
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Email Configuration
|
#region Email Configuration
|
||||||
@ -216,8 +181,8 @@ var app = builder.Build();
|
|||||||
|
|
||||||
//if (app.Environment.IsDevelopment())
|
//if (app.Environment.IsDevelopment())
|
||||||
//{
|
//{
|
||||||
app.UseSwagger();
|
app.UseSwagger();
|
||||||
app.UseSwaggerUI();
|
app.UseSwaggerUI();
|
||||||
//}
|
//}
|
||||||
|
|
||||||
app.UseCors("CORS");
|
app.UseCors("CORS");
|
||||||
@ -227,3 +192,55 @@ app.UseHttpsRedirection();
|
|||||||
app.MapControllers();
|
app.MapControllers();
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
|
|
||||||
|
static void RepositorysAndServices(WebApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
builder.Services.AddScoped<ITicketDom, TicketService>();
|
||||||
|
builder.Services.AddScoped<ITicketRepository, TicketRepository>();
|
||||||
|
|
||||||
|
builder.Services.AddScoped<IAccountTypeDom, AccountTypeService>();
|
||||||
|
builder.Services.AddScoped<IPhSAccountTypeRepository, PhSAccountTypeRepository>();
|
||||||
|
|
||||||
|
builder.Services.AddScoped<ITaxConditionDom, TaxConditionService>();
|
||||||
|
builder.Services.AddScoped<IPhSTaxConditionRepository, PhOhTaxConditionRepository>();
|
||||||
|
|
||||||
|
builder.Services.AddScoped<IDocumentTypeDom, DocumentTypeService>();
|
||||||
|
builder.Services.AddScoped<IPhSDocumentTypeRepository, PhSDocumentTypeRepository>();
|
||||||
|
|
||||||
|
builder.Services.AddScoped<ICustomerDom, CustomerService>();
|
||||||
|
builder.Services.AddScoped<IPhSCustomerRepository, PhSCustomerRepository>();
|
||||||
|
|
||||||
|
builder.Services.AddScoped<IProductDom, ProductService>();
|
||||||
|
builder.Services.AddScoped<IPhSProductRepository, PhSProductRepository>();
|
||||||
|
|
||||||
|
builder.Services.AddScoped<ICustomerDom, CustomerService>();
|
||||||
|
builder.Services.AddScoped<IPhSCustomerRepository, PhSCustomerRepository>();
|
||||||
|
|
||||||
|
builder.Services.AddScoped<IProductCategoryDom, ProductCategoryService>();
|
||||||
|
builder.Services.AddScoped<IPhSProductCategoryRepository, PhSProductCategoryRepository>();
|
||||||
|
|
||||||
|
builder.Services.AddScoped<IBusinessUnitDom, BusinessUnitService>();
|
||||||
|
builder.Services.AddScoped<IPhSBusinessUnitRepository, PhSBusinessUnitRepository>();
|
||||||
|
|
||||||
|
builder.Services.AddScoped<IPatientDom, PatientService>();
|
||||||
|
builder.Services.AddScoped<IPhSPatientRepository, PhSPatientRepository>();
|
||||||
|
|
||||||
|
builder.Services.AddScoped<IProfessionalSpecialtyDom, ProfessionalSpecialtyService>();
|
||||||
|
builder.Services.AddScoped<IPhSProfessionalSpecialtyRepository, PhSProfessionalSpecialtyRepository>();
|
||||||
|
|
||||||
|
builder.Services.AddScoped<IProfessionalDom, ProfessionalService>();
|
||||||
|
builder.Services.AddScoped<IPhSProfessionalRepository, PhSProfessionalRepository>();
|
||||||
|
|
||||||
|
builder.Services.AddScoped<IInstitutionDom, InstitutionService>();
|
||||||
|
builder.Services.AddScoped<IPhSInstitutionRepository, PhSInstitutionRepository>();
|
||||||
|
|
||||||
|
builder.Services.AddScoped<IPeopleDom, PeopleService>();
|
||||||
|
builder.Services.AddScoped<IPhSPeopleRepository, PhSPeopleRepository>();
|
||||||
|
|
||||||
|
builder.Services.AddScoped<IQuoteDom, QuoteService>();
|
||||||
|
|
||||||
|
builder.Services.AddScoped<IPhSQuoteHeaderRepository, PhSQuoteHeaderRepository>();
|
||||||
|
builder.Services.AddScoped<IPhSQuoteDetailRepository, PhSQuoteDetailRepository>();
|
||||||
|
builder.Services.AddScoped<IPhSQuoteRoleRepository, PhSQuoteRoleRepository>();
|
||||||
|
builder.Services.AddScoped<IPhSFormSeriesRepository, PhSFormSeriesRepository>();
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user