diff --git a/src/d2m/actions/create-room.js b/src/d2m/actions/create-room.js index 11a03e5..fc2d35f 100644 --- a/src/d2m/actions/create-room.js +++ b/src/d2m/actions/create-room.js @@ -122,7 +122,7 @@ async function channelToKState(channel, guild, di) { join_rules = {join_rule: PRIVACY_ENUMS.ROOM_JOIN_RULES[privacyLevel]} } - const everyonePermissions = dUtils.getPermissions([], guild.roles, undefined, channel.permission_overwrites) + const everyonePermissions = dUtils.getPermissions(guild.id, [], guild.roles, undefined, channel.permission_overwrites) const everyoneCanSend = dUtils.hasPermission(everyonePermissions, DiscordTypes.PermissionFlagsBits.SendMessages) const everyoneCanMentionEveryone = dUtils.hasAllPermissions(everyonePermissions, ["MentionEveryone"]) diff --git a/src/d2m/actions/register-user.js b/src/d2m/actions/register-user.js index 35da4f5..d20bfb8 100644 --- a/src/d2m/actions/register-user.js +++ b/src/d2m/actions/register-user.js @@ -153,8 +153,8 @@ async function memberToStateContent(user, member, guildID) { function memberToPowerLevel(user, member, guild, channel) { if (!member) return 0 - const permissions = dUtils.getPermissions(member.roles, guild.roles, user.id, channel.permission_overwrites) - const everyonePermissions = dUtils.getPermissions([], guild.roles, undefined, channel.permission_overwrites) + const permissions = dUtils.getPermissions(guild.id, member.roles, guild.roles, user.id, channel.permission_overwrites) + const everyonePermissions = dUtils.getPermissions(guild.id, [], guild.roles, undefined, channel.permission_overwrites) /* * PL 100 = Administrator = People who can brick the room. RATIONALE: * - Administrator. diff --git a/src/d2m/event-dispatcher.js b/src/d2m/event-dispatcher.js index bf7efb9..834cf9d 100644 --- a/src/d2m/event-dispatcher.js +++ b/src/d2m/event-dispatcher.js @@ -87,7 +87,7 @@ module.exports = { const member = guild.members.find(m => m.user?.id === client.user.id) if (!member) return if (!("permission_overwrites" in channel)) continue - const permissions = dUtils.getPermissions(member.roles, guild.roles, client.user.id, channel.permission_overwrites) + const permissions = dUtils.getPermissions(guild.id, member.roles, guild.roles, client.user.id, channel.permission_overwrites) if (!dUtils.hasAllPermissions(permissions, ["ViewChannel", "ReadMessageHistory"])) continue // We don't have permission to look back in this channel /** More recent messages come first. */ @@ -146,7 +146,7 @@ module.exports = { const lastPin = updatePins.convertTimestamp(channel.last_pin_timestamp) // Permissions check - const permissions = dUtils.getPermissions(member.roles, guild.roles, client.user.id, channel.permission_overwrites) + const permissions = dUtils.getPermissions(guild.id, member.roles, guild.roles, client.user.id, channel.permission_overwrites) if (!dUtils.hasAllPermissions(permissions, ["ViewChannel", "ReadMessageHistory"])) continue // We don't have permission to look up the pins in this channel const row = select("channel_room", ["room_id", "last_bridged_pin_timestamp"], {channel_id: channel.id}).get() diff --git a/src/discord/utils.js b/src/discord/utils.js index 963f0b8..441a55c 100644 --- a/src/discord/utils.js +++ b/src/discord/utils.js @@ -15,19 +15,18 @@ require("xxhash-wasm")().then(h => hasher = h) const EPOCH = 1420070400000 /** + * @param {string} guildID * @param {string[]} userRoles * @param {DiscordTypes.APIGuild["roles"]} guildRoles * @param {string} [userID] * @param {DiscordTypes.APIGuildChannel["permission_overwrites"]} [channelOverwrites] */ -function getPermissions(userRoles, guildRoles, userID, channelOverwrites) { +function getPermissions(guildID, userRoles, guildRoles, userID, channelOverwrites) { let allowed = BigInt(0) - let everyoneID // Guild allows for (const role of guildRoles) { - if (role.name === "@everyone") { + if (role.id === guildID) { allowed |= BigInt(role.permissions) - everyoneID = role.id } if (userRoles.includes(role.id)) { allowed |= BigInt(role.permissions) @@ -38,9 +37,9 @@ function getPermissions(userRoles, guildRoles, userID, channelOverwrites) { /** @type {((overwrite: Required) => any)[]} */ const actions = [ // Channel @everyone deny - overwrite => overwrite.id === everyoneID && (allowed &= ~BigInt(overwrite.deny)), + overwrite => overwrite.id === guildID && (allowed &= ~BigInt(overwrite.deny)), // Channel @everyone allow - overwrite => overwrite.id === everyoneID && (allowed |= BigInt(overwrite.allow)), + overwrite => overwrite.id === guildID && (allowed |= BigInt(overwrite.allow)), // Role deny overwrite => userRoles.includes(overwrite.id) && (allowed &= ~BigInt(overwrite.deny)), // Role allow diff --git a/src/discord/utils.test.js b/src/discord/utils.test.js index 516bd2f..3a3e177 100644 --- a/src/discord/utils.test.js +++ b/src/discord/utils.test.js @@ -79,7 +79,7 @@ test("getPermissions: channel overwrite to allow role works", t => { { type: 0, id: "1168988246680801360", deny: "0", allow: "1024" }, { type: 1, id: "353373325575323648", deny: "0", allow: "1024" } ] - const permissions = utils.getPermissions(userRoles, guildRoles, userID, overwrites) + const permissions = utils.getPermissions("1154868424724463687", userRoles, guildRoles, userID, overwrites) const want = BigInt(1 << 10 | 1 << 16) t.equal((permissions & want), want) }) @@ -140,7 +140,7 @@ test("getPermissions: channel overwrite to allow user works", t => { { type: 0, id: "1168988246680801360", deny: "0", allow: "1024" }, { type: 1, id: "353373325575323648", deny: "0", allow: "1024" } ] - const permissions = utils.getPermissions(userRoles, guildRoles, userID, overwrites) + const permissions = utils.getPermissions("1154868424724463687", userRoles, guildRoles, userID, overwrites) const want = BigInt(1 << 10 | 1 << 16) t.equal((permissions & want), want) }) diff --git a/src/m2d/converters/event-to-message.js b/src/m2d/converters/event-to-message.js index 273521c..b9f80f3 100644 --- a/src/m2d/converters/event-to-message.js +++ b/src/m2d/converters/event-to-message.js @@ -868,7 +868,7 @@ async function eventToMessage(event, guild, channel, di) { let shouldSuppress = inBody !== -1 && event.content.body[inBody-1] === "<" if (!shouldSuppress && guild?.roles) { // Suppress if regular users don't have permission - const permissions = dUtils.getPermissions([], guild.roles) + const permissions = dUtils.getPermissions(guild.id, [], guild.roles) const canEmbedLinks = dUtils.hasPermission(permissions, DiscordTypes.PermissionFlagsBits.EmbedLinks) shouldSuppress = !canEmbedLinks } @@ -931,7 +931,7 @@ async function eventToMessage(event, guild, channel, di) { // Suppress if regular users don't have permission if (!shouldSuppress && guild?.roles) { - const permissions = dUtils.getPermissions([], guild.roles, undefined, channel.permission_overwrites) + const permissions = dUtils.getPermissions(guild.id, [], guild.roles, undefined, channel.permission_overwrites) const canEmbedLinks = dUtils.hasPermission(permissions, DiscordTypes.PermissionFlagsBits.EmbedLinks) shouldSuppress = !canEmbedLinks } diff --git a/src/matrix/matrix-command-handler.js b/src/matrix/matrix-command-handler.js index 721c3bd..c1c69f1 100644 --- a/src/matrix/matrix-command-handler.js +++ b/src/matrix/matrix-command-handler.js @@ -114,7 +114,7 @@ const commands = [{ const guild = discord.guilds.get(guildID) assert(guild) const slots = getSlotCount(guild.premium_tier) - const permissions = dUtils.getPermissions([], guild.roles) + const permissions = dUtils.getPermissions(guild.id, [], guild.roles) if (guild.emojis.length >= slots) { matrixOnlyReason = "CAPACITY" } else if (!(permissions & 0x40000000n)) { // MANAGE_GUILD_EXPRESSIONS (apparently CREATE_GUILD_EXPRESSIONS isn't good enough...) @@ -250,7 +250,7 @@ const commands = [{ const guild = discord.guilds.get(guildID) assert(guild) - const permissions = dUtils.getPermissions([], guild.roles) + const permissions = dUtils.getPermissions(guild.id, [], guild.roles) if (!(permissions & 0x800000000n)) { // CREATE_PUBLIC_THREADS return api.sendEvent(event.room_id, "m.room.message", { ...ctx, diff --git a/src/web/pug/guild.pug b/src/web/pug/guild.pug index c09ca7e..c219e29 100644 --- a/src/web/pug/guild.pug +++ b/src/web/pug/guild.pug @@ -13,7 +13,7 @@ mixin badge-private mixin discord(channel, radio=false) //- Previously, we passed guild.roles as the second parameter, but this doesn't quite match Discord's behaviour. See issue #42 for why this was changed. //- Basically we just want to assign badges based on the channel overwrites, without considering the guild's base permissions. /shrug - - let permissions = dUtils.getPermissions([], [{id: guild_id, name: "@everyone", permissions: 1<<10 | 1<<11}], null, channel.permission_overwrites) + - let permissions = dUtils.getPermissions(guild_id, [], [{id: guild_id, name: "@everyone", permissions: 1<<10 | 1<<11}], null, channel.permission_overwrites) .s-user-card.s-user-card__small if !dUtils.hasPermission(permissions, DiscordTypes.PermissionFlagsBits.ViewChannel) != icons.Icons.IconLock diff --git a/src/web/routes/guild.js b/src/web/routes/guild.js index 9037d40..47b710b 100644 --- a/src/web/routes/guild.js +++ b/src/web/routes/guild.js @@ -128,7 +128,7 @@ function getChannelRoomsLinks(guild, rooms, roles) { let unlinkedChannels = unlinkedChannelIDs.map(c => discord.channels.get(c)) let removedWrongTypeChannels = filterTo(unlinkedChannels, c => c && [0, 5].includes(c.type)) let removedPrivateChannels = filterTo(unlinkedChannels, c => { - const permissions = dUtils.getPermissions(roles, guild.roles, botID, c["permission_overwrites"]) + const permissions = dUtils.getPermissions(guild.id, roles, guild.roles, botID, c["permission_overwrites"]) return dUtils.hasPermission(permissions, DiscordTypes.PermissionFlagsBits.ViewChannel) }) unlinkedChannels.sort((a, b) => getPosition(a, discord.channels) - getPosition(b, discord.channels))