Discord: honor Administrator in permission checks

This commit is contained in:
Shadow
2026-02-12 19:52:45 -06:00
parent 22fe30c1df
commit 34c304727b
2 changed files with 45 additions and 0 deletions

View File

@@ -10,6 +10,8 @@ import { normalizeDiscordToken } from "./token.js";
const PERMISSION_ENTRIES = Object.entries(PermissionFlagsBits).filter( const PERMISSION_ENTRIES = Object.entries(PermissionFlagsBits).filter(
([, value]) => typeof value === "bigint", ([, value]) => typeof value === "bigint",
); );
const ALL_PERMISSIONS = PERMISSION_ENTRIES.reduce((acc, [, value]) => acc | value, 0n);
const ADMINISTRATOR_BIT = PermissionFlagsBits.Administrator;
type DiscordClientOpts = { type DiscordClientOpts = {
token?: string; token?: string;
@@ -68,6 +70,10 @@ function bitfieldToPermissions(bitfield: bigint) {
.toSorted(); .toSorted();
} }
function hasAdministrator(bitfield: bigint) {
return (bitfield & ADMINISTRATOR_BIT) === ADMINISTRATOR_BIT;
}
export function isThreadChannelType(channelType?: number) { export function isThreadChannelType(channelType?: number) {
return ( return (
channelType === ChannelType.GuildNewsThread || channelType === ChannelType.GuildNewsThread ||
@@ -121,6 +127,17 @@ export async function fetchChannelPermissionsDiscord(
} }
} }
if (hasAdministrator(base)) {
return {
channelId,
guildId,
permissions: bitfieldToPermissions(ALL_PERMISSIONS),
raw: ALL_PERMISSIONS.toString(),
isDm: false,
channelType,
};
}
let permissions = base; let permissions = base;
const overwrites = const overwrites =
"permission_overwrites" in channel ? (channel.permission_overwrites ?? []) : []; "permission_overwrites" in channel ? (channel.permission_overwrites ?? []) : [];

View File

@@ -447,6 +447,34 @@ describe("fetchChannelPermissionsDiscord", () => {
expect(res.permissions).toContain("SendMessages"); expect(res.permissions).toContain("SendMessages");
expect(res.isDm).toBe(false); expect(res.isDm).toBe(false);
}); });
it("treats Administrator as all permissions despite overwrites", async () => {
const { rest, getMock } = makeRest();
getMock
.mockResolvedValueOnce({
id: "chan1",
guild_id: "guild1",
permission_overwrites: [
{
id: "guild1",
deny: PermissionFlagsBits.ViewChannel.toString(),
allow: "0",
},
],
})
.mockResolvedValueOnce({ id: "bot1" })
.mockResolvedValueOnce({
id: "guild1",
roles: [{ id: "guild1", permissions: PermissionFlagsBits.Administrator.toString() }],
})
.mockResolvedValueOnce({ roles: [] });
const res = await fetchChannelPermissionsDiscord("chan1", {
rest,
token: "t",
});
expect(res.permissions).toContain("Administrator");
expect(res.permissions).toContain("ViewChannel");
});
}); });
describe("readMessagesDiscord", () => { describe("readMessagesDiscord", () => {