Skip to content

Commit 9d59510

Browse files
Support Hydra rooms (matrix-org#1077)
* Updates to support 0.7.1-element.14 * Cleanup * fix bot spec * never * Update express to match bot-sdk * Support new hydra power levels * Update package.json * lint * Add changelog * Add a test for v12 rooms * Fixes for new PR * missed a bit * cleanup * current * fixup * lint * Remove new unused imports * Set currentPl correctly --------- Co-authored-by: Andrew Ferrazzutti <[email protected]>
1 parent 5c13011 commit 9d59510

File tree

5 files changed

+64
-41
lines changed

5 files changed

+64
-41
lines changed

changelog.d/1077.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Support Matrix v12 rooms.

spec/permissions.spec.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,25 @@ describe("Permissions test", () => {
110110
"Room configured to bridge webhooks. See admin room for secret url.",
111111
);
112112
});
113+
114+
test("should allow users with permission to use a service in a v12 room", async () => {
115+
const user = testEnv.getUser("allowed_user");
116+
const roomId = await user.createRoom({
117+
name: "Test room",
118+
invite: [testEnv.botMxid],
119+
room_version: "12",
120+
});
121+
await user.setUserPowerLevel(testEnv.botMxid, roomId, 50);
122+
await user.waitForRoomJoin({ sender: testEnv.botMxid, roomId });
123+
124+
const msgWebhooks = user.waitForRoomEvent<MessageEventContent>({
125+
eventType: "m.room.message",
126+
sender: testEnv.botMxid,
127+
roomId,
128+
});
129+
await user.sendText(roomId, "!hookshot webhook test");
130+
expect((await msgWebhooks).data.content.body).to.include(
131+
"Room configured to bridge webhooks. See admin room for secret url.",
132+
);
133+
});
113134
});

