using System.Security.Authentication; using MesaFabApproval.Shared.Models; using MesaFabApproval.Shared.Services; using MesaFabApprovalAPI.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace MesaFabApproval.API.Controllers; [ApiController] public class AuthenticationController : ControllerBase { private readonly ILogger _logger; private readonly IMonInWorkerClient _monInClient; private readonly IAuthenticationService _authenticationService; public AuthenticationController(ILogger logger, IMonInWorkerClient monInClient, IAuthenticationService authenticationService) { _logger = logger ?? throw new ArgumentNullException("ILogger not injected"); _monInClient = monInClient ?? throw new ArgumentNullException("IMonInWorkerClient not injected"); _authenticationService = authenticationService ?? throw new ArgumentNullException("IAuthenticationService not injected"); } [HttpPost] [AllowAnonymous] [Route("auth/login")] public async Task Login(AuthAttempt login) { DateTime start = DateTime.Now; bool isArgumentError = false; bool isInternalError = false; string errorMessage = ""; try { _logger.LogInformation("Attempting to perform authentication"); if (login is null) throw new ArgumentNullException("Login cannot be null"); LoginResult loginResult = await _authenticationService.AuthenticateUser(login); if (loginResult.IsAuthenticated) return Ok(loginResult); return Unauthorized(); } catch (ArgumentException ex) { isArgumentError = true; errorMessage = $"Invalid argument. {ex.Message}"; return BadRequest(errorMessage); } catch (Exception ex) { isInternalError = true; errorMessage = $"Cannot authenticate user, because {ex.Message}"; return Problem(errorMessage); } finally { string metricName = "Login"; DateTime end = DateTime.Now; double millisecondsDiff = (end - start).TotalMilliseconds; _monInClient.PostAverage(metricName + "Latency", millisecondsDiff); if (isArgumentError) { _logger.LogWarning(errorMessage); _monInClient.PostStatus(metricName, StatusValue.Ok); } else if (isInternalError) { _logger.LogError(errorMessage); _monInClient.PostStatus(metricName, StatusValue.Critical); } else { _monInClient.PostStatus(metricName, StatusValue.Ok); } } } [HttpPost] [AllowAnonymous] [Route("auth/refresh")] public async Task Refresh(AuthAttempt authAttempt) { DateTime start = DateTime.Now; bool isArgumentError = false; bool isInternalError = false; string errorMessage = ""; try { _logger.LogInformation("Attempting to refresh auth tokens"); if (authAttempt is null) throw new ArgumentNullException("AuthAttempt cannot be null"); if (authAttempt.AuthTokens is null) throw new ArgumentNullException("AuthTokens cannot be null"); LoginResult loginResult = await _authenticationService.RefreshAuthTokens(authAttempt); return Ok(loginResult); } catch (ArgumentException ex) { isArgumentError = true; errorMessage = $"Invalid argument. {ex.Message}"; return BadRequest(errorMessage); } catch (AuthenticationException ex) { _logger.LogInformation($"Unable to refresh tokens, because {ex.Message}"); return Unauthorized(); } catch (Exception ex) { isArgumentError = true; errorMessage = $"Cannot authenticate user, because {ex.Message}"; return Problem(errorMessage); } finally { string metricName = "RefreshTokens"; DateTime end = DateTime.Now; double millisecondsDiff = (end - start).TotalMilliseconds; _monInClient.PostAverage(metricName + "Latency", millisecondsDiff); if (isArgumentError) { _logger.LogWarning(errorMessage); _monInClient.PostStatus(metricName, StatusValue.Ok); } else if (isInternalError) { _logger.LogError(errorMessage); _monInClient.PostStatus(metricName, StatusValue.Critical); } else { _monInClient.PostStatus(metricName, StatusValue.Ok); } } } }