Finished permission management
This commit is contained in:
@@ -1,9 +1,16 @@
|
|||||||
using HopFrame.Api.Controller;
|
using HopFrame.Api.Controller;
|
||||||
|
using HopFrame.Security.Authorization;
|
||||||
|
using HopFrame.Security.Claims;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace DatabaseTest.Controllers;
|
namespace DatabaseTest.Controllers;
|
||||||
|
|
||||||
[ApiController]
|
[ApiController]
|
||||||
public class TestController(DatabaseContext context) : SecurityController<DatabaseContext>(context) {
|
public class TestController(DatabaseContext context, ITokenContext userContext) : SecurityController<DatabaseContext>(context) {
|
||||||
|
|
||||||
|
[HttpGet("permissions"), Authorized]
|
||||||
|
public ActionResult<IList<string>> Permissions() {
|
||||||
|
return new ActionResult<IList<string>>(userContext.User.Permissions);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
BIN
DatabaseTest/test.db
Normal file
BIN
DatabaseTest/test.db
Normal file
Binary file not shown.
@@ -20,15 +20,15 @@ public class SecurityController<TDbContext>(TDbContext context) : ControllerBase
|
|||||||
private const string RefreshTokenType = "HopFrame.Security.RefreshToken";
|
private const string RefreshTokenType = "HopFrame.Security.RefreshToken";
|
||||||
|
|
||||||
[HttpPut("login")]
|
[HttpPut("login")]
|
||||||
public async Task<ILogicResult<SingleValueResult<string>>> Login([FromBody] UserLogin login) {
|
public async Task<ActionResult<SingleValueResult<string>>> Login([FromBody] UserLogin login) {
|
||||||
var user = await context.Users.SingleOrDefaultAsync(user => user.Email == login.Email);
|
var user = await context.Users.SingleOrDefaultAsync(user => user.Email == login.Email);
|
||||||
|
|
||||||
if (user is null)
|
if (user is null)
|
||||||
return LogicResult<SingleValueResult<string>>.NotFound("The provided email address was not found");
|
return this.FromLogicResult(LogicResult<SingleValueResult<string>>.NotFound("The provided email address was not found"));
|
||||||
|
|
||||||
var hashedPassword = EncryptionManager.Hash(login.Password, Encoding.Default.GetBytes(user.CreatedAt.ToString(CultureInfo.InvariantCulture)));
|
var hashedPassword = EncryptionManager.Hash(login.Password, Encoding.Default.GetBytes(user.CreatedAt.ToString(CultureInfo.InvariantCulture)));
|
||||||
if (hashedPassword != user.Password)
|
if (hashedPassword != user.Password)
|
||||||
return LogicResult<SingleValueResult<string>>.Forbidden("The provided password is not correct");
|
return this.FromLogicResult(LogicResult<SingleValueResult<string>>.Forbidden("The provided password is not correct"));
|
||||||
|
|
||||||
var refreshToken = new TokenEntry {
|
var refreshToken = new TokenEntry {
|
||||||
CreatedAt = DateTime.Now,
|
CreatedAt = DateTime.Now,
|
||||||
@@ -52,15 +52,16 @@ public class SecurityController<TDbContext>(TDbContext context) : ControllerBase
|
|||||||
await context.Tokens.AddRangeAsync(refreshToken, accessToken);
|
await context.Tokens.AddRangeAsync(refreshToken, accessToken);
|
||||||
await context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
|
|
||||||
return LogicResult<SingleValueResult<string>>.Ok(accessToken.Token);
|
return this.FromLogicResult(LogicResult<SingleValueResult<string>>.Ok(accessToken.Token));
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("register")]
|
[HttpPost("register")]
|
||||||
public async Task<ILogicResult<SingleValueResult<string>>> Register([FromBody] UserRegister register) {
|
public async Task<ActionResult<SingleValueResult<string>>> Register([FromBody] UserRegister register) {
|
||||||
//TODO: Validate Password requirements
|
if (register.Password.Length < 8)
|
||||||
|
return this.FromLogicResult(LogicResult<SingleValueResult<string>>.Conflict("Password needs to be at least 8 characters long"));
|
||||||
|
|
||||||
if (await context.Users.AnyAsync(user => user.Username == register.Username || user.Email == register.Email))
|
if (await context.Users.AnyAsync(user => user.Username == register.Username || user.Email == register.Email))
|
||||||
return LogicResult<SingleValueResult<string>>.Conflict("Username or Email is already registered");
|
return this.FromLogicResult(LogicResult<SingleValueResult<string>>.Conflict("Username or Email is already registered"));
|
||||||
|
|
||||||
var user = new UserEntry {
|
var user = new UserEntry {
|
||||||
CreatedAt = DateTime.Now,
|
CreatedAt = DateTime.Now,
|
||||||
@@ -72,6 +73,17 @@ public class SecurityController<TDbContext>(TDbContext context) : ControllerBase
|
|||||||
|
|
||||||
await context.Users.AddAsync(user);
|
await context.Users.AddAsync(user);
|
||||||
|
|
||||||
|
var defaultGroups = await context.Groups
|
||||||
|
.Where(group => group.Default)
|
||||||
|
.Select(group => "group." + group.Name)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
await context.Permissions.AddRangeAsync(defaultGroups.Select(group => new PermissionEntry {
|
||||||
|
GrantedAt = DateTime.Now,
|
||||||
|
PermissionText = group,
|
||||||
|
UserId = user.Id
|
||||||
|
}));
|
||||||
|
|
||||||
var refreshToken = new TokenEntry {
|
var refreshToken = new TokenEntry {
|
||||||
CreatedAt = DateTime.Now,
|
CreatedAt = DateTime.Now,
|
||||||
Token = Guid.NewGuid().ToString(),
|
Token = Guid.NewGuid().ToString(),
|
||||||
@@ -94,23 +106,23 @@ public class SecurityController<TDbContext>(TDbContext context) : ControllerBase
|
|||||||
await context.Tokens.AddRangeAsync(refreshToken, accessToken);
|
await context.Tokens.AddRangeAsync(refreshToken, accessToken);
|
||||||
await context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
|
|
||||||
return LogicResult<SingleValueResult<string>>.Ok(accessToken.Token);
|
return this.FromLogicResult(LogicResult<SingleValueResult<string>>.Ok(accessToken.Token));
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("authenticate")]
|
[HttpGet("authenticate")]
|
||||||
public async Task<ILogicResult<SingleValueResult<string>>> Authenticate() {
|
public async Task<ActionResult<SingleValueResult<string>>> Authenticate() {
|
||||||
var refreshToken = HttpContext.Request.Cookies[RefreshTokenType];
|
var refreshToken = HttpContext.Request.Cookies[RefreshTokenType];
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(refreshToken))
|
if (string.IsNullOrEmpty(refreshToken))
|
||||||
return LogicResult<SingleValueResult<string>>.Conflict("Refresh token not provided");
|
return this.FromLogicResult(LogicResult<SingleValueResult<string>>.Conflict("Refresh token not provided"));
|
||||||
|
|
||||||
var token = await context.Tokens.SingleOrDefaultAsync(token => token.Token == refreshToken && token.Type == TokenEntry.RefreshTokenType);
|
var token = await context.Tokens.SingleOrDefaultAsync(token => token.Token == refreshToken && token.Type == TokenEntry.RefreshTokenType);
|
||||||
|
|
||||||
if (token is null)
|
if (token is null)
|
||||||
return LogicResult<SingleValueResult<string>>.NotFound("Refresh token not valid");
|
return this.FromLogicResult(LogicResult<SingleValueResult<string>>.NotFound("Refresh token not valid"));
|
||||||
|
|
||||||
if (token.CreatedAt + HopFrameAuthentication<TDbContext>.RefreshTokenTime < DateTime.Now)
|
if (token.CreatedAt + HopFrameAuthentication<TDbContext>.RefreshTokenTime < DateTime.Now)
|
||||||
return LogicResult<SingleValueResult<string>>.Conflict("Refresh token is expired");
|
return this.FromLogicResult(LogicResult<SingleValueResult<string>>.Conflict("Refresh token is expired"));
|
||||||
|
|
||||||
var accessToken = new TokenEntry {
|
var accessToken = new TokenEntry {
|
||||||
CreatedAt = DateTime.Now,
|
CreatedAt = DateTime.Now,
|
||||||
@@ -122,16 +134,16 @@ public class SecurityController<TDbContext>(TDbContext context) : ControllerBase
|
|||||||
await context.Tokens.AddAsync(accessToken);
|
await context.Tokens.AddAsync(accessToken);
|
||||||
await context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
|
|
||||||
return LogicResult<SingleValueResult<string>>.Ok(accessToken.Token);
|
return this.FromLogicResult(LogicResult<SingleValueResult<string>>.Ok(accessToken.Token));
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpDelete("logout"), Authorized]
|
[HttpDelete("logout"), Authorized]
|
||||||
public async Task<ILogicResult> Logout() {
|
public async Task<ActionResult> Logout() {
|
||||||
var accessToken = HttpContext.User.GetAccessTokenId();
|
var accessToken = HttpContext.User.GetAccessTokenId();
|
||||||
var refreshToken = HttpContext.Request.Cookies[RefreshTokenType];
|
var refreshToken = HttpContext.Request.Cookies[RefreshTokenType];
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accessToken) || string.IsNullOrEmpty(refreshToken))
|
if (string.IsNullOrEmpty(accessToken) || string.IsNullOrEmpty(refreshToken))
|
||||||
return LogicResult.Conflict("access or refresh token not provided");
|
return this.FromLogicResult(LogicResult.Conflict("access or refresh token not provided"));
|
||||||
|
|
||||||
var tokenEntries = await context.Tokens.Where(token =>
|
var tokenEntries = await context.Tokens.Where(token =>
|
||||||
(token.Token == accessToken && token.Type == TokenEntry.AccessTokenType) ||
|
(token.Token == accessToken && token.Type == TokenEntry.AccessTokenType) ||
|
||||||
@@ -139,7 +151,7 @@ public class SecurityController<TDbContext>(TDbContext context) : ControllerBase
|
|||||||
.ToArrayAsync();
|
.ToArrayAsync();
|
||||||
|
|
||||||
if (tokenEntries.Length != 2)
|
if (tokenEntries.Length != 2)
|
||||||
return LogicResult.NotFound("One or more of the provided tokens was not found");
|
return this.FromLogicResult(LogicResult.NotFound("One or more of the provided tokens was not found"));
|
||||||
|
|
||||||
context.Tokens.Remove(tokenEntries[0]);
|
context.Tokens.Remove(tokenEntries[0]);
|
||||||
context.Tokens.Remove(tokenEntries[1]);
|
context.Tokens.Remove(tokenEntries[1]);
|
||||||
@@ -147,32 +159,34 @@ public class SecurityController<TDbContext>(TDbContext context) : ControllerBase
|
|||||||
|
|
||||||
HttpContext.Response.Cookies.Delete(RefreshTokenType);
|
HttpContext.Response.Cookies.Delete(RefreshTokenType);
|
||||||
|
|
||||||
return LogicResult.Ok();
|
return this.FromLogicResult(LogicResult.Ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpDelete("delete"), Authorized]
|
[HttpDelete("delete"), Authorized]
|
||||||
public async Task<ILogicResult> Delete([FromBody] UserLogin login) {
|
public async Task<ActionResult> Delete([FromBody] UserLogin login) {
|
||||||
var token = HttpContext.User.GetAccessTokenId();
|
var token = HttpContext.User.GetAccessTokenId();
|
||||||
var userId = (await context.Tokens.SingleOrDefaultAsync(t => t.Token == token && t.Type == TokenEntry.AccessTokenType))?.UserId;
|
var userId = (await context.Tokens.SingleOrDefaultAsync(t => t.Token == token && t.Type == TokenEntry.AccessTokenType))?.UserId;
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(userId))
|
if (string.IsNullOrEmpty(userId))
|
||||||
return LogicResult.NotFound("Access token does not match any user");
|
return this.FromLogicResult(LogicResult.NotFound("Access token does not match any user"));
|
||||||
|
|
||||||
var user = await context.Users.SingleAsync(user => user.Id == userId);
|
var user = await context.Users.SingleAsync(user => user.Id == userId);
|
||||||
|
|
||||||
var password = EncryptionManager.Hash(login.Password, Encoding.Default.GetBytes(user.CreatedAt.ToString(CultureInfo.InvariantCulture)));
|
var password = EncryptionManager.Hash(login.Password, Encoding.Default.GetBytes(user.CreatedAt.ToString(CultureInfo.InvariantCulture)));
|
||||||
if (user.Password != password)
|
if (user.Password != password)
|
||||||
return LogicResult.Forbidden("The provided password is not correct");
|
return this.FromLogicResult(LogicResult.Forbidden("The provided password is not correct"));
|
||||||
|
|
||||||
var tokens = await context.Tokens.Where(t => t.UserId == userId).ToArrayAsync();
|
var tokens = await context.Tokens.Where(t => t.UserId == userId).ToArrayAsync();
|
||||||
|
var permissions = await context.Permissions.Where(perm => perm.UserId == userId).ToArrayAsync();
|
||||||
|
|
||||||
context.Tokens.RemoveRange(tokens);
|
context.Tokens.RemoveRange(tokens);
|
||||||
|
context.Permissions.RemoveRange(permissions);
|
||||||
context.Users.Remove(user);
|
context.Users.Remove(user);
|
||||||
await context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
|
|
||||||
HttpContext.Response.Cookies.Delete(RefreshTokenType);
|
HttpContext.Response.Cookies.Delete(RefreshTokenType);
|
||||||
|
|
||||||
return LogicResult.Ok();
|
return this.FromLogicResult(LogicResult.Ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace HopFrame.Api.Logic;
|
namespace HopFrame.Api.Logic;
|
||||||
|
|
||||||
public class LogicResult : ILogicResult {
|
public class LogicResult : ILogicResult {
|
||||||
|
|||||||
@@ -12,11 +12,14 @@ public class HopDbContextBase : DbContext {
|
|||||||
public virtual DbSet<UserEntry> Users { get; set; }
|
public virtual DbSet<UserEntry> Users { get; set; }
|
||||||
public virtual DbSet<PermissionEntry> Permissions { get; set; }
|
public virtual DbSet<PermissionEntry> Permissions { get; set; }
|
||||||
public virtual DbSet<TokenEntry> Tokens { get; set; }
|
public virtual DbSet<TokenEntry> Tokens { get; set; }
|
||||||
|
public virtual DbSet<GroupEntry> Groups { get; set; }
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder) {
|
protected override void OnModelCreating(ModelBuilder modelBuilder) {
|
||||||
base.OnModelCreating(modelBuilder);
|
base.OnModelCreating(modelBuilder);
|
||||||
|
|
||||||
modelBuilder.Entity<UserEntry>();
|
modelBuilder.Entity<UserEntry>();
|
||||||
modelBuilder.Entity<PermissionEntry>();
|
modelBuilder.Entity<PermissionEntry>();
|
||||||
|
modelBuilder.Entity<TokenEntry>();
|
||||||
|
modelBuilder.Entity<GroupEntry>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
18
HopFrame.Database/Models/Entries/GroupEntry.cs
Normal file
18
HopFrame.Database/Models/Entries/GroupEntry.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace HopFrame.Database.Models.Entries;
|
||||||
|
|
||||||
|
public class GroupEntry {
|
||||||
|
[Key, Required, MaxLength(50)]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[Required, DefaultValue(false)]
|
||||||
|
public bool Default { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(500)]
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ using Microsoft.Extensions.Logging;
|
|||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
|
#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;
|
namespace HopFrame.Security.Authentication;
|
||||||
|
|
||||||
@@ -38,7 +39,7 @@ public class HopFrameAuthentication<TDbContext> : AuthenticationHandler<Authenti
|
|||||||
|
|
||||||
var claims = new List<Claim> {
|
var claims = new List<Claim> {
|
||||||
new(HopFrameClaimTypes.AccessTokenId, accessToken),
|
new(HopFrameClaimTypes.AccessTokenId, accessToken),
|
||||||
new(HopFrameClaimTypes.UserId, tokenEntry.UserId.ToString())
|
new(HopFrameClaimTypes.UserId, tokenEntry.UserId)
|
||||||
};
|
};
|
||||||
|
|
||||||
var permissions = await _context.Permissions
|
var permissions = await _context.Permissions
|
||||||
@@ -46,6 +47,17 @@ public class HopFrameAuthentication<TDbContext> : AuthenticationHandler<Authenti
|
|||||||
.Select(perm => perm.PermissionText)
|
.Select(perm => perm.PermissionText)
|
||||||
.ToListAsync();
|
.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)));
|
claims.AddRange(permissions.Select(perm => new Claim(HopFrameClaimTypes.Permission, perm)));
|
||||||
|
|
||||||
var principal = new ClaimsPrincipal();
|
var principal = new ClaimsPrincipal();
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
using HopFrame.Database;
|
using HopFrame.Database;
|
||||||
|
using HopFrame.Security.Claims;
|
||||||
using Microsoft.AspNetCore.Authentication;
|
using Microsoft.AspNetCore.Authentication;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
|
|
||||||
namespace HopFrame.Security.Authentication;
|
namespace HopFrame.Security.Authentication;
|
||||||
|
|
||||||
public static class HopFrameAuthenticationExtensions {
|
public static class HopFrameAuthenticationExtensions {
|
||||||
|
|
||||||
public static AuthenticationBuilder AddHopFrameAuthentication<TDbContext>(this IServiceCollection service) where TDbContext : HopDbContextBase {
|
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, _ => {});
|
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;
|
||||||
using Microsoft.AspNetCore.Mvc.Authorization;
|
using Microsoft.AspNetCore.Mvc.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
@@ -19,6 +20,13 @@ public class AuthorizedFilter : IAuthorizationFilter {
|
|||||||
return;
|
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;
|
namespace HopFrame.Security.Claims;
|
||||||
|
|
||||||
public interface ITokenContextBase {
|
public interface ITokenContext {
|
||||||
bool IsAuthenticated { get; }
|
bool IsAuthenticated { get; }
|
||||||
User User { get; }
|
User User { get; }
|
||||||
Guid AccessToken { get; }
|
Guid AccessToken { get; }
|
||||||
@@ -4,20 +4,12 @@ using Microsoft.AspNetCore.Http;
|
|||||||
|
|
||||||
namespace HopFrame.Security.Claims;
|
namespace HopFrame.Security.Claims;
|
||||||
|
|
||||||
public class TokenContextImplementor : ITokenContextBase {
|
internal class TokenContextImplementor<TDbContext>(IHttpContextAccessor accessor, TDbContext context) : ITokenContext where TDbContext : HopDbContextBase {
|
||||||
private readonly IHttpContextAccessor _accessor;
|
public bool IsAuthenticated => accessor.HttpContext?.User.Identity?.IsAuthenticated == true;
|
||||||
private readonly HopDbContextBase _context;
|
|
||||||
|
|
||||||
public TokenContextImplementor(IHttpContextAccessor accessor, HopDbContextBase context) {
|
public User User => context.Users
|
||||||
_accessor = accessor;
|
.SingleOrDefault(user => user.Id == accessor.HttpContext.User.GetUserId())?
|
||||||
_context = context;
|
.ToUserModel(context);
|
||||||
}
|
|
||||||
|
public Guid AccessToken => Guid.Parse(accessor.HttpContext?.User.GetAccessTokenId() ?? string.Empty);
|
||||||
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 Guid AccessToken => Guid.Parse(_accessor.HttpContext?.User.GetAccessTokenId() ?? string.Empty);
|
|
||||||
}
|
}
|
||||||
@@ -4,5 +4,5 @@ A simple backend management api for ASP.NET Core Web APIs
|
|||||||
# Features
|
# Features
|
||||||
- [x] Database management
|
- [x] Database management
|
||||||
- [x] User authentication
|
- [x] User authentication
|
||||||
- [ ] Permission management
|
- [x] Permission management
|
||||||
- [ ] Frontend dashboards
|
- [ ] Frontend dashboards
|
||||||
|
|||||||
Reference in New Issue
Block a user