60 lines
1.9 KiB
C#
60 lines
1.9 KiB
C#
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<RequiredPermissionAttribute>()
|
|
.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<bool>(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);
|
|
}
|
|
} |