diff options
Diffstat (limited to 'rtc/src/util/Permissions.ts')
-rw-r--r-- | rtc/src/util/Permissions.ts | 262 |
1 files changed, 0 insertions, 262 deletions
diff --git a/rtc/src/util/Permissions.ts b/rtc/src/util/Permissions.ts deleted file mode 100644 index 445e901f..00000000 --- a/rtc/src/util/Permissions.ts +++ /dev/null @@ -1,262 +0,0 @@ -// https://github.com/discordjs/discord.js/blob/master/src/util/Permissions.js -// Apache License Version 2.0 Copyright 2015 - 2021 Amish Shah -import { MemberDocument, MemberModel } from "../models/Member"; -import { ChannelDocument, ChannelModel } from "../models/Channel"; -import { ChannelPermissionOverwrite } from "../models/Channel"; -import { Role, RoleDocument, RoleModel } from "../models/Role"; -import { BitField } from "./BitField"; -import { GuildDocument, GuildModel } from "../models/Guild"; -// TODO: check role hierarchy permission - -var HTTPError: any; - -try { - HTTPError = require("lambert-server").HTTPError; -} catch (e) { - HTTPError = Error; -} - -export type PermissionResolvable = bigint | number | Permissions | PermissionResolvable[] | PermissionString; - -type PermissionString = - | "CREATE_INSTANT_INVITE" - | "KICK_MEMBERS" - | "BAN_MEMBERS" - | "ADMINISTRATOR" - | "MANAGE_CHANNELS" - | "MANAGE_GUILD" - | "ADD_REACTIONS" - | "VIEW_AUDIT_LOG" - | "PRIORITY_SPEAKER" - | "STREAM" - | "VIEW_CHANNEL" - | "SEND_MESSAGES" - | "SEND_TTS_MESSAGES" - | "MANAGE_MESSAGES" - | "EMBED_LINKS" - | "ATTACH_FILES" - | "READ_MESSAGE_HISTORY" - | "MENTION_EVERYONE" - | "USE_EXTERNAL_EMOJIS" - | "VIEW_GUILD_INSIGHTS" - | "CONNECT" - | "SPEAK" - | "MUTE_MEMBERS" - | "DEAFEN_MEMBERS" - | "MOVE_MEMBERS" - | "USE_VAD" - | "CHANGE_NICKNAME" - | "MANAGE_NICKNAMES" - | "MANAGE_ROLES" - | "MANAGE_WEBHOOKS" - | "MANAGE_EMOJIS"; - -const CUSTOM_PERMISSION_OFFSET = BigInt(1) << BigInt(48); // 16 free custom permission bits, and 16 for discord to add new ones - -export class Permissions extends BitField { - cache: PermissionCache = {}; - - static FLAGS = { - CREATE_INSTANT_INVITE: BigInt(1) << BigInt(0), - KICK_MEMBERS: BigInt(1) << BigInt(1), - BAN_MEMBERS: BigInt(1) << BigInt(2), - ADMINISTRATOR: BigInt(1) << BigInt(3), - MANAGE_CHANNELS: BigInt(1) << BigInt(4), - MANAGE_GUILD: BigInt(1) << BigInt(5), - ADD_REACTIONS: BigInt(1) << BigInt(6), - VIEW_AUDIT_LOG: BigInt(1) << BigInt(7), - PRIORITY_SPEAKER: BigInt(1) << BigInt(8), - STREAM: BigInt(1) << BigInt(9), - VIEW_CHANNEL: BigInt(1) << BigInt(10), - SEND_MESSAGES: BigInt(1) << BigInt(11), - SEND_TTS_MESSAGES: BigInt(1) << BigInt(12), - MANAGE_MESSAGES: BigInt(1) << BigInt(13), - EMBED_LINKS: BigInt(1) << BigInt(14), - ATTACH_FILES: BigInt(1) << BigInt(15), - READ_MESSAGE_HISTORY: BigInt(1) << BigInt(16), - MENTION_EVERYONE: BigInt(1) << BigInt(17), - USE_EXTERNAL_EMOJIS: BigInt(1) << BigInt(18), - VIEW_GUILD_INSIGHTS: BigInt(1) << BigInt(19), - CONNECT: BigInt(1) << BigInt(20), - SPEAK: BigInt(1) << BigInt(21), - MUTE_MEMBERS: BigInt(1) << BigInt(22), - DEAFEN_MEMBERS: BigInt(1) << BigInt(23), - MOVE_MEMBERS: BigInt(1) << BigInt(24), - USE_VAD: BigInt(1) << BigInt(25), - CHANGE_NICKNAME: BigInt(1) << BigInt(26), - MANAGE_NICKNAMES: BigInt(1) << BigInt(27), - MANAGE_ROLES: BigInt(1) << BigInt(28), - MANAGE_WEBHOOKS: BigInt(1) << BigInt(29), - MANAGE_EMOJIS: BigInt(1) << BigInt(30), - /** - * CUSTOM PERMISSIONS ideas: - * - allow user to dm members - * - allow user to pin messages (without MANAGE_MESSAGES) - * - allow user to publish messages (without MANAGE_MESSAGES) - */ - // CUSTOM_PERMISSION: BigInt(1) << BigInt(0) + CUSTOM_PERMISSION_OFFSET - }; - - any(permission: PermissionResolvable, checkAdmin = true) { - return (checkAdmin && super.any(Permissions.FLAGS.ADMINISTRATOR)) || super.any(permission); - } - - /** - * Checks whether the bitfield has a permission, or multiple permissions. - */ - has(permission: PermissionResolvable, checkAdmin = true) { - return (checkAdmin && super.has(Permissions.FLAGS.ADMINISTRATOR)) || super.has(permission); - } - - /** - * Checks whether the bitfield has a permission, or multiple permissions, but throws an Error if user fails to match auth criteria. - */ - hasThrow(permission: PermissionResolvable) { - if (this.has(permission) && this.has("VIEW_CHANNEL")) return true; - // @ts-ignore - throw new HTTPError(`You are missing the following permissions ${permission}`, 403); - } - - overwriteChannel(overwrites: ChannelPermissionOverwrite[]) { - if (!this.cache) throw new Error("permission chache not available"); - overwrites = overwrites.filter((x) => { - if (x.type === 0 && this.cache.roles?.some((r) => r.id === x.id)) return true; - if (x.type === 1 && x.id == this.cache.user_id) return true; - return false; - }); - return new Permissions(Permissions.channelPermission(overwrites, this.bitfield)); - } - - static channelPermission(overwrites: ChannelPermissionOverwrite[], init?: bigint) { - // TODO: do not deny any permissions if admin - return overwrites.reduce((permission, overwrite) => { - // apply disallowed permission - // * permission: current calculated permission (e.g. 010) - // * deny contains all denied permissions (e.g. 011) - // * allow contains all explicitly allowed permisions (e.g. 100) - return (permission & ~BigInt(overwrite.deny)) | BigInt(overwrite.allow); - // ~ operator inverts deny (e.g. 011 -> 100) - // & operator only allows 1 for both ~deny and permission (e.g. 010 & 100 -> 000) - // | operators adds both together (e.g. 000 + 100 -> 100) - }, init || 0n); - } - - static rolePermission(roles: Role[]) { - // adds all permissions of all roles together (Bit OR) - return roles.reduce((permission, role) => permission | BigInt(role.permissions), 0n); - } - - static finalPermission({ - user, - guild, - channel, - }: { - user: { id: string; roles: string[] }; - guild: { roles: Role[] }; - channel?: { - overwrites?: ChannelPermissionOverwrite[]; - recipient_ids?: string[] | null; - owner_id?: string; - }; - }) { - if (user.id === "0") return new Permissions("ADMINISTRATOR"); // system user id - - let roles = guild.roles.filter((x) => user.roles.includes(x.id)); - let permission = Permissions.rolePermission(roles); - - if (channel?.overwrites) { - let overwrites = channel.overwrites.filter((x) => { - if (x.type === 0 && user.roles.includes(x.id)) return true; - if (x.type === 1 && x.id == user.id) return true; - return false; - }); - permission = Permissions.channelPermission(overwrites, permission); - } - - if (channel?.recipient_ids) { - if (channel?.owner_id === user.id) return new Permissions("ADMINISTRATOR"); - if (channel.recipient_ids.includes(user.id)) { - // Default dm permissions - return new Permissions([ - "VIEW_CHANNEL", - "SEND_MESSAGES", - "STREAM", - "ADD_REACTIONS", - "EMBED_LINKS", - "ATTACH_FILES", - "READ_MESSAGE_HISTORY", - "MENTION_EVERYONE", - "USE_EXTERNAL_EMOJIS", - "CONNECT", - "SPEAK", - "MANAGE_CHANNELS", - ]); - } - - return new Permissions(); - } - - return new Permissions(permission); - } -} - -export type PermissionCache = { - channel?: ChannelDocument | null; - member?: MemberDocument | null; - guild?: GuildDocument | null; - roles?: RoleDocument[] | null; - user_id?: string; -}; - -export async function getPermission( - user_id?: string, - guild_id?: string, - channel_id?: string, - cache: PermissionCache = {} -) { - var { channel, member, guild, roles } = cache; - - if (!user_id) throw new HTTPError("User not found"); - - if (channel_id && !channel) { - channel = await ChannelModel.findOne( - { id: channel_id }, - { permission_overwrites: true, recipient_ids: true, owner_id: true, guild_id: true } - ).exec(); - if (!channel) throw new HTTPError("Channel not found", 404); - if (channel.guild_id) guild_id = channel.guild_id; - } - - if (guild_id) { - if (!guild) guild = await GuildModel.findOne({ id: guild_id }, { owner_id: true }).exec(); - if (!guild) throw new HTTPError("Guild not found"); - if (guild.owner_id === user_id) return new Permissions(Permissions.FLAGS.ADMINISTRATOR); - - if (!member) member = await MemberModel.findOne({ guild_id, id: user_id }, "roles").exec(); - if (!member) throw new HTTPError("Member not found"); - - if (!roles) roles = await RoleModel.find({ guild_id, id: { $in: member.roles } }).exec(); - } - - var permission = Permissions.finalPermission({ - user: { - id: user_id, - roles: member?.roles || [], - }, - guild: { - roles: roles || [], - }, - channel: { - overwrites: channel?.permission_overwrites, - owner_id: channel?.owner_id, - recipient_ids: channel?.recipient_ids, - }, - }); - - const obj = new Permissions(permission); - - // pass cache to permission for possible future getPermission calls - obj.cache = { guild, member, channel, roles, user_id }; - - return obj; -} |