using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using DeukBot4.Database; using DeukBot4.MessageHandlers.CommandHandler.RequestStructure; using Discord; using Discord.WebSocket; namespace DeukBot4.MessageHandlers.Permissions { public static class PermissionValidator { private static readonly ConcurrentDictionary> PermissionCache = new ConcurrentDictionary>(); private static async Task GetDatabasePermissionLevelForRole(ulong serverId, ulong roleId) { if (PermissionCache.TryGetValue(serverId, out var serverPermissions)) { if (serverPermissions.TryGetValue(roleId, out var permissions)) { return permissions; } } else { PermissionCache.TryAdd(serverId, new ConcurrentDictionary()); } serverPermissions = PermissionCache[serverId]; try { var permission = await DatabaseRolePermissions.GetRolePermission(serverId, roleId); serverPermissions.TryAdd(serverId, permission); return permission; } catch(Exception e) { await Logger.LogError(e.ToString()); return PermissionLevel.Everyone; } } public static void UpdateCache(ulong serverId, ulong roleId, PermissionLevel level) { if (PermissionCache.TryGetValue(serverId, out var serverPermissions)) { if (serverPermissions.ContainsKey(roleId)) { serverPermissions[roleId] = level; } else { serverPermissions.TryAdd(roleId, level); } } } private static async Task GetDatabasePermissionLevel(ulong serverId, ulong[] roles) { var highestRole = (PermissionLevel)sbyte.MinValue; foreach (var role in roles) { var perms = await GetDatabasePermissionLevelForRole(serverId, role); if (perms > highestRole) { highestRole = perms; } } if (highestRole == (PermissionLevel) sbyte.MinValue) { return PermissionLevel.Everyone; } return highestRole; } public static async Task GetUserPermissionLevel(SocketMessage message) { return await GetUserPermissionLevel(message.Channel, message.Author); } public static async Task GetUserPermissionLevel(ISocketMessageChannel channel, SocketUser user) { if (user.Id == Program.Settings.OwnerId) { return PermissionLevel.BotCreator; } if (user.IsBot) { return PermissionLevel.Bot; } if (!(channel is IGuildChannel serverChannel)) return PermissionLevel.Everyone; if (serverChannel.Guild.OwnerId == user.Id) return PermissionLevel.ServerOwner; if (!(user is IGuildUser guildUser)) return PermissionLevel.Everyone; var perms = await GetDatabasePermissionLevel(serverChannel.GuildId, guildUser.RoleIds.ToArray()); return perms; } } }