From 7bfe140d08a0de749e3dea5ad09547ad8ea3a7d7 Mon Sep 17 00:00:00 2001 From: Cadence Ember Date: Tue, 5 Aug 2025 01:40:56 +1200 Subject: [PATCH] More precise power level checking --- src/matrix/api.js | 10 +++++++--- src/web/routes/link.js | 12 ++++++------ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/matrix/api.js b/src/matrix/api.js index cf82117..41af63f 100644 --- a/src/matrix/api.js +++ b/src/matrix/api.js @@ -317,13 +317,17 @@ async function setUserPower(roomID, mxid, newPower) { const power = await getStateEvent(roomID, "m.room.power_levels", "") power.users = power.users || {} + // Check if it has really changed to avoid sending a useless state event + // (Can't diff kstate here because of (a) circular imports (b) kstate has special behaviour diffing power levels) + const oldPowerLevel = power.users?.[mxid] ?? power.users_default ?? 0 + if (oldPowerLevel === newPower) return + // Bridge bot can't demote equal power users, so need to decide which user will send the event - const oldPowerLevel = power.users?.[mxid] || power.users_default || 0 - const botPowerLevel = power.users?.[`@${reg.sender_localpart}:${reg.ooye.server_name}`] || 100 + const botPowerLevel = power.users?.[`@${reg.sender_localpart}:${reg.ooye.server_name}`] ?? power.users_default ?? 0 const eventSender = oldPowerLevel >= botPowerLevel ? mxid : undefined // Update the event content - if (newPower == null || newPower === (power.users_default || 0)) { + if (newPower == null || newPower === (power.users_default ?? 0)) { delete power.users[mxid] } else { power.users[mxid] = newPower diff --git a/src/web/routes/link.js b/src/web/routes/link.js index 2d0277c..c5f404e 100644 --- a/src/web/routes/link.js +++ b/src/web/routes/link.js @@ -89,12 +89,12 @@ as.router.post("/api/link-space", defineEventHandler(async event => { try { powerLevelsStateContent = await api.getStateEvent(spaceID, "m.room.power_levels", "") } catch (e) {} - const selfPowerLevel = powerLevelsStateContent?.users?.[me] || powerLevelsStateContent?.users_default || 0 - if (selfPowerLevel < (powerLevelsStateContent?.state_default || 50) || selfPowerLevel < 100) throw createError({status: 400, message: "Bad Request", data: "OOYE needs power level 100 (admin) in the target Matrix space"}) + const selfPowerLevel = powerLevelsStateContent?.users?.[me] ?? powerLevelsStateContent?.users_default ?? 0 + if (selfPowerLevel < (powerLevelsStateContent?.state_default ?? 50) || selfPowerLevel < 100) throw createError({status: 400, message: "Bad Request", data: "OOYE needs power level 100 (admin) in the target Matrix space"}) // Check inviting user is a moderator in the space - const invitingPowerLevel = powerLevelsStateContent?.users?.[session.data.mxid] || powerLevelsStateContent?.users_default || 0 - if (invitingPowerLevel < (powerLevelsStateContent?.state_default || 50)) throw createError({status: 403, message: "Forbidden", data: `You need to be at least power level 50 (moderator) in the target Matrix space to set up OOYE, but you are currently power level ${invitingPowerLevel}.`}) + const invitingPowerLevel = powerLevelsStateContent?.users?.[session.data.mxid] ?? powerLevelsStateContent?.users_default ?? 0 + if (invitingPowerLevel < (powerLevelsStateContent?.state_default ?? 50)) throw createError({status: 403, message: "Forbidden", data: `You need to be at least power level 50 (moderator) in the target Matrix space to set up OOYE, but you are currently power level ${invitingPowerLevel}.`}) // Insert database entry db.transaction(() => { @@ -157,8 +157,8 @@ as.router.post("/api/link", defineEventHandler(async event => { try { powerLevelsStateContent = await api.getStateEvent(parsedBody.matrix, "m.room.power_levels", "") } catch (e) {} - const selfPowerLevel = powerLevelsStateContent?.users?.[me] || powerLevelsStateContent?.users_default || 0 - if (selfPowerLevel < (powerLevelsStateContent?.state_default || 50) || selfPowerLevel < 100) throw createError({status: 400, message: "Bad Request", data: "OOYE needs power level 100 (admin) in the target Matrix room"}) + const selfPowerLevel = powerLevelsStateContent?.users?.[me] ?? powerLevelsStateContent?.users_default ?? 0 + if (selfPowerLevel < (powerLevelsStateContent?.state_default ?? 50) || selfPowerLevel < 100) throw createError({status: 400, message: "Bad Request", data: "OOYE needs power level 100 (admin) in the target Matrix room"}) // Insert database entry, but keep the room's existing properties if they are set const nick = await api.getStateEvent(parsedBody.matrix, "m.room.name", "").then(content => content.name || null).catch(() => null)