namespace DysonNetwork.Sphere.Permission; using System; [AttributeUsage(AttributeTargets.Method, Inherited = true)] public class RequiredPermissionAttribute(string area, string key) : Attribute { public string Area { get; set; } = area; public string Key { get; } = key; } public class PermissionMiddleware(RequestDelegate next) { public async Task InvokeAsync(HttpContext httpContext, PermissionService pm) { var endpoint = httpContext.GetEndpoint(); var attr = endpoint?.Metadata .OfType() .FirstOrDefault(); if (attr != null) { if (httpContext.User.Identity?.IsAuthenticated != true) { httpContext.Response.StatusCode = StatusCodes.Status403Forbidden; await httpContext.Response.WriteAsync("Unauthorized"); return; } var currentUserId = httpContext.User.GetUserId(); if (currentUserId == Guid.Empty) { httpContext.Response.StatusCode = StatusCodes.Status403Forbidden; await httpContext.Response.WriteAsync("Unauthorized"); return; } // TODO: Check for superuser from PassClient // if (currentUser.IsSuperuser) // { // // Bypass the permission check for performance // await next(httpContext); // return; // } var actor = $"user:{currentUserId}"; var permNode = await pm.GetPermissionAsync(actor, attr.Area, attr.Key); if (!permNode) { httpContext.Response.StatusCode = StatusCodes.Status403Forbidden; await httpContext.Response.WriteAsync($"Permission {attr.Area}/{attr.Key} = {true} was required."); return; } } await next(httpContext); } }