src/Bridge.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
Intent,
1414
MatrixError,
1515
RoomEvent,
16+
PLManager,
1617
} from "matrix-bot-sdk";
1718
import BotUsersManager from "./managers/BotUsersManager";
1819
import {
@@ -1719,15 +1720,19 @@ export class Bridge {
17191720
log.debug(
17201721
`${roomId} got a new powerlevel change and isn't connected to any connections, testing to see if we should create a setup widget`,
17211722
);
1723+
1724+
const createEvent =
1725+
await botUser.intent.underlyingClient.getRoomCreateEvent(roomId);
17221726
const plEvent = new PowerLevelsEvent(event);
1723-
const currentPl =
1724-
plEvent.content.users?.[botUser.userId] ?? plEvent.defaultUserLevel;
1725-
const previousPl =
1726-
plEvent.previousContent?.users?.[botUser.userId] ??
1727-
plEvent.previousContent?.users_default;
1727+
const plsOld = new PLManager(createEvent, plEvent.previousContent);
1728+
const plsCurrent = new PLManager(createEvent, plEvent.content);
1729+
const previousPl = plsOld.getUserPowerLevel(botUser.userId);
1730+
const currentPl = plsCurrent.getUserPowerLevel(botUser.userId);
17281731
const requiredPl =
1729-
plEvent.content.events?.["im.vector.modular.widgets"] ??
1730-
plEvent.defaultStateEventLevel;
1732+
plsCurrent.currentPL.events?.["im.vector.modular.widgets"] ??
1733+
plsCurrent.currentPL.state_default ??
1734+
50;
1735+
17311736
if (currentPl !== previousPl && currentPl >= requiredPl) {
17321737
// PL changed for bot user, check to see if the widget can be created.
17331738
try {

src/widgets/Api.ts

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {
22
Intent,
33
MatrixError,
44
MembershipEventContent,
5-
PowerLevelsEventContent,
5+
PLManager,
66
} from "matrix-bot-sdk";
77
import { ApiError, ErrCode } from "../api";
88
import { Logger } from "matrix-appservice-bridge";
@@ -57,7 +57,7 @@ export async function assertUserPermissionsInRoom(
5757
ErrCode.NotInRoom,
5858
);
5959
}
60-
if (isNotFoundError(ex)) {
60+
if (ex instanceof MatrixError && ex.errcode === "M_NOT_FOUND") {
6161
throw new ApiError("User is not joined to the room.", ErrCode.NotInRoom);
6262
}
6363
log.warn(`Failed to find member event for ${userId} in room ${roomId}`, ex);
@@ -77,7 +77,7 @@ export async function assertUserPermissionsInRoom(
7777
throw new ApiError("User is not joined to the room.", ErrCode.NotInRoom);
7878
}
7979
} catch (ex) {
80-
if (isNotFoundError(ex)) {
80+
if (ex instanceof MatrixError && ex.errcode === "M_NOT_FOUND") {
8181
throw new ApiError("User is not joined to the room.", ErrCode.NotInRoom);
8282
}
8383
log.warn(`Failed to find member event for ${userId} in room ${roomId}`, ex);
@@ -89,13 +89,16 @@ export async function assertUserPermissionsInRoom(
8989
if (requiredPermission === "read") {
9090
return true;
9191
}
92-
let pls: PowerLevelsEventContent;
92+
let pls: PLManager;
9393
try {
94-
pls = (await intent.underlyingClient.getRoomStateEvent(
95-
roomId,
96-
"m.room.power_levels",
97-
"",
98-
)) as PowerLevelsEventContent;
94+
pls = new PLManager(
95+
await intent.underlyingClient.getRoomCreateEvent(roomId),
96+
await intent.underlyingClient.getRoomStateEventContent(
97+
roomId,
98+
"m.room.power_levels",
99+
"",
100+
),
101+
);
99102
} catch (ex) {
100103
log.warn(`Failed to find PL event for room ${roomId}`, ex);
101104
throw new ApiError(
@@ -105,9 +108,9 @@ export async function assertUserPermissionsInRoom(
105108
}
106109

107110
// TODO: Decide what PL consider "write" permissions
108-
const botPl = pls.users?.[intent.userId] || pls.users_default || 0;
109-
const userPl = pls.users?.[userId] || pls.users_default || 0;
110-
const requiredPl = pls.state_default || 50;
111+
const botPl = pls.getUserPowerLevel(intent.userId);
112+
const userPl = pls.getUserPowerLevel(userId);
113+
const requiredPl = pls.currentPL.state_default || 50;
111114

112115
// Check the bot's permissions
113116
if (botPl < requiredPl) {
@@ -127,12 +130,3 @@ export async function assertUserPermissionsInRoom(
127130
);
128131
}
129132
}
130-
131-
// TODO Use MatrixError as a type once matrix-bot-sdk is updated to a version that exports it
132-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
133-
function isNotFoundError(ex: any) {
134-
return (
135-
"M_NOT_FOUND" ==
136-
(ex instanceof ApiError ? ex.jsonBody.errcode : (ex.body?.errcode ?? ""))
137-
);
138-
}

src/widgets/BridgeWidgetApi.ts

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { IBridgeStorageProvider } from "../stores/StorageProvider";
1313
import { ConnectionManager } from "../ConnectionManager";
1414
import BotUsersManager, { BotUser } from "../managers/BotUsersManager";
1515
import { assertUserPermissionsInRoom, GetConnectionsResponseItem } from "./Api";
16-
import { Appservice, PowerLevelsEvent } from "matrix-bot-sdk";
16+
import { Appservice, PLManager } from "matrix-bot-sdk";
1717
import { GithubInstance } from "../github/GithubInstance";
1818
import {
1919
AllowedTokenTypes,
@@ -216,13 +216,16 @@ export class BridgeWidgetApi extends ProvisioningApi {
216216
botUser.intent,
217217
);
218218
const allConnections = this.connMan.getAllConnectionsForRoom(roomId);
219-
const powerlevel = new PowerLevelsEvent({
220-
content: await botUser.intent.underlyingClient.getRoomStateEvent(
219+
220+
const powerlevel = new PLManager(
221+
await botUser.intent.underlyingClient.getRoomCreateEvent(roomId),
222+
await botUser.intent.underlyingClient.getRoomStateEventContent(
221223
roomId,
222224
"m.room.power_levels",
223225
"",
224226
),
225-
});
227+
);
228+
226229
const serviceFilter = req.params.service;
227230
const connections = allConnections
228231
.map((c) => c.getProvisionerDetails?.(true))
@@ -232,19 +235,18 @@ export class BridgeWidgetApi extends ProvisioningApi {
232235
(c) =>
233236
typeof serviceFilter !== "string" || c?.service === serviceFilter,
234237
) as GetConnectionsResponseItem[];
235-
const userPl =
236-
powerlevel.content.users?.[req.userId] || powerlevel.defaultUserLevel;
237-
const botPl =
238-
powerlevel.content.users?.[botUser.userId] || powerlevel.defaultUserLevel;
238+
const userPl = powerlevel.getUserPowerLevel(req.userId);
239+
const botPl = powerlevel.getUserPowerLevel(botUser.userId);
240+
239241
for (const c of connections) {
240242
// TODO: What about crypto?
241243
const requiredPlForEdit = Math.max(
242-
powerlevel.content.events?.[c.type] ?? 0,
243-
powerlevel.defaultStateEventLevel,
244+
powerlevel.currentPL.events?.[c.type] ?? 0,
245+
powerlevel.currentPL.state_default ?? 50,
244246
);
245247
const requiredPlForMessages = Math.max(
246-
powerlevel.content.events?.["m.room.message"] ??
247-
powerlevel.content.events_default ??
248+
powerlevel.currentPL.events?.["m.room.message"] ??
249+
powerlevel.currentPL.events_default ??
248250
0,
249251
);
250252
c.canEdit = userPl >= requiredPlForEdit;
@@ -256,7 +258,7 @@ export class BridgeWidgetApi extends ProvisioningApi {
256258

257259
return {
258260
connections,
259-
canEdit: userPl >= powerlevel.defaultStateEventLevel,
261+
canEdit: userPl >= (powerlevel.currentPL.state_default ?? 50),
260262
};
261263
}
262264

0 commit comments

Comments
 (0)