You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-08-06 12:02:40 +03:00
Simplify MatrixClient::setPowerLevel
API (#3570)
* Simplify `MatrixClient::setPowerLevel` API While making it more resilient to causing issues like nuking room state * Handle edge case * Fix tests * Add test coverage
This commit is contained in:
committed by
GitHub
parent
5df4ebaada
commit
d2b782a2f5
@@ -1386,14 +1386,11 @@ describe("MatrixClient", function () {
|
||||
expectation: {},
|
||||
},
|
||||
])("should modify power levels of $userId correctly", async ({ userId, powerLevel, expectation }) => {
|
||||
const event = {
|
||||
getType: () => "m.room.power_levels",
|
||||
getContent: () => ({
|
||||
httpBackend!.when("GET", "/state/m.room.power_levels/").respond(200, {
|
||||
users: {
|
||||
"alice@localhost": 50,
|
||||
},
|
||||
}),
|
||||
} as MatrixEvent;
|
||||
});
|
||||
|
||||
httpBackend!
|
||||
.when("PUT", "/state/m.room.power_levels")
|
||||
@@ -1402,7 +1399,76 @@ describe("MatrixClient", function () {
|
||||
})
|
||||
.respond(200, {});
|
||||
|
||||
const prom = client!.setPowerLevel("!room_id:server", userId, powerLevel, event);
|
||||
const prom = client!.setPowerLevel("!room_id:server", userId, powerLevel);
|
||||
await httpBackend!.flushAllExpected();
|
||||
await prom;
|
||||
});
|
||||
|
||||
it("should use power level from room state if available", async () => {
|
||||
client!.clientRunning = true;
|
||||
client!.isInitialSyncComplete = () => true;
|
||||
const room = new Room("!room_id:server", client!, client!.getUserId()!);
|
||||
room.currentState.events.set("m.room.power_levels", new Map());
|
||||
room.currentState.events.get("m.room.power_levels")!.set(
|
||||
"",
|
||||
new MatrixEvent({
|
||||
type: "m.room.power_levels",
|
||||
state_key: "",
|
||||
content: {
|
||||
users: {
|
||||
"@bob:localhost": 50,
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
client!.getRoom = () => room;
|
||||
|
||||
httpBackend!
|
||||
.when("PUT", "/state/m.room.power_levels")
|
||||
.check((req) => {
|
||||
expect(req.data).toStrictEqual({
|
||||
users: {
|
||||
"@bob:localhost": 50,
|
||||
[userId]: 42,
|
||||
},
|
||||
});
|
||||
})
|
||||
.respond(200, {});
|
||||
|
||||
const prom = client!.setPowerLevel("!room_id:server", userId, 42);
|
||||
await httpBackend!.flushAllExpected();
|
||||
await prom;
|
||||
});
|
||||
|
||||
it("should throw error if state API errors", async () => {
|
||||
httpBackend!.when("GET", "/state/m.room.power_levels/").respond(500, {
|
||||
errcode: "ERR_DERP",
|
||||
});
|
||||
|
||||
const prom = client!.setPowerLevel("!room_id:server", userId, 42);
|
||||
await Promise.all([
|
||||
expect(prom).rejects.toMatchInlineSnapshot(`[ERR_DERP: MatrixError: [500] Unknown message]`),
|
||||
httpBackend!.flushAllExpected(),
|
||||
]);
|
||||
});
|
||||
|
||||
it("should not throw error if /state/ API returns M_NOT_FOUND", async () => {
|
||||
httpBackend!.when("GET", "/state/m.room.power_levels/").respond(404, {
|
||||
errcode: "M_NOT_FOUND",
|
||||
});
|
||||
|
||||
httpBackend!
|
||||
.when("PUT", "/state/m.room.power_levels")
|
||||
.check((req) => {
|
||||
expect(req.data).toStrictEqual({
|
||||
users: {
|
||||
[userId]: 42,
|
||||
},
|
||||
});
|
||||
})
|
||||
.respond(200, {});
|
||||
|
||||
const prom = client!.setPowerLevel("!room_id:server", userId, 42);
|
||||
await httpBackend!.flushAllExpected();
|
||||
await prom;
|
||||
});
|
||||
|
@@ -111,7 +111,7 @@ import * as ContentHelpers from "./content-helpers";
|
||||
import { CrossSigningInfo, DeviceTrustLevel, ICacheCallbacks, UserTrustLevel } from "./crypto/CrossSigning";
|
||||
import { Room, NotificationCountType, RoomEvent, RoomEventHandlerMap, RoomNameState } from "./models/room";
|
||||
import { RoomMemberEvent, RoomMemberEventHandlerMap } from "./models/room-member";
|
||||
import { RoomStateEvent, RoomStateEventHandlerMap } from "./models/room-state";
|
||||
import { IPowerLevelsContent, RoomStateEvent, RoomStateEventHandlerMap } from "./models/room-state";
|
||||
import {
|
||||
IAddThreePidOnlyBody,
|
||||
IBindThreePidBody,
|
||||
@@ -4256,24 +4256,48 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
||||
|
||||
/**
|
||||
* Set a power level to one or multiple users.
|
||||
* Will apply changes atop of current power level event from local state if running & synced, falling back
|
||||
* to fetching latest from the `/state/` API.
|
||||
* @param roomId - the room to update power levels in
|
||||
* @param userId - the ID of the user or users to update power levels of
|
||||
* @param powerLevel - the numeric power level to update given users to
|
||||
* @param event - deprecated and no longer used.
|
||||
* @returns Promise which resolves: to an ISendEventResponse object
|
||||
* @returns Rejects: with an error response.
|
||||
*/
|
||||
public setPowerLevel(
|
||||
public async setPowerLevel(
|
||||
roomId: string,
|
||||
userId: string | string[],
|
||||
powerLevel: number | undefined,
|
||||
event: MatrixEvent | null,
|
||||
/**
|
||||
* @deprecated no longer needed, unused.
|
||||
*/
|
||||
event?: MatrixEvent | null,
|
||||
): Promise<ISendEventResponse> {
|
||||
let content = {
|
||||
users: {} as Record<string, number>,
|
||||
};
|
||||
if (event?.getType() === EventType.RoomPowerLevels) {
|
||||
// take a copy of the content to ensure we don't corrupt
|
||||
// existing client state with a failed power level change
|
||||
content = utils.deepCopy(event.getContent());
|
||||
let content: IPowerLevelsContent | undefined;
|
||||
if (this.clientRunning && this.isInitialSyncComplete()) {
|
||||
content = this.getRoom(roomId)?.currentState?.getStateEvents(EventType.RoomPowerLevels, "")?.getContent();
|
||||
}
|
||||
if (!content) {
|
||||
try {
|
||||
content = await this.getStateEvent(roomId, EventType.RoomPowerLevels, "");
|
||||
} catch (e) {
|
||||
// It is possible for a Matrix room to not have a power levels event
|
||||
if (e instanceof MatrixError && e.errcode === "M_NOT_FOUND") {
|
||||
content = {};
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// take a copy of the content to ensure we don't corrupt
|
||||
// existing client state with a failed power level change
|
||||
content = utils.deepCopy(content);
|
||||
|
||||
if (!content?.users) {
|
||||
content.users = {};
|
||||
}
|
||||
const users = Array.isArray(userId) ? userId : [userId];
|
||||
for (const user of users) {
|
||||
if (powerLevel == null) {
|
||||
@@ -4283,10 +4307,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
||||
}
|
||||
}
|
||||
|
||||
const path = utils.encodeUri("/rooms/$roomId/state/m.room.power_levels", {
|
||||
$roomId: roomId,
|
||||
});
|
||||
return this.http.authedRequest(Method.Put, path, undefined, content);
|
||||
return this.sendStateEvent(roomId, EventType.RoomPowerLevels, content, "");
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user