Added authorization rules based on permissions.

master
Tudor Stanciu 2023-04-17 03:33:56 +03:00
parent 5d29bdfe7e
commit c94acf9ba4
10 changed files with 70 additions and 33 deletions

View File

@ -178,6 +178,7 @@
• Permissions and authorizations at the user role level have been added to the application.
• The "Netmash.Security.Authentication.Tuitio" nuget package has been upgraded in backend.
• Added cache and authorization policies.
• Added authorization rules based on permissions.
</Content>
</Note>
</ReleaseNotes>

View File

@ -3,6 +3,7 @@
public struct Policies
{
public const string
OperateMachines = "OPERATE_MACHINES";
OperateMachines = "OPERATE_MACHINES",
ViewMachines = "VIEW_MACHINES";
}
}

View File

@ -16,9 +16,13 @@ namespace NetworkResurrector.Api.Authorization
{
policy.Requirements.Add(new OperateMachinesRequirement());
});
options.AddPolicy(Policies.ViewMachines, policy =>
{
policy.Requirements.Add(new ViewMachinesRequirement());
});
});
services.AddScoped<IAuthorizationHandler, OperateMachinesHandler>();
services.AddScoped<IAuthorizationHandler, PermissionsBasedAuthorizationHandler>();
}
}
}

View File

@ -1,27 +0,0 @@
using Microsoft.AspNetCore.Authorization;
using NetworkResurrector.Api.Application.Services.Abstractions;
using NetworkResurrector.Api.Authorization.Requirements;
using System.Linq;
using System.Threading.Tasks;
namespace NetworkResurrector.Api.Authorization.Handlers
{
public class OperateMachinesHandler : AuthorizationHandler<OperateMachinesRequirement>
{
private readonly IUserContext _userContext;
public OperateMachinesHandler(IUserContext userContext)
{
_userContext=userContext;
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, OperateMachinesRequirement requirement)
{
var permissions = await _userContext.GetUserPermissions();
if (permissions.Contains(requirement.PermissionCode))
{
context.Succeed(requirement);
}
}
}
}

View File

@ -0,0 +1,30 @@
using Microsoft.AspNetCore.Authorization;
using NetworkResurrector.Api.Application.Services.Abstractions;
using NetworkResurrector.Api.Authorization.Requirements;
using NetworkResurrector.Api.Extensions;
using System.Linq;
using System.Threading.Tasks;
namespace NetworkResurrector.Api.Authorization.Handlers
{
public class PermissionsBasedAuthorizationHandler : AuthorizationHandler<IPermissionsBasedAuthorizationRequirement>
{
private readonly IUserContext _userContext;
public PermissionsBasedAuthorizationHandler(IUserContext userContext)
{
_userContext=userContext;
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, IPermissionsBasedAuthorizationRequirement requirement)
{
var permissions = await _userContext.GetUserPermissions();
var condition1 = requirement.AllRequired.IsNullOrEmpty() || requirement.AllRequired.All(permission => permissions.Contains(permission));
var condition2 = requirement.OneOf.IsNullOrEmpty() || requirement.OneOf.Any(permission => permissions.Contains(permission));
if (condition1 && condition2)
{
context.Succeed(requirement);
}
}
}
}

View File

@ -0,0 +1,10 @@
using Microsoft.AspNetCore.Authorization;
namespace NetworkResurrector.Api.Authorization.Requirements
{
public interface IPermissionsBasedAuthorizationRequirement : IAuthorizationRequirement
{
string[] AllRequired { get; }
string[] OneOf { get; }
}
}

View File

@ -1,10 +1,12 @@
using Microsoft.AspNetCore.Authorization;
using NetworkResurrector.Api.Domain.Constants;
using NetworkResurrector.Api.Domain.Constants;
using System;
namespace NetworkResurrector.Api.Authorization.Requirements
{
public class OperateMachinesRequirement : IAuthorizationRequirement
public class OperateMachinesRequirement : IPermissionsBasedAuthorizationRequirement
{
public readonly string PermissionCode = PermissionCodes.OPERATE_MACHINES;
public string[] AllRequired => new string[] { PermissionCodes.OPERATE_MACHINES };
public string[] OneOf => Array.Empty<string>();
}
}

View File

@ -0,0 +1,11 @@
using NetworkResurrector.Api.Domain.Constants;
using System;
namespace NetworkResurrector.Api.Authorization.Requirements
{
public class ViewMachinesRequirement : IPermissionsBasedAuthorizationRequirement
{
public string[] AllRequired => Array.Empty<string>();
public string[] OneOf => new string[] { PermissionCodes.VIEW_MACHINES, PermissionCodes.GUEST_ACCESS };
}
}

View File

@ -2,6 +2,7 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using NetworkResurrector.Api.Application.Queries;
using NetworkResurrector.Api.Authorization.Constants;
using System.Threading.Tasks;
namespace NetworkResurrector.Api.Controllers
@ -19,6 +20,7 @@ namespace NetworkResurrector.Api.Controllers
}
[HttpGet("machines")]
[Authorize(Policy = Policies.ViewMachines)]
public async Task<IActionResult> GetMachines([FromRoute] GetMachines.Query query)
{
var result = await _mediator.Send(query);

View File

@ -4,5 +4,8 @@
{
public static string Nullify(this string value)
=> string.IsNullOrWhiteSpace(value) ? null : value;
public static bool IsNullOrEmpty(this string[] array)
=> array == null || array.Length == 0;
}
}