This repository has been archived on 2025-08-13. You can view files and clone it, but cannot push or open issues or pull requests.
Files
KTUSA-PS/KTUSAPS/Auth/SaPsAuthorizationHandler.cs
Karolis2011 df48e88614 Clean up
2022-01-25 21:11:24 +02:00

118 lines
4.3 KiB
C#

using KTUSAPS.Data;
using KTUSAPS.Data.Model;
using KTUSAPS.Extensions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
namespace KTUSAPS.Auth
{
public class SaPsAuthorizationHandler : IAuthorizationHandler
{
private readonly IServiceProvider serviceProvider;
public SaPsAuthorizationHandler(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
public async Task HandleAsync(AuthorizationHandlerContext context)
{
var cache = new AuthProcessingCache(context.User, serviceProvider);
foreach (var requirement in context.Requirements)
{
if (requirement is AdminRequirement adminRequirement)
await HandleRequirementAsync(context, adminRequirement, cache);
if (requirement is MyIssueRequirement myIssueRequirement)
await HandleRequirementAsync(context, myIssueRequirement, cache);
}
}
private async Task HandleRequirementAsync(AuthorizationHandlerContext context, MyIssueRequirement myIssueRequirement, AuthProcessingCache cache)
{
if(context.Resource is not Issue issue)
throw new Exception($"'{nameof(MyIssueRequirement)}' must be issued with resource of type '{nameof(Issue)}'");
if(issue.UserID == context.User.GetUserId())
{
context.Succeed(myIssueRequirement);
return;
}
if(await cache.DetermineIsAdminAsync())
{
context.Succeed(myIssueRequirement);
return;
}
}
private async Task HandleRequirementAsync(AuthorizationHandlerContext context, AdminRequirement adminRequirement, AuthProcessingCache cache)
{
if(await cache.DetermineIsAdminAsync())
{
context.Succeed(adminRequirement);
return;
}
context.Fail();
}
private class AuthProcessingCache
{
private readonly ClaimsPrincipal _user;
private readonly IServiceProvider _serviceProvider;
private bool? isAdmin;
public bool IsAdmin => determineIsAdminCached();
public AuthProcessingCache(ClaimsPrincipal user, IServiceProvider serviceProvider) {
_user = user;
_serviceProvider = serviceProvider;
}
private bool determineIsAdminCached()
{
if (isAdmin == null)
isAdmin = determineIsAdmin();
return isAdmin.Value;
}
private bool determineIsAdmin()
{
var objectId = _user.GetObjectId();
if (objectId == default)
return false;
using var scope = _serviceProvider.CreateScope();
var dataContext = scope.ServiceProvider.GetRequiredService<SAPSDataContext>();
var admin = dataContext.Admins.Where(a => a.UserId == objectId).FirstOrDefault();
if (admin != default)
return true;
return false;
}
private async ValueTask<bool> determineIsAdminAsync()
{
var idclaim = _user.Claims.Where(c => c.Type == "http://schemas.microsoft.com/identity/claims/objectidentifier").FirstOrDefault();
if (idclaim == default)
return false;
using var scope = _serviceProvider.CreateScope();
var dataContext = scope.ServiceProvider.GetRequiredService<SAPSDataContext>();
var admin = await dataContext.Admins.Where(a => a.UserId == idclaim.Value).FirstOrDefaultAsync();
if (admin != default)
return true;
return false;
}
public async ValueTask<bool> DetermineIsAdminAsync()
{
if (isAdmin == null)
isAdmin = await determineIsAdminAsync();
return isAdmin.Value;
}
}
}
}