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; using Autofac.Core.Lifetime; 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().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().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(); 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; } }