You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-07-31 15:24:23 +03:00
Delete knocked room when knock membership changes (#3729)
* Store leave state when knock is denied Signed-off-by: Mikhail Aheichyk <mikhail.aheichyk@nordeck.net> * Delete knocked room when knock request is cancelled or denied Signed-off-by: Mikhail Aheichyk <mikhail.aheichyk@nordeck.net> * Test is updated Signed-off-by: Mikhail Aheichyk <mikhail.aheichyk@nordeck.net> --------- Signed-off-by: Mikhail Aheichyk <mikhail.aheichyk@nordeck.net> Co-authored-by: Mikhail Aheichyk <mikhail.aheichyk@nordeck.net>
This commit is contained in:
@ -16,7 +16,19 @@ limitations under the License.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { ReceiptType } from "../../src/@types/read_receipts";
|
import { ReceiptType } from "../../src/@types/read_receipts";
|
||||||
import { IJoinedRoom, IKnockedRoom, IStrippedState, ISyncResponse, SyncAccumulator } from "../../src/sync-accumulator";
|
import {
|
||||||
|
IJoinedRoom,
|
||||||
|
IInvitedRoom,
|
||||||
|
IKnockedRoom,
|
||||||
|
IKnockState,
|
||||||
|
ILeftRoom,
|
||||||
|
IRoomEvent,
|
||||||
|
IStateEvent,
|
||||||
|
IStrippedState,
|
||||||
|
ISyncResponse,
|
||||||
|
SyncAccumulator,
|
||||||
|
IInviteState,
|
||||||
|
} from "../../src/sync-accumulator";
|
||||||
import { IRoomSummary } from "../../src";
|
import { IRoomSummary } from "../../src";
|
||||||
import * as utils from "../test-utils/test-utils";
|
import * as utils from "../test-utils/test-utils";
|
||||||
|
|
||||||
@ -295,12 +307,71 @@ describe("SyncAccumulator", function () {
|
|||||||
expect(sa.getJSON().accountData[0]).toEqual(acc2);
|
expect(sa.getJSON().accountData[0]).toEqual(acc2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should delete invite room when invite request is rejected", () => {
|
||||||
|
const initInviteState: IInviteState = {
|
||||||
|
events: [
|
||||||
|
{
|
||||||
|
content: {
|
||||||
|
membership: "invite",
|
||||||
|
},
|
||||||
|
state_key: "bob",
|
||||||
|
sender: "alice",
|
||||||
|
type: "m.room.member",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
sa.accumulate(
|
||||||
|
syncSkeleton(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
"!invite:bar": {
|
||||||
|
invite_state: initInviteState,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(sa.getJSON().roomsData.invite["!invite:bar"].invite_state).toBe(initInviteState);
|
||||||
|
|
||||||
|
const rejectMemberEvent: IStateEvent = {
|
||||||
|
event_id: "$" + Math.random(),
|
||||||
|
content: {
|
||||||
|
membership: "leave",
|
||||||
|
},
|
||||||
|
origin_server_ts: 123456789,
|
||||||
|
state_key: "bob",
|
||||||
|
sender: "bob",
|
||||||
|
type: "m.room.member",
|
||||||
|
unsigned: {
|
||||||
|
prev_content: {
|
||||||
|
membership: "invite",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const leftRoomState = leftRoomSkeleton([rejectMemberEvent]);
|
||||||
|
|
||||||
|
// bob rejects invite
|
||||||
|
sa.accumulate(
|
||||||
|
syncSkeleton(
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
"!invite:bar": leftRoomState,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(sa.getJSON().roomsData.invite["!invite:bar"]).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
it("should accumulate knock state", () => {
|
it("should accumulate knock state", () => {
|
||||||
const initKnockState = {
|
const initKnockState = {
|
||||||
events: [member("alice", "knock")],
|
events: [member("alice", "knock")],
|
||||||
};
|
};
|
||||||
sa.accumulate(
|
sa.accumulate(
|
||||||
syncSkeleton(
|
syncSkeleton(
|
||||||
|
{},
|
||||||
|
{},
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
knock_state: initKnockState,
|
knock_state: initKnockState,
|
||||||
@ -311,6 +382,8 @@ describe("SyncAccumulator", function () {
|
|||||||
|
|
||||||
sa.accumulate(
|
sa.accumulate(
|
||||||
syncSkeleton(
|
syncSkeleton(
|
||||||
|
{},
|
||||||
|
{},
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
knock_state: {
|
knock_state: {
|
||||||
@ -336,6 +409,8 @@ describe("SyncAccumulator", function () {
|
|||||||
|
|
||||||
sa.accumulate(
|
sa.accumulate(
|
||||||
syncSkeleton(
|
syncSkeleton(
|
||||||
|
{},
|
||||||
|
{},
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
knock_state: {
|
knock_state: {
|
||||||
@ -360,6 +435,140 @@ describe("SyncAccumulator", function () {
|
|||||||
).toEqual("Room 2");
|
).toEqual("Room 2");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should delete knocked room when knock request is approved", () => {
|
||||||
|
const initKnockState = makeKnockState();
|
||||||
|
sa.accumulate(
|
||||||
|
syncSkeleton(
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
knock_state: initKnockState,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(sa.getJSON().roomsData.knock["!knock:bar"].knock_state).toBe(initKnockState);
|
||||||
|
|
||||||
|
// alice approves bob's knock request
|
||||||
|
const inviteStateEvents = [
|
||||||
|
{
|
||||||
|
content: {
|
||||||
|
membership: "invite",
|
||||||
|
},
|
||||||
|
state_key: "bob",
|
||||||
|
sender: "alice",
|
||||||
|
type: "m.room.member",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
sa.accumulate(
|
||||||
|
syncSkeleton(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
"!knock:bar": {
|
||||||
|
invite_state: {
|
||||||
|
events: inviteStateEvents,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(sa.getJSON().roomsData.knock["!knock:bar"]).toBeUndefined();
|
||||||
|
expect(sa.getJSON().roomsData.invite["!knock:bar"].invite_state.events).toEqual(inviteStateEvents);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should delete knocked room when knock request is cancelled by user himself", () => {
|
||||||
|
// bob cancels his knock state
|
||||||
|
const memberEvent: IStateEvent = {
|
||||||
|
event_id: "$" + Math.random(),
|
||||||
|
content: {
|
||||||
|
membership: "leave",
|
||||||
|
},
|
||||||
|
origin_server_ts: 123456789,
|
||||||
|
state_key: "bob",
|
||||||
|
sender: "bob",
|
||||||
|
type: "m.room.member",
|
||||||
|
unsigned: {
|
||||||
|
prev_content: {
|
||||||
|
membership: "knock",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const leftRoomState = leftRoomSkeleton([memberEvent]);
|
||||||
|
|
||||||
|
const initKnockState = makeKnockState();
|
||||||
|
sa.accumulate(
|
||||||
|
syncSkeleton(
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
knock_state: initKnockState,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(sa.getJSON().roomsData.knock["!knock:bar"].knock_state).toBe(initKnockState);
|
||||||
|
|
||||||
|
// bob cancels his knock request
|
||||||
|
sa.accumulate(
|
||||||
|
syncSkeleton(
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
"!knock:bar": leftRoomState,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(sa.getJSON().roomsData.knock["!knock:bar"]).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should delete knocked room when knock request is denied by another user", () => {
|
||||||
|
// alice denies bob knock state
|
||||||
|
const memberEvent: IStateEvent = {
|
||||||
|
event_id: "$" + Math.random(),
|
||||||
|
content: {
|
||||||
|
membership: "leave",
|
||||||
|
},
|
||||||
|
origin_server_ts: 123456789,
|
||||||
|
state_key: "bob",
|
||||||
|
sender: "alice",
|
||||||
|
type: "m.room.member",
|
||||||
|
unsigned: {
|
||||||
|
prev_content: {
|
||||||
|
membership: "knock",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const leftRoomState = leftRoomSkeleton([memberEvent]);
|
||||||
|
|
||||||
|
const initKnockState = makeKnockState();
|
||||||
|
sa.accumulate(
|
||||||
|
syncSkeleton(
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
knock_state: initKnockState,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(sa.getJSON().roomsData.knock["!knock:bar"].knock_state).toBe(initKnockState);
|
||||||
|
|
||||||
|
// alice denies bob's knock request
|
||||||
|
sa.accumulate(
|
||||||
|
syncSkeleton(
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
"!knock:bar": leftRoomState,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(sa.getJSON().roomsData.knock["!knock:bar"]).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
it("should accumulate read receipts", () => {
|
it("should accumulate read receipts", () => {
|
||||||
const receipt1 = {
|
const receipt1 = {
|
||||||
type: "m.receipt",
|
type: "m.receipt",
|
||||||
@ -674,7 +883,12 @@ describe("SyncAccumulator", function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function syncSkeleton(joinObj: Partial<IJoinedRoom>, knockObj?: Partial<IKnockedRoom>): ISyncResponse {
|
function syncSkeleton(
|
||||||
|
joinObj: Partial<IJoinedRoom>,
|
||||||
|
invite?: Record<string, IInvitedRoom>,
|
||||||
|
leave?: Record<string, ILeftRoom>,
|
||||||
|
knockObj?: Partial<IKnockedRoom>,
|
||||||
|
): ISyncResponse {
|
||||||
joinObj = joinObj || {};
|
joinObj = joinObj || {};
|
||||||
return {
|
return {
|
||||||
next_batch: "abc",
|
next_batch: "abc",
|
||||||
@ -682,6 +896,8 @@ function syncSkeleton(joinObj: Partial<IJoinedRoom>, knockObj?: Partial<IKnocked
|
|||||||
join: {
|
join: {
|
||||||
"!foo:bar": joinObj,
|
"!foo:bar": joinObj,
|
||||||
},
|
},
|
||||||
|
invite,
|
||||||
|
leave,
|
||||||
knock: knockObj
|
knock: knockObj
|
||||||
? {
|
? {
|
||||||
"!knock:bar": knockObj,
|
"!knock:bar": knockObj,
|
||||||
@ -691,6 +907,37 @@ function syncSkeleton(joinObj: Partial<IJoinedRoom>, knockObj?: Partial<IKnocked
|
|||||||
} as unknown as ISyncResponse;
|
} as unknown as ISyncResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function leftRoomSkeleton(timelineEvents: Array<IRoomEvent | IStateEvent> = []): ILeftRoom {
|
||||||
|
return {
|
||||||
|
state: {
|
||||||
|
events: [],
|
||||||
|
},
|
||||||
|
timeline: {
|
||||||
|
events: timelineEvents,
|
||||||
|
prev_batch: "something",
|
||||||
|
},
|
||||||
|
account_data: {
|
||||||
|
events: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeKnockState(): IKnockState {
|
||||||
|
return {
|
||||||
|
events: [
|
||||||
|
utils.mkEvent({
|
||||||
|
user: "alice",
|
||||||
|
room: "!knock:bar",
|
||||||
|
type: "m.room.name",
|
||||||
|
content: {
|
||||||
|
name: "Room",
|
||||||
|
},
|
||||||
|
}) as IStrippedState,
|
||||||
|
member("bob", "knock"),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function msg(localpart: string, text: string) {
|
function msg(localpart: string, text: string) {
|
||||||
return {
|
return {
|
||||||
event_id: "$" + Math.random(),
|
event_id: "$" + Math.random(),
|
||||||
|
@ -283,6 +283,10 @@ export class SyncAccumulator {
|
|||||||
// * equivalent to "no state"
|
// * equivalent to "no state"
|
||||||
switch (category) {
|
switch (category) {
|
||||||
case Category.Invite: // (5)
|
case Category.Invite: // (5)
|
||||||
|
if (this.knockRooms[roomId]) {
|
||||||
|
// was previously knock, now invite, need to delete knock state
|
||||||
|
delete this.knockRooms[roomId];
|
||||||
|
}
|
||||||
this.accumulateInviteState(roomId, data as IInvitedRoom);
|
this.accumulateInviteState(roomId, data as IInvitedRoom);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -303,7 +307,10 @@ export class SyncAccumulator {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Category.Leave:
|
case Category.Leave:
|
||||||
if (this.inviteRooms[roomId]) {
|
if (this.knockRooms[roomId]) {
|
||||||
|
// delete knock state on leave
|
||||||
|
delete this.knockRooms[roomId];
|
||||||
|
} else if (this.inviteRooms[roomId]) {
|
||||||
// (4)
|
// (4)
|
||||||
delete this.inviteRooms[roomId];
|
delete this.inviteRooms[roomId];
|
||||||
} else {
|
} else {
|
||||||
|
Reference in New Issue
Block a user