Backend/e-suite.API/eSuite.API/Middleware/SecurityAccessMiddleWare.cs

82 lines
2.7 KiB
C#

using e_suite.API.Common;
using e_suite.API.Common.exceptions;
using eSuite.API.security;
using eSuite.API.Utilities;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using Autofac;
namespace eSuite.API.Middleware;
internal class SecurityAccessMiddleWare
{
private readonly RequestDelegate _next;
private readonly ILifetimeScope _lifetimeScope;
public SecurityAccessMiddleWare(RequestDelegate next, ILifetimeScope lifetimeScope)
{
_next = next;
_lifetimeScope = lifetimeScope;
}
public async Task InvokeAsync(HttpContext context)
{
var endpoint = context.GetEndpoint() ?? throw new NotFoundException("Endpoint not found");
if (endpoint is RouteEndpoint routeEndpoint)
{
if (routeEndpoint.RoutePattern.RawText != null)
{
var allowAnonymousAttribute = endpoint?.Metadata.OfType<AllowAnonymousAttribute>().FirstOrDefault();
var routePatternLower = routeEndpoint.RoutePattern.RawText.ToLower().TrimStart('/');
if (allowAnonymousAttribute != null || !(routePatternLower.StartsWith("api") || routePatternLower.StartsWith("account")))
{
await _next.Invoke(context);
return;
}
}
}
var accessKeyAttribute = endpoint?.Metadata.OfType<AccessKeyAttribute>().FirstOrDefault() ?? throw new NotImplementedException("Unable to find AccessKeyAttribute for Endpoint");
var userId = GetUserIdFromContextUser(context.User).GetValueOrDefault();
var accessKey = accessKeyAttribute.SecurityAccess;
await using var requestLifetimeScope = _lifetimeScope.BeginLifetimeScope();
var roleManager = requestLifetimeScope.Resolve<IRoleManager>();
if (await roleManager.HasAnyAccess(userId, accessKey))
{
await _next.Invoke(context);
return;
}
var problemDetails = new ProblemDetails
{
Title = "Unauthorised",
Detail = "User does not have permission to call this method"
};
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(problemDetails.ToJson());
}
private static long? GetUserIdFromContextUser(ClaimsPrincipal user)
{
long? userId;
try
{
userId = user.Id();
}
catch
{
userId = null;
}
return userId;
}
}