New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GuildMember
and GuildChannel
permission-based methods do not reflect permission changes on timeouts
#9730
Comments
Thats just a bitfield, whose behaviour we shouldnt change |
One thing I have noticed is an interaction's |
SuggestionThis is one of the solutions which is a breaking change.
|
permissionsFor(memberOrRole, checkAdmin = true) { | |
const member = this.guild.members.resolve(memberOrRole); | |
if (member) return this.memberPermissions(member, checkAdmin); | |
const role = this.guild.roles.resolve(memberOrRole); | |
return role && this.rolePermissions(role, checkAdmin); | |
} |
After:
permissionsFor(memberOrRole, { checkAdmin = true, checkTimeout = true } = {}) {
const member = this.guild.members.resolve(memberOrRole);
if (member) return this.memberPermissions(member, { checkAdmin, checkTimeout });
const role = this.guild.roles.resolve(memberOrRole);
return role && this.rolePermissions(role, checkAdmin);
}
GuildChannel#memberPermissions()
Private Method
Before:
discord.js/packages/discord.js/src/structures/GuildChannel.js
Lines 216 to 238 in a1a3a95
memberPermissions(member, checkAdmin) { | |
if (checkAdmin && member.id === this.guild.ownerId) { | |
return new PermissionsBitField(PermissionsBitField.All).freeze(); | |
} | |
const roles = member.roles.cache; | |
const permissions = new PermissionsBitField(roles.map(role => role.permissions)); | |
if (checkAdmin && permissions.has(PermissionFlagsBits.Administrator)) { | |
return new PermissionsBitField(PermissionsBitField.All).freeze(); | |
} | |
const overwrites = this.overwritesFor(member, true, roles); | |
return permissions | |
.remove(overwrites.everyone?.deny ?? PermissionsBitField.DefaultBit) | |
.add(overwrites.everyone?.allow ?? PermissionsBitField.DefaultBit) | |
.remove(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.deny) : PermissionsBitField.DefaultBit) | |
.add(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.allow) : PermissionsBitField.DefaultBit) | |
.remove(overwrites.member?.deny ?? PermissionsBitField.DefaultBit) | |
.add(overwrites.member?.allow ?? PermissionsBitField.DefaultBit) | |
.freeze(); | |
} |
After:
memberPermissions(member, { checkAdmin, checkTimeout }) {
if (checkAdmin && member.id === this.guild.ownerId) {
return new PermissionsBitField(PermissionsBitField.All).freeze();
}
const roles = member.roles.cache;
const rolePermissions = new PermissionsBitField(roles.map(role => role.permissions));
if (checkAdmin && rolePermissions.has(PermissionFlagsBits.Administrator)) {
return new PermissionsBitField(PermissionsBitField.All).freeze();
}
const overwrites = this.overwritesFor(member, true, roles);
const channelPermissions = rolePermissions
.remove(overwrites.everyone?.deny ?? PermissionsBitField.DefaultBit)
.add(overwrites.everyone?.allow ?? PermissionsBitField.DefaultBit)
.remove(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.deny) : PermissionsBitField.DefaultBit)
.add(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.allow) : PermissionsBitField.DefaultBit)
.remove(overwrites.member?.deny ?? PermissionsBitField.DefaultBit)
.add(overwrites.member?.allow ?? PermissionsBitField.DefaultBit);
if (
!checkTimeout
|| member.id === this.guild.ownerId
|| channelPermissions.has(PermissionFlagsBits.Administrator)
|| !member.isCommunicationDisabled()
) {
return channelPermissions.freeze();
}
return new PermissionsBitField(
channelPermissions.has(PermissionFlagsBits.ViewChannel) ? PermissionFlagsBits.ViewChannel : PermissionsBitField.DefaultBit |
channelPermissions.has(PermissionFlagsBits.ReadMessageHistory) ? PermissionFlagsBits.ReadMessageHistory : PermissionsBitField.DefaultBit
).freeze();
}
Which package is this bug report for?
discord.js
Issue description
Description
According to docs, timed out members should have lost all permissions except
VIEW_CHANNEL
andREAD_MESSAGE_HISTORY
, if they do not haveADMINISTRATOR
permission. However, the methods mentioned below do not reflect the permission changes on timeouts. I understand that we can check if a guild member is timed out withGuildMember.isCommunicationDisabled()
and many other ways, and then make a function to obtain more accurate permissions, but having a all-in-one method to check the current permissions accurately is more convenient for us.Impacts
channel.permissionsFor(client.user)?.has(['ViewChannel', 'SendMessages']) ?? false
) before requesting the API (e.g. send a message to a text channel). Without reading the code deeply and additional testing, they may not know that the methods do not support timed out member permissions (when the client user is timed out in a guild, plus having no admin permission, suppose itsGuildMember
is cached, the above example will still returntrue
if it has the permissions when timeout is not applied).Code reference
GuildChannel.permissionsFor(memberOrRole, [checkAdmin])
discord.js/packages/discord.js/src/structures/GuildChannel.js
Lines 174 to 179 in d26e022
discord.js/packages/discord.js/src/structures/GuildChannel.js
Lines 215 to 237 in d26e022
GuildMember.permissions
discord.js/packages/discord.js/src/structures/GuildMember.js
Lines 254 to 257 in d26e022
GuildMember.permissionsIn(channel)
discord.js/packages/discord.js/src/structures/GuildMember.js
Lines 320 to 324 in d26e022
Code sample
No response
Versions
Issue priority
Medium (should be fixed soon)
Which partials do you have configured?
Not applicable
Which gateway intents are you subscribing to?
Not applicable
I have tested this issue on a development release
No response
The text was updated successfully, but these errors were encountered: