Fix getPermissions misunderstanding @everyone

This commit is contained in:
Cadence Ember
2026-01-14 15:11:22 +13:00
parent a488c15351
commit fba50e9505
9 changed files with 18 additions and 19 deletions

View File

@@ -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"])

View File

@@ -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.

View File

@@ -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()

View File

@@ -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<DiscordTypes.APIOverwrite>) => 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

View File

@@ -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)
})

View File

@@ -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
}

View File

@@ -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,

View File

@@ -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

View File

@@ -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))