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();
}
}