73 lines
2.7 KiB
C#
73 lines
2.7 KiB
C#
using DysonNetwork.Shared.Proto;
|
|
using Grpc.Core;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace DysonNetwork.Shared.Auth
|
|
{
|
|
[AttributeUsage(AttributeTargets.Method, AllowMultiple = 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.PermissionServiceClient permissionService, ILogger<PermissionMiddleware> logger)
|
|
{
|
|
var endpoint = httpContext.GetEndpoint();
|
|
|
|
var attr = endpoint?.Metadata
|
|
.OfType<RequiredPermissionAttribute>()
|
|
.FirstOrDefault();
|
|
|
|
if (attr != null)
|
|
{
|
|
if (httpContext.Items["CurrentUser"] is not Account currentUser)
|
|
{
|
|
httpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
|
|
await httpContext.Response.WriteAsync("Unauthorized");
|
|
return;
|
|
}
|
|
|
|
// Assuming Account proto has a bool field 'is_superuser' which is generated as 'IsSuperuser'
|
|
if (currentUser.IsSuperuser)
|
|
{
|
|
// Bypass the permission check for performance
|
|
await next(httpContext);
|
|
return;
|
|
}
|
|
|
|
var actor = $"user:{currentUser.Id}";
|
|
|
|
try
|
|
{
|
|
var permResp = await permissionService.HasPermissionAsync(new HasPermissionRequest
|
|
{
|
|
Actor = actor,
|
|
Area = attr.Area,
|
|
Key = attr.Key
|
|
});
|
|
|
|
if (!permResp.HasPermission)
|
|
{
|
|
httpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
|
|
await httpContext.Response.WriteAsync($"Permission {attr.Area}/{attr.Key} was required.");
|
|
return;
|
|
}
|
|
}
|
|
catch (RpcException ex)
|
|
{
|
|
logger.LogError(ex, "gRPC call to PermissionService failed while checking permission {Area}/{Key} for actor {Actor}", attr.Area, attr.Key, actor);
|
|
httpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;
|
|
await httpContext.Response.WriteAsync("Error checking permissions.");
|
|
return;
|
|
}
|
|
}
|
|
|
|
await next(httpContext);
|
|
}
|
|
}
|
|
}
|