Files
OpenWarehouse/OpenWarehouse.auth.api/Controller/Auth.cs
T
2025-02-26 23:42:19 +01:00

226 lines
9.5 KiB
C#

using System.Net.Mime;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using OpenWarehouse.auth.api.Common.AuthTokenRepo;
using OpenWarehouse.auth.api.Common.CustomIdentifyManager;
using OpenWarehouse.auth.api.Common.RegisterTokenManager;
using OpenWarehouse.auth.lib.Model.Account;
using OpenWarehouse.auth.lib.Model.Auth;
namespace OpenWarehouse.auth.api.Controller;
[ApiController]
[Route("[action]")]
public class Auth(
SignInManager<ApplicationUser> signInManager, UserManager<ApplicationUser> userManager,
AuthTokenRepo tokenRepo, ApplicationDbContext applicationDbContext,
RegisterTokenManager registerTokenManager,
ILogger<Auth> logger) : ControllerBase
{
[HttpPost]
[Consumes(MediaTypeNames.Application.Json, MediaTypeNames.Application.Xml)]
public async Task<ActionResult<LoginModel>> Login([FromBody] LoginRequestModel requestModel)
{
logger.LogInformation("Login request received for user: {Login}", requestModel.Login);
if (requestModel.Pass == null || requestModel.Login == null)
{
logger.LogWarning("Invalid login request model.");
return BadRequest("Invalid request model.");
}
var loginModel = new LoginModel();
if (requestModel.Pass == null)
{
loginModel.AccountProblem = "Login and password are required.";
logger.LogWarning("Password is missing in the login request for user: {Login}", requestModel.Login);
return BadRequest(loginModel);
}
var applicationUser = await userManager.FindByNameAsync(requestModel.Login)
?? await userManager.FindByEmailAsync(requestModel.Login);
if (applicationUser == null)
{
logger.LogWarning("User not found for login: {Login}", requestModel.Login);
loginModel.Message = "Incorrect login or password.";
return Unauthorized(loginModel);
}
loginModel.Login = applicationUser.UserName;
loginModel.Email = applicationUser.Email;
var claims = await userManager.GetClaimsAsync(applicationUser);
if (claims.Any(claim => claim.Type.Equals(AccountType.Service.GetValue())))
{
logger.LogWarning("Service account attempted to login: {Login}", requestModel.Login);
return Forbid("This is a service account.");
}
if (applicationUser.LockoutEnabled)
{
logger.LogWarning("Locked account attempted to login: {Login}", requestModel.Login);
return Forbid("Account is locked.");
}
var signInResult = await signInManager.CheckPasswordSignInAsync(applicationUser, requestModel.Pass, false);
if (signInResult.Succeeded)
{
// var expiration = DateTime.UtcNow.AddHours(1);
var expiration = DateTime.UtcNow.AddMinutes(30);
loginModel.Token = await tokenRepo.CreateJwtToken(applicationUser, expiration, null);
loginModel.Exp = expiration.ToBinary();
loginModel.IsLogged = true;
logger.LogInformation("User logged in successfully: {Login}", requestModel.Login);
return Ok(loginModel);
}
if (signInResult.RequiresTwoFactor)
{
logger.LogInformation("Two-factor authentication required for user: {Login}", requestModel.Login);
loginModel.Message = "Two-factor authentication is required.";
loginModel.RequiresTwoFactor = true;
return Ok(loginModel);
}
logger.LogWarning("Incorrect login or password for user: {Login}", requestModel.Login);
loginModel.Message = "Incorrect login or password.";
return Unauthorized(loginModel);
}
[HttpPost]
[Consumes(MediaTypeNames.Application.Json, otherContentTypes: [MediaTypeNames.Application.Xml])]
public async Task<ActionResult<RegisterReturnModel>> Register([FromBody]RegisterModel registerModel)
{
logger.LogInformation("Registration request received for user: {Username}", registerModel.Username);
var registerReturnModel = new RegisterReturnModel();
registerReturnModel.IsCreated = true;
if (registerModel.Username != null)
{
var user = new ApplicationUser(registerModel.Username);
user.Email = registerModel.Email;
if (registerModel.RegisterToken != null)
{
var regToken = await registerTokenManager.GetToken(registerModel.RegisterToken);
if (regToken == null)
{
logger.LogWarning("Registration token not found: {RegisterToken}", registerModel.RegisterToken);
registerReturnModel.IsCreated = false;
registerReturnModel.ProblemWithToken = "Token Not found;";
return Unauthorized(registerReturnModel);
}
if (regToken.IsUsed)
{
logger.LogWarning("Registration token already used: {RegisterToken}", registerModel.RegisterToken);
registerReturnModel.IsCreated = false;
registerReturnModel.ProblemWithToken = "Token is alleredy used;";
}
if (( registerModel.Password ?? "" ).Length > 6)
{
registerReturnModel.IsCreated = false;
}
if (!registerReturnModel.IsCreated) return Unauthorized(registerReturnModel);
if (registerModel.Password != null)
{
var result = await userManager.CreateAsync(user, registerModel.Password);
var resultClaim = await userManager.AddClaimAsync(user, AccountType.User.Claim());
if (result.Succeeded && resultClaim.Succeeded)
{
regToken.IsUsed = true;
await applicationDbContext.SaveChangesAsync();
registerReturnModel.AuthToken =
await tokenRepo.CreateJwtToken(user, DateTime.UtcNow.AddHours(1), null);
logger.LogInformation("User registered successfully: {Username}", registerModel.Username);
}
else
{
foreach (var error in result.Errors)
{
logger.LogError("Error during user registration: {Code} - {Description}", error.Code, error.Description);
registerReturnModel.OtherWithOtherProblem += error.Code + "-" + error.Description + ";";
return Unauthorized(registerReturnModel);
}
}
}
}
else
{
logger.LogWarning("Registration token is required but missing for user: {Username}", registerModel.Username);
return BadRequest("Token are required.");
}
}
return Ok(registerReturnModel);
}
[HttpGet]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public async Task<LogOutModel> LogOut()
{
logger.LogInformation("Logout request received.");
if (Request.Headers.TryGetValue("Authorization", out var token))
{
var tokenStr = token.ToString();
string?[] tokenSplit = tokenStr.Split(" ");
if (tokenSplit.Length > 0) tokenStr = tokenSplit[1];
if (await tokenRepo.LockTokenAsync(tokenStr) > 0)
{
logger.LogInformation("User logged out successfully.");
return new LogOutModel(true, "Logout successful");
}
}
logger.LogWarning("Logout failed due to missing or invalid token.");
return new LogOutModel(false, "Logout Fail");
}
[HttpGet]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public async Task<ActionResult<RegeneratedTokenModel>> RegenerateToken()
{
logger.LogInformation("Token regeneration request received.");
Request.Headers.TryGetValue("Authorization", out var token);
token = token.ToString().Split(" ")[1];
var newTokenStr = await tokenRepo.RegenerateJwtToken(token, DateTime.UtcNow.AddMinutes(30));
logger.LogInformation("Token regenerated successfully");
var respond = new RegeneratedTokenModel()
{
Mess = newTokenStr != null ? "Regeneration success" : "Regeneration fail",
Token = newTokenStr
};
return Ok(respond);
}
[HttpDelete]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[HasPrivilege(GlobalPrivilage.Privilege.GlobalDeleteExpiredToken)]
public async Task<ActionResult<int>> DeleteExpiredToken()
{
logger.LogInformation("Delete expired tokens request received.");
return Ok(await tokenRepo.DeleteInactiveToken());
}
[HttpPost]
public async Task<ActionResult<bool>> TokenIsLock([FromBody] TokenAskIfIsLockModel req)
{
logger.LogInformation("Check if token is locked request received.");
return Ok(await tokenRepo.IsTokenLockAsync(req.Token));
}
}