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: {},
|
expectation: {},
|
||||||
},
|
},
|
||||||
])("should modify power levels of $userId correctly", async ({ userId, powerLevel, expectation }) => {
|
])("should modify power levels of $userId correctly", async ({ userId, powerLevel, expectation }) => {
|
||||||
const event = {
|
httpBackend!.when("GET", "/state/m.room.power_levels/").respond(200, {
|
||||||
getType: () => "m.room.power_levels",
|
users: {
|
||||||
getContent: () => ({
|
"alice@localhost": 50,
|
||||||
users: {
|
},
|
||||||
"alice@localhost": 50,
|
});
|
||||||
},
|
|
||||||
}),
|
|
||||||
} as MatrixEvent;
|
|
||||||
|
|
||||||
httpBackend!
|
httpBackend!
|
||||||
.when("PUT", "/state/m.room.power_levels")
|
.when("PUT", "/state/m.room.power_levels")
|
||||||
@@ -1402,7 +1399,76 @@ describe("MatrixClient", function () {
|
|||||||
})
|
})
|
||||||
.respond(200, {});
|
.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 httpBackend!.flushAllExpected();
|
||||||
await prom;
|
await prom;
|
||||||
});
|
});
|
||||||
|
@@ -111,7 +111,7 @@ import * as ContentHelpers from "./content-helpers";
|
|||||||
import { CrossSigningInfo, DeviceTrustLevel, ICacheCallbacks, UserTrustLevel } from "./crypto/CrossSigning";
|
import { CrossSigningInfo, DeviceTrustLevel, ICacheCallbacks, UserTrustLevel } from "./crypto/CrossSigning";
|
||||||
import { Room, NotificationCountType, RoomEvent, RoomEventHandlerMap, RoomNameState } from "./models/room";
|
import { Room, NotificationCountType, RoomEvent, RoomEventHandlerMap, RoomNameState } from "./models/room";
|
||||||
import { RoomMemberEvent, RoomMemberEventHandlerMap } from "./models/room-member";
|
import { RoomMemberEvent, RoomMemberEventHandlerMap } from "./models/room-member";
|
||||||
import { RoomStateEvent, RoomStateEventHandlerMap } from "./models/room-state";
|
import { IPowerLevelsContent, RoomStateEvent, RoomStateEventHandlerMap } from "./models/room-state";
|
||||||
import {
|
import {
|
||||||
IAddThreePidOnlyBody,
|
IAddThreePidOnlyBody,
|
||||||
IBindThreePidBody,
|
IBindThreePidBody,
|
||||||
@@ -4256,24 +4256,48 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a power level to one or multiple users.
|
* 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 Promise which resolves: to an ISendEventResponse object
|
||||||
* @returns Rejects: with an error response.
|
* @returns Rejects: with an error response.
|
||||||
*/
|
*/
|
||||||
public setPowerLevel(
|
public async setPowerLevel(
|
||||||
roomId: string,
|
roomId: string,
|
||||||
userId: string | string[],
|
userId: string | string[],
|
||||||
powerLevel: number | undefined,
|
powerLevel: number | undefined,
|
||||||
event: MatrixEvent | null,
|
/**
|
||||||
|
* @deprecated no longer needed, unused.
|
||||||
|
*/
|
||||||
|
event?: MatrixEvent | null,
|
||||||
): Promise<ISendEventResponse> {
|
): Promise<ISendEventResponse> {
|
||||||
let content = {
|
let content: IPowerLevelsContent | undefined;
|
||||||
users: {} as Record<string, number>,
|
if (this.clientRunning && this.isInitialSyncComplete()) {
|
||||||
};
|
content = this.getRoom(roomId)?.currentState?.getStateEvents(EventType.RoomPowerLevels, "")?.getContent();
|
||||||
if (event?.getType() === EventType.RoomPowerLevels) {
|
}
|
||||||
// take a copy of the content to ensure we don't corrupt
|
if (!content) {
|
||||||
// existing client state with a failed power level change
|
try {
|
||||||
content = utils.deepCopy(event.getContent());
|
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];
|
const users = Array.isArray(userId) ? userId : [userId];
|
||||||
for (const user of users) {
|
for (const user of users) {
|
||||||
if (powerLevel == null) {
|
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", {
|
return this.sendStateEvent(roomId, EventType.RoomPowerLevels, content, "");
|
||||||
$roomId: roomId,
|
|
||||||
});
|
|
||||||
return this.http.authedRequest(Method.Put, path, undefined, content);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user