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; public sealed class UserRoleManager { private static readonly ILogger Logger = PhantomLogger.Create<UserRoleManager>(); private readonly ApplicationDbContext db; public UserRoleManager(ApplicationDbContext db) { this.db = db; } public Task<Dictionary<Guid, ImmutableArray<RoleEntity>>> GetAllByUserGuid() { return db.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 Task<ImmutableArray<RoleEntity>> GetUserRoles(UserEntity user) { return db.UserRoles .Include(static ur => ur.Role) .Where(ur => ur.UserGuid == user.UserGuid) .Select(static ur => ur.Role) .AsAsyncEnumerable() .ToImmutableArrayAsync(); } public Task<ImmutableHashSet<Guid>> GetUserRoleGuids(UserEntity user) { return db.UserRoles .Where(ur => ur.UserGuid == user.UserGuid) .Select(static ur => ur.RoleGuid) .AsAsyncEnumerable() .ToImmutableSetAsync(); } public async Task<bool> Add(UserEntity user, RoleEntity role) { try { var userRole = await db.UserRoles.FindAsync(user.UserGuid, role.RoleGuid); if (userRole == null) { userRole = new UserRoleEntity(user.UserGuid, role.RoleGuid); db.UserRoles.Add(userRole); await db.SaveChangesAsync(); } Logger.Information("Added user \"{UserName}\" (GUID {UserGuid}) to role \"{RoleName}\" (GUID {RoleGuid}).", user.Name, user.UserGuid, role.Name, role.RoleGuid); return true; } 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; } } public async Task<bool> Remove(UserEntity user, RoleEntity role) { try { var userRole = await db.UserRoles.FindAsync(user.UserGuid, role.RoleGuid); if (userRole != null) { db.UserRoles.Remove(userRole); await db.SaveChangesAsync(); } Logger.Information("Removed user \"{UserName}\" (GUID {UserGuid}) from role \"{RoleName}\" (GUID {RoleGuid}).", user.Name, user.UserGuid, role.Name, role.RoleGuid); return true; } 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; } } }