Add helper for permission calculations
This commit is contained in:
parent
2fb68900c7
commit
bf3d219716
4 changed files with 50 additions and 6 deletions
|
@ -12,7 +12,7 @@ const utils = sync.require("../../m2d/converters/utils")
|
||||||
* @typedef ReactionRemoveRequest
|
* @typedef ReactionRemoveRequest
|
||||||
* @prop {string} eventID
|
* @prop {string} eventID
|
||||||
* @prop {string | null} mxid
|
* @prop {string | null} mxid
|
||||||
* @prop {BigInt} [hash]
|
* @prop {bigint} [hash]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -115,8 +115,7 @@ module.exports = {
|
||||||
if (!member) return
|
if (!member) return
|
||||||
if (!("permission_overwrites" in channel)) continue
|
if (!("permission_overwrites" in channel)) continue
|
||||||
const permissions = dUtils.getPermissions(member.roles, guild.roles, client.user.id, channel.permission_overwrites)
|
const permissions = dUtils.getPermissions(member.roles, guild.roles, client.user.id, channel.permission_overwrites)
|
||||||
const wants = BigInt(1 << 10) | BigInt(1 << 16) // VIEW_CHANNEL + READ_MESSAGE_HISTORY
|
if (!dUtils.hasAllPermissions(permissions, ["ViewChannel", "ReadMessageHistory"])) continue // We don't have permission to look back in this channel
|
||||||
if ((permissions & wants) !== wants) continue // We don't have permission to look back in this channel
|
|
||||||
|
|
||||||
/** More recent messages come first. */
|
/** More recent messages come first. */
|
||||||
// console.log(`[check missed messages] in ${channel.id} (${guild.name} / ${channel.name}) because its last message ${channel.last_message_id} is not in the database`)
|
// console.log(`[check missed messages] in ${channel.id} (${guild.name} / ${channel.name}) because its last message ${channel.last_message_id} is not in the database`)
|
||||||
|
@ -164,8 +163,7 @@ module.exports = {
|
||||||
|
|
||||||
// Permissions check
|
// Permissions check
|
||||||
const permissions = dUtils.getPermissions(member.roles, guild.roles, client.user.id, channel.permission_overwrites)
|
const permissions = dUtils.getPermissions(member.roles, guild.roles, client.user.id, channel.permission_overwrites)
|
||||||
const wants = BigInt(1 << 10) | BigInt(1 << 16) // VIEW_CHANNEL + READ_MESSAGE_HISTORY
|
if (!dUtils.hasAllPermissions(permissions, ["ViewChannel", "ReadMessageHistory"])) continue // We don't have permission to look up the pins in this channel
|
||||||
if ((permissions & wants) !== wants) 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()
|
const row = select("channel_room", ["room_id", "last_bridged_pin_timestamp"], {channel_id: channel.id}).get()
|
||||||
if (!row) continue // Only care about already bridged channels
|
if (!row) continue // Only care about already bridged channels
|
||||||
|
|
|
@ -137,7 +137,7 @@ const commands = [{
|
||||||
// Check CREATE_INSTANT_INVITE permission
|
// Check CREATE_INSTANT_INVITE permission
|
||||||
assert(message.member)
|
assert(message.member)
|
||||||
const guildPermissions = utils.getPermissions(message.member.roles, guild.roles)
|
const guildPermissions = utils.getPermissions(message.member.roles, guild.roles)
|
||||||
if (!(guildPermissions & BigInt(1))) {
|
if (!(guildPermissions & DiscordTypes.PermissionFlagsBits.CreateInstantInvite)) {
|
||||||
return discord.snow.channel.createMessage(channel.id, {
|
return discord.snow.channel.createMessage(channel.id, {
|
||||||
...ctx,
|
...ctx,
|
||||||
content: "You don't have permission to invite people to this Discord server."
|
content: "You don't have permission to invite people to this Discord server."
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
const DiscordTypes = require("discord-api-types/v10")
|
const DiscordTypes = require("discord-api-types/v10")
|
||||||
|
const assert = require("assert").strict
|
||||||
|
|
||||||
const EPOCH = 1420070400000
|
const EPOCH = 1420070400000
|
||||||
|
|
||||||
|
@ -49,6 +50,48 @@ function getPermissions(userRoles, guildRoles, userID, channelOverwrites) {
|
||||||
return allowed
|
return allowed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note: You can only provide one permission bit to permissionToCheckFor. To check multiple permissions, call `hasAllPermissions` or `hasSomePermissions`.
|
||||||
|
* It is designed like this to avoid developer error with bit manipulations.
|
||||||
|
*
|
||||||
|
* @param {bigint} resolvedPermissions
|
||||||
|
* @param {bigint} permissionToCheckFor
|
||||||
|
* @returns {boolean} whether the user has the requested permission
|
||||||
|
* @example
|
||||||
|
* const permissions = getPermissions(userRoles, guildRoles, userID, channelOverwrites)
|
||||||
|
* hasPermission(permissions, DiscordTypes.PermissionFlagsBits.ViewChannel)
|
||||||
|
*/
|
||||||
|
function hasPermission(resolvedPermissions, permissionToCheckFor) {
|
||||||
|
// Make sure permissionToCheckFor has exactly one permission in it
|
||||||
|
assert.equal(permissionToCheckFor.toString(2).match(/1/g), 1)
|
||||||
|
// Do the actual calculation
|
||||||
|
return (resolvedPermissions & permissionToCheckFor) === permissionToCheckFor
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {bigint} resolvedPermissions
|
||||||
|
* @param {(keyof DiscordTypes.PermissionFlagsBits)[]} permissionsToCheckFor
|
||||||
|
* @returns {boolean} whether the user has any of the requested permissions
|
||||||
|
* @example
|
||||||
|
* const permissions = getPermissions(userRoles, guildRoles, userID, channelOverwrites)
|
||||||
|
* hasSomePermissions(permissions, ["ViewChannel", "ReadMessageHistory"])
|
||||||
|
*/
|
||||||
|
function hasSomePermissions(resolvedPermissions, permissionsToCheckFor) {
|
||||||
|
return permissionsToCheckFor.some(x => hasPermission(resolvedPermissions, DiscordTypes.PermissionFlagsBits[x]))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {bigint} resolvedPermissions
|
||||||
|
* @param {(keyof DiscordTypes.PermissionFlagsBits)[]} permissionsToCheckFor
|
||||||
|
* @returns {boolean} whether the user has all of the requested permissions
|
||||||
|
* @example
|
||||||
|
* const permissions = getPermissions(userRoles, guildRoles, userID, channelOverwrites)
|
||||||
|
* hasAllPermissions(permissions, ["ViewChannel", "ReadMessageHistory"])
|
||||||
|
*/
|
||||||
|
function hasAllPermissions(resolvedPermissions, permissionsToCheckFor) {
|
||||||
|
return permissionsToCheckFor.every(x => hasPermission(resolvedPermissions, DiscordTypes.PermissionFlagsBits[x]))
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command interaction responses have a webhook_id for some reason, but still have real author info of a real bot user in the server.
|
* Command interaction responses have a webhook_id for some reason, but still have real author info of a real bot user in the server.
|
||||||
* @param {DiscordTypes.APIMessage} message
|
* @param {DiscordTypes.APIMessage} message
|
||||||
|
@ -69,6 +112,9 @@ function timestampToSnowflakeInexact(timestamp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.getPermissions = getPermissions
|
module.exports.getPermissions = getPermissions
|
||||||
|
module.exports.hasPermission = hasPermission
|
||||||
|
module.exports.hasSomePermissions = hasSomePermissions
|
||||||
|
module.exports.hasAllPermissions = hasAllPermissions
|
||||||
module.exports.isWebhookMessage = isWebhookMessage
|
module.exports.isWebhookMessage = isWebhookMessage
|
||||||
module.exports.snowflakeToTimestampExact = snowflakeToTimestampExact
|
module.exports.snowflakeToTimestampExact = snowflakeToTimestampExact
|
||||||
module.exports.timestampToSnowflakeInexact = timestampToSnowflakeInexact
|
module.exports.timestampToSnowflakeInexact = timestampToSnowflakeInexact
|
||||||
|
|
Loading…
Reference in a new issue