Finished permission management
This commit is contained in:
@@ -8,6 +8,7 @@ using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
|
||||
namespace HopFrame.Security.Authentication;
|
||||
|
||||
@@ -38,13 +39,24 @@ public class HopFrameAuthentication<TDbContext> : AuthenticationHandler<Authenti
|
||||
|
||||
var claims = new List<Claim> {
|
||||
new(HopFrameClaimTypes.AccessTokenId, accessToken),
|
||||
new(HopFrameClaimTypes.UserId, tokenEntry.UserId.ToString())
|
||||
new(HopFrameClaimTypes.UserId, tokenEntry.UserId)
|
||||
};
|
||||
|
||||
var permissions = await _context.Permissions
|
||||
.Where(perm => perm.UserId == tokenEntry.UserId)
|
||||
.Select(perm => perm.PermissionText)
|
||||
.ToListAsync();
|
||||
|
||||
var groups = permissions
|
||||
.Where(perm => perm.StartsWith("group."))
|
||||
.ToList();
|
||||
|
||||
var groupPerms = await _context.Permissions
|
||||
.Where(perm => groups.Contains(perm.UserId))
|
||||
.Select(perm => perm.PermissionText)
|
||||
.ToListAsync();
|
||||
|
||||
permissions.AddRange(groupPerms);
|
||||
|
||||
claims.AddRange(permissions.Select(perm => new Claim(HopFrameClaimTypes.Permission, perm)));
|
||||
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
using HopFrame.Database;
|
||||
using HopFrame.Security.Claims;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
|
||||
namespace HopFrame.Security.Authentication;
|
||||
|
||||
public static class HopFrameAuthenticationExtensions {
|
||||
|
||||
public static AuthenticationBuilder AddHopFrameAuthentication<TDbContext>(this IServiceCollection service) where TDbContext : HopDbContextBase {
|
||||
service.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||
service.AddScoped<ITokenContext, TokenContextImplementor<TDbContext>>();
|
||||
return service.AddAuthentication(HopFrameAuthentication<TDbContext>.SchemeName).AddScheme<AuthenticationSchemeOptions, HopFrameAuthentication<TDbContext>>(HopFrameAuthentication<TDbContext>.SchemeName, _ => {});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using HopFrame.Security.Claims;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
@@ -19,6 +20,13 @@ public class AuthorizedFilter : IAuthorizationFilter {
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO: Check Permissions
|
||||
if (_permissions.Length == 0) return;
|
||||
|
||||
var permissions = context.HttpContext.User.GetPermissions();
|
||||
|
||||
if (!_permissions.Any(permission => PermissionValidator.IncludesPermission(permission, permissions))) {
|
||||
context.Result = new UnauthorizedResult();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
30
HopFrame.Security/Authorization/PermissionValidator.cs
Normal file
30
HopFrame.Security/Authorization/PermissionValidator.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
namespace HopFrame.Security.Authorization;
|
||||
|
||||
internal static class PermissionValidator {
|
||||
|
||||
/// <summary>
|
||||
/// Checks for the user to have the specified permission<br/>
|
||||
/// Permission system:<br/>
|
||||
/// - "*" -> all rights<br/>
|
||||
/// - "group.[name]" -> group member<br/>
|
||||
/// - "[namespace].[name]" -> single permission<br/>
|
||||
/// - "[namespace].*" -> all permissions in the namespace
|
||||
/// </summary>
|
||||
/// <param name="permission">The permission the user needs</param>
|
||||
/// <param name="permissions">All the permissions the user has (includes group permissions)</param>
|
||||
/// <returns></returns>
|
||||
public static bool IncludesPermission(string permission, string[] permissions) {
|
||||
if (permission == "*") return true;
|
||||
if (permissions.Contains(permission)) return true;
|
||||
|
||||
foreach (var perm in permissions) {
|
||||
if (!perm.EndsWith(".*")) continue;
|
||||
|
||||
var permissionGroup = perm.Replace(".*", "");
|
||||
if (permission.StartsWith(permissionGroup)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@ using HopFrame.Database.Models;
|
||||
|
||||
namespace HopFrame.Security.Claims;
|
||||
|
||||
public interface ITokenContextBase {
|
||||
public interface ITokenContext {
|
||||
bool IsAuthenticated { get; }
|
||||
User User { get; }
|
||||
Guid AccessToken { get; }
|
||||
@@ -4,20 +4,12 @@ using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace HopFrame.Security.Claims;
|
||||
|
||||
public class TokenContextImplementor : ITokenContextBase {
|
||||
private readonly IHttpContextAccessor _accessor;
|
||||
private readonly HopDbContextBase _context;
|
||||
internal class TokenContextImplementor<TDbContext>(IHttpContextAccessor accessor, TDbContext context) : ITokenContext where TDbContext : HopDbContextBase {
|
||||
public bool IsAuthenticated => accessor.HttpContext?.User.Identity?.IsAuthenticated == true;
|
||||
|
||||
public TokenContextImplementor(IHttpContextAccessor accessor, HopDbContextBase context) {
|
||||
_accessor = accessor;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public bool IsAuthenticated => _accessor.HttpContext?.User.Identity?.IsAuthenticated == true;
|
||||
|
||||
public User User => _context.Users
|
||||
.SingleOrDefault(user => user.Id == _accessor.HttpContext.User.GetUserId())?
|
||||
.ToUserModel(_context);
|
||||
public User User => context.Users
|
||||
.SingleOrDefault(user => user.Id == accessor.HttpContext.User.GetUserId())?
|
||||
.ToUserModel(context);
|
||||
|
||||
public Guid AccessToken => Guid.Parse(_accessor.HttpContext?.User.GetAccessTokenId() ?? string.Empty);
|
||||
public Guid AccessToken => Guid.Parse(accessor.HttpContext?.User.GetAccessTokenId() ?? string.Empty);
|
||||
}
|
||||
Reference in New Issue
Block a user