diff --git a/README.md b/README.md index f13deb399f3..325ed11114e 100644 --- a/README.md +++ b/README.md @@ -216,7 +216,7 @@ const matrixClient = sdk.createClient({ ```javascript matrixClient.on(RoomMemberEvent.Membership, function (event, member) { - if (member.membership === "invite" && member.userId === myUserId) { + if (member.membership === KnownMembership.Invite && member.userId === myUserId) { matrixClient.joinRoom(member.roomId).then(function () { console.log("Auto-joined %s", member.roomId); }); diff --git a/examples/node/app.js b/examples/node/app.js index e381f6c51cb..5e48e26c404 100644 --- a/examples/node/app.js +++ b/examples/node/app.js @@ -115,7 +115,7 @@ rl.on("line", function (line) { if (line.indexOf("/join ") === 0) { var roomIndex = line.split(" ")[1]; viewingRoom = roomList[roomIndex]; - if (viewingRoom.getMember(myUserId).membership === "invite") { + if (viewingRoom.getMember(myUserId).membership === KnownMembership.Invite) { // join the room first matrixClient.joinRoom(viewingRoom.roomId).then( function (room) { diff --git a/spec/integ/crypto/crypto.spec.ts b/spec/integ/crypto/crypto.spec.ts index 9448b84ecc5..9e2106f0fe2 100644 --- a/spec/integ/crypto/crypto.spec.ts +++ b/spec/integ/crypto/crypto.spec.ts @@ -99,6 +99,7 @@ import { } from "./olm-utils"; import { ToDevicePayload } from "../../../src/models/ToDeviceMessage"; import { AccountDataAccumulator } from "../../test-utils/AccountDataAccumulator"; +import { KnownMembership } from "../../../src/@types/membership"; afterEach(() => { // reset fake-indexeddb after each test, to make sure we don't leak connections @@ -1242,7 +1243,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string, content: { algorithm: "m.megolm.v1.aes-sha2" }, }), testUtils.mkMembership({ - mship: "join", + mship: KnownMembership.Join, sender: aliceClient.getUserId()!, }), ], @@ -1661,7 +1662,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string, type: "m.room.member", state_key: "@alice:localhost", content: { - membership: "invite", + membership: KnownMembership.Invite, }, }, ], @@ -1810,7 +1811,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string, type: "m.room.member", state_key: "@alice:localhost", content: { - membership: "invite", + membership: KnownMembership.Invite, }, }, ], @@ -1886,7 +1887,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string, { type: "m.room.member", state_key: aliceClient.getUserId(), - content: { membership: "join" }, + content: { membership: KnownMembership.Join }, event_id: "$alijoin", }, ], @@ -1913,7 +1914,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string, { type: "m.room.member", state_key: "@other:user", - content: { membership: "invite" }, + content: { membership: KnownMembership.Invite }, event_id: "$otherinvite", }, ], @@ -2061,7 +2062,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string, fetchMock.getOnce(new RegExp(membersPath), { chunk: [ testUtils.mkMembershipCustom({ - membership: "join", + membership: KnownMembership.Join, sender: "@bob:xyz", }), ], @@ -3090,7 +3091,10 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string, const roomResponse = { state: { events: [ - mkMembershipCustom({ membership: "join", sender: persistentStoreClient.getSafeUserId() }), + mkMembershipCustom({ + membership: KnownMembership.Join, + sender: persistentStoreClient.getSafeUserId(), + }), ...stateEvents, ], }, diff --git a/spec/integ/crypto/olm-encryption-spec.ts b/spec/integ/crypto/olm-encryption-spec.ts index aff150adb39..ff79bf28b21 100644 --- a/spec/integ/crypto/olm-encryption-spec.ts +++ b/spec/integ/crypto/olm-encryption-spec.ts @@ -36,6 +36,7 @@ import { TestClient } from "../../TestClient"; import { CRYPTO_ENABLED, IClaimKeysRequest, IQueryKeysRequest, IUploadKeysRequest } from "../../../src/client"; import { ClientEvent, IContent, ISendEventResponse, MatrixClient, MatrixEvent } from "../../../src/matrix"; import { DeviceInfo } from "../../../src/crypto/deviceinfo"; +import { KnownMembership } from "../../../src/@types/membership"; let aliTestClient: TestClient; const roomId = "!room:localhost"; @@ -316,11 +317,11 @@ function firstSync(testClient: TestClient): Promise { state: { events: [ testUtils.mkMembership({ - mship: "join", + mship: KnownMembership.Join, user: aliUserId, }), testUtils.mkMembership({ - mship: "join", + mship: KnownMembership.Join, user: bobUserId, }), ], diff --git a/spec/integ/devicelist-integ.spec.ts b/spec/integ/devicelist-integ.spec.ts index e9dac66efe6..bf29242dd24 100644 --- a/spec/integ/devicelist-integ.spec.ts +++ b/spec/integ/devicelist-integ.spec.ts @@ -19,6 +19,7 @@ limitations under the License. import { TestClient } from "../TestClient"; import * as testUtils from "../test-utils/test-utils"; import { logger } from "../../src/logger"; +import { KnownMembership } from "../../src/@types/membership"; const ROOM_ID = "!room:id"; @@ -43,7 +44,7 @@ function getSyncResponse(roomMembers: string[]) { stateEvents, roomMembers.map((m) => testUtils.mkMembership({ - mship: "join", + mship: KnownMembership.Join, sender: m, }), ), @@ -323,7 +324,7 @@ describe("DeviceList management:", function () { timeline: { events: [ testUtils.mkMembership({ - mship: "leave", + mship: KnownMembership.Leave, sender: "@bob:xyz", }), ], @@ -357,7 +358,7 @@ describe("DeviceList management:", function () { timeline: { events: [ testUtils.mkMembership({ - mship: "leave", + mship: KnownMembership.Leave, sender: "@bob:xyz", }), ], diff --git a/spec/integ/matrix-client-event-emitter.spec.ts b/spec/integ/matrix-client-event-emitter.spec.ts index 24f500572da..07a7233464e 100644 --- a/spec/integ/matrix-client-event-emitter.spec.ts +++ b/spec/integ/matrix-client-event-emitter.spec.ts @@ -28,6 +28,7 @@ import { } from "../../src"; import * as utils from "../test-utils/test-utils"; import { TestClient } from "../TestClient"; +import { KnownMembership } from "../../src/@types/membership"; describe("MatrixClient events", function () { const selfUserId = "@alice:localhost"; @@ -85,7 +86,7 @@ describe("MatrixClient events", function () { events: [ utils.mkMembership({ room: "!erufh:bar", - mship: "join", + mship: KnownMembership.Join, user: "@foo:bar", }), utils.mkEvent({ @@ -272,7 +273,7 @@ describe("MatrixClient events", function () { membersInvokeCount++; expect(member.roomId).toEqual("!erufh:bar"); expect(member.userId).toEqual("@foo:bar"); - expect(member.membership).toEqual("join"); + expect(member.membership).toEqual(KnownMembership.Join); }); client!.on(RoomStateEvent.NewMember, function (event, state, member) { newMemberInvokeCount++; @@ -310,7 +311,7 @@ describe("MatrixClient events", function () { }); client!.on(RoomMemberEvent.Membership, function (event, member) { membershipInvokeCount++; - expect(member.membership).toEqual("join"); + expect(member.membership).toEqual(KnownMembership.Join); }); client!.startClient(); diff --git a/spec/integ/matrix-client-event-timeline.spec.ts b/spec/integ/matrix-client-event-timeline.spec.ts index 55aef20c23f..5785732422d 100644 --- a/spec/integ/matrix-client-event-timeline.spec.ts +++ b/spec/integ/matrix-client-event-timeline.spec.ts @@ -36,6 +36,7 @@ import { TestClient } from "../TestClient"; import { FeatureSupport, Thread, ThreadEvent } from "../../src/models/thread"; import { emitPromise } from "../test-utils/test-utils"; import { Feature, ServerSupport } from "../../src/feature"; +import { KnownMembership } from "../../src/@types/membership"; const userId = "@alice:localhost"; const userName = "Alice"; @@ -63,7 +64,7 @@ const buildRelationPaginationQuery = (params: QueryDict): string => { const USER_MEMBERSHIP_EVENT = utils.mkMembership({ room: roomId, - mship: "join", + mship: KnownMembership.Join, user: userId, name: userName, event: false, @@ -98,7 +99,7 @@ const INITIAL_SYNC_DATA = { events: [ withoutRoomId(ROOM_NAME_EVENT), utils.mkMembership({ - mship: "join", + mship: KnownMembership.Join, user: otherUserId, name: "Bob", event: false, @@ -1921,7 +1922,7 @@ describe("MatrixClient event timelines", function () { // a state event, followed by a redaction thereof const event = utils.mkMembership({ - mship: "join", + mship: KnownMembership.Join, user: otherUserId, }); const redaction = utils.mkEvent({ diff --git a/spec/integ/matrix-client-methods.spec.ts b/spec/integ/matrix-client-methods.spec.ts index ae5ceb93e03..ddfdcf350e1 100644 --- a/spec/integ/matrix-client-methods.spec.ts +++ b/spec/integ/matrix-client-methods.spec.ts @@ -27,6 +27,7 @@ import { ISearchResults } from "../../src/@types/search"; import { IStore } from "../../src/store"; import { CryptoBackend } from "../../src/common-crypto/CryptoBackend"; import { SetPresence } from "../../src/sync"; +import { KnownMembership } from "../../src/@types/membership"; describe("MatrixClient", function () { const userId = "@alice:localhost"; @@ -162,7 +163,7 @@ describe("MatrixClient", function () { utils.mkMembership({ user: userId, room: roomId, - mship: "join", + mship: KnownMembership.Join, event: true, }), ]); @@ -182,7 +183,7 @@ describe("MatrixClient", function () { utils.mkMembership({ user: userId, room: roomId, - mship: "join", + mship: KnownMembership.Join, event: true, }), ]); @@ -269,7 +270,7 @@ describe("MatrixClient", function () { utils.mkMembership({ user: userId, room: roomId, - mship: "knock", + mship: KnownMembership.Knock, event: true, }), ]); @@ -1912,7 +1913,7 @@ const buildEventJoinRules = () => new MatrixEvent({ age: 80123696, content: { - join_rule: "invite", + join_rule: KnownMembership.Invite, }, event_id: "$6JDDeDp7fEc0F6YnTWMruNcKWFltR3e9wk7wWDDJrAU", origin_server_ts: 1643815441191, @@ -1966,7 +1967,7 @@ const buildEventMember = () => content: { avatar_url: "mxc://matrix.org/aNtbVcFfwotudypZcHsIcPOc", displayname: "andybalaam-test1", - membership: "join", + membership: KnownMembership.Join, }, event_id: "$Ex5eVmMs_ti784mo8bgddynbwLvy6231lCycJr7Cl9M", origin_server_ts: 1643815439608, diff --git a/spec/integ/matrix-client-opts.spec.ts b/spec/integ/matrix-client-opts.spec.ts index 15ef324cbf9..75edf1c50eb 100644 --- a/spec/integ/matrix-client-opts.spec.ts +++ b/spec/integ/matrix-client-opts.spec.ts @@ -6,6 +6,7 @@ import { MatrixScheduler } from "../../src/scheduler"; import { MemoryStore } from "../../src/store/memory"; import { MatrixError } from "../../src/http-api"; import { IStore } from "../../src/store"; +import { KnownMembership } from "../../src/@types/membership"; describe("MatrixClient opts", function () { const baseUrl = "http://localhost.or.something"; @@ -43,13 +44,13 @@ describe("MatrixClient opts", function () { }), utils.mkMembership({ room: roomId, - mship: "join", + mship: KnownMembership.Join, user: userB, name: "Bob", }), utils.mkMembership({ room: roomId, - mship: "join", + mship: KnownMembership.Join, user: userId, name: "Alice", }), diff --git a/spec/integ/matrix-client-room-timeline.spec.ts b/spec/integ/matrix-client-room-timeline.spec.ts index 1eb7a0362d5..a5d4c220a95 100644 --- a/spec/integ/matrix-client-room-timeline.spec.ts +++ b/spec/integ/matrix-client-room-timeline.spec.ts @@ -30,6 +30,7 @@ import { Room, } from "../../src"; import { TestClient } from "../TestClient"; +import { KnownMembership } from "../../src/@types/membership"; describe("MatrixClient room timelines", function () { const userId = "@alice:localhost"; @@ -42,7 +43,7 @@ describe("MatrixClient room timelines", function () { const USER_MEMBERSHIP_EVENT = utils.mkMembership({ room: roomId, - mship: "join", + mship: KnownMembership.Join, user: userId, name: userName, }); @@ -76,7 +77,7 @@ describe("MatrixClient room timelines", function () { ROOM_NAME_EVENT, utils.mkMembership({ room: roomId, - mship: "join", + mship: KnownMembership.Join, user: otherUserId, name: "Bob", }), @@ -316,7 +317,7 @@ describe("MatrixClient room timelines", function () { // make an m.room.member event for alice's join const joinMshipEvent = utils.mkMembership({ - mship: "join", + mship: KnownMembership.Join, user: userId, room: roomId, name: "Old Alice", @@ -326,7 +327,7 @@ describe("MatrixClient room timelines", function () { // make an m.room.member event with prev_content for alice's nick // change const oldMshipEvent = utils.mkMembership({ - mship: "join", + mship: KnownMembership.Join, user: userId, room: roomId, name: userName, @@ -335,7 +336,7 @@ describe("MatrixClient room timelines", function () { oldMshipEvent.prev_content = { displayname: "Old Alice", avatar_url: undefined, - membership: "join", + membership: KnownMembership.Join, }; // set the list of events to return on scrollback (/messages) @@ -487,7 +488,7 @@ describe("MatrixClient room timelines", function () { utils.mkMembership({ user: userId, room: roomId, - mship: "join", + mship: KnownMembership.Join, name: "New Name", }), utils.mkMessage({ user: userId, room: roomId }), @@ -554,13 +555,13 @@ describe("MatrixClient room timelines", function () { utils.mkMembership({ user: userC, room: roomId, - mship: "join", + mship: KnownMembership.Join, name: "C", }), utils.mkMembership({ user: userC, room: roomId, - mship: "invite", + mship: KnownMembership.Invite, skey: userD, }), ]; @@ -571,9 +572,9 @@ describe("MatrixClient room timelines", function () { return Promise.all([httpBackend!.flush("/sync", 1), utils.syncPromise(client!)]).then(function () { expect(room.currentState.getMembers().length).toEqual(4); expect(room.currentState.getMember(userC)!.name).toEqual("C"); - expect(room.currentState.getMember(userC)!.membership).toEqual("join"); + expect(room.currentState.getMember(userC)!.membership).toEqual(KnownMembership.Join); expect(room.currentState.getMember(userD)!.name).toEqual(userD); - expect(room.currentState.getMember(userD)!.membership).toEqual("invite"); + expect(room.currentState.getMember(userD)!.membership).toEqual(KnownMembership.Invite); }); }); }); @@ -598,9 +599,9 @@ describe("MatrixClient room timelines", function () { expect(room.timeline[0].event).toEqual(eventData[0]); expect(room.currentState.getMembers().length).toEqual(2); expect(room.currentState.getMember(userId)!.name).toEqual(userName); - expect(room.currentState.getMember(userId)!.membership).toEqual("join"); + expect(room.currentState.getMember(userId)!.membership).toEqual(KnownMembership.Join); expect(room.currentState.getMember(otherUserId)!.name).toEqual("Bob"); - expect(room.currentState.getMember(otherUserId)!.membership).toEqual("join"); + expect(room.currentState.getMember(otherUserId)!.membership).toEqual(KnownMembership.Join); }); }); }); diff --git a/spec/integ/matrix-client-syncing.spec.ts b/spec/integ/matrix-client-syncing.spec.ts index 9a7db5fa580..0135eb152b8 100644 --- a/spec/integ/matrix-client-syncing.spec.ts +++ b/spec/integ/matrix-client-syncing.spec.ts @@ -46,6 +46,7 @@ import * as utils from "../test-utils/test-utils"; import { TestClient } from "../TestClient"; import { emitPromise, mkEvent, mkMessage } from "../test-utils/test-utils"; import { THREAD_RELATION_TYPE } from "../../src/models/thread"; +import { KnownMembership } from "../../src/@types/membership"; describe("MatrixClient syncing", () => { const selfUserId = "@alice:localhost"; @@ -123,7 +124,7 @@ describe("MatrixClient syncing", () => { type: "m.room.member", state_key: selfUserId, content: { - membership: "invite", + membership: KnownMembership.Invite, }, }, ], @@ -151,10 +152,10 @@ describe("MatrixClient syncing", () => { type: "m.room.member", state_key: selfUserId, content: { - membership: "leave", + membership: KnownMembership.Leave, }, prev_content: { - membership: "invite", + membership: KnownMembership.Invite, }, // XXX: And other fields required on an event }, @@ -167,10 +168,10 @@ describe("MatrixClient syncing", () => { type: "m.room.member", state_key: selfUserId, content: { - membership: "leave", + membership: KnownMembership.Leave, }, prev_content: { - membership: "invite", + membership: KnownMembership.Invite, }, // XXX: And other fields required on an event }, @@ -193,22 +194,22 @@ describe("MatrixClient syncing", () => { // Room, string, string fires++; expect(room.roomId).toBe(roomId); - expect(membership).toBe("invite"); + expect(membership).toBe(KnownMembership.Invite); expect(oldMembership).toBeFalsy(); // Second fire: a leave client!.once(RoomEvent.MyMembership, (room, membership, oldMembership) => { fires++; expect(room.roomId).toBe(roomId); - expect(membership).toBe("leave"); - expect(oldMembership).toBe("invite"); + expect(membership).toBe(KnownMembership.Leave); + expect(oldMembership).toBe(KnownMembership.Invite); // Third/final fire: a second invite client!.once(RoomEvent.MyMembership, (room, membership, oldMembership) => { fires++; expect(room.roomId).toBe(roomId); - expect(membership).toBe("invite"); - expect(oldMembership).toBe("leave"); + expect(membership).toBe(KnownMembership.Invite); + expect(oldMembership).toBe(KnownMembership.Leave); }); }); @@ -238,7 +239,7 @@ describe("MatrixClient syncing", () => { type: "m.room.member", state_key: selfUserId, content: { - membership: "knock", + membership: KnownMembership.Knock, }, }, ], @@ -266,10 +267,10 @@ describe("MatrixClient syncing", () => { type: "m.room.member", state_key: selfUserId, content: { - membership: "leave", + membership: KnownMembership.Leave, }, prev_content: { - membership: "knock", + membership: KnownMembership.Knock, }, // XXX: And other fields required on an event }, @@ -282,10 +283,10 @@ describe("MatrixClient syncing", () => { type: "m.room.member", state_key: selfUserId, content: { - membership: "leave", + membership: KnownMembership.Leave, }, prev_content: { - membership: "knock", + membership: KnownMembership.Knock, }, // XXX: And other fields required on an event }, @@ -308,22 +309,22 @@ describe("MatrixClient syncing", () => { // Room, string, string fires++; expect(room.roomId).toBe(roomId); - expect(membership).toBe("knock"); + expect(membership).toBe(KnownMembership.Knock); expect(oldMembership).toBeFalsy(); // Second fire: a leave client!.once(RoomEvent.MyMembership, (room, membership, oldMembership) => { fires++; expect(room.roomId).toBe(roomId); - expect(membership).toBe("leave"); - expect(oldMembership).toBe("knock"); + expect(membership).toBe(KnownMembership.Leave); + expect(oldMembership).toBe(KnownMembership.Knock); // Third/final fire: a second knock client!.once(RoomEvent.MyMembership, (room, membership, oldMembership) => { fires++; expect(room.roomId).toBe(roomId); - expect(membership).toBe("knock"); - expect(oldMembership).toBe("leave"); + expect(membership).toBe(KnownMembership.Knock); + expect(oldMembership).toBe(KnownMembership.Leave); }); }); @@ -381,7 +382,7 @@ describe("MatrixClient syncing", () => { type: "m.room.member", state_key: selfUserId, content: { - membership: "invite", + membership: KnownMembership.Invite, }, }, ], @@ -421,7 +422,7 @@ describe("MatrixClient syncing", () => { type: "m.room.member", state_key: selfUserId, content: { - membership: "knock", + membership: KnownMembership.Knock, }, }, ], @@ -533,12 +534,12 @@ describe("MatrixClient syncing", () => { events: [ utils.mkMembership({ room: roomOne, - mship: "join", + mship: KnownMembership.Join, user: otherUserId, }), utils.mkMembership({ room: roomOne, - mship: "join", + mship: KnownMembership.Join, user: selfUserId, }), utils.mkEvent({ @@ -556,7 +557,7 @@ describe("MatrixClient syncing", () => { syncData.rooms.join[roomOne].state.events.push( utils.mkMembership({ room: roomOne, - mship: "invite", + mship: KnownMembership.Invite, user: userC, }) as IStateEvent, ); @@ -589,7 +590,7 @@ describe("MatrixClient syncing", () => { syncData.rooms.join[roomOne].state.events.push( utils.mkMembership({ room: roomOne, - mship: "invite", + mship: KnownMembership.Invite, user: userC, }) as IStateEvent, ); @@ -617,7 +618,7 @@ describe("MatrixClient syncing", () => { syncData.rooms.join[roomOne].state.events.push( utils.mkMembership({ room: roomOne, - mship: "invite", + mship: KnownMembership.Invite, user: userC, }) as IStateEvent, ); @@ -644,7 +645,7 @@ describe("MatrixClient syncing", () => { syncData.rooms.join[roomOne].state.events.push( utils.mkMembership({ room: roomOne, - mship: "invite", + mship: KnownMembership.Invite, user: userC, }) as IStateEvent, ); @@ -719,12 +720,12 @@ describe("MatrixClient syncing", () => { }), utils.mkMembership({ room: roomOne, - mship: "join", + mship: KnownMembership.Join, user: otherUserId, }), utils.mkMembership({ room: roomOne, - mship: "join", + mship: KnownMembership.Join, user: selfUserId, }), utils.mkEvent({ @@ -750,13 +751,13 @@ describe("MatrixClient syncing", () => { events: [ utils.mkMembership({ room: roomTwo, - mship: "join", + mship: KnownMembership.Join, user: otherUserId, name: otherDisplayName, }), utils.mkMembership({ room: roomTwo, - mship: "join", + mship: KnownMembership.Join, user: selfUserId, }), utils.mkEvent({ @@ -1247,7 +1248,7 @@ describe("MatrixClient syncing", () => { const USER_MEMBERSHIP_EVENT = utils.mkMembership({ room: roomOne, - mship: "join", + mship: KnownMembership.Join, user: userA, }); @@ -1508,12 +1509,12 @@ describe("MatrixClient syncing", () => { }), utils.mkMembership({ room: roomOne, - mship: "join", + mship: KnownMembership.Join, user: otherUserId, }), utils.mkMembership({ room: roomOne, - mship: "join", + mship: KnownMembership.Join, user: selfUserId, }), utils.mkEvent({ @@ -1605,12 +1606,12 @@ describe("MatrixClient syncing", () => { }), utils.mkMembership({ room: roomOne, - mship: "join", + mship: KnownMembership.Join, user: otherUserId, }), utils.mkMembership({ room: roomOne, - mship: "join", + mship: KnownMembership.Join, user: selfUserId, }), utils.mkEvent({ @@ -1761,12 +1762,12 @@ describe("MatrixClient syncing", () => { events: [ utils.mkMembership({ room: roomId, - mship: "join", + mship: KnownMembership.Join, user: otherUserId, }), utils.mkMembership({ room: roomId, - mship: "join", + mship: KnownMembership.Join, user: selfUserId, }), utils.mkEvent({ @@ -1901,7 +1902,7 @@ describe("MatrixClient syncing", () => { it("should return a room based on the room initialSync API", async () => { httpBackend!.when("GET", `/rooms/${encodeURIComponent(roomOne)}/initialSync`).respond(200, { room_id: roomOne, - membership: "leave", + membership: KnownMembership.Leave, messages: { start: "start", end: "end", @@ -1950,7 +1951,7 @@ describe("MatrixClient syncing", () => { const room = await prom; expect(room.roomId).toBe(roomOne); - expect(room.getMyMembership()).toBe("leave"); + expect(room.getMyMembership()).toBe(KnownMembership.Leave); expect(room.name).toBe("Room Name"); expect(room.currentState.getStateEvents("m.room.name", "")?.getId()).toBe("$eventId"); expect(room.timeline[0].getContent().body).toBe("Message 1"); @@ -2042,7 +2043,7 @@ describe("MatrixClient syncing (IndexedDB version)", () => { type: "m.room.member", state_key: selfUserId, content: { - membership: "invite", + membership: KnownMembership.Invite, }, }, ], diff --git a/spec/integ/matrix-client-unread-notifications.spec.ts b/spec/integ/matrix-client-unread-notifications.spec.ts index 8238f4e1e8b..7b35cbbf582 100644 --- a/spec/integ/matrix-client-unread-notifications.spec.ts +++ b/spec/integ/matrix-client-unread-notifications.spec.ts @@ -34,6 +34,7 @@ import { TestClient } from "../TestClient"; import { ReceiptType } from "../../src/@types/read_receipts"; import { mkThread } from "../test-utils/thread"; import { SyncState } from "../../src/sync"; +import { KnownMembership } from "../../src/@types/membership"; const userA = "@alice:localhost"; const userB = "@bob:localhost"; @@ -229,7 +230,7 @@ describe("MatrixClient syncing", () => { content: { avatar_url: "", displayname: userB, - membership: "join", + membership: KnownMembership.Join, }, origin_server_ts: 2, sender: userB, @@ -270,7 +271,7 @@ describe("MatrixClient syncing", () => { }, { content: { - join_rule: "invite", + join_rule: KnownMembership.Invite, }, origin_server_ts: 4, sender: userB, @@ -316,7 +317,7 @@ describe("MatrixClient syncing", () => { avatar_url: "", displayname: userA, is_direct: true, - membership: "invite", + membership: KnownMembership.Invite, }, origin_server_ts: 8, sender: userB, @@ -338,7 +339,7 @@ describe("MatrixClient syncing", () => { content: { avatar_url: "", displayname: userA, - membership: "join", + membership: KnownMembership.Join, }, origin_server_ts: 10, sender: userA, diff --git a/spec/integ/sliding-sync-sdk.spec.ts b/spec/integ/sliding-sync-sdk.spec.ts index d67e66852e9..aaf4a1a04a3 100644 --- a/spec/integ/sliding-sync-sdk.spec.ts +++ b/spec/integ/sliding-sync-sdk.spec.ts @@ -43,6 +43,7 @@ import { IStoredClientOpts } from "../../src"; import { logger } from "../../src/logger"; import { emitPromise } from "../test-utils/test-utils"; import { defer } from "../../src/utils"; +import { KnownMembership } from "../../src/@types/membership"; describe("SlidingSyncSdk", () => { let client: MatrixClient | undefined; @@ -189,7 +190,7 @@ describe("SlidingSyncSdk", () => { name: "A", required_state: [ mkOwnStateEvent(EventType.RoomCreate, {}, ""), - mkOwnStateEvent(EventType.RoomMember, { membership: "join" }, selfUserId), + mkOwnStateEvent(EventType.RoomMember, { membership: KnownMembership.Join }, selfUserId), mkOwnStateEvent(EventType.RoomPowerLevels, { users: { [selfUserId]: 100 } }, ""), mkOwnStateEvent(EventType.RoomName, { name: "A" }, ""), ], @@ -204,7 +205,7 @@ describe("SlidingSyncSdk", () => { required_state: [], timeline: [ mkOwnStateEvent(EventType.RoomCreate, {}, ""), - mkOwnStateEvent(EventType.RoomMember, { membership: "join" }, selfUserId), + mkOwnStateEvent(EventType.RoomMember, { membership: KnownMembership.Join }, selfUserId), mkOwnStateEvent(EventType.RoomPowerLevels, { users: { [selfUserId]: 100 } }, ""), mkOwnEvent(EventType.RoomMessage, { body: "hello B" }), mkOwnEvent(EventType.RoomMessage, { body: "world B" }), @@ -216,7 +217,7 @@ describe("SlidingSyncSdk", () => { required_state: [], timeline: [ mkOwnStateEvent(EventType.RoomCreate, {}, ""), - mkOwnStateEvent(EventType.RoomMember, { membership: "join" }, selfUserId), + mkOwnStateEvent(EventType.RoomMember, { membership: KnownMembership.Join }, selfUserId), mkOwnStateEvent(EventType.RoomPowerLevels, { users: { [selfUserId]: 100 } }, ""), mkOwnEvent(EventType.RoomMessage, { body: "hello C" }), mkOwnEvent(EventType.RoomMessage, { body: "world C" }), @@ -229,7 +230,7 @@ describe("SlidingSyncSdk", () => { required_state: [], timeline: [ mkOwnStateEvent(EventType.RoomCreate, {}, ""), - mkOwnStateEvent(EventType.RoomMember, { membership: "join" }, selfUserId), + mkOwnStateEvent(EventType.RoomMember, { membership: KnownMembership.Join }, selfUserId), mkOwnStateEvent(EventType.RoomPowerLevels, { users: { [selfUserId]: 100 } }, ""), mkOwnEvent(EventType.RoomMessage, { body: "hello D" }), mkOwnEvent(EventType.RoomMessage, { body: "world D" }), @@ -244,7 +245,7 @@ describe("SlidingSyncSdk", () => { invite_state: [ { type: EventType.RoomMember, - content: { membership: "invite" }, + content: { membership: KnownMembership.Invite }, state_key: selfUserId, sender: "@bob:localhost", event_id: "$room_e_invite", @@ -265,7 +266,7 @@ describe("SlidingSyncSdk", () => { name: "#foo:localhost", required_state: [ mkOwnStateEvent(EventType.RoomCreate, {}, ""), - mkOwnStateEvent(EventType.RoomMember, { membership: "join" }, selfUserId), + mkOwnStateEvent(EventType.RoomMember, { membership: KnownMembership.Join }, selfUserId), mkOwnStateEvent(EventType.RoomPowerLevels, { users: { [selfUserId]: 100 } }, ""), mkOwnStateEvent(EventType.RoomCanonicalAlias, { alias: "#foo:localhost" }, ""), mkOwnStateEvent(EventType.RoomName, { name: "This should be ignored" }, ""), @@ -281,7 +282,7 @@ describe("SlidingSyncSdk", () => { required_state: [], timeline: [ mkOwnStateEvent(EventType.RoomCreate, {}, ""), - mkOwnStateEvent(EventType.RoomMember, { membership: "join" }, selfUserId), + mkOwnStateEvent(EventType.RoomMember, { membership: KnownMembership.Join }, selfUserId), mkOwnStateEvent(EventType.RoomPowerLevels, { users: { [selfUserId]: 100 } }, ""), ], joined_count: 5, @@ -293,7 +294,7 @@ describe("SlidingSyncSdk", () => { required_state: [], timeline: [ mkOwnStateEvent(EventType.RoomCreate, {}, ""), - mkOwnStateEvent(EventType.RoomMember, { membership: "join" }, selfUserId), + mkOwnStateEvent(EventType.RoomMember, { membership: KnownMembership.Join }, selfUserId), mkOwnStateEvent(EventType.RoomPowerLevels, { users: { [selfUserId]: 100 } }, ""), mkOwnEvent(EventType.RoomMessage, { body: "live event" }), ], @@ -308,7 +309,7 @@ describe("SlidingSyncSdk", () => { const gotRoom = client!.getRoom(roomA); expect(gotRoom).toBeTruthy(); expect(gotRoom!.name).toEqual(data[roomA].name); - expect(gotRoom!.getMyMembership()).toEqual("join"); + expect(gotRoom!.getMyMembership()).toEqual(KnownMembership.Join); assertTimelineEvents(gotRoom!.getLiveTimeline().getEvents().slice(-2), data[roomA].timeline); }); @@ -318,7 +319,7 @@ describe("SlidingSyncSdk", () => { const gotRoom = client!.getRoom(roomB); expect(gotRoom).toBeTruthy(); expect(gotRoom!.name).toEqual(data[roomB].name); - expect(gotRoom!.getMyMembership()).toEqual("join"); + expect(gotRoom!.getMyMembership()).toEqual(KnownMembership.Join); assertTimelineEvents(gotRoom!.getLiveTimeline().getEvents().slice(-5), data[roomB].timeline); }); @@ -372,7 +373,7 @@ describe("SlidingSyncSdk", () => { const gotRoom = client!.getRoom(roomH); expect(gotRoom).toBeTruthy(); expect(gotRoom!.name).toEqual(data[roomH].name); - expect(gotRoom!.getMyMembership()).toEqual("join"); + expect(gotRoom!.getMyMembership()).toEqual(KnownMembership.Join); // check the entire timeline is correct assertTimelineEvents(gotRoom!.getLiveTimeline().getEvents(), data[roomH].timeline); await expect(seenLiveEventDeferred.promise).resolves.toBeTruthy(); @@ -383,7 +384,7 @@ describe("SlidingSyncSdk", () => { await emitPromise(client!, ClientEvent.Room); const gotRoom = client!.getRoom(roomE); expect(gotRoom).toBeTruthy(); - expect(gotRoom!.getMyMembership()).toEqual("invite"); + expect(gotRoom!.getMyMembership()).toEqual(KnownMembership.Invite); expect(gotRoom!.currentState.getJoinRule()).toEqual(JoinRule.Invite); }); @@ -603,9 +604,9 @@ describe("SlidingSyncSdk", () => { required_state: [], timeline: [ mkOwnStateEvent(EventType.RoomCreate, {}, ""), - mkOwnStateEvent(EventType.RoomMember, { membership: "join" }, selfUserId), + mkOwnStateEvent(EventType.RoomMember, { membership: KnownMembership.Join }, selfUserId), mkOwnStateEvent(EventType.RoomPowerLevels, { users: { [selfUserId]: 100 } }, ""), - mkOwnStateEvent(EventType.RoomMember, { membership: "invite" }, invitee), + mkOwnStateEvent(EventType.RoomMember, { membership: KnownMembership.Invite }, invitee), ], }); await httpBackend!.flush("/profile", 1, 1000); @@ -719,7 +720,7 @@ describe("SlidingSyncSdk", () => { required_state: [], timeline: [ mkOwnStateEvent(EventType.RoomCreate, {}, ""), - mkOwnStateEvent(EventType.RoomMember, { membership: "join" }, selfUserId), + mkOwnStateEvent(EventType.RoomMember, { membership: KnownMembership.Join }, selfUserId), mkOwnStateEvent(EventType.RoomPowerLevels, { users: { [selfUserId]: 100 } }, ""), mkOwnEvent(EventType.RoomMessage, { body: "hello" }), ], @@ -923,7 +924,7 @@ describe("SlidingSyncSdk", () => { required_state: [], timeline: [ mkOwnStateEvent(EventType.RoomCreate, {}, ""), - mkOwnStateEvent(EventType.RoomMember, { membership: "join" }, selfUserId), + mkOwnStateEvent(EventType.RoomMember, { membership: KnownMembership.Join }, selfUserId), mkOwnStateEvent(EventType.RoomPowerLevels, { users: { [selfUserId]: 100 } }, ""), mkOwnEvent(EventType.RoomMessage, { body: "hello" }), ], @@ -964,7 +965,7 @@ describe("SlidingSyncSdk", () => { required_state: [], timeline: [ mkOwnStateEvent(EventType.RoomCreate, {}, ""), - mkOwnStateEvent(EventType.RoomMember, { membership: "join" }, selfUserId), + mkOwnStateEvent(EventType.RoomMember, { membership: KnownMembership.Join }, selfUserId), mkOwnStateEvent(EventType.RoomPowerLevels, { users: { [selfUserId]: 100 } }, ""), mkOwnEvent(EventType.RoomMessage, { body: "hello" }), ], @@ -1050,12 +1051,12 @@ describe("SlidingSyncSdk", () => { required_state: [], timeline: [ mkOwnStateEvent(EventType.RoomCreate, {}, ""), - mkOwnStateEvent(EventType.RoomMember, { membership: "join" }, selfUserId), + mkOwnStateEvent(EventType.RoomMember, { membership: KnownMembership.Join }, selfUserId), mkOwnStateEvent(EventType.RoomPowerLevels, { users: { [selfUserId]: 100 } }, ""), { type: EventType.RoomMember, state_key: alice, - content: { membership: "join" }, + content: { membership: KnownMembership.Join }, sender: alice, origin_server_ts: Date.now(), event_id: "$alice", diff --git a/spec/test-utils/test-utils.ts b/spec/test-utils/test-utils.ts index 1e4f8d38eb3..965a6a08806 100644 --- a/spec/test-utils/test-utils.ts +++ b/spec/test-utils/test-utils.ts @@ -19,6 +19,7 @@ import { import { SyncState } from "../../src/sync"; import { eventMapperFor } from "../../src/event-mapper"; import { TEST_ROOM_ID } from "./test-data"; +import { KnownMembership, Membership } from "../../src/@types/membership"; /** * Return a promise that is resolved when the client next emits a @@ -87,7 +88,7 @@ export function getSyncResponse(roomMembers: string[], roomId = TEST_ROOM_ID): I for (let i = 0; i < roomMembers.length; i++) { roomResponse.state.events.push( mkMembershipCustom({ - membership: "join", + membership: KnownMembership.Join, sender: roomMembers[i], }), ); @@ -251,7 +252,7 @@ export function mkPresence(opts: IPresenceOpts & { event?: boolean }): Partial( - base: T & { membership: string; sender: string; content?: IContent }, + base: T & { membership: Membership; sender: string; content?: IContent }, ): T & { type: EventType; sender: string; state_key: string; content: IContent } & GeneratedMetadata { const content = base.content || {}; return mkEventCustom({ diff --git a/spec/unit/crypto.spec.ts b/spec/unit/crypto.spec.ts index 1a61d731165..680b973ad56 100644 --- a/spec/unit/crypto.spec.ts +++ b/spec/unit/crypto.spec.ts @@ -25,6 +25,7 @@ import { UserTrustLevel } from "../../src/crypto/CrossSigning"; import { CryptoBackend } from "../../src/common-crypto/CryptoBackend"; import { EventDecryptionResult } from "../../src/common-crypto/CryptoBackend"; import * as testData from "../test-utils/test-data"; +import { KnownMembership } from "../../src/@types/membership"; const Olm = global.Olm; @@ -463,7 +464,7 @@ describe("Crypto", function () { type: "m.room.member", sender: "@alice:example.com", room_id: roomId, - content: { membership: "invite" }, + content: { membership: KnownMembership.Invite }, state_key: "@bob:example.com", }), ]); @@ -795,7 +796,7 @@ describe("Crypto", function () { type: "m.room.member", sender: "@clara:example.com", room_id: roomId, - content: { membership: "invite" }, + content: { membership: KnownMembership.Invite }, state_key: "@bob:example.com", }), ]); diff --git a/spec/unit/crypto/algorithms/megolm.spec.ts b/spec/unit/crypto/algorithms/megolm.spec.ts index e5e92aebdb2..b27e59d4934 100644 --- a/spec/unit/crypto/algorithms/megolm.spec.ts +++ b/spec/unit/crypto/algorithms/megolm.spec.ts @@ -36,6 +36,7 @@ import { DeviceTrustLevel } from "../../../../src/crypto/CrossSigning"; import { MegolmEncryption as MegolmEncryptionClass } from "../../../../src/crypto/algorithms/megolm"; import { recursiveMapToObject } from "../../../../src/utils"; import { sleep } from "../../../../src/utils"; +import { KnownMembership } from "../../../../src/@types/membership"; const MegolmDecryption = algorithms.DECRYPTION_CLASSES.get("m.megolm.v1.aes-sha2")!; const MegolmEncryption = algorithms.ENCRYPTION_CLASSES.get("m.megolm.v1.aes-sha2")!; @@ -806,11 +807,11 @@ describe("MegolmDecryption", function () { aliceRoom.getEncryptionTargetMembers = jest.fn().mockResolvedValue([ { userId: "@alice:example.com", - membership: "join", + membership: KnownMembership.Join, }, { userId: "@bob:example.com", - membership: "join", + membership: KnownMembership.Join, }, ]); const BOB_DEVICES = { diff --git a/spec/unit/event-timeline.spec.ts b/spec/unit/event-timeline.spec.ts index 2ac49c49f39..52ef23c3625 100644 --- a/spec/unit/event-timeline.spec.ts +++ b/spec/unit/event-timeline.spec.ts @@ -7,6 +7,7 @@ import { MatrixClient } from "../../src/matrix"; import { Room } from "../../src/models/room"; import { RoomMember } from "../../src/models/room-member"; import { EventTimelineSet } from "../../src/models/event-timeline-set"; +import { KnownMembership } from "../../src/@types/membership"; describe("EventTimeline", function () { const roomId = "!foo:bar"; @@ -50,7 +51,7 @@ describe("EventTimeline", function () { const events = [ utils.mkMembership({ room: roomId, - mship: "invite", + mship: KnownMembership.Invite, user: userB, skey: userA, event: true, @@ -87,7 +88,7 @@ describe("EventTimeline", function () { const state = [ utils.mkMembership({ room: roomId, - mship: "invite", + mship: KnownMembership.Invite, user: userB, skey: userA, event: true, @@ -203,11 +204,11 @@ describe("EventTimeline", function () { it("should set event.sender for new and old events", function () { const sentinel = new RoomMember(roomId, userA); sentinel.name = "Alice"; - sentinel.membership = "join"; + sentinel.membership = KnownMembership.Join; const oldSentinel = new RoomMember(roomId, userA); sentinel.name = "Old Alice"; - sentinel.membership = "join"; + sentinel.membership = KnownMembership.Join; mocked(timeline.getState(EventTimeline.FORWARDS)!).getSentinelMember.mockImplementation(function (uid) { if (uid === userA) { @@ -246,11 +247,11 @@ describe("EventTimeline", function () { it("should set event.target for new and old m.room.member events", function () { const sentinel = new RoomMember(roomId, userA); sentinel.name = "Alice"; - sentinel.membership = "join"; + sentinel.membership = KnownMembership.Join; const oldSentinel = new RoomMember(roomId, userA); sentinel.name = "Old Alice"; - sentinel.membership = "join"; + sentinel.membership = KnownMembership.Join; mocked(timeline.getState(EventTimeline.FORWARDS)!).getSentinelMember.mockImplementation(function (uid) { if (uid === userA) { @@ -267,14 +268,14 @@ describe("EventTimeline", function () { const newEv = utils.mkMembership({ room: roomId, - mship: "invite", + mship: KnownMembership.Invite, user: userB, skey: userA, event: true, }); const oldEv = utils.mkMembership({ room: roomId, - mship: "ban", + mship: KnownMembership.Ban, user: userB, skey: userA, event: true, @@ -291,7 +292,7 @@ describe("EventTimeline", function () { const events = [ utils.mkMembership({ room: roomId, - mship: "invite", + mship: KnownMembership.Invite, user: userB, skey: userA, event: true, @@ -330,7 +331,7 @@ describe("EventTimeline", function () { const events = [ utils.mkMembership({ room: roomId, - mship: "invite", + mship: KnownMembership.Invite, user: userB, skey: userA, event: true, diff --git a/spec/unit/matrix-client.spec.ts b/spec/unit/matrix-client.spec.ts index ac43580913a..f80531f86bb 100644 --- a/spec/unit/matrix-client.spec.ts +++ b/spec/unit/matrix-client.spec.ts @@ -71,6 +71,7 @@ import * as featureUtils from "../../src/feature"; import { StubStore } from "../../src/store/stub"; import { SecretStorageKeyDescriptionAesV1, ServerSideSecretStorageImpl } from "../../src/secret-storage"; import { CryptoBackend } from "../../src/common-crypto/CryptoBackend"; +import { KnownMembership } from "../../src/@types/membership"; jest.useFakeTimers(); @@ -750,7 +751,7 @@ describe("MatrixClient", function () { it("should get (unstable) file trees with valid state", async () => { const roomId = "!room:example.org"; const mockRoom = { - getMyMembership: () => "join", + getMyMembership: () => KnownMembership.Join, currentState: { getStateEvents: (eventType, stateKey) => { /* eslint-disable jest/no-conditional-expect */ @@ -789,7 +790,7 @@ describe("MatrixClient", function () { it("should not get (unstable) file trees if not joined", async () => { const roomId = "!room:example.org"; const mockRoom = { - getMyMembership: () => "leave", // "not join" + getMyMembership: () => KnownMembership.Leave, // "not join" } as unknown as Room; client.getRoom = (getRoomId) => { expect(getRoomId).toEqual(roomId); @@ -812,7 +813,7 @@ describe("MatrixClient", function () { it("should not get (unstable) file trees with invalid create contents", async () => { const roomId = "!room:example.org"; const mockRoom = { - getMyMembership: () => "join", + getMyMembership: () => KnownMembership.Join, currentState: { getStateEvents: (eventType, stateKey) => { /* eslint-disable jest/no-conditional-expect */ @@ -849,7 +850,7 @@ describe("MatrixClient", function () { it("should not get (unstable) file trees with invalid purpose/subtype contents", async () => { const roomId = "!room:example.org"; const mockRoom = { - getMyMembership: () => "join", + getMyMembership: () => KnownMembership.Join, currentState: { getStateEvents: (eventType, stateKey) => { /* eslint-disable jest/no-conditional-expect */ @@ -1309,7 +1310,7 @@ describe("MatrixClient", function () { describe("redactEvent", () => { const roomId = "!room:example.org"; const mockRoom = { - getMyMembership: () => "join", + getMyMembership: () => KnownMembership.Join, currentState: { getStateEvents: (eventType, stateKey) => { if (eventType === EventType.RoomEncryption) { @@ -1448,7 +1449,7 @@ describe("MatrixClient", function () { const txnId = "m12345"; const mockRoom = { - getMyMembership: () => "join", + getMyMembership: () => KnownMembership.Join, updatePendingEvent: (event: MatrixEvent, status: EventStatus) => event.setStatus(status), hasEncryptionStateEvent: jest.fn().mockReturnValue(true), } as unknown as Room; diff --git a/spec/unit/matrixrtc/MatrixRTCSession.spec.ts b/spec/unit/matrixrtc/MatrixRTCSession.spec.ts index 2c40e9a2230..d061c60d0cb 100644 --- a/spec/unit/matrixrtc/MatrixRTCSession.spec.ts +++ b/spec/unit/matrixrtc/MatrixRTCSession.spec.ts @@ -15,6 +15,7 @@ limitations under the License. */ import { EventTimeline, EventType, MatrixClient, MatrixError, MatrixEvent, Room } from "../../../src"; +import { KnownMembership } from "../../../src/@types/membership"; import { CallMembershipData } from "../../../src/matrixrtc/CallMembership"; import { MatrixRTCSession, MatrixRTCSessionEvent } from "../../../src/matrixrtc/MatrixRTCSession"; import { EncryptionKeysEventContent } from "../../../src/matrixrtc/types"; @@ -76,7 +77,7 @@ describe("MatrixRTCSession", () => { it("ignores memberships events of members not in the room", () => { const mockRoom = makeMockRoom([membershipTemplate]); - mockRoom.hasMembershipState = (state) => state === "join"; + mockRoom.hasMembershipState = (state) => state === KnownMembership.Join; sess = MatrixRTCSession.roomSessionForRoom(client, mockRoom); expect(sess?.memberships.length).toEqual(0); }); diff --git a/spec/unit/models/MSC3089TreeSpace.spec.ts b/spec/unit/models/MSC3089TreeSpace.spec.ts index 9ff97f253e4..8f000d84496 100644 --- a/spec/unit/models/MSC3089TreeSpace.spec.ts +++ b/spec/unit/models/MSC3089TreeSpace.spec.ts @@ -25,6 +25,7 @@ import { } from "../../../src/models/MSC3089TreeSpace"; import { DEFAULT_ALPHABET } from "../../../src/utils"; import { MatrixError } from "../../../src/http-api"; +import { KnownMembership } from "../../../src/@types/membership"; describe("MSC3089TreeSpace", () => { let client: MatrixClient; @@ -458,14 +459,14 @@ describe("MSC3089TreeSpace", () => { expect(stateKey).toBeUndefined(); return [ // Partial implementations - { getContent: () => ({ membership: "join" }), getStateKey: () => joinMemberId }, - { getContent: () => ({ membership: "knock" }), getStateKey: () => knockMemberId }, - { getContent: () => ({ membership: "invite" }), getStateKey: () => inviteMemberId }, - { getContent: () => ({ membership: "leave" }), getStateKey: () => leaveMemberId }, - { getContent: () => ({ membership: "ban" }), getStateKey: () => banMemberId }, + { getContent: () => ({ membership: KnownMembership.Join }), getStateKey: () => joinMemberId }, + { getContent: () => ({ membership: KnownMembership.Knock }), getStateKey: () => knockMemberId }, + { getContent: () => ({ membership: KnownMembership.Invite }), getStateKey: () => inviteMemberId }, + { getContent: () => ({ membership: KnownMembership.Leave }), getStateKey: () => leaveMemberId }, + { getContent: () => ({ membership: KnownMembership.Ban }), getStateKey: () => banMemberId }, // ensure we don't kick ourselves - { getContent: () => ({ membership: "join" }), getStateKey: () => selfUserId }, + { getContent: () => ({ membership: KnownMembership.Join }), getStateKey: () => selfUserId }, ]; }, }; diff --git a/spec/unit/room-member.spec.ts b/spec/unit/room-member.spec.ts index 99a2d589598..f304d48de4f 100644 --- a/spec/unit/room-member.spec.ts +++ b/spec/unit/room-member.spec.ts @@ -27,6 +27,7 @@ import { UNSTABLE_MSC2666_QUERY_MUTUAL_ROOMS, UNSTABLE_MSC2666_SHARED_ROOMS, } from "../../src"; +import { KnownMembership } from "../../src/@types/membership"; describe("RoomMember", function () { const roomId = "!foo:bar"; @@ -50,7 +51,7 @@ describe("RoomMember", function () { room: roomId, user: userA, content: { - membership: "join", + membership: KnownMembership.Join, avatar_url: "mxc://flibble/wibble", }, }); @@ -282,11 +283,11 @@ describe("RoomMember", function () { describe("isKicked", () => { it("should return false if membership is not `leave`", () => { const member1 = new RoomMember(roomId, userA); - member1.membership = "join"; + member1.membership = KnownMembership.Join; expect(member1.isKicked()).toBeFalsy(); const member2 = new RoomMember(roomId, userA); - member2.membership = "invite"; + member2.membership = KnownMembership.Invite; expect(member2.isKicked()).toBeFalsy(); const member3 = new RoomMember(roomId, userA); @@ -295,17 +296,17 @@ describe("RoomMember", function () { it("should return false if the membership event is unknown", () => { const member = new RoomMember(roomId, userA); - member.membership = "leave"; + member.membership = KnownMembership.Leave; expect(member.isKicked()).toBeFalsy(); }); it("should return false if the member left of their own accord", () => { const member = new RoomMember(roomId, userA); - member.membership = "leave"; + member.membership = KnownMembership.Leave; member.events.member = utils.mkMembership({ event: true, sender: userA, - mship: "leave", + mship: KnownMembership.Leave, skey: userA, }); expect(member.isKicked()).toBeFalsy(); @@ -313,11 +314,11 @@ describe("RoomMember", function () { it("should return true if the member's leave was sent by another user", () => { const member = new RoomMember(roomId, userA); - member.membership = "leave"; + member.membership = KnownMembership.Leave; member.events.member = utils.mkMembership({ event: true, sender: userB, - mship: "leave", + mship: KnownMembership.Leave, skey: userA, }); expect(member.isKicked()).toBeTruthy(); @@ -327,11 +328,11 @@ describe("RoomMember", function () { describe("getDMInviter", () => { it("should return userId of the sender of the invite if is_direct=true", () => { const member = new RoomMember(roomId, userA); - member.membership = "invite"; + member.membership = KnownMembership.Invite; member.events.member = utils.mkMembership({ event: true, sender: userB, - mship: "invite", + mship: KnownMembership.Invite, skey: userA, }); member.events.member.event.content!.is_direct = true; @@ -340,11 +341,11 @@ describe("RoomMember", function () { it("should not return userId of the sender of the invite if is_direct=false", () => { const member = new RoomMember(roomId, userA); - member.membership = "invite"; + member.membership = KnownMembership.Invite; member.events.member = utils.mkMembership({ event: true, sender: userB, - mship: "invite", + mship: KnownMembership.Invite, skey: userA, }); member.events.member.event.content!.is_direct = false; @@ -355,7 +356,7 @@ describe("RoomMember", function () { describe("setMembershipEvent", function () { const joinEvent = utils.mkMembership({ event: true, - mship: "join", + mship: KnownMembership.Join, user: userA, room: roomId, name: "Alice", @@ -363,7 +364,7 @@ describe("RoomMember", function () { const inviteEvent = utils.mkMembership({ event: true, - mship: "invite", + mship: KnownMembership.Invite, user: userB, skey: userA, room: roomId, @@ -371,10 +372,10 @@ describe("RoomMember", function () { it("should set 'membership' and assign the event to 'events.member'.", function () { member.setMembershipEvent(inviteEvent); - expect(member.membership).toEqual("invite"); + expect(member.membership).toEqual(KnownMembership.Invite); expect(member.events.member).toEqual(inviteEvent); member.setMembershipEvent(joinEvent); - expect(member.membership).toEqual("join"); + expect(member.membership).toEqual(KnownMembership.Join); expect(member.events.member).toEqual(joinEvent); }); @@ -387,13 +388,13 @@ describe("RoomMember", function () { return [ utils.mkMembership({ event: true, - mship: "join", + mship: KnownMembership.Join, room: roomId, user: userB, }), utils.mkMembership({ event: true, - mship: "join", + mship: KnownMembership.Join, room: roomId, user: userC, name: "Alice", @@ -443,7 +444,7 @@ describe("RoomMember", function () { it("should set 'name' to user_id if it is just whitespace", function () { const joinEvent = utils.mkMembership({ event: true, - mship: "join", + mship: KnownMembership.Join, user: userA, room: roomId, name: " \u200b ", @@ -457,7 +458,7 @@ describe("RoomMember", function () { it("should disambiguate users on a fuzzy displayname match", function () { const joinEvent = utils.mkMembership({ event: true, - mship: "join", + mship: KnownMembership.Join, user: userA, room: roomId, name: "Alíce\u200b", // note diacritic and zero width char @@ -471,7 +472,7 @@ describe("RoomMember", function () { return [ utils.mkMembership({ event: true, - mship: "join", + mship: KnownMembership.Join, room: roomId, user: userC, name: "Alice", diff --git a/spec/unit/room-state.spec.ts b/spec/unit/room-state.spec.ts index 6c60d08f908..64a268dde14 100644 --- a/spec/unit/room-state.spec.ts +++ b/spec/unit/room-state.spec.ts @@ -28,6 +28,7 @@ import { MatrixClient } from "../../src/client"; import { DecryptionError } from "../../src/crypto/algorithms"; import { defer } from "../../src/utils"; import { Room } from "../../src/models/room"; +import { KnownMembership } from "../../src/@types/membership"; describe("RoomState", function () { const roomId = "!foo:bar"; @@ -44,14 +45,14 @@ describe("RoomState", function () { utils.mkMembership({ // userA joined event: true, - mship: "join", + mship: KnownMembership.Join, user: userA, room: roomId, }), utils.mkMembership({ // userB joined event: true, - mship: "join", + mship: KnownMembership.Join, user: userB, room: roomId, }), @@ -102,20 +103,20 @@ describe("RoomState", function () { it("should return a member which changes as state changes", function () { const member = state.getMember(userB); - expect(member?.membership).toEqual("join"); + expect(member?.membership).toEqual(KnownMembership.Join); expect(member?.name).toEqual(userB); state.setStateEvents([ utils.mkMembership({ room: roomId, user: userB, - mship: "leave", + mship: KnownMembership.Leave, event: true, name: "BobGone", }), ]); - expect(member?.membership).toEqual("leave"); + expect(member?.membership).toEqual(KnownMembership.Leave); expect(member?.name).toEqual("BobGone"); }); }); @@ -131,17 +132,17 @@ describe("RoomState", function () { utils.mkMembership({ room: roomId, user: userA, - mship: "leave", + mship: KnownMembership.Leave, event: true, name: "AliceIsGone", }), ]); const postLeaveUser = state.getSentinelMember(userA); - expect(preLeaveUser?.membership).toEqual("join"); + expect(preLeaveUser?.membership).toEqual(KnownMembership.Join); expect(preLeaveUser?.name).toEqual(userA); - expect(postLeaveUser?.membership).toEqual("leave"); + expect(postLeaveUser?.membership).toEqual(KnownMembership.Leave); expect(postLeaveUser?.name).toEqual("AliceIsGone"); }); }); @@ -166,7 +167,7 @@ describe("RoomState", function () { it("should return a single MatrixEvent if a state_key was specified", function () { const event = state.getStateEvents("m.room.member", userA); expect(event?.getContent()).toMatchObject({ - membership: "join", + membership: KnownMembership.Join, }); }); }); @@ -176,13 +177,13 @@ describe("RoomState", function () { const memberEvents = [ utils.mkMembership({ user: "@cleo:bar", - mship: "invite", + mship: KnownMembership.Invite, room: roomId, event: true, }), utils.mkMembership({ user: "@daisy:bar", - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, }), @@ -202,13 +203,13 @@ describe("RoomState", function () { const memberEvents = [ utils.mkMembership({ user: "@cleo:bar", - mship: "invite", + mship: KnownMembership.Invite, room: roomId, event: true, }), utils.mkMembership({ user: "@daisy:bar", - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, }), @@ -228,7 +229,7 @@ describe("RoomState", function () { const events = [ utils.mkMembership({ user: "@cleo:bar", - mship: "invite", + mship: KnownMembership.Invite, room: roomId, event: true, }), @@ -282,7 +283,7 @@ describe("RoomState", function () { it("should call setPowerLevelEvent on a new RoomMember if power levels exist", function () { const memberEvent = utils.mkMembership({ - mship: "join", + mship: KnownMembership.Join, user: userC, room: roomId, event: true, @@ -312,7 +313,7 @@ describe("RoomState", function () { it("should call setMembershipEvent on the right RoomMember", function () { const memberEvent = utils.mkMembership({ user: userB, - mship: "leave", + mship: KnownMembership.Leave, room: roomId, event: true, }); @@ -447,7 +448,7 @@ describe("RoomState", function () { it("should add a new member", function () { const oobMemberEvent = utils.mkMembership({ user: userLazy, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, }); @@ -462,7 +463,7 @@ describe("RoomState", function () { state.setOutOfBandMembers([ utils.mkMembership({ user: userLazy, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, }), @@ -474,7 +475,7 @@ describe("RoomState", function () { const userLazy = "@oob:hs"; const oobMemberEvent = utils.mkMembership({ user: userLazy, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, }); @@ -491,7 +492,7 @@ describe("RoomState", function () { it("should never overwrite existing members", function () { const oobMemberEvent = utils.mkMembership({ user: userA, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, }); @@ -506,7 +507,7 @@ describe("RoomState", function () { const doesntExistYetUserId = "@doesntexistyet:hs"; const oobMemberEvent = utils.mkMembership({ user: doesntExistYetUserId, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, }); @@ -529,7 +530,7 @@ describe("RoomState", function () { state.setOutOfBandMembers([ utils.mkMembership({ user: userLazy, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, }), @@ -554,7 +555,7 @@ describe("RoomState", function () { copy.setOutOfBandMembers([ utils.mkMembership({ user: userA, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, }), @@ -563,7 +564,7 @@ describe("RoomState", function () { state.setOutOfBandMembers([ utils.mkMembership({ user: userLazy, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, }), @@ -576,7 +577,7 @@ describe("RoomState", function () { copy.setStateEvents([ utils.mkMembership({ user: userLazy, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, }), @@ -697,9 +698,13 @@ describe("RoomState", function () { }); it("should update after adding joined member", function () { - state.setStateEvents([utils.mkMembership({ event: true, mship: "join", user: userA, room: roomId })]); + state.setStateEvents([ + utils.mkMembership({ event: true, mship: KnownMembership.Join, user: userA, room: roomId }), + ]); expect(state.getJoinedMemberCount()).toEqual(1); - state.setStateEvents([utils.mkMembership({ event: true, mship: "join", user: userC, room: roomId })]); + state.setStateEvents([ + utils.mkMembership({ event: true, mship: KnownMembership.Join, user: userC, room: roomId }), + ]); expect(state.getJoinedMemberCount()).toEqual(2); }); }); @@ -710,9 +715,13 @@ describe("RoomState", function () { }); it("should update after adding invited member", function () { - state.setStateEvents([utils.mkMembership({ event: true, mship: "invite", user: userA, room: roomId })]); + state.setStateEvents([ + utils.mkMembership({ event: true, mship: KnownMembership.Invite, user: userA, room: roomId }), + ]); expect(state.getInvitedMemberCount()).toEqual(1); - state.setStateEvents([utils.mkMembership({ event: true, mship: "invite", user: userC, room: roomId })]); + state.setStateEvents([ + utils.mkMembership({ event: true, mship: KnownMembership.Invite, user: userC, room: roomId }), + ]); expect(state.getInvitedMemberCount()).toEqual(2); }); }); @@ -723,19 +732,27 @@ describe("RoomState", function () { }); it("should, once used, override counting members from state", function () { - state.setStateEvents([utils.mkMembership({ event: true, mship: "join", user: userA, room: roomId })]); + state.setStateEvents([ + utils.mkMembership({ event: true, mship: KnownMembership.Join, user: userA, room: roomId }), + ]); expect(state.getJoinedMemberCount()).toEqual(1); state.setJoinedMemberCount(100); expect(state.getJoinedMemberCount()).toEqual(100); - state.setStateEvents([utils.mkMembership({ event: true, mship: "join", user: userC, room: roomId })]); + state.setStateEvents([ + utils.mkMembership({ event: true, mship: KnownMembership.Join, user: userC, room: roomId }), + ]); expect(state.getJoinedMemberCount()).toEqual(100); }); it("should, once used, override counting members from state, " + "also after clone", function () { - state.setStateEvents([utils.mkMembership({ event: true, mship: "join", user: userA, room: roomId })]); + state.setStateEvents([ + utils.mkMembership({ event: true, mship: KnownMembership.Join, user: userA, room: roomId }), + ]); state.setJoinedMemberCount(100); const copy = state.clone(); - copy.setStateEvents([utils.mkMembership({ event: true, mship: "join", user: userC, room: roomId })]); + copy.setStateEvents([ + utils.mkMembership({ event: true, mship: KnownMembership.Join, user: userC, room: roomId }), + ]); expect(state.getJoinedMemberCount()).toEqual(100); }); }); @@ -746,19 +763,27 @@ describe("RoomState", function () { }); it("should, once used, override counting members from state", function () { - state.setStateEvents([utils.mkMembership({ event: true, mship: "invite", user: userB, room: roomId })]); + state.setStateEvents([ + utils.mkMembership({ event: true, mship: KnownMembership.Invite, user: userB, room: roomId }), + ]); expect(state.getInvitedMemberCount()).toEqual(1); state.setInvitedMemberCount(100); expect(state.getInvitedMemberCount()).toEqual(100); - state.setStateEvents([utils.mkMembership({ event: true, mship: "invite", user: userC, room: roomId })]); + state.setStateEvents([ + utils.mkMembership({ event: true, mship: KnownMembership.Invite, user: userC, room: roomId }), + ]); expect(state.getInvitedMemberCount()).toEqual(100); }); it("should, once used, override counting members from state, " + "also after clone", function () { - state.setStateEvents([utils.mkMembership({ event: true, mship: "invite", user: userB, room: roomId })]); + state.setStateEvents([ + utils.mkMembership({ event: true, mship: KnownMembership.Invite, user: userB, room: roomId }), + ]); state.setInvitedMemberCount(100); const copy = state.clone(); - copy.setStateEvents([utils.mkMembership({ event: true, mship: "invite", user: userC, room: roomId })]); + copy.setStateEvents([ + utils.mkMembership({ event: true, mship: KnownMembership.Invite, user: userC, room: roomId }), + ]); expect(state.getInvitedMemberCount()).toEqual(100); }); }); diff --git a/spec/unit/room.spec.ts b/spec/unit/room.spec.ts index 4e14ca099a4..93b6ed47e0b 100644 --- a/spec/unit/room.spec.ts +++ b/spec/unit/room.spec.ts @@ -56,6 +56,7 @@ import { getMockClientWithEventEmitter, mockClientMethodsUser } from "../test-ut import { logger } from "../../src/logger"; import { IMessageOpts } from "../test-utils/test-utils"; import { flushPromises } from "../test-utils/flushPromises"; +import { KnownMembership } from "../../src/@types/membership"; describe("Room", function () { const roomId = "!foo:bar"; @@ -408,7 +409,7 @@ describe("Room", function () { const events: MatrixEvent[] = [ utils.mkMembership({ room: roomId, - mship: "invite", + mship: KnownMembership.Invite, user: userB, skey: userA, event: true, @@ -434,7 +435,7 @@ describe("Room", function () { it("should synthesize read receipts for the senders of events", async function () { const sentinel = { userId: userA, - membership: "join", + membership: KnownMembership.Join, name: "Alice", } as unknown as RoomMember; mocked(room.currentState.getSentinelMember).mockImplementation(function (uid) { @@ -636,12 +637,12 @@ describe("Room", function () { it("should set event.sender for new and old events", async function () { const sentinel = { userId: userA, - membership: "join", + membership: KnownMembership.Join, name: "Alice", } as unknown as RoomMember; const oldSentinel = { userId: userA, - membership: "join", + membership: KnownMembership.Join, name: "Old Alice", } as unknown as RoomMember; mocked(room.currentState.getSentinelMember).mockImplementation(function (uid) { @@ -680,12 +681,12 @@ describe("Room", function () { it("should set event.target for new and old m.room.member events", async function () { const sentinel = { userId: userA, - membership: "join", + membership: KnownMembership.Join, name: "Alice", } as unknown as RoomMember; const oldSentinel = { userId: userA, - membership: "join", + membership: KnownMembership.Join, name: "Old Alice", } as unknown as RoomMember; mocked(room.currentState.getSentinelMember).mockImplementation(function (uid) { @@ -703,14 +704,14 @@ describe("Room", function () { const newEv = utils.mkMembership({ room: roomId, - mship: "invite", + mship: KnownMembership.Invite, user: userB, skey: userA, event: true, }); const oldEv = utils.mkMembership({ room: roomId, - mship: "ban", + mship: KnownMembership.Ban, user: userB, skey: userA, event: true, @@ -727,7 +728,7 @@ describe("Room", function () { const events: MatrixEvent[] = [ utils.mkMembership({ room: roomId, - mship: "invite", + mship: KnownMembership.Invite, user: userB, skey: userA, event: true, @@ -948,9 +949,9 @@ describe("Room", function () { it("should return members whose membership is 'join'", function () { mocked(room.currentState.getMembers).mockImplementation(function () { return [ - { userId: "@alice:bar", membership: "join" } as unknown as RoomMember, - { userId: "@bob:bar", membership: "invite" } as unknown as RoomMember, - { userId: "@cleo:bar", membership: "leave" } as unknown as RoomMember, + { userId: "@alice:bar", membership: KnownMembership.Join } as unknown as RoomMember, + { userId: "@bob:bar", membership: KnownMembership.Invite } as unknown as RoomMember, + { userId: "@cleo:bar", membership: KnownMembership.Leave } as unknown as RoomMember, ]; }); const res = room.getJoinedMembers(); @@ -960,7 +961,7 @@ describe("Room", function () { it("should return an empty list if no membership is 'join'", function () { mocked(room.currentState.getMembers).mockImplementation(function () { - return [{ userId: "@bob:bar", membership: "invite" } as unknown as RoomMember]; + return [{ userId: "@bob:bar", membership: KnownMembership.Invite } as unknown as RoomMember]; }); const res = room.getJoinedMembers(); expect(res.length).toEqual(0); @@ -971,42 +972,42 @@ describe("Room", function () { it("should return true for a matching userId and membership", function () { mocked(room.currentState.getMember).mockImplementation(function (userId) { return { - "@alice:bar": { userId: "@alice:bar", membership: "join" }, - "@bob:bar": { userId: "@bob:bar", membership: "invite" }, + "@alice:bar": { userId: "@alice:bar", membership: KnownMembership.Join }, + "@bob:bar": { userId: "@bob:bar", membership: KnownMembership.Invite }, }[userId] as unknown as RoomMember; }); - expect(room.hasMembershipState("@bob:bar", "invite")).toBe(true); + expect(room.hasMembershipState("@bob:bar", KnownMembership.Invite)).toBe(true); }); it("should return false if match membership but no match userId", function () { mocked(room.currentState.getMember).mockImplementation(function (userId) { return { - "@alice:bar": { userId: "@alice:bar", membership: "join" }, + "@alice:bar": { userId: "@alice:bar", membership: KnownMembership.Join }, }[userId] as unknown as RoomMember; }); - expect(room.hasMembershipState("@bob:bar", "join")).toBe(false); + expect(room.hasMembershipState("@bob:bar", KnownMembership.Join)).toBe(false); }); it("should return false if match userId but no match membership", function () { mocked(room.currentState.getMember).mockImplementation(function (userId) { return { - "@alice:bar": { userId: "@alice:bar", membership: "join" }, + "@alice:bar": { userId: "@alice:bar", membership: KnownMembership.Join }, }[userId] as unknown as RoomMember; }); - expect(room.hasMembershipState("@alice:bar", "ban")).toBe(false); + expect(room.hasMembershipState("@alice:bar", KnownMembership.Ban)).toBe(false); }); it("should return false if no match membership or userId", function () { mocked(room.currentState.getMember).mockImplementation(function (userId) { return { - "@alice:bar": { userId: "@alice:bar", membership: "join" }, + "@alice:bar": { userId: "@alice:bar", membership: KnownMembership.Join }, }[userId] as unknown as RoomMember; }); - expect(room.hasMembershipState("@bob:bar", "invite")).toBe(false); + expect(room.hasMembershipState("@bob:bar", KnownMembership.Invite)).toBe(false); }); it("should return false if no members exist", function () { - expect(room.hasMembershipState("@foo:bar", "join")).toBe(false); + expect(room.hasMembershipState("@foo:bar", KnownMembership.Join)).toBe(false); }); }); @@ -1061,7 +1062,7 @@ describe("Room", function () { }), ]); }; - const addMember = async function (userId: string, state = "join", opts: any = {}) { + const addMember = async function (userId: string, state = KnownMembership.Join, opts: any = {}) { opts.room = roomId; opts.mship = state; opts.user = opts.user || userId; @@ -1083,7 +1084,7 @@ describe("Room", function () { async function () { const roomName = "flibble"; - const event = await addMember(userA, "invite"); + const event = await addMember(userA, KnownMembership.Invite); event.event.unsigned = {}; event.event.unsigned.invite_room_state = [ { @@ -1102,7 +1103,7 @@ describe("Room", function () { ); it("should not clobber state events if it isn't an invite room", async function () { - const event = await addMember(userA, "join"); + const event = await addMember(userA, KnownMembership.Join); const roomName = "flibble"; setRoomName(roomName); const roomNameToIgnore = "ignoreme"; @@ -1125,7 +1126,7 @@ describe("Room", function () { describe("Room.recalculate => Room Name using room summary", function () { it("should use room heroes if available", function () { - addMember(userA, "invite"); + addMember(userA, KnownMembership.Invite); addMember(userB); addMember(userC); addMember(userD); @@ -1149,8 +1150,8 @@ describe("Room", function () { it("uses hero name from state", function () { const name = "Mr B"; - addMember(userA, "invite"); - addMember(userB, "join", { name }); + addMember(userA, KnownMembership.Invite); + addMember(userB, KnownMembership.Join, { name }); room.setSummary({ "m.heroes": [userB], }); @@ -1161,7 +1162,7 @@ describe("Room", function () { it("uses counts from summary", function () { const name = "Mr B"; - addMember(userB, "join", { name }); + addMember(userB, KnownMembership.Join, { name }); room.setSummary({ "m.heroes": [userB], "m.joined_member_count": 50, @@ -1174,8 +1175,8 @@ describe("Room", function () { it("relies on heroes in case of absent counts", function () { const nameB = "Mr Bean"; const nameC = "Mel C"; - addMember(userB, "join", { name: nameB }); - addMember(userC, "join", { name: nameC }); + addMember(userB, KnownMembership.Join, { name: nameB }); + addMember(userC, KnownMembership.Join, { name: nameC }); room.setSummary({ "m.heroes": [userB, userC], }); @@ -1185,8 +1186,8 @@ describe("Room", function () { it("uses only heroes", function () { const nameB = "Mr Bean"; - addMember(userB, "join", { name: nameB }); - addMember(userC, "join"); + addMember(userB, KnownMembership.Join, { name: nameB }); + addMember(userC, KnownMembership.Join); room.setSummary({ "m.heroes": [userB], }); @@ -1306,7 +1307,7 @@ describe("Room", function () { " (invite join_rules) rooms if you are invited to it.", function () { setJoinRule(JoinRule.Invite); - addMember(userA, "invite", { user: userB }); + addMember(userA, KnownMembership.Invite, { user: userB }); addMember(userB); room.recalculate(); const name = room.name; @@ -1396,8 +1397,8 @@ describe("Room", function () { it("should return '[inviter display name] if state event " + "available", function () { setJoinRule(JoinRule.Invite); - addMember(userB, "join", { name: "Alice" }); - addMember(userA, "invite", { user: userA }); + addMember(userB, KnownMembership.Join, { name: "Alice" }); + addMember(userA, KnownMembership.Invite, { user: userA }); room.recalculate(); const name = room.name; expect(name).toEqual("Alice"); @@ -1406,7 +1407,7 @@ describe("Room", function () { it("should return inviter mxid if display name not available", function () { setJoinRule(JoinRule.Invite); addMember(userB); - addMember(userA, "invite", { user: userA }); + addMember(userA, KnownMembership.Invite, { user: userA }); room.recalculate(); const name = room.name; expect(name).toEqual(userB); @@ -2063,7 +2064,7 @@ describe("Room", function () { const memberEvent = utils.mkMembership({ user: "@user_a:bar", - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User A", @@ -2083,7 +2084,7 @@ describe("Room", function () { it("should take members from storage if available", async function () { const memberEvent2 = utils.mkMembership({ user: "@user_a:bar", - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "Ms A", @@ -2112,7 +2113,7 @@ describe("Room", function () { describe("getMyMembership", function () { it("should return synced membership if membership isn't available yet", function () { const room = new Room(roomId, null!, userA); - room.updateMyMembership(JoinRule.Invite); + room.updateMyMembership(KnownMembership.Invite); expect(room.getMyMembership()).toEqual(JoinRule.Invite); }); it("should emit a Room.myMembership event on a change", function () { @@ -2124,15 +2125,15 @@ describe("Room", function () { room.on(RoomEvent.MyMembership, (_room, membership, oldMembership) => { events.push({ membership, oldMembership }); }); - room.updateMyMembership(JoinRule.Invite); + room.updateMyMembership(KnownMembership.Invite); expect(room.getMyMembership()).toEqual(JoinRule.Invite); - expect(events[0]).toEqual({ membership: "invite", oldMembership: undefined }); + expect(events[0]).toEqual({ membership: KnownMembership.Invite, oldMembership: undefined }); events.splice(0); //clear - room.updateMyMembership(JoinRule.Invite); + room.updateMyMembership(KnownMembership.Invite); expect(events.length).toEqual(0); - room.updateMyMembership("join"); - expect(room.getMyMembership()).toEqual("join"); - expect(events[0]).toEqual({ membership: "join", oldMembership: "invite" }); + room.updateMyMembership(KnownMembership.Join); + expect(room.getMyMembership()).toEqual(KnownMembership.Join); + expect(events[0]).toEqual({ membership: KnownMembership.Join, oldMembership: KnownMembership.Invite }); }); }); @@ -2146,7 +2147,7 @@ describe("Room", function () { state_key: userA, sender: userB, content: { - membership: "invite", + membership: KnownMembership.Invite, is_direct: true, }, }), @@ -2157,7 +2158,7 @@ describe("Room", function () { it("should fall back to summary heroes and return the first one", () => { const room = new Room(roomId, null!, userA); - room.updateMyMembership("invite"); + room.updateMyMembership(KnownMembership.Invite); room.setSummary({ "m.heroes": [userA, userC], "m.joined_member_count": 1, @@ -2170,7 +2171,7 @@ describe("Room", function () { it("should return undefined if we're not joined or invited to the room", () => { const room = new Room(roomId, null!, userA); expect(room.getDMInviter()).toBeUndefined(); - room.updateMyMembership("leave"); + room.updateMyMembership(KnownMembership.Leave); expect(room.getDMInviter()).toBeUndefined(); }); }); @@ -2190,7 +2191,7 @@ describe("Room", function () { await room.addLiveEvents([ utils.mkMembership({ user: userB, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, }), @@ -2220,7 +2221,7 @@ describe("Room", function () { state_key: userD, sender: userD, content: { - membership: "join", + membership: KnownMembership.Join, }, }), ]); @@ -2308,11 +2309,11 @@ describe("Room", function () { describe("maySendMessage", function () { it("should return false if synced membership not join", function () { const room = new Room(roomId, { isRoomEncrypted: () => false } as any, userA); - room.updateMyMembership(JoinRule.Invite); + room.updateMyMembership(KnownMembership.Invite); expect(room.maySendMessage()).toEqual(false); - room.updateMyMembership("leave"); + room.updateMyMembership(KnownMembership.Leave); expect(room.maySendMessage()).toEqual(false); - room.updateMyMembership("join"); + room.updateMyMembership(KnownMembership.Join); expect(room.maySendMessage()).toEqual(true); }); }); @@ -2328,14 +2329,14 @@ describe("Room", function () { await room.addLiveEvents([ utils.mkMembership({ user: userA, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User A", }), utils.mkMembership({ user: userB, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User B", @@ -2349,14 +2350,14 @@ describe("Room", function () { await room.addLiveEvents([ utils.mkMembership({ user: userA, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User A", }), utils.mkMembership({ user: userB, - mship: "ban", + mship: KnownMembership.Ban, room: roomId, event: true, name: "User B", @@ -2370,14 +2371,14 @@ describe("Room", function () { await room.addLiveEvents([ utils.mkMembership({ user: userA, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User A", }), utils.mkMembership({ user: userB, - mship: "invite", + mship: KnownMembership.Invite, room: roomId, event: true, name: "User B", @@ -2391,14 +2392,14 @@ describe("Room", function () { await room.addLiveEvents([ utils.mkMembership({ user: userA, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User A", }), utils.mkMembership({ user: userB, - mship: "leave", + mship: KnownMembership.Leave, room: roomId, event: true, name: "User B", @@ -2412,21 +2413,21 @@ describe("Room", function () { await room.addLiveEvents([ utils.mkMembership({ user: userA, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User A", }), utils.mkMembership({ user: userB, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User B", }), utils.mkMembership({ user: userC, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User C", @@ -2440,28 +2441,28 @@ describe("Room", function () { await room.addLiveEvents([ utils.mkMembership({ user: userA, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User A", }), utils.mkMembership({ user: userB, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User B", }), utils.mkMembership({ user: userC, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User C", }), utils.mkMembership({ user: userD, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User D", @@ -2477,14 +2478,14 @@ describe("Room", function () { await room.addLiveEvents([ utils.mkMembership({ user: userA, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User A", }), utils.mkMembership({ user: userB, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User B", @@ -2507,14 +2508,14 @@ describe("Room", function () { await room.addLiveEvents([ utils.mkMembership({ user: userA, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User A", }), utils.mkMembership({ user: userB, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User B", @@ -2537,14 +2538,14 @@ describe("Room", function () { await room.addLiveEvents([ utils.mkMembership({ user: userA, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User A", }), utils.mkMembership({ user: userB, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User B", @@ -2567,14 +2568,14 @@ describe("Room", function () { await room.addLiveEvents([ utils.mkMembership({ user: userA, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User A", }), utils.mkMembership({ user: userB, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User B", @@ -2597,21 +2598,21 @@ describe("Room", function () { await room.addLiveEvents([ utils.mkMembership({ user: userA, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User A", }), utils.mkMembership({ user: userB, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User B", }), utils.mkMembership({ user: userC, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User C", @@ -2635,21 +2636,21 @@ describe("Room", function () { await room.addLiveEvents([ utils.mkMembership({ user: userA, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User A", }), utils.mkMembership({ user: userB, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User B", }), utils.mkMembership({ user: userC, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User C", @@ -2673,14 +2674,14 @@ describe("Room", function () { await room.addLiveEvents([ utils.mkMembership({ user: userA, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User A", }), utils.mkMembership({ user: userB, - mship: "join", + mship: KnownMembership.Join, room: roomId, event: true, name: "User B", diff --git a/spec/unit/rust-crypto/RoomEncryptor.spec.ts b/spec/unit/rust-crypto/RoomEncryptor.spec.ts index 9094ef38e23..608d9643e05 100644 --- a/spec/unit/rust-crypto/RoomEncryptor.spec.ts +++ b/spec/unit/rust-crypto/RoomEncryptor.spec.ts @@ -30,6 +30,7 @@ import { RoomEncryptor, toRustHistoryVisibility } from "../../../src/rust-crypto import { KeyClaimManager } from "../../../src/rust-crypto/KeyClaimManager"; import { defer } from "../../../src/utils"; import { OutgoingRequestsManager } from "../../../src/rust-crypto/OutgoingRequestsManager"; +import { KnownMembership } from "../../../src/@types/membership"; describe("RoomEncryptor", () => { describe("History Visibility", () => { @@ -54,7 +55,7 @@ describe("RoomEncryptor", () => { const mockRoomMember = { userId: "@alice:example.org", - membership: "join", + membership: KnownMembership.Join, } as unknown as Mocked; function createMockEvent(text: string): Mocked { diff --git a/spec/unit/scheduler.spec.ts b/spec/unit/scheduler.spec.ts index 35d057081ac..ecdd729a928 100644 --- a/spec/unit/scheduler.spec.ts +++ b/spec/unit/scheduler.spec.ts @@ -6,6 +6,7 @@ import { MatrixError } from "../../src/http-api"; import { MatrixScheduler } from "../../src/scheduler"; import * as utils from "../test-utils/test-utils"; import { MatrixEvent } from "../../src"; +import { KnownMembership } from "../../src/@types/membership"; jest.useFakeTimers(); @@ -336,7 +337,7 @@ describe("MatrixScheduler", function () { utils.mkMembership({ user: "@alice:bar", room: roomId, - mship: "join", + mship: KnownMembership.Join, event: true, }), ), diff --git a/spec/unit/sync-accumulator.spec.ts b/spec/unit/sync-accumulator.spec.ts index d95c8d056bb..c68de970a85 100644 --- a/spec/unit/sync-accumulator.spec.ts +++ b/spec/unit/sync-accumulator.spec.ts @@ -31,6 +31,7 @@ import { } from "../../src/sync-accumulator"; import { IRoomSummary } from "../../src"; import * as utils from "../test-utils/test-utils"; +import { KnownMembership, Membership } from "../../src/@types/membership"; // The event body & unsigned object get frozen to assert that they don't get altered // by the impl @@ -95,7 +96,7 @@ describe("SyncAccumulator", function () { ephemeral: { events: [] }, unread_notifications: {}, state: { - events: [member("alice", "join"), member("bob", "join")], + events: [member("alice", KnownMembership.Join), member("bob", KnownMembership.Join)], }, summary: { "m.heroes": undefined, @@ -111,7 +112,7 @@ describe("SyncAccumulator", function () { knock: { "!knock": { knock_state: { - events: [member("alice", "knock")], + events: [member("alice", KnownMembership.Knock)], }, }, }, @@ -128,7 +129,7 @@ describe("SyncAccumulator", function () { // 10 timeline messages with a prev_batch of "pinned_to_1" sa.accumulate( syncSkeleton({ - state: { events: [member("alice", "join")] }, + state: { events: [member("alice", KnownMembership.Join)] }, timeline: { events: [ msg("alice", "1"), @@ -204,7 +205,7 @@ describe("SyncAccumulator", function () { it("should remove the stored timeline on limited syncs", () => { sa.accumulate( syncSkeleton({ - state: { events: [member("alice", "join")] }, + state: { events: [member("alice", KnownMembership.Join)] }, timeline: { events: [msg("alice", "1"), msg("alice", "2"), msg("alice", "3")], prev_batch: "pinned_to_1", @@ -312,7 +313,7 @@ describe("SyncAccumulator", function () { events: [ { content: { - membership: "invite", + membership: KnownMembership.Invite, }, state_key: "bob", sender: "alice", @@ -336,7 +337,7 @@ describe("SyncAccumulator", function () { const rejectMemberEvent: IStateEvent = { event_id: "$" + Math.random(), content: { - membership: "leave", + membership: KnownMembership.Leave, }, origin_server_ts: 123456789, state_key: "bob", @@ -344,7 +345,7 @@ describe("SyncAccumulator", function () { type: "m.room.member", unsigned: { prev_content: { - membership: "invite", + membership: KnownMembership.Invite, }, }, }; @@ -366,7 +367,7 @@ describe("SyncAccumulator", function () { it("should accumulate knock state", () => { const initKnockState = { - events: [member("alice", "knock")], + events: [member("alice", KnownMembership.Knock)], }; sa.accumulate( syncSkeleton( @@ -453,7 +454,7 @@ describe("SyncAccumulator", function () { const inviteStateEvents = [ { content: { - membership: "invite", + membership: KnownMembership.Invite, }, state_key: "bob", sender: "alice", @@ -482,7 +483,7 @@ describe("SyncAccumulator", function () { const memberEvent: IStateEvent = { event_id: "$" + Math.random(), content: { - membership: "leave", + membership: KnownMembership.Leave, }, origin_server_ts: 123456789, state_key: "bob", @@ -490,7 +491,7 @@ describe("SyncAccumulator", function () { type: "m.room.member", unsigned: { prev_content: { - membership: "knock", + membership: KnownMembership.Knock, }, }, }; @@ -528,7 +529,7 @@ describe("SyncAccumulator", function () { const memberEvent: IStateEvent = { event_id: "$" + Math.random(), content: { - membership: "leave", + membership: KnownMembership.Leave, }, origin_server_ts: 123456789, state_key: "bob", @@ -536,7 +537,7 @@ describe("SyncAccumulator", function () { type: "m.room.member", unsigned: { prev_content: { - membership: "knock", + membership: KnownMembership.Knock, }, }, }; @@ -933,7 +934,7 @@ function makeKnockState(): IKnockState { name: "Room", }, }) as IStrippedState, - member("bob", "knock"), + member("bob", KnownMembership.Knock), ], }; } @@ -950,7 +951,7 @@ function msg(localpart: string, text: string) { }; } -function member(localpart: string, membership: string) { +function member(localpart: string, membership: Membership) { return { event_id: "$" + Math.random(), content: { diff --git a/spec/unit/webrtc/groupCall.spec.ts b/spec/unit/webrtc/groupCall.spec.ts index 7723b4c17c0..ea04a1f3ed8 100644 --- a/spec/unit/webrtc/groupCall.spec.ts +++ b/spec/unit/webrtc/groupCall.spec.ts @@ -47,6 +47,7 @@ import { flushPromises } from "../../test-utils/flushPromises"; import { CallFeedReport } from "../../../src/webrtc/stats/statsReport"; import { CallFeedStatsReporter } from "../../../src/webrtc/stats/callFeedStatsReporter"; import { StatsReportEmitter } from "../../../src/webrtc/stats/statsReportEmitter"; +import { KnownMembership } from "../../../src/@types/membership"; const FAKE_STATE_EVENTS = [ { @@ -143,7 +144,7 @@ describe("Group Call", function () { groupCall = new GroupCall(mockClient, room, GroupCallType.Video, false, GroupCallIntent.Prompt); room.currentState.members[FAKE_USER_ID_1] = { userId: FAKE_USER_ID_1, - membership: "join", + membership: KnownMembership.Join, } as unknown as RoomMember; }); @@ -651,11 +652,11 @@ describe("Group Call", function () { client1Room.currentState.members[FAKE_USER_ID_1] = client2Room.currentState.members[FAKE_USER_ID_1] = { userId: FAKE_USER_ID_1, - membership: "join", + membership: KnownMembership.Join, } as unknown as RoomMember; client1Room.currentState.members[FAKE_USER_ID_2] = client2Room.currentState.members[FAKE_USER_ID_2] = { userId: FAKE_USER_ID_2, - membership: "join", + membership: KnownMembership.Join, } as unknown as RoomMember; groupCall1 = new GroupCall( @@ -831,11 +832,11 @@ describe("Group Call", function () { room.currentState.getStateEvents = jest.fn().mockImplementation(mockGetStateEvents()); room.currentState.members[FAKE_USER_ID_1] = { userId: FAKE_USER_ID_1, - membership: "join", + membership: KnownMembership.Join, } as unknown as RoomMember; room.currentState.members[FAKE_USER_ID_2] = { userId: FAKE_USER_ID_2, - membership: "join", + membership: KnownMembership.Join, } as unknown as RoomMember; }); @@ -1026,11 +1027,11 @@ describe("Group Call", function () { room = new Room(FAKE_ROOM_ID, mockClient, FAKE_USER_ID_2); room.currentState.members[FAKE_USER_ID_1] = { userId: FAKE_USER_ID_1, - membership: "join", + membership: KnownMembership.Join, } as unknown as RoomMember; room.currentState.members[FAKE_USER_ID_2] = { userId: FAKE_USER_ID_2, - membership: "join", + membership: KnownMembership.Join, } as unknown as RoomMember; groupCall = await createAndEnterGroupCall(mockClient, room); @@ -1260,11 +1261,11 @@ describe("Group Call", function () { room = new Room(FAKE_ROOM_ID, mockClient, FAKE_USER_ID_1); room.currentState.members[FAKE_USER_ID_1] = { userId: FAKE_USER_ID_1, - membership: "join", + membership: KnownMembership.Join, } as unknown as RoomMember; room.currentState.members[FAKE_USER_ID_2] = { userId: FAKE_USER_ID_2, - membership: "join", + membership: KnownMembership.Join, } as unknown as RoomMember; room.currentState.getStateEvents = jest.fn().mockImplementation(mockGetStateEvents()); @@ -1741,11 +1742,11 @@ describe("Group Call", function () { const room = new Room(FAKE_ROOM_ID, mockClient, FAKE_USER_ID_1); room.currentState.members[FAKE_USER_ID_1] = { userId: FAKE_USER_ID_1, - membership: "join", + membership: KnownMembership.Join, } as unknown as RoomMember; room.currentState.members[FAKE_USER_ID_2] = { userId: FAKE_USER_ID_2, - membership: "join", + membership: KnownMembership.Join, } as unknown as RoomMember; room.currentState.getStateEvents = jest.fn().mockImplementation(mockGetStateEvents()); groupCall = await createAndEnterGroupCall(mockClient, room); diff --git a/spec/unit/webrtc/groupCallEventHandler.spec.ts b/spec/unit/webrtc/groupCallEventHandler.spec.ts index 7fe5cb6a014..850ba403787 100644 --- a/spec/unit/webrtc/groupCallEventHandler.spec.ts +++ b/spec/unit/webrtc/groupCallEventHandler.spec.ts @@ -31,6 +31,7 @@ import { RoomState } from "../../../src/models/room-state"; import { GroupCallEventHandler, GroupCallEventHandlerEvent } from "../../../src/webrtc/groupCallEventHandler"; import { flushPromises } from "../../test-utils/flushPromises"; import { makeMockGroupCallStateEvent, MockCallMatrixClient } from "../../test-utils/webrtc"; +import { KnownMembership } from "../../../src/@types/membership"; const FAKE_USER_ID = "@alice:test.dummy"; const FAKE_DEVICE_ID = "AAAAAAA"; @@ -50,7 +51,7 @@ describe("Group Call Event Handler", function () { mockMember = { userId: FAKE_USER_ID, - membership: "join", + membership: KnownMembership.Join, } as unknown as RoomMember; const mockEvent = makeMockGroupCallStateEvent(FAKE_ROOM_ID, FAKE_GROUP_CALL_ID); diff --git a/src/@types/membership.ts b/src/@types/membership.ts new file mode 100644 index 00000000000..3d6a100ad54 --- /dev/null +++ b/src/@types/membership.ts @@ -0,0 +1,57 @@ +/* +Copyright 2024 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/** + * Well-known values (from the spec or MSCs) that are allowed in the + * {@link Membership} type. + */ +export enum KnownMembership { + /** + * The user has been banned from the room, and is no longer allowed to join + * it until they are un-banned from the room (by having their membership + * state set to a value other than ban). + */ + Ban = "ban", + /** + * The user has been invited to join a room, but has not yet joined it. + * They may not participate in the room until they join. + * */ + Invite = "invite", + /** + * The user has joined the room (possibly after accepting an invite), and + * may participate in it. + */ + Join = "join", + /** + * The user has knocked on the room, requesting permission to participate. + * They may not participate in the room until they join. + */ + Knock = "knock", + /** + * The user was once joined to the room, but has since left (possibly by + * choice, or possibly by being kicked). + */ + Leave = "leave", +} + +/** + * The membership state for a user in a room [1]. A value from + * {@link KnownMembership} should be used where available, but all string values + * are allowed to provide flexibility for upcoming spec changes or proposals. + * + * [1] https://spec.matrix.org/latest/client-server-api/#mroommember + */ +export type Membership = KnownMembership | string; diff --git a/src/client.ts b/src/client.ts index 9c85963ba76..56ec1030cd6 100644 --- a/src/client.ts +++ b/src/client.ts @@ -222,6 +222,7 @@ import { import { RegisterRequest, RegisterResponse } from "./@types/registration"; import { MatrixRTCSessionManager } from "./matrixrtc/MatrixRTCSessionManager"; import { getRelationsThreadFilter } from "./thread-utils"; +import { KnownMembership, Membership } from "./@types/membership"; export type Store = IStore; @@ -721,7 +722,7 @@ export interface IOpenIDToken { interface IRoomInitialSyncResponse { room_id: string; - membership: "invite" | "join" | "leave" | "ban"; + membership: Membership; messages?: { start?: string; end?: string; @@ -866,7 +867,7 @@ interface IThirdPartyUser { interface IRoomSummary extends Omit { room_type?: RoomType; - membership?: string; + membership?: Membership; is_encrypted: boolean; } @@ -4357,7 +4358,7 @@ export class MatrixClient extends TypedEventEmitter = Promise.resolve(); @@ -4386,7 +4387,7 @@ export class MatrixClient extends TypedEventEmitter { const room = this.getRoom(roomIdOrAlias); - if (room?.hasMembershipState(this.credentials.userId!, "knock")) { + if (room?.hasMembershipState(this.credentials.userId!, KnownMembership.Knock)) { return Promise.resolve({ room_id: room.roomId }); } @@ -5548,7 +5549,7 @@ export class MatrixClient extends TypedEventEmitter { - return this.membershipChange(roomId, userId, "invite", reason); + return this.membershipChange(roomId, userId, KnownMembership.Invite, reason); } /** @@ -5603,7 +5604,7 @@ export class MatrixClient extends TypedEventEmitter { - return this.membershipChange(roomId, undefined, "leave"); + return this.membershipChange(roomId, undefined, KnownMembership.Leave); } /** @@ -5661,7 +5662,7 @@ export class MatrixClient extends TypedEventEmitter { - return this.membershipChange(roomId, userId, "ban", reason); + return this.membershipChange(roomId, userId, KnownMembership.Ban, reason); } /** @@ -5720,7 +5721,7 @@ export class MatrixClient extends TypedEventEmitter { // API returns an empty object @@ -9780,7 +9781,7 @@ export class MatrixClient extends TypedEventEmitter } if (this.joinedMemberCount === null) { this.joinedMemberCount = this.getMembers().reduce((count, m) => { - return m.membership === "join" ? count + 1 : count; + return m.membership === KnownMembership.Join ? count + 1 : count; }, 0); } return this.joinedMemberCount; @@ -230,7 +231,7 @@ export class RoomState extends TypedEventEmitter } if (this.invitedMemberCount === null) { this.invitedMemberCount = this.getMembers().reduce((count, m) => { - return m.membership === "invite" ? count + 1 : count; + return m.membership === KnownMembership.Invite ? count + 1 : count; }, 0); } return this.invitedMemberCount; @@ -434,7 +435,10 @@ export class RoomState extends TypedEventEmitter // leave events apparently elide the displayname or avatar_url, // so let's fake one up so that we don't leak user ids // into the timeline - if (event.getContent().membership === "leave" || event.getContent().membership === "ban") { + if ( + event.getContent().membership === KnownMembership.Leave || + event.getContent().membership === KnownMembership.Ban + ) { event.getContent().avatar_url = event.getContent().avatar_url || event.getPrevContent().avatar_url; event.getContent().displayname = event.getContent().displayname || event.getPrevContent().displayname; @@ -776,7 +780,7 @@ export class RoomState extends TypedEventEmitter */ public maySendRedactionForEvent(mxEvent: MatrixEvent, userId: string): boolean { const member = this.getMember(userId); - if (!member || member.membership === "leave") return false; + if (!member || member.membership === KnownMembership.Leave) return false; if (mxEvent.status || mxEvent.isRedacted()) return false; diff --git a/src/models/room.ts b/src/models/room.ts index 7289185e6f6..c38a8dffd34 100644 --- a/src/models/room.ts +++ b/src/models/room.ts @@ -68,6 +68,7 @@ import { ReadReceipt, synthesizeReceipt } from "./read-receipt"; import { isPollEvent, Poll, PollEvent } from "./poll"; import { RoomReceipts } from "./room-receipts"; import { compareEventOrdering } from "./compare-event-ordering"; +import { KnownMembership, Membership } from "../@types/membership"; // These constants are used as sane defaults when the homeserver doesn't support // the m.room_versions capability. In practice, KNOWN_SAFE_ROOM_VERSION should be @@ -177,7 +178,7 @@ export type RoomEventHandlerMap = { * @param membership - The new membership value * @param prevMembership - The previous membership value */ - [RoomEvent.MyMembership]: (room: Room, membership: string, prevMembership?: string) => void; + [RoomEvent.MyMembership]: (room: Room, membership: Membership, prevMembership?: Membership) => void; /** * Fires whenever a room's tags are updated. * @param event - The tags event @@ -351,7 +352,7 @@ export class Room extends ReadReceipt { private readonly pendingEventList?: MatrixEvent[]; // read by megolm via getter; boolean value - null indicates "use global value" private blacklistUnverifiedDevices?: boolean; - private selfMembership?: string; + private selfMembership?: Membership; private summaryHeroes: string[] | null = null; // flags to stop logspam about missing m.room.create events private getTypeWarning = false; @@ -863,8 +864,8 @@ export class Room extends ReadReceipt { /** * @returns the membership type (join | leave | invite | knock) for the logged in user */ - public getMyMembership(): string { - return this.selfMembership ?? "leave"; + public getMyMembership(): Membership { + return this.selfMembership ?? KnownMembership.Leave; } /** @@ -878,7 +879,7 @@ export class Room extends ReadReceipt { return me.getDMInviter(); } - if (this.selfMembership === "invite") { + if (this.selfMembership === KnownMembership.Invite) { // fall back to summary information const memberCount = this.getInvitedAndJoinedMemberCount(); if (memberCount === 2) { @@ -989,11 +990,11 @@ export class Room extends ReadReceipt { * Sets the membership this room was received as during sync * @param membership - join | leave | invite */ - public updateMyMembership(membership: string): void { + public updateMyMembership(membership: Membership): void { const prevMembership = this.selfMembership; this.selfMembership = membership; if (prevMembership !== membership) { - if (membership === "leave") { + if (membership === KnownMembership.Leave) { this.cleanupAfterLeaving(); } this.emit(RoomEvent.MyMembership, this, membership, prevMembership); @@ -1002,7 +1003,12 @@ export class Room extends ReadReceipt { private async loadMembersFromServer(): Promise { const lastSyncToken = this.client.store.getSyncToken(); - const response = await this.client.members(this.roomId, undefined, "leave", lastSyncToken ?? undefined); + const response = await this.client.members( + this.roomId, + undefined, + KnownMembership.Leave, + lastSyncToken ?? undefined, + ); return response.chunk; } @@ -1709,7 +1715,7 @@ export class Room extends ReadReceipt { * @returns A list of currently joined members. */ public getJoinedMembers(): RoomMember[] { - return this.getMembersWithMembership("join"); + return this.getMembersWithMembership(KnownMembership.Join); } /** @@ -1744,7 +1750,7 @@ export class Room extends ReadReceipt { * @param membership - The membership state. * @returns A list of members with the given membership state. */ - public getMembersWithMembership(membership: string): RoomMember[] { + public getMembersWithMembership(membership: Membership): RoomMember[] { return this.currentState.getMembers().filter(function (m) { return m.membership === membership; }); @@ -1757,9 +1763,9 @@ export class Room extends ReadReceipt { */ public async getEncryptionTargetMembers(): Promise { await this.loadMembersIfNeeded(); - let members = this.getMembersWithMembership("join"); + let members = this.getMembersWithMembership(KnownMembership.Join); if (this.shouldEncryptForInvitedMembers()) { - members = members.concat(this.getMembersWithMembership("invite")); + members = members.concat(this.getMembersWithMembership(KnownMembership.Invite)); } return members; } @@ -1790,7 +1796,7 @@ export class Room extends ReadReceipt { * @param membership - The membership e.g. `'join'` * @returns True if this user_id has the given membership state. */ - public hasMembershipState(userId: string, membership: string): boolean { + public hasMembershipState(userId: string, membership: Membership): boolean { const member = this.getMember(userId); if (!member) { return false; @@ -3119,7 +3125,7 @@ export class Room extends ReadReceipt { const membership = membershipEvent.getContent().membership; this.updateMyMembership(membership!); - if (membership === "invite") { + if (membership === KnownMembership.Invite) { const strippedStateEvents = membershipEvent.getUnsigned().invite_room_state || []; strippedStateEvents.forEach((strippedEvent) => { const existingEvent = this.currentState.getStateEvents(strippedEvent.type, strippedEvent.state_key); @@ -3205,7 +3211,7 @@ export class Room extends ReadReceipt { */ public maySendMessage(): boolean { return ( - this.getMyMembership() === "join" && + this.getMyMembership() === KnownMembership.Join && (this.hasEncryptionStateEvent() ? this.currentState.maySendEvent(EventType.RoomMessageEncrypted, this.myUserId) : this.currentState.maySendEvent(EventType.RoomMessage, this.myUserId)) @@ -3218,7 +3224,7 @@ export class Room extends ReadReceipt { * @returns true if the user should be permitted to issue invites for this room. */ public canInvite(userId: string): boolean { - let canInvite = this.getMyMembership() === "join"; + let canInvite = this.getMyMembership() === KnownMembership.Join; const powerLevelsEvent = this.currentState.getStateEvents(EventType.RoomPowerLevels, ""); const powerLevels = powerLevelsEvent && powerLevelsEvent.getContent(); const me = this.getMember(userId); @@ -3400,7 +3406,10 @@ export class Room extends ReadReceipt { }); } else { let otherMembers = this.currentState.getMembers().filter((m) => { - return m.userId !== userId && (m.membership === "invite" || m.membership === "join"); + return ( + m.userId !== userId && + (m.membership === KnownMembership.Invite || m.membership === KnownMembership.Join) + ); }); otherMembers = otherMembers.filter(({ userId }) => { // filter service members @@ -3428,7 +3437,7 @@ export class Room extends ReadReceipt { const myMembership = this.getMyMembership(); // if I have created a room and invited people through // 3rd party invites - if (myMembership == "join") { + if (myMembership == KnownMembership.Join) { const thirdPartyInvites = this.currentState.getStateEvents(EventType.RoomThirdPartyInvite); if (thirdPartyInvites?.length) { @@ -3452,7 +3461,11 @@ export class Room extends ReadReceipt { leftNames = this.currentState .getMembers() .filter((m) => { - return m.userId !== userId && m.membership !== "invite" && m.membership !== "join"; + return ( + m.userId !== userId && + m.membership !== KnownMembership.Invite && + m.membership !== KnownMembership.Join + ); }) .map((m) => m.name); } diff --git a/src/rust-crypto/RoomEncryptor.ts b/src/rust-crypto/RoomEncryptor.ts index 2de00f19b34..7447ae61a74 100644 --- a/src/rust-crypto/RoomEncryptor.ts +++ b/src/rust-crypto/RoomEncryptor.ts @@ -34,6 +34,7 @@ import { RoomMember } from "../models/room-member"; import { HistoryVisibility } from "../@types/partials"; import { OutgoingRequestsManager } from "./OutgoingRequestsManager"; import { logDuration } from "../utils"; +import { KnownMembership } from "../@types/membership"; /** * RoomEncryptor: responsible for encrypting messages to a given room @@ -100,8 +101,8 @@ export class RoomEncryptor { */ public onRoomMembership(member: RoomMember): void { if ( - member.membership == "join" || - (member.membership == "invite" && this.room.shouldEncryptForInvitedMembers()) + member.membership == KnownMembership.Join || + (member.membership == KnownMembership.Invite && this.room.shouldEncryptForInvitedMembers()) ) { // make sure we are tracking the deviceList for this user logDuration(this.prefixedLogger, "updateTrackedUsers", async () => { diff --git a/src/sliding-sync-sdk.ts b/src/sliding-sync-sdk.ts index e5a371e1407..4a99cc4e72b 100644 --- a/src/sliding-sync-sdk.ts +++ b/src/sliding-sync-sdk.ts @@ -46,6 +46,7 @@ import { EventType } from "./@types/event"; import { IPushRules } from "./@types/PushRules"; import { RoomStateEvent } from "./models/room-state"; import { RoomMemberEvent } from "./models/room-member"; +import { KnownMembership } from "./@types/membership"; // Number of consecutive failed syncs that will lead to a syncState of ERROR as opposed // to RECONNECTING. This is needed to inform the client of server issues when the @@ -649,7 +650,7 @@ export class SlidingSyncSdk { inviteStateEvents.forEach((e) => { this.client.emit(ClientEvent.Event, e); }); - room.updateMyMembership("invite"); + room.updateMyMembership(KnownMembership.Invite); return; } @@ -719,7 +720,7 @@ export class SlidingSyncSdk { // local fields must be set before any async calls because call site assumes // synchronous execution prior to emitting SlidingSyncState.Complete - room.updateMyMembership("join"); + room.updateMyMembership(KnownMembership.Join); room.recalculate(); if (roomData.initial) { @@ -845,7 +846,7 @@ export class SlidingSyncSdk { const client = this.client; // For each invited room member we want to give them a displayname/avatar url // if they have one (the m.room.member invites don't contain this). - room.getMembersWithMembership("invite").forEach(function (member) { + room.getMembersWithMembership(KnownMembership.Invite).forEach(function (member) { if (member.requestedProfileInfo) return; member.requestedProfileInfo = true; // try to get a cached copy first. @@ -865,7 +866,7 @@ export class SlidingSyncSdk { // the code paths remain the same between invite/join display name stuff // which is a worthy trade-off for some minor pollution. const inviteEvent = member.events.member!; - if (inviteEvent.getContent().membership !== "invite") { + if (inviteEvent.getContent().membership !== KnownMembership.Invite) { // between resolving and now they have since joined, so don't clobber return; } diff --git a/src/store/memory.ts b/src/store/memory.ts index 8eeb53b85b2..7251be1c6b5 100644 --- a/src/store/memory.ts +++ b/src/store/memory.ts @@ -32,6 +32,7 @@ import { IStateEventWithRoomId } from "../@types/search"; import { IndexedToDeviceBatch, ToDeviceBatchWithTxnId } from "../models/ToDeviceMessage"; import { IStoredClientOpts } from "../client"; import { MapWithDefault } from "../utils"; +import { KnownMembership } from "../@types/membership"; function isValidFilterId(filterId?: string | number | null): boolean { const isValidStr = @@ -118,7 +119,7 @@ export class MemoryStore implements IStore { * updated. */ private onRoomMember = (event: MatrixEvent | null, state: RoomState, member: RoomMember): void => { - if (member.membership === "invite") { + if (member.membership === KnownMembership.Invite) { // We do NOT add invited members because people love to typo user IDs // which would then show up in these lists (!) return; diff --git a/src/sync.ts b/src/sync.ts index 372260d5615..8fe60698e9b 100644 --- a/src/sync.ts +++ b/src/sync.ts @@ -61,6 +61,7 @@ import { IEventsResponse } from "./@types/requests"; import { UNREAD_THREAD_NOTIFICATIONS } from "./@types/sync"; import { Feature, ServerSupport } from "./feature"; import { Crypto } from "./crypto"; +import { KnownMembership } from "./@types/membership"; const DEBUG = true; @@ -1720,7 +1721,7 @@ export class SyncApi { const client = this.client; // For each invited room member we want to give them a displayname/avatar url // if they have one (the m.room.member invites don't contain this). - room.getMembersWithMembership("invite").forEach(function (member) { + room.getMembersWithMembership(KnownMembership.Invite).forEach(function (member) { if (member.requestedProfileInfo) return; member.requestedProfileInfo = true; // try to get a cached copy first. @@ -1740,7 +1741,7 @@ export class SyncApi { // the code paths remain the same between invite/join display name stuff // which is a worthy trade-off for some minor pollution. const inviteEvent = member.events.member; - if (inviteEvent?.getContent().membership !== "invite") { + if (inviteEvent?.getContent().membership !== KnownMembership.Invite) { // between resolving and now they have since joined, so don't clobber return; } diff --git a/src/types.ts b/src/types.ts index dd2d3bef894..1edb3979564 100644 --- a/src/types.ts +++ b/src/types.ts @@ -22,3 +22,4 @@ limitations under the License. */ export type * from "./@types/media"; +export * from "./@types/membership"; diff --git a/src/webrtc/groupCall.ts b/src/webrtc/groupCall.ts index 362db27a25d..e5711986894 100644 --- a/src/webrtc/groupCall.ts +++ b/src/webrtc/groupCall.ts @@ -34,6 +34,7 @@ import { } from "./stats/statsReport"; import { SummaryStatsReportGatherer } from "./stats/summaryStatsReportGatherer"; import { CallFeedStatsReporter } from "./stats/callFeedStatsReporter"; +import { KnownMembership } from "../@types/membership"; export enum GroupCallIntent { Ring = "m.ring", @@ -1485,7 +1486,7 @@ export class GroupCall extends TypedEventEmitter< } // Must have a connected device and be joined to the room - if (validDevices.length > 0 && member?.membership === "join") { + if (validDevices.length > 0 && member?.membership === KnownMembership.Join) { const deviceMap = new Map(); participants.set(member, deviceMap);