Clean up
This commit is contained in:
117
KTUSAPS/Auth/SaPsAuthorizationHandler.cs
Normal file
117
KTUSAPS/Auth/SaPsAuthorizationHandler.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user