using System.Collections.Immutable; using Microsoft.EntityFrameworkCore; using Spacebar.Models.Db.Contexts; using Spacebar.Models.Generic.Constants; namespace Spacebar.UApi.Services; public class PermissionService(SpacebarDbContext db) { /// /// Asserts that user has all the relevant guild permissions /// /// Guild ID /// Member ID public async Task GetUserGuildPermissions(long guildId, long userId) { var member = await db.Members .Include(x => x.Roles) .SingleAsync(x => x.Id == userId && x.GuildId == guildId); if (member is null) throw new InvalidOperationException("You are not a member of this guild."); var permissions = member.Roles.Aggregate((Permissions)0UL, (current, role) => current | (Permissions)ulong.Parse(role.Permissions)); if (member.CommunicationDisabledUntil is not null && member.CommunicationDisabledUntil > DateTime.UtcNow) { permissions &= Permissions.ViewChannel | Permissions.ReadMessageHistory; } return permissions; } /// /// Asserts that user has all the relevant guild permissions /// /// Permissions to require /// Guild ID /// Member ID /// Has one or more missing permissions public async Task AssertUserHasGuildPermission(Permissions permission, long guildId, long userId) { var permissions = await GetUserGuildPermissions(guildId, userId); if (!permissions.HasFlag(permission)) throw new PermissionException(Enum.GetValues().Where(p => !permissions.HasFlag(p) && permission.HasFlag(p)).ToList()); } } /// /// Thrown when a user is missing a given permission /// public class PermissionException : Exception { /// /// The list of missing permissions /// public ImmutableList MissingPermissions { get; } /// public PermissionException(IReadOnlyCollection missingPermissions) : base( $"You do not have the required permissions to perform this action: {string.Join(", ", missingPermissions)}") { MissingPermissions = missingPermissions.ToImmutableList(); } }