MRB webassembly
This commit is contained in:
13
MesaFabApproval.API/.config/dotnet-tools.json
Normal file
13
MesaFabApproval.API/.config/dotnet-tools.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"dotnet-ef": {
|
||||
"version": "8.0.6",
|
||||
"commands": [
|
||||
"dotnet-ef"
|
||||
],
|
||||
"rollForward": false
|
||||
}
|
||||
}
|
||||
}
|
20
MesaFabApproval.API/Clients/SmtpClientWrapper.cs
Normal file
20
MesaFabApproval.API/Clients/SmtpClientWrapper.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System.Net.Mail;
|
||||
|
||||
namespace MesaFabApproval.API.Clients;
|
||||
|
||||
public interface ISmtpClientWrapper {
|
||||
void Send(MailMessage message);
|
||||
}
|
||||
|
||||
public class SmtpClientWrapper : ISmtpClientWrapper {
|
||||
private SmtpClient _client;
|
||||
|
||||
public SmtpClientWrapper(SmtpClient client) {
|
||||
_client = client ??
|
||||
throw new ArgumentNullException("SmtpClient not injected");
|
||||
}
|
||||
|
||||
public void Send(MailMessage message) {
|
||||
_client.Send(message);
|
||||
}
|
||||
}
|
401
MesaFabApproval.API/Controllers/ApprovalController.cs
Normal file
401
MesaFabApproval.API/Controllers/ApprovalController.cs
Normal file
@ -0,0 +1,401 @@
|
||||
using MesaFabApproval.API.Services;
|
||||
using MesaFabApproval.Shared.Models;
|
||||
using MesaFabApproval.Shared.Services;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace MesaFabApproval.API.Controllers;
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class ApprovalController : ControllerBase {
|
||||
private readonly ILogger<ApprovalController> _logger;
|
||||
private readonly IApprovalService _approvalService;
|
||||
private readonly IMonInWorkerClient _monInClient;
|
||||
|
||||
public ApprovalController(ILogger<ApprovalController> logger, IApprovalService approvalService,
|
||||
IMonInWorkerClient monInClient) {
|
||||
_logger = logger ?? throw new ArgumentNullException("ILogger not injected");
|
||||
_approvalService = approvalService ?? throw new ArgumentNullException("IApprovalService not injected");
|
||||
_monInClient = monInClient ?? throw new ArgumentNullException("IMonInWorkerClient not injected");
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("approval")]
|
||||
public async Task<IActionResult> CreateApproval(Approval approval) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to generate a new approval");
|
||||
|
||||
if (approval is null) throw new ArgumentNullException("Approval cannot be null");
|
||||
|
||||
await _approvalService.CreateApproval(approval);
|
||||
|
||||
return Ok();
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot create new approval, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "CreateApproval";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("approval/issue")]
|
||||
public async Task<IActionResult> GetApprovalsForIssueId(int issueId, bool bypassCache) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to get approvals for issue {issueId}");
|
||||
|
||||
if (issueId <= 0) throw new ArgumentException($"{issueId} is not a valid issue ID");
|
||||
|
||||
IEnumerable<Approval> approvals = await _approvalService.GetApprovalsForIssueId(issueId, bypassCache);
|
||||
|
||||
return Ok(approvals);
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot get approvals, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "GetApprovalsForIssueId";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("approval/user")]
|
||||
public async Task<IActionResult> GetApprovalsForUserId(int userId, bool bypassCache) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to get approvals for user ID {userId}");
|
||||
|
||||
if (userId <= 0) throw new ArgumentException($"{userId} is not a valid user ID");
|
||||
|
||||
IEnumerable<Approval> approvals = await _approvalService.GetApprovalsForUserId(userId, bypassCache);
|
||||
|
||||
return Ok(approvals);
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot get approvals, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "GetApprovalsForUserId";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("approval/members")]
|
||||
public async Task<IActionResult> GetApprovalGroupMembers(int subRoleId) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to get approval group members for group {subRoleId}");
|
||||
|
||||
if (subRoleId <= 0) throw new ArgumentException($"{subRoleId} is not a valid sub role ID");
|
||||
|
||||
IEnumerable<User> members = await _approvalService.GetApprovalGroupMembers(subRoleId);
|
||||
|
||||
return Ok(members);
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot get approval group members, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "GetApprovalsGroupMembers";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPut]
|
||||
[Route("approval")]
|
||||
public async Task<IActionResult> UpdateApproval(Approval approval) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to update approval");
|
||||
|
||||
if (approval is null) throw new ArgumentNullException($"approval cannot be null");
|
||||
|
||||
await _approvalService.UpdateApproval(approval);
|
||||
|
||||
return Ok();
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot update approval, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "UpdateApproval";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPut]
|
||||
[Route("approval/approve")]
|
||||
public async Task<IActionResult> Approve(Approval approval) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation($"attempting to submit approval");
|
||||
|
||||
if (approval is null) throw new ArgumentNullException($"approval cannot be null");
|
||||
|
||||
await _approvalService.Approve(approval);
|
||||
|
||||
return Ok();
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot approve, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "Approve";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPut]
|
||||
[Route("approval/deny")]
|
||||
public async Task<IActionResult> Deny(Approval approval) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation($"attempting to deny approval");
|
||||
|
||||
if (approval is null) throw new ArgumentNullException($"approval cannot be null");
|
||||
|
||||
await _approvalService.Deny(approval);
|
||||
|
||||
return Ok();
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Approval denial failed, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "Deny";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("approval/roleId")]
|
||||
public async Task<IActionResult> GetRoleIdForRoleName(string roleName) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to get role ID by role name");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(roleName)) throw new ArgumentException("role name cannot be null or empty");
|
||||
|
||||
int roleId = await _approvalService.GetRoleIdForRoleName(roleName);
|
||||
|
||||
return Ok(roleId);
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot get role ID, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "GetRoleIdForRoleName";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("approval/subRoles")]
|
||||
public async Task<IActionResult> GetSubRolesForSubRoleName(string subRoleName, int roleId) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to get sub roles by sub role name");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(subRoleName)) throw new ArgumentException("sub role name cannot be null or empty");
|
||||
if (roleId <= 0) throw new ArgumentException($"{roleId} is not a valid role ID");
|
||||
|
||||
IEnumerable<SubRole> subRoles = await _approvalService.GetSubRolesForSubRoleName(subRoleName, roleId);
|
||||
|
||||
return Ok(subRoles);
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot get role ID, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "GetSubRoleIdForSubRoleName";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
178
MesaFabApproval.API/Controllers/AuthenticationController.cs
Normal file
178
MesaFabApproval.API/Controllers/AuthenticationController.cs
Normal file
@ -0,0 +1,178 @@
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Principal;
|
||||
|
||||
using MesaFabApproval.Shared.Models;
|
||||
using MesaFabApproval.Shared.Services;
|
||||
|
||||
using MesaFabApprovalAPI.Services;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace MesaFabApproval.API.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[AllowAnonymous]
|
||||
public class AuthenticationController : ControllerBase {
|
||||
private readonly ILogger<AuthenticationController> _logger;
|
||||
private readonly IMonInWorkerClient _monInClient;
|
||||
private readonly IAuthenticationService _authenticationService;
|
||||
|
||||
public AuthenticationController(ILogger<AuthenticationController> 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]
|
||||
[Route("auth/login")]
|
||||
public async Task<IActionResult> 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]
|
||||
[Route("auth/login/localWindows")]
|
||||
public async Task<IActionResult> LoginLocalWindows(WindowsIdentity identity) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to perform local Windows authentication");
|
||||
|
||||
if (identity is null) throw new ArgumentNullException("identity cannot be null");
|
||||
|
||||
LoginResult loginResult = await _authenticationService.AttemptLocalUserAuth(identity);
|
||||
|
||||
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 local Windows user, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "LoginLocalWindows";
|
||||
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]
|
||||
[Route("auth/refresh")]
|
||||
public async Task<IActionResult> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpOptions]
|
||||
[Route("auth/refresh")]
|
||||
public IActionResult RefreshOptions() {
|
||||
try {
|
||||
_logger.LogInformation("Auth refresh options");
|
||||
|
||||
return Ok();
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Error in auth refresh options. Exception: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
56
MesaFabApproval.API/Controllers/CAController.cs
Normal file
56
MesaFabApproval.API/Controllers/CAController.cs
Normal file
@ -0,0 +1,56 @@
|
||||
using MesaFabApproval.API.Services;
|
||||
using MesaFabApproval.Shared.Models;
|
||||
using MesaFabApproval.Shared.Services;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace MesaFabApproval.API.Controllers;
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class CAController : ControllerBase {
|
||||
private readonly ILogger<ApprovalController> _logger;
|
||||
private readonly ICAService _caService;
|
||||
private readonly IMonInWorkerClient _monInClient;
|
||||
|
||||
public CAController(ILogger<ApprovalController> logger, ICAService caService,
|
||||
IMonInWorkerClient monInClient) {
|
||||
_logger = logger ?? throw new ArgumentNullException("ILogger not injected");
|
||||
_caService = caService ?? throw new ArgumentNullException("ICAService not injected");
|
||||
_monInClient = monInClient ?? throw new ArgumentNullException("IMonInWorkerClient not injected");
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("ca/isValidCANumber")]
|
||||
public async Task<IActionResult> IsValidCANumber(int number) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to determine if {number} is a valid CA#");
|
||||
|
||||
if (number <= 0) return Ok(false);
|
||||
|
||||
bool isValid = await _caService.IsValidCANumber(number);
|
||||
|
||||
return Ok(isValid);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot determine if {number} is a valid CA#, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "IsValidCANumber";
|
||||
DateTime end = DateTime.Now;
|
||||
double millisecondsDiff = (end - start).TotalMilliseconds;
|
||||
_monInClient.PostAverage(metricName + "Latency", millisecondsDiff);
|
||||
|
||||
if (isInternalError) {
|
||||
_logger.LogError(errorMessage);
|
||||
_monInClient.PostStatus(metricName, StatusValue.Critical);
|
||||
} else {
|
||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
57
MesaFabApproval.API/Controllers/CustomerController.cs
Normal file
57
MesaFabApproval.API/Controllers/CustomerController.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using MesaFabApproval.API.Services;
|
||||
using MesaFabApproval.Shared.Models;
|
||||
using MesaFabApproval.Shared.Services;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace MesaFabApproval.API.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class CustomerController : ControllerBase {
|
||||
private readonly ILogger<CustomerController> _logger;
|
||||
private readonly IMonInWorkerClient _monInClient;
|
||||
private readonly IMemoryCache _cache;
|
||||
private readonly ICustomerService _customerService;
|
||||
|
||||
public CustomerController(ILogger<CustomerController> logger, IMonInWorkerClient monInClient, IMemoryCache cache, ICustomerService customerService) {
|
||||
_logger = logger ?? throw new ArgumentNullException("ILogger not injected");
|
||||
_monInClient = monInClient ?? throw new ArgumentNullException("IMonInWorkerClient not injected");
|
||||
_cache = cache ?? throw new ArgumentNullException("IMemoryCache not injected");
|
||||
_customerService = customerService ?? throw new ArgumentNullException("ICustomerService");
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("customer/all")]
|
||||
public async Task<IActionResult> GetAllCustomerNames() {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get all customer names");
|
||||
|
||||
IEnumerable<string> customerNames = await _customerService.GetCustomerNames();
|
||||
|
||||
return Ok(customerNames);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot get user by LoginID, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "GetAllCustomerNames";
|
||||
DateTime end = DateTime.Now;
|
||||
double millisecondsDiff = (end - start).TotalMilliseconds;
|
||||
_monInClient.PostAverage(metricName + "Latency", millisecondsDiff);
|
||||
|
||||
if (isInternalError) {
|
||||
_logger.LogError(errorMessage);
|
||||
_monInClient.PostStatus(metricName, StatusValue.Critical);
|
||||
} else {
|
||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
56
MesaFabApproval.API/Controllers/ECNController.cs
Normal file
56
MesaFabApproval.API/Controllers/ECNController.cs
Normal file
@ -0,0 +1,56 @@
|
||||
using MesaFabApproval.API.Services;
|
||||
using MesaFabApproval.Shared.Models;
|
||||
using MesaFabApproval.Shared.Services;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace MesaFabApproval.API.Controllers;
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class ECNController : ControllerBase {
|
||||
private readonly ILogger<ApprovalController> _logger;
|
||||
private readonly IECNService _ecnService;
|
||||
private readonly IMonInWorkerClient _monInClient;
|
||||
|
||||
public ECNController(ILogger<ApprovalController> logger, IECNService ecnService,
|
||||
IMonInWorkerClient monInClient) {
|
||||
_logger = logger ?? throw new ArgumentNullException("ILogger not injected");
|
||||
_ecnService = ecnService ?? throw new ArgumentNullException("IECNService not injected");
|
||||
_monInClient = monInClient ?? throw new ArgumentNullException("IMonInWorkerClient not injected");
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("ecn/isValidEcnNumber")]
|
||||
public async Task<IActionResult> IsValidEcnNumber(int number) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to determine if {number} is a valid ECN#");
|
||||
|
||||
if (number <= 0) return Ok(false);
|
||||
|
||||
bool isValid = await _ecnService.IsValidECNNumber(number);
|
||||
|
||||
return Ok(isValid);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot determine if {number} is a valid ECN#, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "IsValidEcnNumber";
|
||||
DateTime end = DateTime.Now;
|
||||
double millisecondsDiff = (end - start).TotalMilliseconds;
|
||||
_monInClient.PostAverage(metricName + "Latency", millisecondsDiff);
|
||||
|
||||
if (isInternalError) {
|
||||
_logger.LogError(errorMessage);
|
||||
_monInClient.PostStatus(metricName, StatusValue.Critical);
|
||||
} else {
|
||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
910
MesaFabApproval.API/Controllers/MRBController.cs
Normal file
910
MesaFabApproval.API/Controllers/MRBController.cs
Normal file
@ -0,0 +1,910 @@
|
||||
using MesaFabApproval.API.Services;
|
||||
using MesaFabApproval.Shared.Models;
|
||||
using MesaFabApproval.Shared.Services;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
|
||||
namespace MesaFabApproval.API.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class MRBController : ControllerBase {
|
||||
private readonly ILogger<MRBController> _logger;
|
||||
private readonly IMRBService _mrbService;
|
||||
private readonly IMonInWorkerClient _monInClient;
|
||||
|
||||
public MRBController(ILogger<MRBController> logger, IMRBService mrbService, IMonInWorkerClient monInClient) {
|
||||
_logger = logger ?? throw new ArgumentNullException("ILogger not injected");
|
||||
_mrbService = mrbService ?? throw new ArgumentNullException("IMRBService not injected");
|
||||
_monInClient = monInClient ?? throw new ArgumentNullException("IMonInWorkerClient not injected");
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("mrb/new")]
|
||||
public async Task<IActionResult> CreateNewMRB(MRB mrb) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to generate a new MRB");
|
||||
|
||||
if (mrb is null) throw new ArgumentNullException("MRB cannot be null");
|
||||
|
||||
await _mrbService.CreateNewMRB(mrb);
|
||||
|
||||
return Ok();
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot create new MRB, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "CreateNewMRB";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpDelete]
|
||||
[Route("mrb/delete")]
|
||||
public async Task<IActionResult> DeleteMRB(int mrbNumber) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to delete MRB# {mrbNumber}");
|
||||
|
||||
if (mrbNumber <= 0) throw new ArgumentException($"{mrbNumber} is not a valid MRB number");
|
||||
|
||||
await _mrbService.DeleteMRB(mrbNumber);
|
||||
|
||||
return Ok();
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot delete MRB {mrbNumber}, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "DeleteMRB";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("mrb/all")]
|
||||
public async Task<IActionResult> GetAllMRBs(bool bypassCache) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get all MRBs");
|
||||
|
||||
IEnumerable<MRB> allMrbs = await _mrbService.GetAllMRBs(bypassCache);
|
||||
|
||||
return Ok(allMrbs);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot get all MRBs, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "GetAllMRBs";
|
||||
DateTime end = DateTime.Now;
|
||||
double millisecondsDiff = (end - start).TotalMilliseconds;
|
||||
_monInClient.PostAverage(metricName + "Latency", millisecondsDiff);
|
||||
|
||||
if (isInternalError) {
|
||||
_logger.LogError(errorMessage);
|
||||
_monInClient.PostStatus(metricName, StatusValue.Critical);
|
||||
} else {
|
||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("mrb/numberIsValid")]
|
||||
public async Task<IActionResult> NumberIsValid(int number) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to determine if {number} is a valid MRB#");
|
||||
|
||||
bool isValid = await _mrbService.MRBNumberIsValid(number);
|
||||
|
||||
return Ok(isValid);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Unable to determine if {number} is a valid MRB#, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "IsValidMRBNumber";
|
||||
DateTime end = DateTime.Now;
|
||||
double millisecondsDiff = (end - start).TotalMilliseconds;
|
||||
_monInClient.PostAverage(metricName + "Latency", millisecondsDiff);
|
||||
|
||||
if (isInternalError) {
|
||||
_logger.LogError(errorMessage);
|
||||
_monInClient.PostStatus(metricName, StatusValue.Critical);
|
||||
} else {
|
||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("mrb/getById")]
|
||||
public async Task<IActionResult> GetMRBById(int id, bool bypassCache = false) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get an MRB by Id");
|
||||
|
||||
if (id <= 0) throw new ArgumentException("Invalid MRB number");
|
||||
|
||||
MRB mrb = await _mrbService.GetMRBById(id, bypassCache);
|
||||
|
||||
return Ok(mrb);
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot get MRB by Id, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "GetMRBbyId";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("mrb/getByTitle")]
|
||||
public async Task<IActionResult> GetMRBByTitle(string title, bool bypassCache) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get an MRB by Title");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(title)) throw new ArgumentException("Title cannot be null or empty");
|
||||
|
||||
MRB mrb = await _mrbService.GetMRBByTitle(title, bypassCache);
|
||||
|
||||
return Ok(mrb);
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot get MRB by title, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "GetMRBbyTitle";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPut]
|
||||
[Route("mrb")]
|
||||
public async Task<IActionResult> UpdateMRB(MRB mrb) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to update an MRB");
|
||||
|
||||
if (mrb is null) throw new ArgumentNullException("MRB cannot be null");
|
||||
|
||||
await _mrbService.UpdateMRB(mrb);
|
||||
|
||||
return Ok();
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot update MRB, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "UpdateMRB";
|
||||
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]
|
||||
[Route("mrbAction")]
|
||||
public async Task<IActionResult> CreateMRBAction(MRBAction mrbAction) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to generate a new MRB");
|
||||
|
||||
if (mrbAction is null) throw new ArgumentNullException("MRB action cannot be null");
|
||||
|
||||
await _mrbService.CreateMRBAction(mrbAction);
|
||||
|
||||
return Ok();
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot create new MRB action, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "CreateNewMRBAction";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("mrbAction")]
|
||||
public async Task<IActionResult> GetMRBActionsForMRB(int mrbNumber, bool bypassCache) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get all MRBs");
|
||||
|
||||
if (mrbNumber <= 0) throw new ArgumentException($"{mrbNumber} is not a valid MRB number");
|
||||
|
||||
IEnumerable<MRBAction> mrbActions = await _mrbService.GetMRBActionsForMRB(mrbNumber, bypassCache);
|
||||
|
||||
return Ok(mrbActions);
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot get all MRBs, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "GetMRBActionsForMRB";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPut]
|
||||
[Route("mrbAction")]
|
||||
public async Task<IActionResult> UpdateMRBAction(MRBAction mrbAction) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to update an MRB action");
|
||||
|
||||
if (mrbAction is null) throw new ArgumentNullException("MRB action cannot be null");
|
||||
|
||||
await _mrbService.UpdateMRBAction(mrbAction);
|
||||
|
||||
return Ok();
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot update MRB action, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "UpdateMRBAction";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpDelete]
|
||||
[Route("mrbAction")]
|
||||
public async Task<IActionResult> DeleteMRBAction(int mrbActionID, int mrbNumber) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to delete MRB action {mrbActionID}");
|
||||
|
||||
if (mrbActionID <= 0) throw new ArgumentException($"{mrbActionID} is not a valid MRB ActionID");
|
||||
if (mrbNumber <= 0) throw new ArgumentException($"{mrbNumber} is not a valid MRBNumber");
|
||||
|
||||
await _mrbService.DeleteMRBAction(mrbActionID, mrbNumber);
|
||||
|
||||
return Ok();
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot delete MRB action, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "DeleteMRBAction";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("mrb/attachments")]
|
||||
public async Task<IActionResult> GetAttachmentsForMRB(int mrbNumber, bool bypassCache) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to get MRB attachments for MRB {mrbNumber}");
|
||||
|
||||
if (mrbNumber <= 0) throw new ArgumentException($"{mrbNumber} is not a valid MRB number");
|
||||
|
||||
List<MRBAttachment> attachments = (await _mrbService.GetAllAttachmentsForMRB(mrbNumber, bypassCache)).ToList();
|
||||
|
||||
return Ok(attachments);
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot get attachments for MRB {mrbNumber}, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "GetMRBAttachments";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("mrb/action/attachments")]
|
||||
public async Task<IActionResult> GetActionAttachmentsForMRB(int mrbNumber, bool bypassCache) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to get action attachments for MRB {mrbNumber}");
|
||||
|
||||
if (mrbNumber <= 0) throw new ArgumentException($"{mrbNumber} is not a valid MRB#");
|
||||
|
||||
List<MRBActionAttachment> attachments =
|
||||
(await _mrbService.GetAllActionAttachmentsForMRB(mrbNumber, bypassCache)).ToList();
|
||||
|
||||
return Ok(attachments);
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot get action attachments for MRB# {mrbNumber}, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "GetMRBActionAttachments";
|
||||
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]
|
||||
[Route("mrb/attach")]
|
||||
public async Task<IActionResult> SaveMRBAttachment([FromForm] IEnumerable<IFormFile> files, int mrbNumber) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to save MRB attachments");
|
||||
|
||||
if (files is null) throw new ArgumentNullException("Files cannot be null");
|
||||
if (files.Count() <= 0) throw new ArgumentException("Files cannot be empty");
|
||||
if (mrbNumber <= 0) throw new ArgumentException($"{mrbNumber} is not a valid MRB number");
|
||||
|
||||
IEnumerable<UploadResult> uploadResults = (await _mrbService.UploadAttachments(files, mrbNumber)).ToList();
|
||||
|
||||
return Ok(uploadResults);
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot save MRB attachments, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "SaveMRBAttachments";
|
||||
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]
|
||||
[Route("mrb/action/attach")]
|
||||
public async Task<IActionResult> SaveMRBActionAttachment([FromForm] IEnumerable<IFormFile> files, int actionId) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to save MRB action attachments");
|
||||
|
||||
if (files is null) throw new ArgumentNullException("Files cannot be null");
|
||||
if (files.Count() <= 0) throw new ArgumentException("Files cannot be empty");
|
||||
if (actionId <= 0) throw new ArgumentException($"{actionId} is not a valid MRB action ID");
|
||||
|
||||
IEnumerable<UploadResult> uploadResults = (await _mrbService.UploadActionAttachments(files, actionId)).ToList();
|
||||
|
||||
return Ok(uploadResults);
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot save MRB action attachments, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "SaveMRBActionAttachments";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[HttpGet]
|
||||
[Route("mrb/attachmentFile")]
|
||||
public async Task<IActionResult> GetMRBAttachmentFile(string path, string fileName) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get MRB attachment file");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("Path cannot be null or empty");
|
||||
if (!System.IO.File.Exists(path)) throw new ArgumentException("No file exists at provided path");
|
||||
if (string.IsNullOrWhiteSpace(fileName)) throw new ArgumentException("Filename cannot be null or empty");
|
||||
|
||||
byte[] fs = System.IO.File.ReadAllBytes(path);
|
||||
|
||||
const string defaultContentType = "application/octet-stream";
|
||||
|
||||
FileExtensionContentTypeProvider contentTypeProvider = new FileExtensionContentTypeProvider();
|
||||
|
||||
if (!contentTypeProvider.TryGetContentType(path, out string? contentType)) {
|
||||
contentType = defaultContentType;
|
||||
}
|
||||
|
||||
return new FileContentResult(fs, contentType) {
|
||||
FileDownloadName = fileName
|
||||
};
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot get MRB attachment file, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "GetMRBAttachmentFile";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpDelete]
|
||||
[Route("mrb/attach")]
|
||||
public async Task<IActionResult> DeleteMRBAttachment(MRBAttachment attachment) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to delete MRB attachment");
|
||||
|
||||
if (attachment is null) throw new ArgumentNullException("Attachment cannot be null");
|
||||
|
||||
await _mrbService.DeleteAttachment(attachment);
|
||||
|
||||
return Ok();
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot get MRB attachment file, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "DeleteMRBAttachment";
|
||||
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]
|
||||
[Route("mrb/notify/new-approvals")]
|
||||
public async Task<IActionResult> NotifyNewApprovals(MRB mrb) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to notify new approvers");
|
||||
|
||||
if (mrb is null) throw new ArgumentNullException("MRB cannot be null");
|
||||
|
||||
await _mrbService.NotifyNewApprovals(mrb);
|
||||
|
||||
return Ok();
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Unable to notify new approvers, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "NotifyNewMRBApprovers";
|
||||
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]
|
||||
[Route("mrb/notify/approvers")]
|
||||
public async Task<IActionResult> NotifyApprovers(MRBNotification notification) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to notify approvers");
|
||||
|
||||
if (notification is null) throw new ArgumentNullException("notification cannot be null");
|
||||
if (notification.MRB is null) throw new ArgumentNullException("MRB cannot be null");
|
||||
if (string.IsNullOrWhiteSpace(notification.Message)) throw new ArgumentException("message cannot be null or empty");
|
||||
|
||||
await _mrbService.NotifyApprovers(notification);
|
||||
|
||||
return Ok();
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Unable to notify approvers, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "NotifyMRBApprovers";
|
||||
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]
|
||||
[Route("mrb/notify/originator")]
|
||||
public async Task<IActionResult> NotifyOriginator(MRBNotification notification) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to notify originator");
|
||||
|
||||
if (notification is null) throw new ArgumentNullException("MRBNotification cannot be null");
|
||||
if (notification.MRB is null) throw new ArgumentNullException("MRB cannot be null");
|
||||
if (string.IsNullOrWhiteSpace(notification.Message)) throw new ArgumentException("Message cannot be null or empty");
|
||||
|
||||
await _mrbService.NotifyOriginator(notification);
|
||||
|
||||
return Ok();
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Unable to notify originator, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "NotifyMRBOriginator";
|
||||
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]
|
||||
[Route("mrb/notify/qa-pre-approver")]
|
||||
public async Task<IActionResult> NotifyQAPreApprover(MRBNotification notification) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to notify QA pre approver");
|
||||
|
||||
if (notification is null) throw new ArgumentNullException("MRBNotification cannot be null");
|
||||
if (notification.MRB is null) throw new ArgumentNullException("MRB cannot be null");
|
||||
if (string.IsNullOrWhiteSpace(notification.Message)) throw new ArgumentException("Message cannot be null or empty");
|
||||
|
||||
await _mrbService.NotifyQAPreApprover(notification);
|
||||
|
||||
return Ok();
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Unable to notify QA pre approver, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "NotifyQAPreApprover";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
264
MesaFabApproval.API/Controllers/PCRBController.cs
Normal file
264
MesaFabApproval.API/Controllers/PCRBController.cs
Normal file
@ -0,0 +1,264 @@
|
||||
using MesaFabApproval.API.Services;
|
||||
using MesaFabApproval.Shared.Models;
|
||||
using MesaFabApproval.Shared.Services;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace MesaFabApproval.API.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class PCRBController : ControllerBase {
|
||||
private readonly ILogger<MRBController> _logger;
|
||||
private readonly IPCRBService _pcrbService;
|
||||
private readonly IMonInWorkerClient _monInClient;
|
||||
|
||||
public PCRBController(ILogger<MRBController> logger, IPCRBService pcrbService, IMonInWorkerClient monInClient) {
|
||||
_logger = logger ?? throw new ArgumentNullException("ILogger not injected");
|
||||
_pcrbService = pcrbService ?? throw new ArgumentNullException("IPCRBService not injected");
|
||||
_monInClient = monInClient ?? throw new ArgumentNullException("IMonInWorkerClient not injected");
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("pcrb")]
|
||||
public async Task<IActionResult> CreateNewPCRB(PCRB pcrb) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to generate a new PCRB");
|
||||
|
||||
if (pcrb is null) throw new ArgumentNullException("PCRB cannot be null");
|
||||
|
||||
await _pcrbService.CreateNewPCRB(pcrb);
|
||||
|
||||
return Ok();
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot create new PCRB, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "CreateNewPCRB";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("pcrb/all")]
|
||||
public async Task<IActionResult> GetAllPCRBs(bool bypassCache) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get all PCRBs");
|
||||
|
||||
IEnumerable<PCRB> allPCRBs = await _pcrbService.GetAllPCRBs(bypassCache);
|
||||
|
||||
return Ok(allPCRBs);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot get all PCRBs, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "GetAllPCRBs";
|
||||
DateTime end = DateTime.Now;
|
||||
double millisecondsDiff = (end - start).TotalMilliseconds;
|
||||
_monInClient.PostAverage(metricName + "Latency", millisecondsDiff);
|
||||
|
||||
if (isInternalError) {
|
||||
_logger.LogError(errorMessage);
|
||||
_monInClient.PostStatus(metricName, StatusValue.Critical);
|
||||
} else {
|
||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("pcrb/getByTitle")]
|
||||
public async Task<IActionResult> GetPCRBByTitle(string title, bool bypassCache) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get an PCRB by Title");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(title)) throw new ArgumentException("Title cannot be null or empty");
|
||||
|
||||
PCRB pcrb = await _pcrbService.GetPCRBByTitle(title, bypassCache);
|
||||
|
||||
return Ok(pcrb);
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot get PCRB by title, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "GetPCRBbyTitle";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("pcrb/getByPlanNumber")]
|
||||
public async Task<IActionResult> GetPCRBByPlanNumber(int planNumber, bool bypassCache) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get an PCRB by Title");
|
||||
|
||||
if (planNumber <= 0) throw new ArgumentException($"{planNumber} is not a valid PCRB plan #");
|
||||
|
||||
PCRB pcrb = await _pcrbService.GetPCRBByPlanNumber(planNumber, bypassCache);
|
||||
|
||||
return Ok(pcrb);
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot get PCRB by plan number, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "GetPCRBbyPlanNumber";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPut]
|
||||
[Route("pcrb")]
|
||||
public async Task<IActionResult> UpdatePCRB(PCRB pcrb) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to update a PCRB");
|
||||
|
||||
if (pcrb is null) throw new ArgumentNullException("PCRB cannot be null");
|
||||
|
||||
await _pcrbService.UpdatePCRB(pcrb);
|
||||
|
||||
return Ok();
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot update PCRB, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "UpdatePCRB";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpDelete]
|
||||
[Route("pcrb")]
|
||||
public async Task<IActionResult> DeletePCRB(int planNumber) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to delete PCRB# {planNumber}");
|
||||
|
||||
if (planNumber <= 0) throw new ArgumentException($"{planNumber} is not a valid PCRB plan #");
|
||||
|
||||
await _pcrbService.DeletePCRB(planNumber);
|
||||
|
||||
return Ok();
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = ex.Message;
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot delete PCRB# {planNumber}, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "DeletePCRB";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
223
MesaFabApproval.API/Controllers/UserController.cs
Normal file
223
MesaFabApproval.API/Controllers/UserController.cs
Normal file
@ -0,0 +1,223 @@
|
||||
using MesaFabApproval.API.Services;
|
||||
using MesaFabApproval.Shared.Models;
|
||||
using MesaFabApproval.Shared.Services;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace MesaFabApproval.API.Controllers;
|
||||
|
||||
[ApiController]
|
||||
public class UserController : ControllerBase {
|
||||
private readonly ILogger<UserController> _logger;
|
||||
private readonly IMonInWorkerClient _monInClient;
|
||||
private readonly IMemoryCache _cache;
|
||||
private readonly IUserService _userService;
|
||||
|
||||
public UserController(ILogger<UserController> logger,
|
||||
IMonInWorkerClient monInClient,
|
||||
IMemoryCache cache,
|
||||
IUserService userService) {
|
||||
_logger = logger ?? throw new ArgumentNullException("ILogger not injected");
|
||||
_monInClient = monInClient ?? throw new ArgumentNullException("IMonInWorkerClient not injected");
|
||||
_cache = cache ?? throw new ArgumentNullException("IMemoryCache not injected");
|
||||
_userService = userService ?? throw new ArgumentNullException("IUserService not injected");
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("/user/loginId")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> GetUserByLoginId(string loginId) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get user by LoginID");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(loginId))
|
||||
throw new ArgumentException("LoginID cannot be null or empty");
|
||||
|
||||
User? user = _cache.Get<User>($"user{loginId}");
|
||||
|
||||
if (user is null) {
|
||||
user = await _userService.GetUserByLoginId(loginId);
|
||||
|
||||
_cache.Set($"user{loginId}", user, DateTimeOffset.Now.AddDays(1));
|
||||
}
|
||||
|
||||
if (user is not null) return Ok(user);
|
||||
|
||||
throw new Exception($"User with LoginID {loginId} not found");
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = $"Invalid argument. {ex.Message}";
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot get user by LoginID, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "GetUserByLoginId";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("/user/userId")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> GetUserByUserId(int userId) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get user by LoginID");
|
||||
|
||||
if (userId <= 0) throw new ArgumentException($"{userId} is not a valid user ID");
|
||||
|
||||
User? user = _cache.Get<User>($"user{userId}");
|
||||
|
||||
if (user is null) {
|
||||
user = await _userService.GetUserByUserId(userId);
|
||||
|
||||
_cache.Set($"user{userId}", user, DateTimeOffset.Now.AddDays(1));
|
||||
}
|
||||
|
||||
if (user is not null) return Ok(user);
|
||||
|
||||
throw new Exception($"User with UserID {userId} not found");
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = $"Invalid argument. {ex.Message}";
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot get user by User ID, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "GetUserByUserId";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("/users/active")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> GetAllActiveUsers() {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get all active users");
|
||||
|
||||
IEnumerable<User>? activeUsers = _cache.Get<IEnumerable<User>>($"activeUsers");
|
||||
|
||||
if (activeUsers is null) {
|
||||
activeUsers = await _userService.GetAllActiveUsers();
|
||||
|
||||
_cache.Set($"activeUsers", activeUsers, DateTimeOffset.Now.AddDays(1));
|
||||
}
|
||||
|
||||
if (activeUsers is not null) return Ok(activeUsers);
|
||||
|
||||
throw new Exception($"No active users found");
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot get all active users, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "GetAllActiveUsers";
|
||||
DateTime end = DateTime.Now;
|
||||
double millisecondsDiff = (end - start).TotalMilliseconds;
|
||||
_monInClient.PostAverage(metricName + "Latency", millisecondsDiff);
|
||||
|
||||
if (isInternalError) {
|
||||
_logger.LogError(errorMessage);
|
||||
_monInClient.PostStatus(metricName, StatusValue.Critical);
|
||||
} else {
|
||||
_monInClient.PostStatus(metricName, StatusValue.Ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("/approver")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> GetApproverUserIdsForSubRoleCategoryItem(string subRoleCategoryItem) {
|
||||
DateTime start = DateTime.Now;
|
||||
bool isArgumentError = false;
|
||||
bool isInternalError = false;
|
||||
string errorMessage = "";
|
||||
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get approver user IDs");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(subRoleCategoryItem))
|
||||
throw new ArgumentException("SubRoleCategoryItem cannot be null or empty");
|
||||
|
||||
IEnumerable<int>? approverUserIds = _cache.Get<IEnumerable<int>>($"approvers{subRoleCategoryItem}");
|
||||
|
||||
if (approverUserIds is null) {
|
||||
approverUserIds = await _userService.GetApproverUserIdsBySubRoleCategoryItem(subRoleCategoryItem);
|
||||
|
||||
_cache.Set($"approvers{subRoleCategoryItem}", approverUserIds, DateTimeOffset.Now.AddDays(1));
|
||||
}
|
||||
|
||||
if (approverUserIds is not null) return Ok(approverUserIds);
|
||||
|
||||
throw new Exception($"Approvers for SubRoleCategoryItem {subRoleCategoryItem} not found");
|
||||
} catch (ArgumentException ex) {
|
||||
isArgumentError = true;
|
||||
errorMessage = $"Invalid argument. {ex.Message}";
|
||||
return BadRequest(errorMessage);
|
||||
} catch (Exception ex) {
|
||||
isInternalError = true;
|
||||
errorMessage = $"Cannot get approver user IDs, because {ex.Message}";
|
||||
return Problem(errorMessage);
|
||||
} finally {
|
||||
string metricName = "GetApproverUserIds";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
9
MesaFabApproval.API/GlobalSuppressions.cs
Normal file
9
MesaFabApproval.API/GlobalSuppressions.cs
Normal file
@ -0,0 +1,9 @@
|
||||
// This file is used by Code Analysis to maintain SuppressMessage
|
||||
// attributes that are applied to this project.
|
||||
// Project-level suppressions either have no target or are given
|
||||
// a specific target and scoped to a namespace, type, member, etc.
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>", Scope = "member", Target = "~M:MesaFabApprovalAPI.Services.AuthenticationService.AuthenticateUser(MesaFabApproval.Shared.Models.AuthAttempt)~System.Threading.Tasks.Task{MesaFabApproval.Shared.Models.LoginResult}")]
|
||||
[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>", Scope = "member", Target = "~M:MesaFabApprovalAPI.Services.AuthenticationService.AttemptLocalUserAuth(System.Security.Principal.WindowsIdentity)~System.Threading.Tasks.Task{MesaFabApproval.Shared.Models.LoginResult}")]
|
32
MesaFabApproval.API/MesaFabApproval.API.csproj
Normal file
32
MesaFabApproval.API/MesaFabApproval.API.csproj
Normal file
@ -0,0 +1,32 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Dapper" Version="2.1.35" />
|
||||
<PackageReference Include="Dapper.Contrib" Version="2.0.78" />
|
||||
<PackageReference Include="dotenv.net" Version="3.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.8" />
|
||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" />
|
||||
<PackageReference Include="NLog" Version="5.3.3" />
|
||||
<PackageReference Include="NLog.Web.AspNetCore" Version="5.3.12" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.7.0" />
|
||||
<PackageReference Include="System.DirectoryServices.AccountManagement" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MesaFabApproval.Shared\MesaFabApproval.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="System.DirectoryServices.AccountManagement">
|
||||
<HintPath>..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.DirectoryServices.AccountManagement.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
145
MesaFabApproval.API/Program.cs
Normal file
145
MesaFabApproval.API/Program.cs
Normal file
@ -0,0 +1,145 @@
|
||||
using MesaFabApproval.Shared.Services;
|
||||
using NLog.Web;
|
||||
using MesaFabApprovalAPI.Services;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using dotenv.net;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using MesaFabApproval.API.Services;
|
||||
using NLog.Extensions.Logging;
|
||||
using MesaFabApproval.API.Clients;
|
||||
using System.Net.Mail;
|
||||
using Microsoft.AspNetCore.HttpLogging;
|
||||
|
||||
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
DotEnv.Load();
|
||||
|
||||
builder.Logging.ClearProviders();
|
||||
builder.Logging.SetMinimumLevel(LogLevel.Trace);
|
||||
builder.Logging.AddNLog();
|
||||
|
||||
/*builder.Services.AddHttpLogging(o => {
|
||||
o.LoggingFields = HttpLoggingFields.All;
|
||||
o.RequestHeaders.Add("bearer");
|
||||
o.MediaTypeOptions.AddText("application/javascript");
|
||||
o.RequestBodyLogLimit = 4096;
|
||||
o.ResponseBodyLogLimit = 4096;
|
||||
o.CombineLogs = true;
|
||||
});*/
|
||||
|
||||
builder.Services.AddMemoryCache();
|
||||
|
||||
string jwtIssuer = Environment.GetEnvironmentVariable("FabApprovalJwtIssuer") ??
|
||||
throw new ArgumentNullException("FabApprovalJwtIssuer environment variable not found");
|
||||
string jwtAudience = Environment.GetEnvironmentVariable("FabApprovalJwtAudience") ??
|
||||
throw new ArgumentNullException("FabApprovalJwtAudience environment variable not found");
|
||||
string jwtKey = Environment.GetEnvironmentVariable("FabApprovalJwtKey") ??
|
||||
throw new ArgumentNullException("FabApprovalJwtKey environment variable not found");
|
||||
|
||||
builder.Services.AddAuthentication(options => {
|
||||
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
})
|
||||
.AddJwtBearer(options => {
|
||||
options.RequireHttpsMetadata = false;
|
||||
options.SaveToken = true;
|
||||
options.TokenValidationParameters = new TokenValidationParameters {
|
||||
ValidateIssuerSigningKey = true,
|
||||
ValidIssuer = jwtIssuer,
|
||||
ValidateAudience = false,
|
||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtKey)),
|
||||
ClockSkew = TimeSpan.Zero
|
||||
};
|
||||
});
|
||||
|
||||
builder.Services.AddAuthorization(options => {
|
||||
options.DefaultPolicy = new AuthorizationPolicyBuilder()
|
||||
.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
|
||||
.RequireAuthenticatedUser()
|
||||
.Build();
|
||||
});
|
||||
|
||||
builder.Services.AddHttpClient();
|
||||
|
||||
builder.Services.AddCors(options => {
|
||||
options.AddDefaultPolicy(options => {
|
||||
options.AllowAnyOrigin();
|
||||
options.AllowAnyMethod();
|
||||
options.AllowAnyHeader();
|
||||
});
|
||||
});
|
||||
|
||||
builder.Services.AddScoped<IDbConnectionService, DbConnectionService>();
|
||||
builder.Services.AddScoped<IDalService, DalService>();
|
||||
builder.Services.AddScoped<SmtpClient>((serviceProvider) => {
|
||||
return new SmtpClient("mailrelay-external.infineon.com");
|
||||
});
|
||||
builder.Services.AddScoped<ISmtpClientWrapper, SmtpClientWrapper>();
|
||||
builder.Services.AddScoped<ICustomerService, CustomerService>();
|
||||
builder.Services.AddScoped<ICAService, CAService>();
|
||||
builder.Services.AddScoped<IECNService, ECNService>();
|
||||
builder.Services.AddScoped<ISmtpService, SmtpService>();
|
||||
builder.Services.AddScoped<IUserService, UserService>();
|
||||
builder.Services.AddScoped<IMonInWorkerClient, MonInWorkerClient>();
|
||||
builder.Services.AddScoped<IAuthenticationService, AuthenticationService>();
|
||||
builder.Services.AddScoped<IMRBService, MRBService>();
|
||||
builder.Services.AddScoped<IPCRBService, PCRBService>();
|
||||
builder.Services.AddScoped<IApprovalService, ApprovalService>();
|
||||
|
||||
builder.Services.AddControllers();
|
||||
|
||||
#if DEBUG
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen(c => {
|
||||
c.SwaggerDoc("v1", new OpenApiInfo {
|
||||
Title = "Mesa Fab Approval API",
|
||||
Version = "v1"
|
||||
});
|
||||
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme {
|
||||
In = ParameterLocation.Header,
|
||||
Description = "Please insert JWT with Bearer into field",
|
||||
Name = "Authorization",
|
||||
Type = SecuritySchemeType.ApiKey
|
||||
});
|
||||
c.AddSecurityRequirement(new OpenApiSecurityRequirement {
|
||||
{
|
||||
new OpenApiSecurityScheme
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Type = ReferenceType.SecurityScheme,
|
||||
Id = "Bearer"
|
||||
}
|
||||
},
|
||||
new string[] { }
|
||||
}
|
||||
});
|
||||
});
|
||||
#endif
|
||||
|
||||
WebApplication app = builder.Build();
|
||||
|
||||
app.UseCors();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
}
|
||||
|
||||
// app.UseHttpLogging();
|
||||
|
||||
app.UseAuthentication();
|
||||
|
||||
app.UseAuthorization();
|
||||
|
||||
app.MapControllers();
|
||||
|
||||
app.Run();
|
||||
|
||||
NLog.LogManager.Flush();
|
||||
NLog.LogManager.Shutdown();
|
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<DeleteExistingFiles>true</DeleteExistingFiles>
|
||||
<ExcludeApp_Data>false</ExcludeApp_Data>
|
||||
<LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
|
||||
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
|
||||
<LastUsedPlatform>Any CPU</LastUsedPlatform>
|
||||
<PublishProvider>FileSystem</PublishProvider>
|
||||
<PublishUrl>bin\Release\net8.0\publish\</PublishUrl>
|
||||
<WebPublishMethod>FileSystem</WebPublishMethod>
|
||||
<_TargetId>Folder</_TargetId>
|
||||
<SiteUrlToLaunchAfterPublish />
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<ProjectGuid>852e528d-015a-43b5-999d-f281e3359e5e</ProjectGuid>
|
||||
<SelfContained>true</SelfContained>
|
||||
<PublishReadyToRun>true</PublishReadyToRun>
|
||||
</PropertyGroup>
|
||||
</Project>
|
320
MesaFabApproval.API/Services/ApprovalService.cs
Normal file
320
MesaFabApproval.API/Services/ApprovalService.cs
Normal file
@ -0,0 +1,320 @@
|
||||
using System.Text;
|
||||
|
||||
using MesaFabApproval.Shared.Models;
|
||||
using MesaFabApproval.Shared.Utilities;
|
||||
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace MesaFabApproval.API.Services;
|
||||
|
||||
public interface IApprovalService {
|
||||
Task<int> GetRoleIdForRoleName(string roleName);
|
||||
Task<IEnumerable<SubRole>> GetSubRolesForSubRoleName(string subRoleName, int roleId);
|
||||
Task<IEnumerable<User>> GetApprovalGroupMembers(int subRoleId);
|
||||
Task CreateApproval(Approval approval);
|
||||
Task UpdateApproval(Approval approval);
|
||||
Task Approve(Approval approval);
|
||||
Task Deny(Approval approval);
|
||||
Task<IEnumerable<Approval>> GetApprovalsForIssueId(int issueId, bool bypassCache);
|
||||
Task<IEnumerable<Approval>> GetApprovalsForUserId(int userId, bool bypassCache);
|
||||
}
|
||||
|
||||
public class ApprovalService : IApprovalService {
|
||||
private readonly ILogger<ApprovalService> _logger;
|
||||
private readonly IMemoryCache _cache;
|
||||
private readonly IDalService _dalService;
|
||||
private readonly IUserService _userService;
|
||||
|
||||
public ApprovalService(ILogger<ApprovalService> logger, IMemoryCache cache, IDalService dalService, IUserService userService) {
|
||||
_logger = logger ?? throw new ArgumentNullException("ILogger not injected");
|
||||
_cache = cache ?? throw new ArgumentNullException("IMemoryCache not injected");
|
||||
_dalService = dalService ?? throw new ArgumentNullException("IDalService not injected");
|
||||
_userService = userService ?? throw new ArgumentNullException("IUserService not injected");
|
||||
}
|
||||
|
||||
public async Task CreateApproval(Approval approval) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to generate new Approval");
|
||||
|
||||
if (approval is null) throw new ArgumentNullException("Approval cannot be null");
|
||||
|
||||
StringBuilder queryBuilder = new();
|
||||
queryBuilder.Append("insert into Approval (IssueID, RoleName, SubRole, UserID, SubRoleID, ItemStatus, ");
|
||||
queryBuilder.Append("AssignedDate, DocumentTypeID, DisplayDeniedDocument, Step, TaskID) ");
|
||||
queryBuilder.Append($"values ({approval.IssueID}, '{approval.RoleName}', '{approval.SubRole}', {approval.UserID}, ");
|
||||
queryBuilder.Append($"{approval.SubRoleID}, 0, '{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
||||
queryBuilder.Append($"3, 0, {approval.Step}, {approval.TaskID});");
|
||||
|
||||
int rowsCreated = await _dalService.ExecuteAsync(queryBuilder.ToString());
|
||||
|
||||
if (rowsCreated <= 0) throw new Exception("Unable to insert approval in database");
|
||||
|
||||
await GetApprovalsForIssueId(approval.IssueID, true);
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"An exception occurred when attempting to create new Approval. Exception: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Approval>> GetApprovalsForIssueId(int issueId, bool bypassCache) {
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to get all approvals for issue {issueId}");
|
||||
|
||||
if (issueId <= 0) throw new ArgumentException($"{issueId} is not a valid issue ID");
|
||||
|
||||
IEnumerable<Approval>? approvals = new List<Approval>();
|
||||
|
||||
if (!bypassCache)
|
||||
approvals = _cache.Get<IEnumerable<Approval>>($"approvals{issueId}");
|
||||
|
||||
if (approvals is null || approvals.Count() == 0) {
|
||||
StringBuilder queryBuilder = new();
|
||||
queryBuilder.Append("select a.*, src.SubRoleCategoryItem from Approval a ");
|
||||
queryBuilder.Append("join SubRole sr on a.SubRoleID=sr.SubRoleID ");
|
||||
queryBuilder.Append("join SubRoleCategory src on sr.SubRoleCategoryID=src.SubRoleCategoryID ");
|
||||
queryBuilder.Append($"where a.IssueID={issueId}");
|
||||
|
||||
approvals = (await _dalService.QueryAsync<Approval>(queryBuilder.ToString())).ToList();
|
||||
|
||||
foreach (Approval approval in approvals) {
|
||||
int successfulUpdates = 0;
|
||||
|
||||
User? user = await _userService.GetUserByUserId(approval.UserID);
|
||||
if (user is not null) {
|
||||
approval.User = user;
|
||||
successfulUpdates++;
|
||||
}
|
||||
|
||||
if (approval.ItemStatus < 0)
|
||||
approval.StatusMessage = "Denied";
|
||||
if (approval.ItemStatus == 0)
|
||||
approval.StatusMessage = "Assigned";
|
||||
if (approval.ItemStatus > 0)
|
||||
approval.StatusMessage = "Approved";
|
||||
}
|
||||
|
||||
_cache.Set($"approvals{issueId}", approvals, DateTimeOffset.Now.AddMinutes(5));
|
||||
}
|
||||
|
||||
return approvals;
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to fetch approvals for issue {issueId}, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<int> GetRoleIdForRoleName(string roleName) {
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to get role ID by name");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(roleName))
|
||||
throw new ArgumentException("Role name cannot be null or empty");
|
||||
|
||||
int roleId = _cache.Get<int>($"role{roleName}");
|
||||
|
||||
if (roleId <= 0) {
|
||||
string sql = $"select RoleID from Role where RoleName = '{roleName}'";
|
||||
|
||||
roleId = (await _dalService.QueryAsync<int>(sql)).ToList().FirstOrDefault();
|
||||
|
||||
if (roleId > 0)
|
||||
_cache.Set($"role{roleName}", roleId, DateTimeOffset.Now.AddDays(1));
|
||||
}
|
||||
|
||||
if (roleId <= 0)
|
||||
throw new Exception($"Unable to find role with name {roleName}");
|
||||
|
||||
return roleId;
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to find role ID, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<SubRole>> GetSubRolesForSubRoleName(string subRoleName, int roleId) {
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to get sub role ID by name for role ID {roleId}");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(subRoleName))
|
||||
throw new ArgumentException("sub role name cannot be null or empty");
|
||||
if (roleId <= 0) throw new ArgumentException($"{roleId} is not a valid role ID");
|
||||
|
||||
IEnumerable<SubRole>? subRoles = _cache.Get<IEnumerable<SubRole>>($"subRoles{subRoleName}");
|
||||
|
||||
if (subRoles is null || subRoles.Count() <= 0) {
|
||||
StringBuilder queryBuilder = new();
|
||||
queryBuilder.Append("select src.SubRoleCategoryID, sr.SubRole as SubRoleName, src.SubRoleCategoryItem, sr.SubRoleID ");
|
||||
queryBuilder.Append("from SubRole sr join SubRoleCategory src on sr.SubRoleCategoryID=src.SubRoleCategoryID ");
|
||||
queryBuilder.Append($"where sr.RoleID={roleId} and sr.SubRole='{subRoleName}'");
|
||||
|
||||
subRoles = (await _dalService.QueryAsync<SubRole>(queryBuilder.ToString())).ToList();
|
||||
|
||||
if (subRoles is not null && subRoles.Count() > 0)
|
||||
_cache.Set($"subRole{subRoleName}", subRoles, DateTimeOffset.Now.AddDays(1));
|
||||
}
|
||||
|
||||
if (subRoles is null || subRoles.Count() <= 0)
|
||||
throw new Exception($"Unable to find sub role with name {subRoleName} for role {roleId}");
|
||||
|
||||
return subRoles;
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to find sub roles, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<User>> GetApprovalGroupMembers(int subRoleId) {
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to get members of sub role {subRoleId}");
|
||||
|
||||
if (subRoleId <= 0) throw new ArgumentException($"{subRoleId} is not a valid sub role ID");
|
||||
|
||||
List<User>? members = _cache.Get<List<User>>($"approvalMembers{subRoleId}");
|
||||
|
||||
if (members is null || members.Count() <= 0) {
|
||||
IEnumerable<int>? memberIds = _cache.Get<IEnumerable<int>>($"approvalMemberIds{subRoleId}");
|
||||
|
||||
if (memberIds is null) {
|
||||
string sql = $"select UserID from UserSubRole where SubRoleID = {subRoleId};";
|
||||
|
||||
memberIds = await _dalService.QueryAsync<int>(sql);
|
||||
|
||||
if (memberIds is null || memberIds.Count() <= 0)
|
||||
throw new Exception($"No members found in sub role {subRoleId}");
|
||||
|
||||
_cache.Set($"approvalMemberIds{subRoleId}", memberIds, DateTimeOffset.Now.AddHours(1));
|
||||
}
|
||||
|
||||
members = new();
|
||||
foreach (int id in memberIds) {
|
||||
User member = await _userService.GetUserByUserId(id);
|
||||
|
||||
members.Add(member);
|
||||
}
|
||||
|
||||
if (members.Count() <= 0) throw new Exception("No users found with IDs matching those found in SubRole");
|
||||
|
||||
_cache.Set($"approvalMembers{subRoleId}", members, DateTimeOffset.Now.AddHours(1));
|
||||
}
|
||||
|
||||
return members;
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to get sub role {subRoleId} members, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Approval>> GetApprovalsForUserId(int userId, bool bypassCache) {
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to get approvals for user ID {userId}");
|
||||
|
||||
if (userId <= 0) throw new ArgumentException($"{userId} is not a valid user ID");
|
||||
|
||||
IEnumerable<Approval>? approvals = null;
|
||||
|
||||
if (!bypassCache) approvals = _cache.Get<IEnumerable<Approval>>($"approvalMembers{userId}");
|
||||
|
||||
if (approvals is null) {
|
||||
StringBuilder queryBuilder = new();
|
||||
queryBuilder.Append($"select a.*, src.SubRoleCategoryItem from Approval a ");
|
||||
queryBuilder.Append("join SubRole sr on a.SubRoleID=sr.SubRoleID ");
|
||||
queryBuilder.Append("join SubRoleCategory src on sr.SubRoleCategoryID=src.SubRoleCategoryID ");
|
||||
queryBuilder.Append($"where UserID={userId} and ");
|
||||
queryBuilder.Append($"((CompletedDate >= '{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}') or ");
|
||||
queryBuilder.Append($"(CompletedDate is null));");
|
||||
string sql = queryBuilder.ToString();
|
||||
|
||||
approvals = (await _dalService.QueryAsync<Approval>(sql)).ToList();
|
||||
|
||||
_cache.Set($"approvalMembers{userId}", approvals, DateTimeOffset.Now.AddHours(1));
|
||||
}
|
||||
|
||||
return approvals;
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to get approvals for user ID {userId}, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdateApproval(Approval approval) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to update an approval");
|
||||
|
||||
if (approval is null) throw new ArgumentNullException("Approval cannot be null");
|
||||
|
||||
StringBuilder queryBuilder = new();
|
||||
queryBuilder.Append($"update Approval set IssueID={approval.IssueID}, RoleName='{approval.RoleName}', ");
|
||||
queryBuilder.Append($"SubRole='{approval.SubRole}', UserID={approval.UserID}, SubRoleID={approval.SubRoleID}, ");
|
||||
queryBuilder.Append($"ItemStatus={Convert.ToInt32(approval.ItemStatus)}, Step={approval.Step}, ");
|
||||
queryBuilder.Append($"NotifyDate='{approval.NotifyDate.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
||||
queryBuilder.Append($"AssignedDate='{approval.AssignedDate.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
||||
queryBuilder.Append($"CompletedDate='{approval.CompletedDate.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
||||
queryBuilder.Append($"Comments='{approval.Comments}', ");
|
||||
queryBuilder.Append($"TaskID={approval.TaskID} ");
|
||||
queryBuilder.Append($"where ApprovalID={approval.ApprovalID};");
|
||||
|
||||
int rowsUpdated = await _dalService.ExecuteAsync(queryBuilder.ToString());
|
||||
|
||||
if (rowsUpdated <= 0) throw new Exception("Unable to update approval in database");
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Approval update failed, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Approve(Approval approval) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to submit approval");
|
||||
|
||||
if (approval is null) throw new ArgumentNullException("Approval cannot be null");
|
||||
|
||||
StringBuilder queryBuilder = new();
|
||||
queryBuilder.Append($"update Approval set IssueID={approval.IssueID}, RoleName='{approval.RoleName}', ");
|
||||
queryBuilder.Append($"SubRole='{approval.SubRole}', UserID={approval.UserID}, SubRoleID={approval.SubRoleID}, ");
|
||||
queryBuilder.Append($"ItemStatus=1, Step={approval.Step}, ");
|
||||
if (approval.NotifyDate < DateTimeUtilities.MIN_DT)
|
||||
approval.NotifyDate = DateTimeUtilities.MIN_DT;
|
||||
queryBuilder.Append($"NotifyDate='{approval.NotifyDate.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
||||
queryBuilder.Append($"AssignedDate='{approval.AssignedDate.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
||||
queryBuilder.Append($"CompletedDate='{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
||||
queryBuilder.Append($"Comments='{approval.Comments}', ");
|
||||
queryBuilder.Append($"TaskID={approval.TaskID} ");
|
||||
queryBuilder.Append($"where ApprovalID={approval.ApprovalID};");
|
||||
|
||||
int rowsUpdated = await _dalService.ExecuteAsync(queryBuilder.ToString());
|
||||
|
||||
if (rowsUpdated <= 0) throw new Exception("Unable to submit approval in database");
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Approval failed, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Deny(Approval approval) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to deny approval");
|
||||
|
||||
if (approval is null) throw new ArgumentNullException("Approval cannot be null");
|
||||
|
||||
StringBuilder queryBuilder = new();
|
||||
queryBuilder.Append($"update Approval set IssueID={approval.IssueID}, RoleName='{approval.RoleName}', ");
|
||||
queryBuilder.Append($"SubRole='{approval.SubRole}', UserID={approval.UserID}, SubRoleID={approval.SubRoleID}, ");
|
||||
queryBuilder.Append($"ItemStatus=-1, Step={approval.Step}, ");
|
||||
if (approval.NotifyDate < DateTimeUtilities.MIN_DT)
|
||||
approval.NotifyDate = DateTimeUtilities.MIN_DT;
|
||||
queryBuilder.Append($"NotifyDate='{approval.NotifyDate.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
||||
queryBuilder.Append($"AssignedDate='{approval.AssignedDate.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
||||
queryBuilder.Append($"CompletedDate='{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
||||
queryBuilder.Append($"Comments='{approval.Comments}', ");
|
||||
queryBuilder.Append($"TaskID={approval.TaskID} ");
|
||||
queryBuilder.Append($"where ApprovalID={approval.ApprovalID};");
|
||||
|
||||
int rowsUpdated = await _dalService.ExecuteAsync(queryBuilder.ToString());
|
||||
|
||||
if (rowsUpdated <= 0) throw new Exception("Unable to deny approval in database");
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Approval denial failed, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
254
MesaFabApproval.API/Services/AuthenticationService.cs
Normal file
254
MesaFabApproval.API/Services/AuthenticationService.cs
Normal file
@ -0,0 +1,254 @@
|
||||
using System.DirectoryServices.AccountManagement;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
|
||||
using MesaFabApproval.API.Services;
|
||||
using MesaFabApproval.Shared.Models;
|
||||
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
namespace MesaFabApprovalAPI.Services;
|
||||
|
||||
public interface IAuthenticationService {
|
||||
public Task<LoginResult> AuthenticateUser(AuthAttempt login);
|
||||
public Task<LoginResult> AttemptLocalUserAuth(WindowsIdentity identity);
|
||||
public AuthTokens GenerateAuthTokens(AuthAttempt authAttempt, IEnumerable<string> roles);
|
||||
public Task<LoginResult> RefreshAuthTokens(AuthAttempt authAttempt);
|
||||
}
|
||||
|
||||
public class AuthenticationService : IAuthenticationService {
|
||||
private readonly ILogger<AuthenticationService> _logger;
|
||||
private readonly IMemoryCache _cache;
|
||||
private readonly IUserService _userService;
|
||||
|
||||
private readonly string _jwtIssuer;
|
||||
private readonly string _jwtAudience;
|
||||
private readonly string _jwtKey;
|
||||
|
||||
public AuthenticationService(ILogger<AuthenticationService> logger, IMemoryCache cache, IUserService userService) {
|
||||
_logger = logger ?? throw new ArgumentNullException("ILogger not injected");
|
||||
_cache = cache ?? throw new ArgumentNullException("IMemoryCache not injected");
|
||||
_userService = userService ?? throw new ArgumentNullException("IUserService not injected");
|
||||
|
||||
_jwtIssuer = Environment.GetEnvironmentVariable("FabApprovalJwtIssuer") ??
|
||||
throw new ArgumentNullException("FabApprovalJwtIssuer environment variable not found");
|
||||
_jwtAudience = Environment.GetEnvironmentVariable("FabApprovalJwtAudience") ??
|
||||
throw new ArgumentNullException("FabApprovalJwtAudience environment variable not found");
|
||||
_jwtKey = Environment.GetEnvironmentVariable("FabApprovalJwtKey") ??
|
||||
throw new ArgumentNullException("FabApprovalJwtKey environment variable not found");
|
||||
}
|
||||
|
||||
public async Task<LoginResult> AuthenticateUser(AuthAttempt login) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to authenticate user");
|
||||
|
||||
if (login is null) throw new ArgumentNullException("Login cannot be null");
|
||||
|
||||
string domain = "infineon.com";
|
||||
|
||||
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, domain)) {
|
||||
bool isValid = pc.ValidateCredentials(login.LoginID, login.Password);
|
||||
|
||||
if (isValid) {
|
||||
User? user = _cache.Get<User>($"user{login.LoginID}");
|
||||
|
||||
if (user is null) {
|
||||
user = await _userService.GetUserByLoginId(login.LoginID);
|
||||
|
||||
_cache.Set<User>($"user{login.LoginID}", user, DateTimeOffset.Now.AddDays(1));
|
||||
}
|
||||
|
||||
List<string> roles = new();
|
||||
|
||||
if (user.IsManager) roles.Add("manager");
|
||||
if (user.IsAdmin) roles.Add("admin");
|
||||
|
||||
AuthTokens tokens = GenerateAuthTokens(login, roles);
|
||||
|
||||
return new LoginResult {
|
||||
IsAuthenticated = true,
|
||||
AuthTokens = tokens,
|
||||
User = user
|
||||
};
|
||||
} else {
|
||||
return new LoginResult() {
|
||||
IsAuthenticated= false,
|
||||
AuthTokens = new() {
|
||||
JwtToken = "",
|
||||
RefreshToken = ""
|
||||
},
|
||||
User = null
|
||||
};
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"An exception occurred when attempting to authenticate user. Exception: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<LoginResult> AttemptLocalUserAuth(WindowsIdentity identity) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to authenticate local Windows system user");
|
||||
|
||||
if (identity is null) throw new ArgumentNullException("WindowsIdentity cannot be null");
|
||||
|
||||
User user = await _userService.GetUserByLoginId(identity.Name);
|
||||
|
||||
List<string> roles = new();
|
||||
|
||||
if (user.IsManager) roles.Add("manager");
|
||||
if (user.IsAdmin) roles.Add("admin");
|
||||
|
||||
AuthAttempt authAttempt = new() {
|
||||
LoginID = user.LoginID,
|
||||
};
|
||||
|
||||
AuthTokens tokens = GenerateAuthTokens(authAttempt, roles);
|
||||
|
||||
return new LoginResult {
|
||||
IsAuthenticated = true,
|
||||
AuthTokens = tokens,
|
||||
User = user
|
||||
};
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to authenticate local Windows system user, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public AuthTokens GenerateAuthTokens(AuthAttempt authAttempt, IEnumerable<string> roles) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to generate JWT");
|
||||
|
||||
if (authAttempt is null) throw new ArgumentNullException("AuthAttempt cannot be null");
|
||||
if (string.IsNullOrWhiteSpace(authAttempt.LoginID)) throw new ArgumentException("UserName cannot be null or empty");
|
||||
if (roles is null) throw new ArgumentNullException("roles cannot be null");
|
||||
|
||||
byte[] key = Encoding.ASCII.GetBytes(_jwtKey);
|
||||
|
||||
List<Claim> claims = new() {
|
||||
new Claim(nameof(authAttempt.LoginID), authAttempt.LoginID)
|
||||
};
|
||||
|
||||
foreach (string role in roles) {
|
||||
claims.Add(new Claim(ClaimTypes.Role, role));
|
||||
}
|
||||
|
||||
ClaimsIdentity identity = new ClaimsIdentity(claims);
|
||||
|
||||
SecurityTokenDescriptor tokenDescriptor = new SecurityTokenDescriptor {
|
||||
Issuer = _jwtIssuer,
|
||||
Audience = _jwtAudience,
|
||||
Subject = identity,
|
||||
NotBefore = DateTime.Now,
|
||||
Expires = DateTime.Now.AddHours(2),
|
||||
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
|
||||
};
|
||||
|
||||
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
|
||||
|
||||
JwtSecurityToken token = tokenHandler.CreateJwtSecurityToken(tokenDescriptor);
|
||||
|
||||
string jwt = tokenHandler.WriteToken(token);
|
||||
|
||||
string refreshToken = GenerateRefreshToken();
|
||||
|
||||
List<string>? refreshTokensForUser = _cache.Get<List<string>>(authAttempt.LoginID);
|
||||
|
||||
if (refreshTokensForUser is null)
|
||||
refreshTokensForUser = new List<string>();
|
||||
|
||||
if (refreshTokensForUser.Count > 9)
|
||||
refreshTokensForUser.RemoveRange(9, refreshTokensForUser.Count - 9);
|
||||
|
||||
refreshTokensForUser.Insert(0, refreshToken);
|
||||
|
||||
_cache.Set<List<string>>(authAttempt.LoginID, refreshTokensForUser, DateTimeOffset.Now.AddHours(4));
|
||||
|
||||
return new AuthTokens {
|
||||
JwtToken = jwt,
|
||||
RefreshToken = refreshToken
|
||||
};
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"An exception occurred when attempting to generate JWT. Exception: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<LoginResult> RefreshAuthTokens(AuthAttempt authAttempt) {
|
||||
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");
|
||||
|
||||
bool refreshTokenIsValid = IsRefreshTokenValid(authAttempt.LoginID, authAttempt.AuthTokens.RefreshToken);
|
||||
|
||||
if (refreshTokenIsValid) {
|
||||
User? user = _cache.Get<User>($"user{authAttempt.LoginID}");
|
||||
|
||||
if (user is null) {
|
||||
user = await _userService.GetUserByLoginId(authAttempt.LoginID);
|
||||
|
||||
_cache.Set<User>($"user{authAttempt.LoginID}", user, DateTimeOffset.Now.AddDays(1));
|
||||
}
|
||||
|
||||
List<string> roles = new();
|
||||
|
||||
if (user.IsManager) roles.Add("manager");
|
||||
if (user.IsAdmin) roles.Add("admin");
|
||||
|
||||
AuthTokens refreshedTokens = GenerateAuthTokens(authAttempt, roles);
|
||||
|
||||
LoginResult loginResult = new LoginResult() {
|
||||
IsAuthenticated = true,
|
||||
AuthTokens = refreshedTokens,
|
||||
User = user
|
||||
};
|
||||
|
||||
return loginResult;
|
||||
} else {
|
||||
throw new AuthenticationException("Invalid refresh token");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"An exception occurred when attempting to refresh auth tokens. Exception: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private string GenerateRefreshToken() {
|
||||
byte[] randomNumber = new byte[32];
|
||||
using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) {
|
||||
rng.GetBytes(randomNumber);
|
||||
return Convert.ToBase64String(randomNumber);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsRefreshTokenValid(string loginId, string refreshToken) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to determine if refresh token is valid");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(loginId)) throw new ArgumentNullException("LoginID cannot be null or empty");
|
||||
if (string.IsNullOrWhiteSpace(refreshToken))
|
||||
throw new ArgumentNullException("Refresh token cannot be null or empty");
|
||||
|
||||
List<string>? cachedRefreshTokensForUser = _cache.Get<List<string>>(loginId);
|
||||
|
||||
if (cachedRefreshTokensForUser is null || !cachedRefreshTokensForUser.Contains(refreshToken)) {
|
||||
_logger.LogInformation($"Could not find cached refresh tokens for user {loginId}");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"An exception occurred when attempting to validate refresh token. Exception: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
46
MesaFabApproval.API/Services/CAService.cs
Normal file
46
MesaFabApproval.API/Services/CAService.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace MesaFabApproval.API.Services;
|
||||
|
||||
public interface ICAService {
|
||||
Task<bool> IsValidCANumber(int number);
|
||||
}
|
||||
|
||||
public class CAService : ICAService {
|
||||
private readonly ILogger<CAService> _logger;
|
||||
private readonly IMemoryCache _cache;
|
||||
private readonly IDalService _dalService;
|
||||
|
||||
public CAService(ILogger<CAService> logger, IMemoryCache cache, IDalService dalService) {
|
||||
_logger = logger ?? throw new ArgumentNullException("ILogger not injected");
|
||||
_cache = cache ?? throw new ArgumentNullException("IMemoryCache not injected");
|
||||
_dalService = dalService ?? throw new ArgumentNullException("IDalService not injected");
|
||||
}
|
||||
|
||||
public async Task<bool> IsValidCANumber(int number) {
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to determine if {number} is a valid CA#");
|
||||
|
||||
if (number <= 0) return false;
|
||||
|
||||
IEnumerable<int> caNumbers = _cache.Get<IEnumerable<int>>("caNumbers") ?? new HashSet<int>();
|
||||
|
||||
if (caNumbers.Contains(number)) return true;
|
||||
|
||||
string sql = $"select count(CANo) as count from _8DCorrectiveAction where CANo={number}";
|
||||
|
||||
int rowsReturned = (await _dalService.QueryAsync<int>(sql)).FirstOrDefault();
|
||||
|
||||
if (rowsReturned > 0) {
|
||||
caNumbers.Append(number);
|
||||
_cache.Set("caNumbers", caNumbers);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to determine if {number} is a valid CA#, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
38
MesaFabApproval.API/Services/CustomerService.cs
Normal file
38
MesaFabApproval.API/Services/CustomerService.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace MesaFabApproval.API.Services;
|
||||
|
||||
public interface ICustomerService {
|
||||
Task<IEnumerable<string>> GetCustomerNames();
|
||||
}
|
||||
|
||||
public class CustomerService : ICustomerService {
|
||||
private readonly ILogger<CustomerService> _logger;
|
||||
private readonly IDalService _dalService;
|
||||
private readonly IMemoryCache _cache;
|
||||
|
||||
public CustomerService(ILogger<CustomerService> logger, IDalService dalService, IMemoryCache cache) {
|
||||
_logger = logger ?? throw new ArgumentNullException("ILogger not injected");
|
||||
_dalService = dalService ?? throw new ArgumentNullException("IDalService not injected");
|
||||
_cache = cache ?? throw new ArgumentNullException("IMemoryCache not injected");
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<string>> GetCustomerNames() {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get customer names");
|
||||
|
||||
IEnumerable<string>? customerNames = _cache.Get<IEnumerable<string>>("allCustomerNames");
|
||||
|
||||
if (customerNames is null) {
|
||||
string sql = "select ProductFamily from ProductFamilies;";
|
||||
|
||||
customerNames = (await _dalService.QueryAsync<string>(sql)).ToList();
|
||||
}
|
||||
|
||||
return customerNames;
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to get customer names, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
89
MesaFabApproval.API/Services/DalService.cs
Normal file
89
MesaFabApproval.API/Services/DalService.cs
Normal file
@ -0,0 +1,89 @@
|
||||
using System.Data;
|
||||
|
||||
using Dapper;
|
||||
|
||||
namespace MesaFabApproval.API.Services;
|
||||
|
||||
public interface IDalService {
|
||||
Task<IEnumerable<T>> QueryAsync<T>(string sql);
|
||||
Task<int> ExecuteAsync(string sql);
|
||||
}
|
||||
|
||||
public class DalService : IDalService {
|
||||
private static readonly int RETRIES = 3;
|
||||
private static readonly int BACKOFF_SECONDS_INTERVAL = 30;
|
||||
|
||||
private readonly ILogger<DalService> _logger;
|
||||
private readonly IDbConnectionService _dbConnectionService;
|
||||
|
||||
public DalService(IDbConnectionService dbConnectionService, ILogger<DalService> logger) {
|
||||
_dbConnectionService = dbConnectionService ??
|
||||
throw new ArgumentNullException("IDbConnectionService not injected");
|
||||
_logger = logger ??
|
||||
throw new ArgumentNullException("ILogger not injected");
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<T>> QueryAsync<T>(string sql) {
|
||||
if (sql is null) throw new ArgumentNullException("sql cannot be null");
|
||||
|
||||
int remainingRetries = RETRIES;
|
||||
bool queryWasSuccessful = false;
|
||||
Exception exception = null;
|
||||
IEnumerable<T> result = new List<T>();
|
||||
while (!queryWasSuccessful && remainingRetries > 0) {
|
||||
int backoffSeconds = (RETRIES - remainingRetries--) * BACKOFF_SECONDS_INTERVAL;
|
||||
Task.Delay(backoffSeconds * 1000).Wait();
|
||||
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to perform query with {sql}. Remaining retries: {remainingRetries}");
|
||||
|
||||
using (IDbConnection conn = _dbConnectionService.GetConnection()) {
|
||||
result = await conn.QueryAsync<T>(sql);
|
||||
}
|
||||
|
||||
queryWasSuccessful = true;
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"An exception occurred while attempting to perform a query. Exception: {ex.Message}");
|
||||
exception = ex;
|
||||
}
|
||||
}
|
||||
|
||||
if (!queryWasSuccessful && exception is not null) {
|
||||
throw exception;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<int> ExecuteAsync(string sql) {
|
||||
if (sql is null) throw new ArgumentNullException("sql cannot be null");
|
||||
|
||||
int remainingRetries = RETRIES;
|
||||
bool queryWasSuccessful = false;
|
||||
Exception exception = null;
|
||||
int rowsAffected = 0;
|
||||
while (!queryWasSuccessful && remainingRetries > 0) {
|
||||
int backoffSeconds = (RETRIES - remainingRetries--) * BACKOFF_SECONDS_INTERVAL;
|
||||
Task.Delay(backoffSeconds * 1000).Wait();
|
||||
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to execute {sql}. Remaining retries: {remainingRetries}");
|
||||
|
||||
using (IDbConnection conn = _dbConnectionService.GetConnection()) {
|
||||
rowsAffected = await conn.ExecuteAsync(sql);
|
||||
}
|
||||
|
||||
queryWasSuccessful = true;
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"An exception occurred while attempting to execute a query. Exception: {ex.Message}");
|
||||
exception = ex;
|
||||
}
|
||||
}
|
||||
|
||||
if (!queryWasSuccessful && exception is not null) {
|
||||
throw exception;
|
||||
}
|
||||
|
||||
return rowsAffected;
|
||||
}
|
||||
}
|
22
MesaFabApproval.API/Services/DbConnectionService.cs
Normal file
22
MesaFabApproval.API/Services/DbConnectionService.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System.Data;
|
||||
|
||||
using Microsoft.Data.SqlClient;
|
||||
|
||||
namespace MesaFabApproval.API.Services;
|
||||
|
||||
public interface IDbConnectionService {
|
||||
IDbConnection GetConnection();
|
||||
}
|
||||
|
||||
public class DbConnectionService : IDbConnectionService {
|
||||
private readonly string _dbConnectionString;
|
||||
|
||||
public DbConnectionService() {
|
||||
_dbConnectionString = Environment.GetEnvironmentVariable("FabApprovalDbConnectionString") ??
|
||||
throw new ArgumentNullException("FabApprovalDbConnectionString environment variable not found");
|
||||
}
|
||||
|
||||
public IDbConnection GetConnection() {
|
||||
return new SqlConnection(_dbConnectionString);
|
||||
}
|
||||
}
|
46
MesaFabApproval.API/Services/ECNService.cs
Normal file
46
MesaFabApproval.API/Services/ECNService.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace MesaFabApproval.API.Services;
|
||||
|
||||
public interface IECNService {
|
||||
Task<bool> IsValidECNNumber(int number);
|
||||
}
|
||||
|
||||
public class ECNService : IECNService {
|
||||
private readonly ILogger<ECNService> _logger;
|
||||
private readonly IMemoryCache _cache;
|
||||
private readonly IDalService _dalService;
|
||||
|
||||
public ECNService(ILogger<ECNService> logger, IMemoryCache cache, IDalService dalService) {
|
||||
_logger = logger ?? throw new ArgumentNullException("ILogger not injected");
|
||||
_cache = cache ?? throw new ArgumentNullException("IMemoryCache not injected");
|
||||
_dalService = dalService ?? throw new ArgumentNullException("IDalService not injected");
|
||||
}
|
||||
|
||||
public async Task<bool> IsValidECNNumber(int number) {
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to determine if {number} is a valid ECN#");
|
||||
|
||||
if (number <= 0) return false;
|
||||
|
||||
IEnumerable<int> ecnNumbers = _cache.Get<IEnumerable<int>>("ecnNumbers") ?? new HashSet<int>();
|
||||
|
||||
if (ecnNumbers.Contains(number)) return true;
|
||||
|
||||
string sql = $"select count(ECNNumber) as count from ECN where ECNNumber={number}";
|
||||
|
||||
int rowsReturned = (await _dalService.QueryAsync<int>(sql)).FirstOrDefault();
|
||||
|
||||
if (rowsReturned > 0) {
|
||||
ecnNumbers.Append(number);
|
||||
_cache.Set("ecnNumbers", ecnNumbers);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to determine if {number} is a valid ECN#, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
825
MesaFabApproval.API/Services/MRBService.cs
Normal file
825
MesaFabApproval.API/Services/MRBService.cs
Normal file
@ -0,0 +1,825 @@
|
||||
using System.Net;
|
||||
using System.Net.Mail;
|
||||
using System.Text;
|
||||
|
||||
using MesaFabApproval.Shared.Models;
|
||||
using MesaFabApproval.Shared.Utilities;
|
||||
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace MesaFabApproval.API.Services;
|
||||
|
||||
public interface IMRBService {
|
||||
Task<IEnumerable<MRB>> GetAllMRBs(bool bypassCache);
|
||||
Task<bool> MRBNumberIsValid(int number);
|
||||
Task<MRB> GetMRBById(int id, bool bypassCache = false);
|
||||
Task<MRB> GetMRBByTitle(string title, bool bypassCache);
|
||||
Task CreateNewMRB(MRB mrb);
|
||||
Task UpdateMRB(MRB mrb);
|
||||
Task CreateMRBAction(MRBAction mrbAction);
|
||||
Task<IEnumerable<MRBAction>> GetMRBActionsForMRB(int mrbNumber, bool bypassCache);
|
||||
Task UpdateMRBAction(MRBAction mrbAction);
|
||||
Task DeleteMRBAction(int mrbActionID, int mrbNumber);
|
||||
Task<IEnumerable<UploadResult>> UploadAttachments(IEnumerable<IFormFile> files, int mrbNumber);
|
||||
Task<IEnumerable<UploadResult>> UploadActionAttachments(IEnumerable<IFormFile> files, int actionId);
|
||||
Task<IEnumerable<MRBAttachment>> GetAllAttachmentsForMRB(int mrbNumber, bool bypassCache);
|
||||
Task<IEnumerable<MRBActionAttachment>> GetAllActionAttachmentsForMRB(int mrbNumber, bool bypassCache);
|
||||
Task DeleteAttachment(MRBAttachment attachment);
|
||||
Task NotifyNewApprovals(MRB mrb);
|
||||
Task NotifyApprovers(MRBNotification notification);
|
||||
Task NotifyOriginator(MRBNotification notification);
|
||||
Task NotifyQAPreApprover(MRBNotification notification);
|
||||
Task DeleteMRB(int mrbNumber);
|
||||
}
|
||||
|
||||
public class MRBService : IMRBService {
|
||||
private readonly ILogger<MRBService> _logger;
|
||||
private readonly IDalService _dalService;
|
||||
private readonly IMemoryCache _cache;
|
||||
private readonly IUserService _userService;
|
||||
private readonly IApprovalService _approvalService;
|
||||
private readonly ISmtpService _smtpService;
|
||||
|
||||
private readonly string _siteBaseUrl;
|
||||
private readonly string _mrbAttachmentPath;
|
||||
|
||||
public MRBService(ILogger<MRBService> logger,
|
||||
IDalService dalService,
|
||||
IMemoryCache cache,
|
||||
IUserService userService,
|
||||
IApprovalService approvalService,
|
||||
ISmtpService smtpService) {
|
||||
_logger = logger ?? throw new ArgumentNullException("ILogger not injected");
|
||||
_dalService = dalService ?? throw new ArgumentNullException("IDalService not injected");
|
||||
_cache = cache ?? throw new ArgumentNullException("IMemoryCache not injected");
|
||||
_userService = userService ?? throw new ArgumentNullException("IUserService not injected");
|
||||
_approvalService = approvalService ?? throw new ArgumentNullException("IApprovalService not injected");
|
||||
_smtpService = smtpService ?? throw new ArgumentNullException("ISmtpService not injected");
|
||||
_siteBaseUrl = Environment.GetEnvironmentVariable("NewFabApprovalBaseUrl") ??
|
||||
throw new ArgumentNullException("FabApprovalBaseUrl environment variable not found");
|
||||
_mrbAttachmentPath = Environment.GetEnvironmentVariable("FabApprovalMrbAttachmentPath") ??
|
||||
throw new ArgumentNullException("FabApprovalMrbAttachmentPath environment variable not found");
|
||||
}
|
||||
public async Task CreateNewMRB(MRB mrb) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to generate new MRB");
|
||||
|
||||
if (mrb is null) throw new ArgumentNullException("MRB cannot be null");
|
||||
|
||||
StringBuilder queryBuilder = new();
|
||||
queryBuilder.Append("insert into MRB (OriginatorID, Title, SubmittedDate, ");
|
||||
queryBuilder.Append("CloseDate, CancelDate, NumberOfLotsAffected, ApprovalDate, ");
|
||||
queryBuilder.Append("IssueDescription, CustomerImpacted, Department, Process, Val, RMANo, ");
|
||||
queryBuilder.Append("PCRBNo, SpecsImpacted, TrainingRequired, Status, StageNo, ");
|
||||
queryBuilder.Append("CustomerImpactedName, ProcessECNNumber, Tool, Category) values (");
|
||||
queryBuilder.Append($"{mrb.OriginatorID}, '{mrb.Title}', ");
|
||||
if (mrb.SubmittedDate < DateTimeUtilities.MIN_DT)
|
||||
mrb.SubmittedDate = DateTimeUtilities.MIN_DT;
|
||||
queryBuilder.Append($"'{mrb.SubmittedDate.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
||||
if (mrb.CloseDate > DateTimeUtilities.MAX_DT)
|
||||
mrb.CloseDate = DateTimeUtilities.MAX_DT;
|
||||
queryBuilder.Append($"'{mrb.CloseDate.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
||||
if (mrb.CancelDate > DateTimeUtilities.MAX_DT)
|
||||
mrb.CancelDate = DateTimeUtilities.MAX_DT;
|
||||
queryBuilder.Append($"'{mrb.CancelDate.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
||||
queryBuilder.Append($"{mrb.NumberOfLotsAffected}, ");
|
||||
if (mrb.ApprovalDate > DateTimeUtilities.MAX_DT)
|
||||
mrb.ApprovalDate = DateTimeUtilities.MAX_DT;
|
||||
queryBuilder.Append($"'{mrb.ApprovalDate.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
||||
queryBuilder.Append($"'{mrb.IssueDescription}', {Convert.ToUInt32(mrb.CustomerImpacted)}, ");
|
||||
queryBuilder.Append($"'{mrb.Department}', '{mrb.Process}', {mrb.Val}, {mrb.RMANo}, '{mrb.PCRBNo}', ");
|
||||
queryBuilder.Append($"{Convert.ToInt32(mrb.SpecsImpacted)}, {Convert.ToInt32(mrb.TrainingRequired)}, ");
|
||||
queryBuilder.Append($"'{mrb.Status}', {mrb.StageNo}, '{mrb.CustomerImpactedName}', ");
|
||||
queryBuilder.Append($"{mrb.ProcessECNNumber}, '{mrb.Tool}', '{mrb.Category}');");
|
||||
|
||||
int rowsCreated = await _dalService.ExecuteAsync(queryBuilder.ToString());
|
||||
|
||||
if (rowsCreated <= 0) throw new Exception("Unable to create new MRB");
|
||||
|
||||
mrb = await GetMRBByTitle(mrb.Title, true);
|
||||
|
||||
_cache.Set($"mrb{mrb.MRBNumber}", mrb, DateTimeOffset.Now.AddHours(1));
|
||||
_cache.Set($"mrb{mrb.Title}", mrb, DateTimeOffset.Now.AddHours(1));
|
||||
|
||||
IEnumerable<MRB>? allMrbs = _cache.Get<IEnumerable<MRB>>("allMrbs");
|
||||
if (allMrbs is not null) {
|
||||
List<MRB> mrbList = allMrbs.ToList();
|
||||
mrbList.Add(mrb);
|
||||
_cache.Set("allMrbs", mrbList, DateTimeOffset.Now.AddHours(1));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"An exception occurred when attempting to create new MRB. Exception: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<MRB>> GetAllMRBs(bool bypassCache) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get all MRBs");
|
||||
|
||||
IEnumerable<MRB>? allMrbs = null;
|
||||
if (!bypassCache) allMrbs = _cache.Get<IEnumerable<MRB>>("allMrbs");
|
||||
|
||||
if (allMrbs is null) {
|
||||
StringBuilder queryBuilder = new();
|
||||
queryBuilder.Append("select (u.FirstName + ' ' + u.LastName) as OriginatorName, m.* ");
|
||||
queryBuilder.Append("from MRB m join Users u on m.OriginatorID = u.UserID;");
|
||||
|
||||
allMrbs = (await _dalService.QueryAsync<MRB>(queryBuilder.ToString())).ToList();
|
||||
|
||||
_cache.Set("allMrbs", allMrbs, DateTimeOffset.Now.AddHours(1));
|
||||
}
|
||||
|
||||
if (allMrbs is null || allMrbs.Count() == 0)
|
||||
throw new Exception("No MRBs found");
|
||||
|
||||
return allMrbs;
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"An exception occurred when attempting to get all MRBs. Exception: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> MRBNumberIsValid(int number) {
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to determine if {number} is a valid MRB#");
|
||||
|
||||
if (number <= 0) return false;
|
||||
|
||||
IEnumerable<int> mrbNumbers = _cache.Get<IEnumerable<int>>("mrbNumbers") ??
|
||||
new HashSet<int>();
|
||||
|
||||
if (mrbNumbers.Contains(number)) return true;
|
||||
|
||||
string sql = $"select count(MRBNumber) as count from MRB where MRBNumber={number}";
|
||||
|
||||
int rowsReturned = (await _dalService.QueryAsync<int>(sql)).FirstOrDefault();
|
||||
|
||||
if (rowsReturned > 0) {
|
||||
mrbNumbers.Append(number);
|
||||
_cache.Set("mrbNumbers", mrbNumbers);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to determine if {number} is a valid MRB#, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<MRB> GetMRBById(int id, bool bypassCache = false) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get an MRB by ID");
|
||||
|
||||
if (id < 0) throw new ArgumentException("Invalid MRB number");
|
||||
|
||||
MRB? mrb = null;
|
||||
if (!bypassCache)
|
||||
mrb = _cache.Get<MRB>($"mrb{id}");
|
||||
|
||||
if (mrb is null) {
|
||||
StringBuilder queryBuilder = new();
|
||||
queryBuilder.Append("select (u.FirstName + ' ' + u.LastName) as OriginatorName, m.* ");
|
||||
queryBuilder.Append("from MRB m join Users u on m.OriginatorID = u.UserID ");
|
||||
queryBuilder.Append($"where m.MRBNumber = {id}");
|
||||
|
||||
mrb = (await _dalService.QueryAsync<MRB>(queryBuilder.ToString())).FirstOrDefault();
|
||||
|
||||
_cache.Set($"mrb{id}", mrb, DateTimeOffset.Now.AddHours(1));
|
||||
}
|
||||
|
||||
if (mrb is null) throw new Exception($"Unable to get MRB {id}");
|
||||
|
||||
return mrb;
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"An exception occurred when attempting to get an MRB. Exception: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<MRB> GetMRBByTitle(string title, bool bypassCache) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get an MRB by title");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(title)) throw new ArgumentException("Title cannot be null or empty");
|
||||
|
||||
MRB? mrb = null;
|
||||
|
||||
if (!bypassCache) mrb = _cache.Get<MRB>($"mrb{title}");
|
||||
|
||||
if (mrb is null) {
|
||||
StringBuilder queryBuilder = new();
|
||||
queryBuilder.Append("select (u.FirstName + ' ' + u.LastName) as OriginatorName, m.* ");
|
||||
queryBuilder.Append("from MRB m join Users u on m.OriginatorID = u.UserID ");
|
||||
queryBuilder.Append($"where m.Title = '{title}'");
|
||||
|
||||
mrb = (await _dalService.QueryAsync<MRB>(queryBuilder.ToString())).FirstOrDefault();
|
||||
|
||||
_cache.Set($"mrb{title}", mrb, DateTimeOffset.Now.AddHours(1));
|
||||
}
|
||||
|
||||
if (mrb is null) throw new Exception($"Unable to get MRB {title}");
|
||||
|
||||
return mrb;
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"An exception occurred when attempting to get an MRB. Exception: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdateMRB(MRB mrb) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to update an MRB");
|
||||
|
||||
if (mrb is null) throw new ArgumentNullException("MRB cannot be null");
|
||||
|
||||
StringBuilder queryBuilder = new();
|
||||
queryBuilder.Append($"update MRB set OriginatorID = {mrb.OriginatorID}, ");
|
||||
queryBuilder.Append($"Title = '{mrb.Title}', ");
|
||||
if (mrb.SubmittedDate < DateTimeUtilities.MIN_DT)
|
||||
mrb.SubmittedDate = DateTimeUtilities.MIN_DT;
|
||||
queryBuilder.Append($"SubmittedDate = '{mrb.SubmittedDate.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
||||
if (mrb.CloseDate > DateTimeUtilities.MAX_DT)
|
||||
mrb.CloseDate = DateTimeUtilities.MAX_DT;
|
||||
queryBuilder.Append($"CloseDate = '{mrb.CloseDate.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
||||
if (mrb.CancelDate > DateTimeUtilities.MAX_DT)
|
||||
mrb.CancelDate = DateTimeUtilities.MAX_DT;
|
||||
queryBuilder.Append($"CancelDate = '{mrb.CancelDate.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
||||
queryBuilder.Append($"NumberOfLotsAffected = {mrb.NumberOfLotsAffected}, ");
|
||||
if (mrb.ApprovalDate > DateTimeUtilities.MAX_DT)
|
||||
mrb.ApprovalDate = DateTimeUtilities.MAX_DT;
|
||||
queryBuilder.Append($"ApprovalDate = '{mrb.ApprovalDate.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
||||
queryBuilder.Append($"IssueDescription = '{mrb.IssueDescription}', ");
|
||||
queryBuilder.Append($"CustomerImpacted = {Convert.ToInt32(mrb.CustomerImpacted)}, ");
|
||||
queryBuilder.Append($"Department = '{mrb.Department}', ");
|
||||
queryBuilder.Append($"Process = '{mrb.Process}', ");
|
||||
queryBuilder.Append($"Val = {mrb.Val}, ");
|
||||
queryBuilder.Append($"RMANo = {mrb.RMANo}, ");
|
||||
queryBuilder.Append($"PCRBNo = '{mrb.PCRBNo}', ");
|
||||
queryBuilder.Append($"SpecsImpacted = {Convert.ToInt32(mrb.SpecsImpacted)}, ");
|
||||
queryBuilder.Append($"TrainingRequired = {Convert.ToInt32(mrb.TrainingRequired)}, ");
|
||||
queryBuilder.Append($"Status = '{mrb.Status}', StageNo = {mrb.StageNo}, ");
|
||||
queryBuilder.Append($"CustomerImpactedName = '{mrb.CustomerImpactedName}', ");
|
||||
queryBuilder.Append($"ProcessECNNumber = '{mrb.ProcessECNNumber}', ");
|
||||
queryBuilder.Append($"Tool = '{mrb.Tool}', Category = '{mrb.Category}' ");
|
||||
queryBuilder.Append($"where MRBNumber = {mrb.MRBNumber};");
|
||||
|
||||
int rowsAffected = await _dalService.ExecuteAsync(queryBuilder.ToString());
|
||||
|
||||
if (rowsAffected <= 0) throw new Exception($"Unable to update MRB {mrb.MRBNumber}");
|
||||
|
||||
_cache.Set($"mrb{mrb.MRBNumber}", mrb, DateTimeOffset.Now.AddHours(1));
|
||||
_cache.Set($"mrb{mrb.Title}", mrb, DateTimeOffset.Now.AddHours(1));
|
||||
|
||||
IEnumerable<MRB>? allMrbs = _cache.Get<IEnumerable<MRB>>("allMrbs");
|
||||
if (allMrbs is not null) {
|
||||
List<MRB> mrbList = allMrbs.ToList();
|
||||
mrbList.RemoveAll(m => m.MRBNumber ==mrb.MRBNumber);
|
||||
mrbList.Add(mrb);
|
||||
_cache.Set("allMrbs", mrbList, DateTimeOffset.Now.AddHours(1));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"An exception occurred when attempting to update an MRB. Exception: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task CreateMRBAction(MRBAction mrbAction) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to generate new MRB action");
|
||||
|
||||
if (mrbAction is null) throw new ArgumentNullException("MRB action cannot be null");
|
||||
|
||||
StringBuilder queryBuilder = new();
|
||||
queryBuilder.Append("insert into MRBAction (Action, Customer, Quantity, PartNumber, LotNumber, MRBNumber, ");
|
||||
queryBuilder.Append("ConvertFrom, ConvertTo, Justification) ");
|
||||
queryBuilder.Append($"values ('{mrbAction.Action}', '{mrbAction.Customer}', {mrbAction.Quantity}, ");
|
||||
queryBuilder.Append($"'{mrbAction.PartNumber}', '{mrbAction.LotNumber}', {mrbAction.MRBNumber}, ");
|
||||
queryBuilder.Append($"'{mrbAction.ConvertFrom}', '{mrbAction.ConvertTo}', '{mrbAction.Justification}');");
|
||||
|
||||
int rowsAffected = await _dalService.ExecuteAsync(queryBuilder.ToString());
|
||||
|
||||
if (rowsAffected <= 0) throw new Exception("Unable to create MRB action in database");
|
||||
|
||||
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"An exception occurred when attempting to create new MRB action. Exception: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<MRBAction>> GetMRBActionsForMRB(int mrbNumber, bool bypassCache) {
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to get MRB actions for MRB {mrbNumber}");
|
||||
|
||||
if (mrbNumber <= 0) throw new ArgumentException($"{mrbNumber} is not a valid MRB number");
|
||||
|
||||
IEnumerable<MRBAction>? mrbActions = null;
|
||||
|
||||
if (!bypassCache)
|
||||
_cache.Get<IEnumerable<MRBAction>>($"mrbActions{mrbNumber}");
|
||||
|
||||
if (mrbActions is null) {
|
||||
string sql = $"select * from MRBAction where MRBNumber = {mrbNumber}";
|
||||
|
||||
mrbActions = (await _dalService.QueryAsync<MRBAction>(sql)).ToList();
|
||||
|
||||
if (mrbActions is not null) {
|
||||
foreach (MRBAction action in mrbActions) {
|
||||
if (action.CompletedDate < DateTime.MaxValue && action.CompletedByUserID > 0) {
|
||||
action.CompletedByUser = await _userService.GetUserByUserId(action.CompletedByUserID);
|
||||
}
|
||||
}
|
||||
|
||||
_cache.Set($"mrbActions{mrbNumber}", mrbActions, DateTimeOffset.Now.AddMinutes(30));
|
||||
}
|
||||
}
|
||||
|
||||
if (mrbActions is null) throw new Exception($"Unable to find MRB actions for MRB {mrbNumber}");
|
||||
|
||||
return mrbActions;
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to get MRB actions for MRB {mrbNumber}, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdateMRBAction(MRBAction mrbAction) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to update MRB action");
|
||||
|
||||
if (mrbAction is null) throw new ArgumentNullException("MRB action cannot be null");
|
||||
|
||||
StringBuilder queryBuilder = new();
|
||||
queryBuilder.Append($"update MRBAction set Action = '{mrbAction.Action}', ");
|
||||
queryBuilder.Append($"Customer = '{mrbAction.Customer}', ");
|
||||
queryBuilder.Append($"Quantity = {mrbAction.Quantity}, ");
|
||||
queryBuilder.Append($"PartNumber = '{mrbAction.PartNumber}', ");
|
||||
queryBuilder.Append($"LotNumber = '{mrbAction.LotNumber}', ");
|
||||
if (mrbAction.AssignedDate < DateTimeUtilities.MIN_DT)
|
||||
mrbAction.AssignedDate = DateTimeUtilities.MIN_DT;
|
||||
queryBuilder.Append($"AssignedDate= '{mrbAction.AssignedDate.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
||||
if (mrbAction.CompletedDate > DateTimeUtilities.MAX_DT)
|
||||
mrbAction.CompletedDate = DateTimeUtilities.MAX_DT;
|
||||
queryBuilder.Append($"CompletedDate= '{mrbAction.CompletedDate.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
||||
queryBuilder.Append($"CompletedByUserID={mrbAction.CompletedByUserID}, ");
|
||||
queryBuilder.Append($"ConvertFrom='{mrbAction.ConvertFrom}', ");
|
||||
queryBuilder.Append($"ConvertTo='{mrbAction.ConvertTo}', ");
|
||||
queryBuilder.Append($"Justification='{mrbAction.Justification}' ");
|
||||
queryBuilder.Append($"where ActionID={mrbAction.ActionID};");
|
||||
|
||||
int rowsAffected = await _dalService.ExecuteAsync(queryBuilder.ToString());
|
||||
|
||||
if (rowsAffected <= 0) throw new Exception($"There were no MRB actions found with MRB# {mrbAction.MRBNumber}");
|
||||
|
||||
List<MRBAction>? mrbActions = _cache.Get<IEnumerable<MRBAction>>($"mrbActions{mrbAction.MRBNumber}")?.ToList();
|
||||
if (mrbActions is not null) {
|
||||
mrbActions.RemoveAll(m => m.ActionID == mrbAction.ActionID);
|
||||
mrbActions.Add(mrbAction);
|
||||
_cache.Set($"mrbActions{mrbAction.MRBNumber}", mrbActions, DateTimeOffset.Now.AddMinutes(30));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to update MRB action, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DeleteMRBAction(int mrbActionID, int mrbNumber) {
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to delete MRB action {mrbActionID}");
|
||||
|
||||
if (mrbActionID <= 0) throw new ArgumentException($"{mrbActionID} is not a valid MRBActionID");
|
||||
if (mrbNumber <= 0) throw new ArgumentException($"{mrbNumber} is not a valid MRBNumber");
|
||||
|
||||
string sql = $"delete from MRBAction where ActionID = {mrbActionID};";
|
||||
|
||||
int rowsAffected = await _dalService.ExecuteAsync(sql);
|
||||
|
||||
if (rowsAffected <= 0) throw new Exception($"No MRB action was found to delete for ActionID {mrbActionID}");
|
||||
|
||||
List<MRBAction>? mrbActions = _cache.Get<IEnumerable<MRBAction>>($"mrbActions{mrbNumber}")?.ToList();
|
||||
if (mrbActions is not null) {
|
||||
mrbActions.RemoveAll(m => m.ActionID == mrbActionID);
|
||||
_cache.Set($"mrbActions{mrbNumber}", mrbActions, DateTimeOffset.Now.AddMinutes(30));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"An exception occurred when attempting to delete MRB action {mrbActionID}. Exception: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<UploadResult>> UploadAttachments(IEnumerable<IFormFile> files, int mrbNumber) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to upload attachments");
|
||||
|
||||
List<UploadResult> uploadResults = new();
|
||||
|
||||
if (files is null) throw new ArgumentNullException("Files cannot be null");
|
||||
if (files.Count() <= 0) throw new ArgumentException("Files cannot be empty");
|
||||
if (mrbNumber <= 0) throw new ArgumentException($"{mrbNumber} is not a valid MRB number");
|
||||
|
||||
foreach (IFormFile file in files) {
|
||||
try {
|
||||
if (file is null) throw new ArgumentException("File cannot be null");
|
||||
if (file.Length <= 0) throw new ArgumentException("File size cannot be zero");
|
||||
|
||||
string encodedName = WebUtility.HtmlEncode(file.FileName);
|
||||
string path = $"{_mrbAttachmentPath}\\{mrbNumber}\\{encodedName}";
|
||||
|
||||
await SaveFileToFileSystem(file, path);
|
||||
await SaveAttachmentInDb(file, path, mrbNumber);
|
||||
|
||||
UploadResult uploadResult = new() {
|
||||
UploadSuccessful = true,
|
||||
FileName = file.FileName
|
||||
};
|
||||
uploadResults.Add(uploadResult);
|
||||
} catch (Exception ex) {
|
||||
UploadResult uploadResult = new() {
|
||||
UploadSuccessful = false,
|
||||
FileName = file.FileName,
|
||||
Error = ex.Message
|
||||
};
|
||||
uploadResults.Add(uploadResult);
|
||||
}
|
||||
}
|
||||
|
||||
return uploadResults;
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"An exception occurred when attempting to upload attachment. Exception: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<UploadResult>> UploadActionAttachments(IEnumerable<IFormFile> files, int actionId) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to upload action attachments");
|
||||
|
||||
List<UploadResult> uploadResults = new();
|
||||
|
||||
if (files is null) throw new ArgumentNullException("Files cannot be null");
|
||||
if (files.Count() <= 0) throw new ArgumentException("Files cannot be empty");
|
||||
if (actionId <= 0) throw new ArgumentException($"{actionId} is not a valid MRB action ID");
|
||||
|
||||
List<Task> taskList = new();
|
||||
foreach (IFormFile file in files) {
|
||||
try {
|
||||
if (file is null) throw new ArgumentException("File cannot be null");
|
||||
if (file.Length <= 0) throw new ArgumentException("File size cannot be zero");
|
||||
|
||||
string encodedName = WebUtility.HtmlEncode(file.FileName);
|
||||
string path = $"{_mrbAttachmentPath}\\{actionId}\\{encodedName}";
|
||||
|
||||
taskList.Add(SaveFileToFileSystem(file, path));
|
||||
taskList.Add(SaveActionAttachmentInDb(file, path, actionId));
|
||||
|
||||
UploadResult uploadResult = new() {
|
||||
UploadSuccessful = true,
|
||||
FileName = file.Name
|
||||
};
|
||||
uploadResults.Add(uploadResult);
|
||||
} catch (Exception ex) {
|
||||
UploadResult uploadResult = new() {
|
||||
UploadSuccessful = false,
|
||||
FileName = file.Name,
|
||||
Error = ex.Message
|
||||
};
|
||||
uploadResults.Add(uploadResult);
|
||||
}
|
||||
}
|
||||
|
||||
Task.WaitAll(taskList.ToArray());
|
||||
|
||||
return uploadResults;
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"An exception occurred when attempting to upload action attachment. Exception: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<MRBAttachment>> GetAllAttachmentsForMRB(int mrbNumber, bool bypassCache) {
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to get all attachments for MRB {mrbNumber}");
|
||||
|
||||
if (mrbNumber <= 0) throw new ArgumentException($"{mrbNumber} is not a valid MRB number");
|
||||
|
||||
IEnumerable<MRBAttachment>? attachments = null;
|
||||
if (!bypassCache)
|
||||
_cache.Get<IEnumerable<MRBAttachment>>($"mrbAttachments{mrbNumber}");
|
||||
|
||||
if (attachments is null) {
|
||||
string sql = $"select * from MRBAttachment where MRBNumber = {mrbNumber};";
|
||||
|
||||
attachments = (await _dalService.QueryAsync<MRBAttachment>(sql)).ToList();
|
||||
|
||||
_cache.Set($"mrbAttachments{mrbNumber}", attachments, DateTimeOffset.Now.AddMinutes(15));
|
||||
}
|
||||
|
||||
return attachments;
|
||||
} catch (Exception ex) {
|
||||
StringBuilder errMsgBuilder = new();
|
||||
errMsgBuilder.Append($"An error occurred when attempting to get all attachments for MRB {mrbNumber}. ");
|
||||
errMsgBuilder.Append($"Exception: {ex.Message}");
|
||||
_logger.LogError(errMsgBuilder.ToString());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<MRBActionAttachment>> GetAllActionAttachmentsForMRB(int mrbNumber, bool bypassCache) {
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to get all action attachments for MRB {mrbNumber}");
|
||||
|
||||
if (mrbNumber <= 0) throw new ArgumentException($"{mrbNumber} is not a valid MRB#");
|
||||
|
||||
List<MRBActionAttachment>? attachments = null;
|
||||
if (!bypassCache)
|
||||
attachments = _cache.Get<List<MRBActionAttachment>>($"mrbActionAttachments{mrbNumber}");
|
||||
|
||||
if (attachments is null) {
|
||||
attachments = new List<MRBActionAttachment>();
|
||||
|
||||
foreach (MRBAction action in await GetMRBActionsForMRB(mrbNumber, false)) {
|
||||
string sql = $"select * from MRBActionAttachment where ActionID = {action.ActionID};";
|
||||
|
||||
IEnumerable<MRBActionAttachment> newAttachments =
|
||||
(await _dalService.QueryAsync<MRBActionAttachment>(sql)).ToList();
|
||||
|
||||
attachments.AddRange(newAttachments);
|
||||
}
|
||||
|
||||
_cache.Set($"mrbActionAttachments{mrbNumber}", attachments, DateTimeOffset.Now.AddMinutes(15));
|
||||
}
|
||||
|
||||
return attachments;
|
||||
} catch (Exception ex) {
|
||||
StringBuilder errMsgBuilder = new();
|
||||
errMsgBuilder.Append($"An error occurred when attempting to get all attachments for MRB action {mrbNumber}. ");
|
||||
errMsgBuilder.Append($"Exception: {ex.Message}");
|
||||
_logger.LogError(errMsgBuilder.ToString());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DeleteAttachment(MRBAttachment attachment) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to delete an attachment");
|
||||
|
||||
if (attachment is null) throw new ArgumentNullException("Attachment cannot be null");
|
||||
if (!File.Exists(attachment.Path)) throw new FileNotFoundException("No file found at provided path");
|
||||
|
||||
File.Delete(attachment.Path);
|
||||
|
||||
string sql = $"delete from MRBAttachment where AttachmentID = {attachment.AttachmentID};";
|
||||
|
||||
int rowsDeleted = await _dalService.ExecuteAsync(sql);
|
||||
|
||||
if (rowsDeleted <= 0)
|
||||
throw new Exception($"No attachments found in the database with attachment ID {attachment.AttachmentID}");
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"An exception occurred when attempting to delete an attachment. Exception: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task NotifyNewApprovals(MRB mrb) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to notify approvers");
|
||||
|
||||
if (mrb is null) throw new ArgumentNullException("MRB cannot be null");
|
||||
|
||||
IEnumerable<Approval> approvals = await _approvalService.GetApprovalsForIssueId(mrb.MRBNumber, true);
|
||||
|
||||
List<Approval> approvalsNeedingNotification = approvals.Where(a => a.NotifyDate <= DateTimeUtilities.MIN_DT).ToList();
|
||||
|
||||
HashSet<string> emailsAlreadySent = new();
|
||||
foreach (Approval approval in approvalsNeedingNotification) {
|
||||
User user = await _userService.GetUserByUserId(approval.UserID);
|
||||
|
||||
if (!emailsAlreadySent.Contains(user.Email)) {
|
||||
emailsAlreadySent.Add(user.Email);
|
||||
|
||||
List<MailAddress> toAddresses = new();
|
||||
toAddresses.Add(new MailAddress(user.Email));
|
||||
|
||||
List<MailAddress> ccAddresses = new();
|
||||
|
||||
string subject = $"[New Task] Mesa Fab Approval - MRB# {mrb.MRBNumber} - {mrb.Title}";
|
||||
|
||||
StringBuilder bodyBuilder = new();
|
||||
bodyBuilder.Append($"MRB# {mrb.MRBNumber} [{mrb.Title}] is ready for your approval. ");
|
||||
bodyBuilder.Append($"The assigned role is {approval.SubRoleCategoryItem}. <br /> <br />");
|
||||
bodyBuilder.Append($"Click {_siteBaseUrl}/redirect?redirectPath=mrb/{approval.IssueID} to view the task.");
|
||||
|
||||
await _smtpService.SendEmail(toAddresses, ccAddresses, subject, bodyBuilder.ToString());
|
||||
|
||||
approval.NotifyDate = DateTime.Now;
|
||||
await _approvalService.UpdateApproval(approval);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to notify approvers, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task NotifyApprovers(MRBNotification notification) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to send notification to approvers");
|
||||
|
||||
if (notification is null) throw new ArgumentNullException("notification cannot be null");
|
||||
if (notification.MRB is null) throw new ArgumentNullException("MRB cannot be null");
|
||||
if (string.IsNullOrWhiteSpace(notification.Message)) throw new ArgumentException("message cannot be null or empty");
|
||||
|
||||
IEnumerable<Approval> approvals = await _approvalService.GetApprovalsForIssueId(notification.MRB.MRBNumber, true);
|
||||
|
||||
HashSet<string> emailsAlreadySent = new();
|
||||
foreach (Approval approval in approvals) {
|
||||
User user = await _userService.GetUserByUserId(approval.UserID);
|
||||
|
||||
if (!emailsAlreadySent.Contains(user.Email)) {
|
||||
emailsAlreadySent.Add(user.Email);
|
||||
|
||||
List<MailAddress> toAddresses = new();
|
||||
toAddresses.Add(new MailAddress(user.Email));
|
||||
|
||||
List<MailAddress> ccAddresses = new();
|
||||
|
||||
string subject = $"[Update] Mesa Fab Approval - MRB# {notification.MRB.MRBNumber} - {notification.MRB.Title}";
|
||||
|
||||
StringBuilder bodyBuilder = new();
|
||||
bodyBuilder.Append($"{notification.Message} <br /> <br />");
|
||||
bodyBuilder.Append($"Click {_siteBaseUrl}/redirect?redirectPath=mrb/{approval.IssueID} to view the MRB.");
|
||||
|
||||
await _smtpService.SendEmail(toAddresses, ccAddresses, subject, bodyBuilder.ToString());
|
||||
|
||||
approval.NotifyDate = DateTime.Now;
|
||||
await _approvalService.UpdateApproval(approval);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to send notification to originator, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task NotifyOriginator(MRBNotification notification) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to send notification to originator");
|
||||
|
||||
if (notification is null) throw new ArgumentNullException("notification cannot be null");
|
||||
if (notification.MRB is null) throw new ArgumentNullException("MRB cannot be null");
|
||||
if (string.IsNullOrWhiteSpace(notification.Message)) throw new ArgumentException("message cannot be null or empty");
|
||||
|
||||
User user = await _userService.GetUserByUserId(notification.MRB.OriginatorID);
|
||||
|
||||
List<MailAddress> toAddresses = new();
|
||||
toAddresses.Add(new MailAddress(user.Email));
|
||||
|
||||
List<MailAddress> ccAddresses = new();
|
||||
|
||||
string subject = $"[Update] Mesa Fab Approval - MRB# {notification.MRB.MRBNumber} - {notification.MRB.Title}";
|
||||
|
||||
StringBuilder bodyBuilder = new();
|
||||
bodyBuilder.Append($"{notification.Message} <br /> <br />");
|
||||
bodyBuilder.Append($"Click {_siteBaseUrl}/redirect?redirectPath=mrb/{notification.MRB.MRBNumber} to view the MRB.");
|
||||
|
||||
await _smtpService.SendEmail(toAddresses, ccAddresses, subject, bodyBuilder.ToString());
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to send notification to originator, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task NotifyQAPreApprover(MRBNotification notification) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to send notification to QA pre approver");
|
||||
|
||||
if (notification is null) throw new ArgumentNullException("notification cannot be null");
|
||||
if (notification.MRB is null) throw new ArgumentNullException("MRB cannot be null");
|
||||
if (string.IsNullOrWhiteSpace(notification.Message)) throw new ArgumentException("message cannot be null or empty");
|
||||
|
||||
string roleName = "QA_PRE_APPROVAL";
|
||||
|
||||
int roleId = await _approvalService.GetRoleIdForRoleName(roleName);
|
||||
|
||||
if (roleId <= 0) throw new Exception($"could not find {roleName} role ID");
|
||||
|
||||
SubRole? subRole = (await _approvalService.GetSubRolesForSubRoleName(roleName, roleId)).FirstOrDefault();
|
||||
|
||||
if (subRole is null)
|
||||
throw new Exception("Unable to find QA pre approver role");
|
||||
|
||||
IEnumerable<User> members = await _approvalService.GetApprovalGroupMembers(subRole.SubRoleID);
|
||||
|
||||
List<MailAddress> toAddresses = new();
|
||||
foreach (User member in members)
|
||||
toAddresses.Add(new MailAddress(member.Email));
|
||||
|
||||
List<MailAddress> ccAddresses = new();
|
||||
|
||||
string subject = $"[Update] Mesa Fab Approval - MRB# {notification.MRB.MRBNumber} - {notification.MRB.Title}";
|
||||
|
||||
StringBuilder bodyBuilder = new();
|
||||
bodyBuilder.Append($"{notification.Message} <br /> <br />");
|
||||
bodyBuilder.Append($"Click {_siteBaseUrl}/redirect?redirectPath=mrb/{notification.MRB.MRBNumber} to view the MRB.");
|
||||
|
||||
await _smtpService.SendEmail(toAddresses, ccAddresses, subject, bodyBuilder.ToString());
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to send notification to QA pre approver, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DeleteMRB(int mrbNumber) {
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to delete MRB# {mrbNumber}");
|
||||
|
||||
if (mrbNumber <= 0) throw new ArgumentException($"{mrbNumber} is not a valid MRB number");
|
||||
|
||||
string sql = $"delete from MRB where MRBNumber={mrbNumber}";
|
||||
|
||||
int rowsAffected = await _dalService.ExecuteAsync(sql);
|
||||
|
||||
if (rowsAffected <= 0) throw new Exception($"MRB {mrbNumber} not deleted from database");
|
||||
|
||||
IEnumerable<MRB>? allMrbs = _cache.Get<IEnumerable<MRB>>("allMrbs");
|
||||
if (allMrbs is not null) {
|
||||
List<MRB> mrbList = allMrbs.ToList();
|
||||
mrbList.RemoveAll(m => m.MRBNumber == mrbNumber);
|
||||
_cache.Set("allMrbs", mrbList, DateTimeOffset.Now.AddHours(1));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to delete MRB {mrbNumber}, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveFileToFileSystem(IFormFile file, string path) {
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to save file to file system");
|
||||
|
||||
if (file is null) throw new ArgumentNullException("File cannot be null");
|
||||
if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("Path cannot be null or empty");
|
||||
|
||||
if (File.Exists(path)) throw new Exception($"A file already exists with name {file.FileName}");
|
||||
|
||||
string? directoryPath = Path.GetDirectoryName(path);
|
||||
if (!string.IsNullOrWhiteSpace(directoryPath))
|
||||
Directory.CreateDirectory(directoryPath);
|
||||
|
||||
using (Stream stream = File.Create(path)) {
|
||||
await file.CopyToAsync(stream);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"An exception occurred when attempting to save file to file system. Exception: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveAttachmentInDb(IFormFile file, string path, int mrbNumber) {
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to save attachment to database");
|
||||
|
||||
if (file is null) throw new ArgumentNullException("File cannot be null");
|
||||
if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("Path cannot be null or empty");
|
||||
if (mrbNumber <= 0) throw new ArgumentException($"{mrbNumber} is not a valid MRB number");
|
||||
|
||||
StringBuilder queryBuilder = new();
|
||||
queryBuilder.Append("insert into MRBAttachment (MRBNumber, FileName, UploadDate, Path) ");
|
||||
queryBuilder.Append($"values ({mrbNumber}, '{file.FileName}', ");
|
||||
queryBuilder.Append($"'{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}', '{path}');");
|
||||
|
||||
int rowsAffected = await _dalService.ExecuteAsync(queryBuilder.ToString());
|
||||
|
||||
if (rowsAffected <= 0)
|
||||
throw new Exception("Unable to insert attachment in database");
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"An exception occurred when attempting to save file to DB. Exception: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveActionAttachmentInDb(IFormFile file, string path, int actionId) {
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to save action attachment to database");
|
||||
|
||||
if (file is null) throw new ArgumentNullException("File cannot be null");
|
||||
if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("Path cannot be null or empty");
|
||||
if (actionId <= 0) throw new ArgumentException($"{actionId} is not a valid MRB action ID");
|
||||
|
||||
StringBuilder queryBuilder = new();
|
||||
queryBuilder.Append("insert into MRBActionAttachment (ActionID, FileName, UploadDate, Path) ");
|
||||
queryBuilder.Append($"values ({actionId}, '{file.FileName}', ");
|
||||
queryBuilder.Append($"'{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}', '{path}');");
|
||||
|
||||
int rowsAffected = await _dalService.ExecuteAsync(queryBuilder.ToString());
|
||||
|
||||
if (rowsAffected <= 0)
|
||||
throw new Exception("Unable to insert action attachment in database");
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"An exception occurred when attempting to save file to DB. Exception: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
214
MesaFabApproval.API/Services/PCRBService.cs
Normal file
214
MesaFabApproval.API/Services/PCRBService.cs
Normal file
@ -0,0 +1,214 @@
|
||||
using System.Text;
|
||||
|
||||
using MesaFabApproval.Shared.Models;
|
||||
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace MesaFabApproval.API.Services;
|
||||
|
||||
public interface IPCRBService {
|
||||
public Task CreateNewPCRB(PCRB pcrb);
|
||||
public Task<IEnumerable<PCRB>> GetAllPCRBs(bool bypassCache);
|
||||
public Task<PCRB> GetPCRBByPlanNumber(int planNumber, bool bypassCache);
|
||||
public Task<PCRB> GetPCRBByTitle(string title, bool bypassCache);
|
||||
public Task UpdatePCRB(PCRB pcrb);
|
||||
public Task DeletePCRB(int planNumber);
|
||||
}
|
||||
|
||||
public class PCRBService : IPCRBService {
|
||||
private readonly ILogger<PCRBService> _logger;
|
||||
private readonly IDalService _dalService;
|
||||
private readonly IMemoryCache _cache;
|
||||
private readonly IUserService _userService;
|
||||
|
||||
|
||||
public PCRBService(ILogger<PCRBService> logger,
|
||||
IDalService dalService,
|
||||
IMemoryCache cache,
|
||||
IUserService userService) {
|
||||
_logger = logger ?? throw new ArgumentNullException("ILogger not injected");
|
||||
_dalService = dalService ?? throw new ArgumentNullException("IDalService not injected");
|
||||
_cache = cache ?? throw new ArgumentNullException("IMemoryCache not injected");
|
||||
_userService = userService ?? throw new ArgumentNullException("IUserService not injected");
|
||||
}
|
||||
|
||||
public async Task CreateNewPCRB(PCRB pcrb) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to create new PCRB");
|
||||
|
||||
if (pcrb is null) throw new ArgumentNullException("PCRB cannot be null");
|
||||
|
||||
StringBuilder queryBuilder = new();
|
||||
queryBuilder.Append("insert into CCChangeControl (OwnerID, Title, ChangeLevel, ReasonForChange, ");
|
||||
queryBuilder.Append("ChangeDescription, IsITAR, CurrentStep, InsertTimeStamp, LastUpdateDate) ");
|
||||
queryBuilder.Append($"values ({pcrb.OwnerID}, '{pcrb.Title}', '{pcrb.ChangeLevel}', ");
|
||||
queryBuilder.Append($"'{pcrb.ReasonForChange}', '{pcrb.ChangeDescription}', ");
|
||||
queryBuilder.Append($"{Convert.ToInt32(pcrb.IsITAR)}, {pcrb.CurrentStep}, ");
|
||||
queryBuilder.Append($"'{pcrb.InsertTimeStamp.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
||||
queryBuilder.Append($"'{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}')");
|
||||
|
||||
int rowsCreated = await _dalService.ExecuteAsync(queryBuilder.ToString());
|
||||
|
||||
if (rowsCreated <= 0) throw new Exception("unable to insert new PCRB in the database");
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to create new PCRB, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PCRB>> GetAllPCRBs(bool bypassCache) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get all PCRBs");
|
||||
|
||||
IEnumerable<PCRB>? allPCRBs = null;
|
||||
if (!bypassCache) allPCRBs = _cache.Get<IEnumerable<PCRB>>("allPCRBs");
|
||||
|
||||
if (allPCRBs is null) {
|
||||
string sql = "select * from CCChangeControl";
|
||||
|
||||
allPCRBs = (await _dalService.QueryAsync<PCRB>(sql)).ToList();
|
||||
|
||||
foreach (PCRB pcrb in allPCRBs) {
|
||||
if (string.IsNullOrWhiteSpace(pcrb.OwnerName) && pcrb.OwnerID > 0)
|
||||
pcrb.OwnerName = (await _userService.GetUserByUserId(pcrb.OwnerID)).GetFullName();
|
||||
}
|
||||
|
||||
_cache.Set("allPCRBs", allPCRBs, DateTimeOffset.Now.AddHours(1));
|
||||
}
|
||||
|
||||
if (allPCRBs is null || allPCRBs.Count() == 0)
|
||||
throw new Exception("no PCRBs found");
|
||||
|
||||
return allPCRBs;
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to get all PCRBs, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<PCRB> GetPCRBByPlanNumber(int planNumber, bool bypassCache) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get a PCRB by plan#");
|
||||
|
||||
if (planNumber <= 0) throw new ArgumentException($"{planNumber} is not a valid PCRB#");
|
||||
|
||||
PCRB? pcrb = null;
|
||||
|
||||
if (!bypassCache) pcrb = _cache.Get<PCRB>($"pcrb{planNumber}");
|
||||
|
||||
if (pcrb is null) {
|
||||
string sql = $"select * from CCChangeControl where PlanNumber={planNumber}";
|
||||
|
||||
pcrb = (await _dalService.QueryAsync<PCRB>(sql)).FirstOrDefault();
|
||||
|
||||
if (pcrb is not null) {
|
||||
if (string.IsNullOrWhiteSpace(pcrb.OwnerName) && pcrb.OwnerID > 0)
|
||||
pcrb.OwnerName = (await _userService.GetUserByUserId(pcrb.OwnerID)).GetFullName();
|
||||
|
||||
_cache.Set($"pcrb{planNumber}", pcrb, DateTimeOffset.Now.AddHours(1));
|
||||
_cache.Set($"pcrb{pcrb.Title}", pcrb, DateTimeOffset.Now.AddHours(1));
|
||||
}
|
||||
}
|
||||
|
||||
if (pcrb is null) throw new Exception($"unable to find PCRB {planNumber}");
|
||||
|
||||
return pcrb;
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to get PCRB by Plan #, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<PCRB> GetPCRBByTitle(string title, bool bypassCache) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get a PCRB by title");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(title)) throw new ArgumentException("Title cannot be null or empty");
|
||||
|
||||
PCRB? pcrb = null;
|
||||
|
||||
if (!bypassCache) pcrb = _cache.Get<PCRB>($"pcrb{title}");
|
||||
|
||||
if (pcrb is null) {
|
||||
string sql = $"select * from CCChangeControl where Title='{title}'";
|
||||
|
||||
pcrb = (await _dalService.QueryAsync<PCRB>(sql)).FirstOrDefault();
|
||||
|
||||
if (pcrb is not null) {
|
||||
if (string.IsNullOrWhiteSpace(pcrb.OwnerName) && pcrb.OwnerID > 0)
|
||||
pcrb.OwnerName = (await _userService.GetUserByUserId(pcrb.OwnerID)).GetFullName();
|
||||
|
||||
_cache.Set($"pcrb{title}", pcrb, DateTimeOffset.Now.AddHours(1));
|
||||
_cache.Set($"pcrb{pcrb.PlanNumber}", pcrb, DateTimeOffset.Now.AddHours(1));
|
||||
}
|
||||
}
|
||||
|
||||
if (pcrb is null) throw new Exception($"unable to find PCRB {title}");
|
||||
|
||||
return pcrb;
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to get PCRB by title, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdatePCRB(PCRB pcrb) {
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to update PCRB");
|
||||
|
||||
if (pcrb is null) throw new ArgumentNullException("PCRB cannot be null");
|
||||
|
||||
StringBuilder queryBuilder = new();
|
||||
queryBuilder.Append($"update CCChangeControl set OwnerID={pcrb.OwnerID}, ");
|
||||
queryBuilder.Append($"Title='{pcrb.Title}', ChangeLevel='{pcrb.ChangeLevel}', ");
|
||||
queryBuilder.Append($"CurrentStep={pcrb.CurrentStep}, ReasonForChange='{pcrb.ReasonForChange}', ");
|
||||
queryBuilder.Append($"ChangeDescription='{pcrb.ChangeDescription}', ");
|
||||
queryBuilder.Append($"IsITAR={Convert.ToInt32(pcrb.IsITAR)}, ");
|
||||
queryBuilder.Append($"InsertTimeStamp='{pcrb.InsertTimeStamp.ToString("yyyy-MM-dd HH:mm:ss")}', ");
|
||||
queryBuilder.Append($"LastUpdateDate='{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}' ");
|
||||
queryBuilder.Append($"where PlanNumber={pcrb.PlanNumber}");
|
||||
|
||||
int rowsAffected = await _dalService.ExecuteAsync(queryBuilder.ToString());
|
||||
|
||||
if (rowsAffected <= 0) throw new Exception("unable to perform update in database");
|
||||
|
||||
_cache.Set($"pcrb{pcrb.Title}", pcrb, DateTimeOffset.Now.AddHours(1));
|
||||
_cache.Set($"pcrb{pcrb.PlanNumber}", pcrb, DateTimeOffset.Now.AddHours(1));
|
||||
|
||||
IEnumerable<PCRB>? allPCRBs = _cache.Get<IEnumerable<PCRB>>("allPCRBs");
|
||||
if (allPCRBs is not null) {
|
||||
List<PCRB> pcrbList = allPCRBs.ToList();
|
||||
pcrbList.RemoveAll(p => p.PlanNumber == pcrb.PlanNumber);
|
||||
pcrbList.Add(pcrb);
|
||||
_cache.Set("allPCRBs", pcrbList, DateTimeOffset.Now.AddHours(1));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to update PCRB, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DeletePCRB(int planNumber) {
|
||||
try {
|
||||
_logger.LogInformation($"Attempting to delete PCRB {planNumber}");
|
||||
|
||||
if (planNumber <= 0) throw new ArgumentException($"{planNumber} is not a valid PCRB Plan #");
|
||||
|
||||
string sql = $"delete from CCChangeControl where PlanNumber={planNumber}";
|
||||
|
||||
int rowsAffected = await _dalService.ExecuteAsync(sql);
|
||||
|
||||
if (rowsAffected <= 0) throw new Exception("delete operation failed in database");
|
||||
|
||||
IEnumerable<PCRB>? allPCRBs = _cache.Get<IEnumerable<PCRB>>("allPCRBs");
|
||||
if (allPCRBs is not null) {
|
||||
List<PCRB> pcrbList = allPCRBs.ToList();
|
||||
pcrbList.RemoveAll(p => p.PlanNumber == planNumber);
|
||||
_cache.Set("allPCRBs", pcrbList, DateTimeOffset.Now.AddHours(1));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Unable to delete PCRB {planNumber}, because {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
79
MesaFabApproval.API/Services/SmtpService.cs
Normal file
79
MesaFabApproval.API/Services/SmtpService.cs
Normal file
@ -0,0 +1,79 @@
|
||||
using MesaFabApproval.API.Clients;
|
||||
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
using System.Net.Mail;
|
||||
|
||||
namespace MesaFabApproval.API.Services;
|
||||
|
||||
public interface ISmtpService {
|
||||
Task<bool> SendEmail(IEnumerable<MailAddress> recipients, IEnumerable<MailAddress> ccRecipients, string subject, string body);
|
||||
}
|
||||
|
||||
public class SmtpService : ISmtpService {
|
||||
private readonly ILogger<SmtpService> _logger;
|
||||
private readonly ISmtpClientWrapper _smtpClient;
|
||||
private readonly bool _shouldSendEmail;
|
||||
|
||||
public SmtpService(ILogger<SmtpService> logger, ISmtpClientWrapper smtpClient) {
|
||||
_logger = logger ??
|
||||
throw new ArgumentNullException("ILogger not injected");
|
||||
_smtpClient = smtpClient ??
|
||||
throw new ArgumentNullException("SmtpClient not injected");
|
||||
if (!Boolean.TryParse(Environment.GetEnvironmentVariable("FabApprovalShouldSendEmail"), out _shouldSendEmail))
|
||||
throw new ArgumentNullException("FabApprovalShouldSendEmail environment variable not found");
|
||||
}
|
||||
|
||||
public async Task<bool> SendEmail(IEnumerable<MailAddress> recipients,
|
||||
IEnumerable<MailAddress> ccRecipients,
|
||||
string subject,
|
||||
string body) {
|
||||
if (recipients.IsNullOrEmpty()) throw new ArgumentNullException("recipients cannot be null or empty!");
|
||||
if (ccRecipients is null) throw new ArgumentNullException("ccRecipients cannot be null!");
|
||||
if (subject.IsNullOrEmpty()) throw new ArgumentNullException("subject cannot be null or empty!");
|
||||
if (body.IsNullOrEmpty()) throw new ArgumentNullException("body cannot be null or empty!");
|
||||
|
||||
return await Task.Run(() => {
|
||||
int maxRetries = 3;
|
||||
int backoffSeconds = 30;
|
||||
|
||||
bool messageWasSent = false;
|
||||
|
||||
try {
|
||||
if (_shouldSendEmail) {
|
||||
int remainingRetries = maxRetries;
|
||||
while (!messageWasSent && remainingRetries > 0) {
|
||||
try {
|
||||
Task.Delay((maxRetries - remainingRetries--) * backoffSeconds * 1000);
|
||||
|
||||
_logger.LogInformation($"Attempting to send notification. Remaining retries: {remainingRetries}");
|
||||
|
||||
MailMessage msg = new MailMessage();
|
||||
msg.IsBodyHtml = true;
|
||||
msg.From = new MailAddress("MesaFabApproval@infineon.com", "Mesa Fab Approval");
|
||||
msg.Sender = new MailAddress("MesaFabApproval@infineon.com", "Mesa Fab Approval");
|
||||
foreach (MailAddress recipient in recipients) msg.To.Add(recipient);
|
||||
msg.Bcc.Add("chase.tucker@infineon.com");
|
||||
foreach (MailAddress ccRecipient in ccRecipients) msg.CC.Add(ccRecipient);
|
||||
msg.Subject = subject;
|
||||
msg.Body = body;
|
||||
|
||||
_smtpClient.Send(msg);
|
||||
|
||||
messageWasSent = true;
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Message not sent successfully. Exception: {ex.Message}");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_logger.LogInformation("Not sending email per local configuration");
|
||||
messageWasSent = true;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"An exception occurred when attempting to send notification. Exception: {ex.Message}");
|
||||
}
|
||||
|
||||
return messageWasSent;
|
||||
});
|
||||
}
|
||||
}
|
147
MesaFabApproval.API/Services/UserService.cs
Normal file
147
MesaFabApproval.API/Services/UserService.cs
Normal file
@ -0,0 +1,147 @@
|
||||
using System.Text;
|
||||
|
||||
using MesaFabApproval.Shared.Models;
|
||||
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace MesaFabApproval.API.Services;
|
||||
|
||||
public interface IUserService {
|
||||
Task<IEnumerable<User>> GetAllActiveUsers();
|
||||
Task<User> GetUserByLoginId(string loginId);
|
||||
Task<User> GetUserByUserId(int userId);
|
||||
Task<IEnumerable<int>> GetApproverUserIdsBySubRoleCategoryItem(string item);
|
||||
}
|
||||
|
||||
public class UserService : IUserService {
|
||||
private readonly ILogger<UserService> _logger;
|
||||
private readonly IDalService _dalService;
|
||||
private readonly IMemoryCache _cache;
|
||||
|
||||
public UserService(ILogger<UserService> logger, IDalService dalService, IMemoryCache cache) {
|
||||
_logger = logger ??
|
||||
throw new ArgumentNullException("ILogger not injected");
|
||||
_dalService = dalService ??
|
||||
throw new ArgumentNullException("IDalService not injected");
|
||||
_cache = cache ??
|
||||
throw new ArgumentNullException("IMemoryCache not injected");
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<User>> GetAllActiveUsers() {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get all active users");
|
||||
|
||||
IEnumerable<User>? allActiveUsers = _cache.Get<IEnumerable<User>>("allActiveUsers");
|
||||
|
||||
if (allActiveUsers is null) {
|
||||
string sql = "select * from Users where IsActive = 1";
|
||||
|
||||
allActiveUsers = (await _dalService.QueryAsync<User>(sql)).ToList();
|
||||
|
||||
_cache.Set("allActiveUsers", allActiveUsers, DateTimeOffset.Now.AddHours(1));
|
||||
}
|
||||
|
||||
if (allActiveUsers is null || allActiveUsers.Count() == 0) {
|
||||
throw new Exception("No users found");
|
||||
}
|
||||
|
||||
return allActiveUsers;
|
||||
} catch (Exception ex) {
|
||||
string errMsg = $"An exception occurred when attempting to get all users. Exception: {ex.Message}";
|
||||
_logger.LogError(errMsg);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<User> GetUserByLoginId(string loginId) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get user by LoginId");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(loginId))
|
||||
throw new ArgumentException("LoginId cannot be null or empty");
|
||||
|
||||
User? user = _cache.Get<User>($"userByLoginId{loginId}");
|
||||
|
||||
if (user is null)
|
||||
user = _cache.Get<IEnumerable<User>>("allActiveUsers")?.FirstOrDefault(u => u.LoginID == loginId);
|
||||
|
||||
if (user is null) {
|
||||
string sql = $"select * from Users where LoginID = '{loginId}';";
|
||||
|
||||
user = (await _dalService.QueryAsync<User>(sql)).FirstOrDefault();
|
||||
|
||||
_cache.Set($"userByLoginId{loginId}", user, DateTimeOffset.Now.AddHours(1));
|
||||
}
|
||||
|
||||
if (user is null) throw new Exception($"No user found with LoginID {loginId}");
|
||||
|
||||
return user;
|
||||
} catch (Exception ex) {
|
||||
string errMsg = $"An exception occurred when attempting to get user for LoginID {loginId}. Exception: {ex.Message}";
|
||||
_logger.LogError(errMsg);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<User> GetUserByUserId(int userId) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get user by user ID");
|
||||
|
||||
if (userId <= 0) throw new ArgumentException($"{userId} is not a valid user ID");
|
||||
|
||||
User? user = _cache.Get<User>($"userByUserId{userId}");
|
||||
|
||||
if (user is null)
|
||||
user = _cache.Get<IEnumerable<User>>("allActiveUsers")?.FirstOrDefault(u => u.UserID == userId);
|
||||
|
||||
if (user is null) {
|
||||
string sql = $"select * from Users where UserID = '{userId}';";
|
||||
|
||||
user = (await _dalService.QueryAsync<User>(sql)).FirstOrDefault();
|
||||
|
||||
_cache.Set($"userByUserId{userId}", user, DateTimeOffset.Now.AddHours(1));
|
||||
}
|
||||
|
||||
if (user is null) throw new Exception($"No user found with UserID {userId}");
|
||||
|
||||
return user;
|
||||
} catch (Exception ex) {
|
||||
string errMsg = $"An exception occurred when attempting to get user for UserID {userId}. Exception: {ex.Message}";
|
||||
_logger.LogError(errMsg);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<int>> GetApproverUserIdsBySubRoleCategoryItem(string item) {
|
||||
try {
|
||||
_logger.LogInformation("Attempting to get approver user IDs");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(item)) throw new ArgumentException("SubRoleCategoryItem cannot be null or empty");
|
||||
|
||||
IEnumerable<int>? userIds = _cache.Get<IEnumerable<int>>($"approverUserIdsBySubRollCategory{item}");
|
||||
|
||||
if (userIds is null) {
|
||||
StringBuilder queryBuilder = new();
|
||||
queryBuilder.Append("select us.UserID ");
|
||||
queryBuilder.Append("from SubRole as sr ");
|
||||
queryBuilder.Append("join UserSubRole as us on sr.SubRoleID=us.SubRoleID ");
|
||||
queryBuilder.Append("join SubRoleCategory as sc on sr.SubRoleCategoryID=sc.SubRoleCategoryID ");
|
||||
queryBuilder.Append($"where sc.SubRoleCategoryItem='{item}'");
|
||||
|
||||
userIds = (await _dalService.QueryAsync<int>(queryBuilder.ToString())).ToList();
|
||||
|
||||
_cache.Set($"approverUserIdsBySubRollCategory{item}", userIds, DateTimeOffset.Now.AddHours(1));
|
||||
}
|
||||
|
||||
if (userIds is null || userIds.Count() == 0) {
|
||||
throw new Exception($"No users found for SubRoleCategoryItem {item}");
|
||||
}
|
||||
|
||||
return userIds;
|
||||
} catch (Exception ex) {
|
||||
string errMsg = $"An exception occurred when attempting to get approver user IDs. Exception: {ex.Message}";
|
||||
_logger.LogError(errMsg);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
3
MesaFabApproval.API/appsettings.json
Normal file
3
MesaFabApproval.API/appsettings.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"AllowedHosts": "*"
|
||||
}
|
33
MesaFabApproval.API/nLog.config
Normal file
33
MesaFabApproval.API/nLog.config
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
autoReload="true">
|
||||
|
||||
<extensions>
|
||||
<add assembly="NLog.Web.AspNetCore"/>
|
||||
</extensions>
|
||||
|
||||
<targets>
|
||||
<target name="asyncLog" xsi:type="AsyncWrapper">
|
||||
<target
|
||||
name="appLog"
|
||||
xsi:type="File"
|
||||
fileName="d:\logs\MesaFabApproval.API\log.txt"
|
||||
archiveFilename="d:\logs\MesaFabApproval.API\archive\log-${shortdate}.txt"
|
||||
maxArchiveFiles="30"
|
||||
archiveEvery="Day"
|
||||
/>
|
||||
<target
|
||||
name="consoleLog"
|
||||
xsi:type="Console"
|
||||
/>
|
||||
</target>
|
||||
</targets>
|
||||
|
||||
<rules>
|
||||
<logger name="Microsoft.*" finalMinLevel="Warn" />
|
||||
<logger name="Microsoft.AspNetCore.HttpLogging.*" finalMinLevel="Info" />
|
||||
<logger name="System.Net.Http.HttpClient.*" finalMinLevel="Warn" />
|
||||
<logger name="*" minlevel="Info" writeTo="asyncLog" />
|
||||
</rules>
|
||||
</nlog>
|
Reference in New Issue
Block a user