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 Phantom.Utils.Tasks; using ILogger = Serilog.ILogger; namespace Phantom.Controller.Services.Users; public sealed class RoleManager { private static readonly ILogger Logger = PhantomLogger.Create<RoleManager>(); private const int MaxRoleNameLength = 40; private readonly ApplicationDbContext db; public RoleManager(ApplicationDbContext db) { this.db = db; } public Task<List<RoleEntity>> GetAll() { return db.Roles.ToListAsync(); } public Task<ImmutableHashSet<string>> GetAllNames() { return db.Roles.Select(static role => role.Name).AsAsyncEnumerable().ToImmutableSetAsync(); } public ValueTask<RoleEntity?> GetByGuid(Guid guid) { return db.Roles.FindAsync(guid); } public async Task<Result<RoleEntity, AddRoleError>> Create(Guid guid, string name) { if (string.IsNullOrWhiteSpace(name)) { return Result.Fail<RoleEntity, AddRoleError>(AddRoleError.NameIsEmpty); } else if (name.Length > MaxRoleNameLength) { return Result.Fail<RoleEntity, AddRoleError>(AddRoleError.NameIsTooLong); } try { if (await db.Roles.AnyAsync(role => role.Name == name)) { return Result.Fail<RoleEntity, AddRoleError>(AddRoleError.NameAlreadyExists); } var role = new RoleEntity(guid, name); db.Roles.Add(role); await db.SaveChangesAsync(); Logger.Information("Created role \"{Name}\" (GUID {Guid}).", name, guid); return Result.Ok<RoleEntity, AddRoleError>(role); } catch (Exception e) { Logger.Error(e, "Could not create role \"{Name}\" (GUID {Guid}).", name, guid); return Result.Fail<RoleEntity, AddRoleError>(AddRoleError.UnknownError); } } }