51 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			51 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using Microsoft.AspNetCore.Http;
 | 
						|
 | 
						|
namespace DysonNetwork.Pass.Permission;
 | 
						|
 | 
						|
[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.Items["CurrentUser"] is not Shared.Models.Account currentUser)
 | 
						|
            {
 | 
						|
                httpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
 | 
						|
                await httpContext.Response.WriteAsync("Unauthorized");
 | 
						|
                return;
 | 
						|
            }
 | 
						|
 | 
						|
            if (currentUser.IsSuperuser)
 | 
						|
            {
 | 
						|
                // Bypass the permission check for performance
 | 
						|
                await next(httpContext);
 | 
						|
                return;
 | 
						|
            }
 | 
						|
 | 
						|
            var actor = $"user:{currentUser.Id}";
 | 
						|
            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);
 | 
						|
    } 
 | 
						|
} |