Restructured projects and created Services for permissions and users
This commit is contained in:
@@ -1,43 +1,31 @@
|
||||
using HopFrame.Database.Models;
|
||||
|
||||
namespace HopFrame.Security.Services;
|
||||
|
||||
public interface IPermissionService {
|
||||
|
||||
/// <summary>
|
||||
/// Checks for the user to have the specified permission
|
||||
/// 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>
|
||||
/// <returns>rather the user has the permission or not</returns>
|
||||
Task<bool> HasPermission(string permission);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the user has all the specified permissions
|
||||
/// </summary>
|
||||
/// <param name="permissions">list of the permissions</param>
|
||||
/// <returns>rather the user has all the permissions or not</returns>
|
||||
Task<bool> HasPermissions(params string[] permissions);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the user has any of the specified permissions
|
||||
/// </summary>
|
||||
/// <param name="permissions">list of the permissions</param>
|
||||
/// <returns>rather the user has any permission or not</returns>
|
||||
Task<bool> HasAnyPermission(params string[] permissions);
|
||||
|
||||
Task<bool> HasPermission(string permission, Guid user);
|
||||
|
||||
Task<PermissionGroup> GetPermissionGroup(string name);
|
||||
|
||||
Task CreatePermissionGroup(string name, bool isDefault = false, string description = null);
|
||||
|
||||
Task DeletePermissionGroup(PermissionGroup group);
|
||||
|
||||
/// <summary>
|
||||
/// Checks for the user to have the specified permission
|
||||
/// Permission system:<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="user">The user who gets checked</param>
|
||||
/// <returns>rather the user has the permission or not</returns>
|
||||
Task<bool> HasPermission(string permission, Guid user);
|
||||
/// <param name="owner"></param>
|
||||
/// <param name="permission"></param>
|
||||
/// <returns></returns>
|
||||
Task AddPermission(IPermissionOwner owner, string permission);
|
||||
|
||||
Task DeletePermission(Permission permission);
|
||||
|
||||
internal Task<string[]> GetFullPermissions(string user);
|
||||
|
||||
}
|
||||
27
HopFrame.Security/Services/IUserService.cs
Normal file
27
HopFrame.Security/Services/IUserService.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using HopFrame.Database.Models;
|
||||
using HopFrame.Security.Models;
|
||||
|
||||
namespace HopFrame.Security.Services;
|
||||
|
||||
public interface IUserService {
|
||||
Task<IList<User>> GetUsers();
|
||||
|
||||
Task<User> GetUser(Guid userId);
|
||||
|
||||
Task<User> GetUserByEmail(string email);
|
||||
|
||||
Task<User> GetUserByUsername(string username);
|
||||
|
||||
Task<User> AddUser(UserRegister user);
|
||||
|
||||
/// <summary>
|
||||
/// IMPORTANT:<br/>
|
||||
/// This function does not add or remove any permissions to the user.
|
||||
/// For that please use <see cref="IPermissionService"/>
|
||||
/// </summary>
|
||||
Task UpdateUser(User user);
|
||||
|
||||
Task DeleteUser(User user);
|
||||
|
||||
Task<string> GetUserPassword(User user);
|
||||
}
|
||||
105
HopFrame.Security/Services/Implementation/PermissionService.cs
Normal file
105
HopFrame.Security/Services/Implementation/PermissionService.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using HopFrame.Database;
|
||||
using HopFrame.Database.Models;
|
||||
using HopFrame.Database.Models.Entries;
|
||||
using HopFrame.Security.Authorization;
|
||||
using HopFrame.Security.Claims;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace HopFrame.Security.Services.Implementation;
|
||||
|
||||
internal sealed class PermissionService<TDbContext>(TDbContext context, ITokenContext current) : IPermissionService where TDbContext : HopDbContextBase {
|
||||
public async Task<bool> HasPermission(string permission) {
|
||||
return await HasPermission(permission, current.User.Id);
|
||||
}
|
||||
|
||||
public async Task<bool> HasPermissions(params string[] permissions) {
|
||||
var user = current.User.Id.ToString();
|
||||
var perms = await GetFullPermissions(user);
|
||||
|
||||
foreach (var permission in permissions) {
|
||||
if (!PermissionValidator.IncludesPermission(permission, perms)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<bool> HasAnyPermission(params string[] permissions) {
|
||||
var user = current.User.Id.ToString();
|
||||
var perms = await GetFullPermissions(user);
|
||||
|
||||
foreach (var permission in permissions) {
|
||||
if (PermissionValidator.IncludesPermission(permission, perms)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task<bool> HasPermission(string permission, Guid user) {
|
||||
var permissions = await GetFullPermissions(user.ToString());
|
||||
|
||||
return PermissionValidator.IncludesPermission(permission, permissions);
|
||||
}
|
||||
|
||||
public Task<PermissionGroup> GetPermissionGroup(string name) {
|
||||
return context.Groups
|
||||
.Where(group => group.Name == name)
|
||||
.Select(group => group.ToPermissionGroup(context))
|
||||
.SingleOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task CreatePermissionGroup(string name, bool isDefault = false, string description = null) {
|
||||
var group = new GroupEntry {
|
||||
Name = name,
|
||||
Description = description,
|
||||
Default = isDefault,
|
||||
CreatedAt = DateTime.Now
|
||||
};
|
||||
|
||||
await context.Groups.AddAsync(group);
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task DeletePermissionGroup(PermissionGroup group) {
|
||||
var entry = await context.Groups.SingleOrDefaultAsync(entry => entry.Name == group.Name);
|
||||
context.Groups.Remove(entry);
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task AddPermission(IPermissionOwner owner, string permission) {
|
||||
var userId = owner is User user ? user.Id.ToString() : (owner as PermissionGroup)?.Name;
|
||||
|
||||
await context.Permissions.AddAsync(new PermissionEntry {
|
||||
UserId = userId,
|
||||
PermissionText = permission,
|
||||
GrantedAt = DateTime.Now
|
||||
});
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task DeletePermission(Permission permission) {
|
||||
var entry = await context.Permissions.SingleOrDefaultAsync(entry => entry.RecordId == permission.Id);
|
||||
context.Permissions.Remove(entry);
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task<string[]> GetFullPermissions(string user) {
|
||||
var permissions = await context.Permissions
|
||||
.Where(perm => perm.UserId == user)
|
||||
.Select(perm => perm.PermissionText)
|
||||
.ToListAsync();
|
||||
|
||||
var groups = permissions
|
||||
.Where(perm => perm.StartsWith("group."))
|
||||
.ToList();
|
||||
|
||||
var groupPerms = new List<string>();
|
||||
foreach (var group in groups) {
|
||||
var perms = await GetFullPermissions(group);
|
||||
groupPerms.AddRange(perms);
|
||||
}
|
||||
|
||||
permissions.AddRange(groupPerms);
|
||||
|
||||
return permissions.ToArray();
|
||||
}
|
||||
}
|
||||
110
HopFrame.Security/Services/Implementation/UserService.cs
Normal file
110
HopFrame.Security/Services/Implementation/UserService.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using HopFrame.Database;
|
||||
using HopFrame.Database.Models;
|
||||
using HopFrame.Database.Models.Entries;
|
||||
using HopFrame.Security.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace HopFrame.Security.Services.Implementation;
|
||||
|
||||
internal sealed class UserService<TDbContext>(TDbContext context) : IUserService where TDbContext : HopDbContextBase {
|
||||
public async Task<IList<User>> GetUsers() {
|
||||
return await context.Users
|
||||
.Select(user => user.ToUserModel(context))
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
public Task<User> GetUser(Guid userId) {
|
||||
var id = userId.ToString();
|
||||
|
||||
return context.Users
|
||||
.Where(user => user.Id == id)
|
||||
.Select(user => user.ToUserModel(context))
|
||||
.SingleOrDefaultAsync();
|
||||
}
|
||||
|
||||
public Task<User> GetUserByEmail(string email) {
|
||||
return context.Users
|
||||
.Where(user => user.Email == email)
|
||||
.Select(user => user.ToUserModel(context))
|
||||
.SingleOrDefaultAsync();
|
||||
}
|
||||
|
||||
public Task<User> GetUserByUsername(string username) {
|
||||
return context.Users
|
||||
.Where(user => user.Username == username)
|
||||
.Select(user => user.ToUserModel(context))
|
||||
.SingleOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<User> AddUser(UserRegister user) {
|
||||
var entry = new UserEntry {
|
||||
Id = Guid.NewGuid().ToString(),
|
||||
Email = user.Email,
|
||||
Username = user.Username,
|
||||
CreatedAt = DateTime.Now
|
||||
};
|
||||
entry.Password = EncryptionManager.Hash(user.Password, Encoding.Default.GetBytes(entry.CreatedAt.ToString(CultureInfo.InvariantCulture)));
|
||||
|
||||
await context.Users.AddAsync(entry);
|
||||
|
||||
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 = entry.Id
|
||||
}));
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
return entry.ToUserModel(context);
|
||||
}
|
||||
|
||||
public async Task UpdateUser(User user) {
|
||||
var id = user.Id.ToString();
|
||||
var entry = await context.Users
|
||||
.SingleOrDefaultAsync(entry => entry.Id == id);
|
||||
if (entry is null) return;
|
||||
|
||||
entry.Email = user.Email;
|
||||
entry.Username = user.Username;
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task DeleteUser(User user) {
|
||||
var id = user.Id.ToString();
|
||||
var entry = await context.Users
|
||||
.SingleOrDefaultAsync(entry => entry.Id == id);
|
||||
|
||||
if (entry is null) return;
|
||||
|
||||
context.Users.Remove(entry);
|
||||
|
||||
var userTokens = await context.Tokens
|
||||
.Where(token => token.UserId == id)
|
||||
.ToArrayAsync();
|
||||
context.Tokens.RemoveRange(userTokens);
|
||||
|
||||
var userPermissions = await context.Permissions
|
||||
.Where(perm => perm.UserId == id)
|
||||
.ToArrayAsync();
|
||||
context.Permissions.RemoveRange(userPermissions);
|
||||
|
||||
context.OnUserDelete(entry);
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public Task<string> GetUserPassword(User user) {
|
||||
var id = user.Id.ToString();
|
||||
return context.Users
|
||||
.Where(entry => entry.Id == id)
|
||||
.Select(entry => entry.Password)
|
||||
.SingleOrDefaultAsync();
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
using HopFrame.Database;
|
||||
using HopFrame.Security.Authorization;
|
||||
using HopFrame.Security.Claims;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace HopFrame.Security.Services;
|
||||
|
||||
internal class PermissionService<TDbContext>(TDbContext context, ITokenContext current) : IPermissionService where TDbContext : HopDbContextBase {
|
||||
public async Task<bool> HasPermission(string permission) {
|
||||
return await HasPermission(permission, current.User.Id);
|
||||
}
|
||||
|
||||
public async Task<bool> HasPermissions(params string[] permissions) {
|
||||
var user = current.User.Id.ToString();
|
||||
var perms = await GetFullPermissions(user);
|
||||
|
||||
foreach (var permission in permissions) {
|
||||
if (!PermissionValidator.IncludesPermission(permission, perms)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<bool> HasAnyPermission(params string[] permissions) {
|
||||
var user = current.User.Id.ToString();
|
||||
var perms = await GetFullPermissions(user);
|
||||
|
||||
foreach (var permission in permissions) {
|
||||
if (PermissionValidator.IncludesPermission(permission, perms)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task<bool> HasPermission(string permission, Guid user) {
|
||||
var permissions = await GetFullPermissions(user.ToString());
|
||||
|
||||
return PermissionValidator.IncludesPermission(permission, permissions);
|
||||
}
|
||||
|
||||
private async Task<string[]> GetFullPermissions(string user) {
|
||||
var permissions = await context.Permissions
|
||||
.Where(perm => perm.UserId == user)
|
||||
.Select(perm => perm.PermissionText)
|
||||
.ToListAsync();
|
||||
|
||||
var groups = permissions
|
||||
.Where(perm => perm.StartsWith("group."))
|
||||
.ToList();
|
||||
|
||||
var groupPerms = await context.Permissions
|
||||
.Where(perm => groups.Contains(user))
|
||||
.Select(perm => perm.PermissionText)
|
||||
.ToListAsync();
|
||||
|
||||
permissions.AddRange(groupPerms);
|
||||
|
||||
return permissions.ToArray();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user