using System.Collections.Immutable; using Microsoft.EntityFrameworkCore; using Phantom.Common.Logging; using Phantom.Controller.Database; using Phantom.Controller.Database.Entities; using Phantom.Utils.Collections; using ILogger = Serilog.ILogger; namespace Phantom.Controller.Services.Users.Roles; public sealed class UserRoleManager { private static readonly ILogger Logger = PhantomLogger.Create<UserRoleManager>(); private readonly IDatabaseProvider databaseProvider; public UserRoleManager(IDatabaseProvider databaseProvider) { this.databaseProvider = databaseProvider; } public async Task<Dictionary<Guid, ImmutableArray<RoleEntity>>> GetAllByUserGuid() { await using var ctx = databaseProvider.Provide(); return await ctx.UserRoles .Include(static ur => ur.Role) .GroupBy(static ur => ur.UserGuid, static ur => ur.Role) .ToDictionaryAsync(static group => group.Key, static group => group.ToImmutableArray()); } public async Task<ImmutableArray<RoleEntity>> GetUserRoles(UserEntity user) { await using var ctx = databaseProvider.Provide(); return await ctx.UserRoles .Include(static ur => ur.Role) .Where(ur => ur.UserGuid == user.UserGuid) .Select(static ur => ur.Role) .AsAsyncEnumerable() .ToImmutableArrayAsync(); } public async Task<ImmutableHashSet<Guid>> GetUserRoleGuids(UserEntity user) { await using var ctx = databaseProvider.Provide(); return await ctx.UserRoles .Where(ur => ur.UserGuid == user.UserGuid) .Select(static ur => ur.RoleGuid) .AsAsyncEnumerable() .ToImmutableSetAsync(); } public async Task<bool> Add(UserEntity user, RoleEntity role) { try { await using var ctx = databaseProvider.Provide(); var userRole = await ctx.UserRoles.FindAsync(user.UserGuid, role.RoleGuid); if (userRole == null) { userRole = new UserRoleEntity(user.UserGuid, role.RoleGuid); ctx.UserRoles.Add(userRole); await ctx.SaveChangesAsync(); } } catch (Exception e) { Logger.Error(e, "Could not add user \"{UserName}\" (GUID {UserGuid}) to role \"{RoleName}\" (GUID {RoleGuid}).", user.Name, user.UserGuid, role.Name, role.RoleGuid); return false; } Logger.Information("Added user \"{UserName}\" (GUID {UserGuid}) to role \"{RoleName}\" (GUID {RoleGuid}).", user.Name, user.UserGuid, role.Name, role.RoleGuid); return true; } public async Task<bool> Remove(UserEntity user, RoleEntity role) { try { await using var ctx = databaseProvider.Provide(); var userRole = await ctx.UserRoles.FindAsync(user.UserGuid, role.RoleGuid); if (userRole != null) { ctx.UserRoles.Remove(userRole); await ctx.SaveChangesAsync(); } } catch (Exception e) { Logger.Error(e, "Could not remove user \"{UserName}\" (GUID {UserGuid}) from role \"{RoleName}\" (GUID {RoleGuid}).", user.Name, user.UserGuid, role.Name, role.RoleGuid); return false; } Logger.Information("Removed user \"{UserName}\" (GUID {UserGuid}) from role \"{RoleName}\" (GUID {RoleGuid}).", user.Name, user.UserGuid, role.Name, role.RoleGuid); return true; } }