From 666ec3e855ab0993c596d4228af9a219c3ede153 Mon Sep 17 00:00:00 2001 From: Rory& Date: Tue, 25 Nov 2025 20:31:47 +0100 Subject: [PATCH] Channel: revert part of permission unification PR --- src/util/entities/Channel.ts | 56 +++++++++++++++++++++++++++++++++++- src/util/util/Permissions.ts | 16 ++++++++++- 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/src/util/entities/Channel.ts b/src/util/entities/Channel.ts index 8d94bf63b..252fb8f9e 100644 --- a/src/util/entities/Channel.ts +++ b/src/util/entities/Channel.ts @@ -429,7 +429,61 @@ export class Channel extends BaseClass { } async getUserPermissions(opts: { user_id?: string; user?: User; member?: Member; guild?: Guild }): Promise { - return getPermission(opts.user_id || opts.user?.id, opts.guild, this); + if(this.isDm()) this.owner_id == (opts.user_id ?? opts.user?.id) ? Permissions.ALL : Permissions.DEFAULT_DM_PERMISSIONS; + let guild = opts.guild; + if (!guild) { + if (this.guild) guild = this.guild; + else if (this.guild_id) guild = await Guild.findOneOrFail({ where: { id: this.guild_id } }); + else { + console.error("Channel.getUserPermissions: called without guild for non-DM channel."); + return Permissions.NONE; + } + } + + // check if we can resolve here to short-circuit possibly calling the database unnecessarily + // TODO: do we want to have an instance-wide opt out of this behavior? It would just be an extra if statement here + const ownerId = guild?.owner?.id ?? guild?.owner_id; + if (!!opts.user_id && ownerId === opts.user_id) return Permissions.ALL; + if (!!opts.user?.id && ownerId === opts.user?.id) return Permissions.ALL; + if (!!opts.member?.id && ownerId === opts.member?.id) return Permissions.ALL; + + let member = opts.member; + if (!member) { + if (opts.user) member = await Member.findOneOrFail({ where: { guild_id: guild.id, id: opts.user.id }, relations: ["roles"] }); + else if (opts.user_id) member = await Member.findOneOrFail({ where: { guild_id: guild.id, id: opts.user_id }, relations: ["roles"] }); + else { + console.error("Channel.getUserPermissions: called without user or member for non-DM channel."); + return Permissions.NONE; + } + } + + const roles = ( + member.roles || + ( + await Member.findOneOrFail({ + where: { guild_id: guild.id, index: member.index }, + relations: ["roles"], + select: { + roles: { + id: true, + permissions: true, + position: true, + }, + }, + loadEagerRelations: false + }) + ).roles + ).sort((a, b) => a.position - b.position); // ascending by position + + return Permissions.finalPermission({ + user: { + ...member, + roles: roles.map((r) => r.id), + flags: member.user?.flags ?? (await User.findOneOrFail({ where: { id: member.id }, select: { flags: true } })).flags, + }, + guild: { id: guild.id, owner_id: guild.owner_id!, roles }, // We don't care about including *all* guild roles, as not all of them are relevant... + channel: this, + }); } // TODO: should we throw for missing args? diff --git a/src/util/util/Permissions.ts b/src/util/util/Permissions.ts index 6b792fc1d..a50c23be3 100644 --- a/src/util/util/Permissions.ts +++ b/src/util/util/Permissions.ts @@ -197,7 +197,7 @@ export class Permissions extends BitField { if (user.communication_disabled_until > new Date()) return new Permissions(permission & Permissions.TIMED_OUT_MASK.bitfield); else { user.communication_disabled_until = null; - Member.update({ id: user.id, guild_id: guild.id }, { communication_disabled_until: null }).catch(_ => { + Member.update({ id: user.id, guild_id: guild.id }, { communication_disabled_until: null }).catch((_) => { // ignored }); } @@ -212,6 +212,20 @@ export class Permissions extends BitField { static NONE: Permissions = new Permissions(0); static TIMED_OUT_MASK: Permissions = new Permissions(Permissions.FLAGS.VIEW_CHANNEL | Permissions.FLAGS.READ_MESSAGE_HISTORY); static QUARANTINED_MASK: Permissions = new Permissions(Permissions.FLAGS.VIEW_CHANNEL | Permissions.FLAGS.READ_MESSAGE_HISTORY | Permissions.FLAGS.CHANGE_NICKNAME); + static DEFAULT_DM_PERMISSIONS: Permissions = new Permissions( + Permissions.FLAGS.VIEW_CHANNEL | + Permissions.FLAGS.SEND_MESSAGES | + Permissions.FLAGS.STREAM | + Permissions.FLAGS.ADD_REACTIONS | + Permissions.FLAGS.EMBED_LINKS | + Permissions.FLAGS.ATTACH_FILES | + Permissions.FLAGS.READ_MESSAGE_HISTORY | + Permissions.FLAGS.MENTION_EVERYONE | + Permissions.FLAGS.USE_EXTERNAL_EMOJIS | + Permissions.FLAGS.CONNECT | + Permissions.FLAGS.SPEAK | + Permissions.FLAGS.MANAGE_CHANNELS, + ); static ALL: Permissions = new Permissions(Object.values(Permissions.FLAGS).reduce((total, val) => total | val, BigInt(0))); }