Files
vigilcare-clinical/VigilCareClinicalAPI/Authorization/PermissionAuthorizationHandler.cs
T
2026-06-21 19:53:19 +08:00

57 lines
2.0 KiB
C#

using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
public class PermissionAuthorizationHandler : AuthorizationHandler<PermissionRequirement>
{
private readonly ILogger<PermissionAuthorizationHandler> _logger;
private readonly IHttpContextAccessor _http;
private readonly ClinicalMetrics _metrics;
public PermissionAuthorizationHandler(
ILogger<PermissionAuthorizationHandler> logger,
IHttpContextAccessor http,
ClinicalMetrics metrics)
{
_logger = logger;
_http = http;
_metrics = metrics;
}
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
PermissionRequirement requirement)
{
var roleClaim = context.User.FindFirst("clinical_role")?.Value;
if (roleClaim is null)
{
LogAuthorizationFailure(context.User, "none", requirement.Permission);
return Task.CompletedTask;
}
var role = ClinicalRoleExtensions.FromDbString(roleClaim);
if (ClinicalRolePermissionMap.HasPermission(role, requirement.Permission))
{
context.Succeed(requirement);
}
else
{
LogAuthorizationFailure(context.User, roleClaim, requirement.Permission);
}
return Task.CompletedTask;
}
private void LogAuthorizationFailure(ClaimsPrincipal user, string role, string permission)
{
var username = user.FindFirst(ClaimTypes.Name)?.Value ?? "unknown";
var userId = user.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? "unknown";
var endpoint = _http.HttpContext?.GetEndpoint()?.DisplayName ?? "unknown";
_logger.LogWarning(
"Authorization denied: user={User} (id={UserId}), role={Role}, " +
"requiredPermission={Permission}, endpoint={Endpoint}",
username, userId, role, permission, endpoint);
_metrics.AuthorizationFailuresTotal.WithLabels(permission, role).Inc();
}
}