1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-07-30 04:23:07 +03:00

Fix issue with sentinels being incorrect on m.room.member events (#4609)

* Fix issue with sentinels being incorrect on m.room.member events

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Simplify change

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Add test

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski
2025-01-10 10:16:45 +00:00
committed by GitHub
parent 5b85ae491e
commit 1da26b5cd1
4 changed files with 77 additions and 24 deletions

View File

@ -23,6 +23,7 @@ import {
EventTimelineSet, EventTimelineSet,
EventType, EventType,
Filter, Filter,
KnownMembership,
MatrixClient, MatrixClient,
MatrixEvent, MatrixEvent,
MatrixEventEvent, MatrixEventEvent,
@ -138,6 +139,31 @@ describe("EventTimelineSet", () => {
expect(eventsInLiveTimeline.length).toStrictEqual(1); expect(eventsInLiveTimeline.length).toStrictEqual(1);
expect(eventsInLiveTimeline[0]).toStrictEqual(duplicateMessageEvent); expect(eventsInLiveTimeline[0]).toStrictEqual(duplicateMessageEvent);
}); });
it("should set event.target after applying the membership state update", () => {
const eventTimelineSet = room.getUnfilteredTimelineSet();
const ev1 = utils.mkMembership({
room: roomId,
mship: KnownMembership.Invite,
user: "@sender:server",
skey: userA,
event: true,
});
const ev2 = utils.mkMembership({
room: roomId,
mship: KnownMembership.Join,
user: userA,
skey: userA,
name: "This is my displayname",
event: true,
});
eventTimelineSet.addLiveEvent(ev1, { addToState: true });
expect(ev1.target?.name).toBe(userA);
eventTimelineSet.addLiveEvent(ev2, { addToState: true });
expect(ev2.target?.name).toBe("This is my displayname");
});
}); });
describe("addEventToTimeline", () => { describe("addEventToTimeline", () => {

View File

@ -7348,10 +7348,8 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
const sr = SearchResult.fromJson(roomEvents.results![i], mapper); const sr = SearchResult.fromJson(roomEvents.results![i], mapper);
const room = this.getRoom(sr.context.getEvent().getRoomId()); const room = this.getRoom(sr.context.getEvent().getRoomId());
if (room) { if (room) {
// Copy over a known event sender if we can
for (const ev of sr.context.getTimeline()) { for (const ev of sr.context.getTimeline()) {
const sender = room.getMember(ev.getSender()!); ev.setMetadata(room.currentState, false);
if (!ev.sender && sender) ev.sender = sender;
} }
} }
searchResults.results.push(sr); searchResults.results.push(sr);

View File

@ -68,27 +68,7 @@ export class EventTimeline {
* @param toStartOfTimeline - if true the event's forwardLooking flag is set false * @param toStartOfTimeline - if true the event's forwardLooking flag is set false
*/ */
public static setEventMetadata(event: MatrixEvent, stateContext: RoomState, toStartOfTimeline: boolean): void { public static setEventMetadata(event: MatrixEvent, stateContext: RoomState, toStartOfTimeline: boolean): void {
// When we try to generate a sentinel member before we have that member event.setMetadata(stateContext, toStartOfTimeline);
// in the members object, we still generate a sentinel but it doesn't
// have a membership event, so test to see if events.member is set. We
// check this to avoid overriding non-sentinel members by sentinel ones
// when adding the event to a filtered timeline
if (!event.sender?.events?.member) {
event.sender = stateContext.getSentinelMember(event.getSender()!);
}
if (!event.target?.events?.member && event.getType() === EventType.RoomMember) {
event.target = stateContext.getSentinelMember(event.getStateKey()!);
}
if (event.isState()) {
// room state has no concept of 'old' or 'current', but we want the
// room state to regress back to previous values if toStartOfTimeline
// is set, which means inspecting prev_content if it exists. This
// is done by toggling the forwardLooking flag.
if (toStartOfTimeline) {
event.forwardLooking = false;
}
}
} }
private readonly roomId: string | null; private readonly roomId: string | null;

View File

@ -48,6 +48,7 @@ import { Room } from "./room.ts";
import { EventTimeline } from "./event-timeline.ts"; import { EventTimeline } from "./event-timeline.ts";
import { Membership } from "../@types/membership.ts"; import { Membership } from "../@types/membership.ts";
import { DecryptionFailureCode } from "../crypto-api/index.ts"; import { DecryptionFailureCode } from "../crypto-api/index.ts";
import { RoomState } from "./room-state.ts";
export { EventStatus } from "./event-status.ts"; export { EventStatus } from "./event-status.ts";
@ -232,6 +233,7 @@ export enum MatrixEventEvent {
Status = "Event.status", Status = "Event.status",
Replaced = "Event.replaced", Replaced = "Event.replaced",
RelationsCreated = "Event.relationsCreated", RelationsCreated = "Event.relationsCreated",
SentinelUpdated = "Event.sentinelUpdated",
} }
export type MatrixEventEmittedEvents = MatrixEventEvent | ThreadEvent.Update; export type MatrixEventEmittedEvents = MatrixEventEvent | ThreadEvent.Update;
@ -244,6 +246,7 @@ export type MatrixEventHandlerMap = {
[MatrixEventEvent.Status]: (event: MatrixEvent, status: EventStatus | null) => void; [MatrixEventEvent.Status]: (event: MatrixEvent, status: EventStatus | null) => void;
[MatrixEventEvent.Replaced]: (event: MatrixEvent) => void; [MatrixEventEvent.Replaced]: (event: MatrixEvent) => void;
[MatrixEventEvent.RelationsCreated]: (relationType: string, eventType: string) => void; [MatrixEventEvent.RelationsCreated]: (relationType: string, eventType: string) => void;
[MatrixEventEvent.SentinelUpdated]: () => void;
} & Pick<ThreadEventHandlerMap, ThreadEvent.Update>; } & Pick<ThreadEventHandlerMap, ThreadEvent.Update>;
export class MatrixEvent extends TypedEventEmitter<MatrixEventEmittedEvents, MatrixEventHandlerMap> { export class MatrixEvent extends TypedEventEmitter<MatrixEventEmittedEvents, MatrixEventHandlerMap> {
@ -328,6 +331,7 @@ export class MatrixEvent extends TypedEventEmitter<MatrixEventEmittedEvents, Mat
* Should be read-only * Should be read-only
*/ */
public sender: RoomMember | null = null; public sender: RoomMember | null = null;
/** /**
* The room member who is the target of this event, e.g. * The room member who is the target of this event, e.g.
* the invitee, the person being banned, etc. * the invitee, the person being banned, etc.
@ -335,6 +339,51 @@ export class MatrixEvent extends TypedEventEmitter<MatrixEventEmittedEvents, Mat
* Should be read-only * Should be read-only
*/ */
public target: RoomMember | null = null; public target: RoomMember | null = null;
/**
* Update the sentinels and forwardLooking flag for this event.
* @param stateContext - the room state to be queried
* @param toStartOfTimeline - if true the event's forwardLooking flag is set false
* @internal
*/
public setMetadata(stateContext: RoomState, toStartOfTimeline: boolean): void {
// If an event is an m.room.member state event then we should set the sentinels again in case setEventMetadata
// was already called before the state was applied and thus the sentinel points at the member from before this event.
const affectsSelf =
this.isState() && this.getType() === EventType.RoomMember && this.getSender() === this.getStateKey();
let changed = false;
// When we try to generate a sentinel member before we have that member
// in the members object, we still generate a sentinel but it doesn't
// have a membership event, so test to see if events.member is set. We
// check this to avoid overriding non-sentinel members by sentinel ones
// when adding the event to a filtered timeline
if (affectsSelf || !this.sender?.events?.member) {
const newSender = stateContext.getSentinelMember(this.getSender()!);
if (newSender !== this.sender) changed = true;
this.sender = newSender;
}
if (affectsSelf || (!this.target?.events?.member && this.getType() === EventType.RoomMember)) {
const newTarget = stateContext.getSentinelMember(this.getStateKey()!);
if (newTarget !== this.target) changed = true;
this.target = newTarget;
}
if (this.isState()) {
// room state has no concept of 'old' or 'current', but we want the
// room state to regress back to previous values if toStartOfTimeline
// is set, which means inspecting prev_content if it exists. This
// is done by toggling the forwardLooking flag.
if (toStartOfTimeline) {
this.forwardLooking = false;
}
}
if (changed) {
this.emit(MatrixEventEvent.SentinelUpdated);
}
}
/** /**
* The sending status of the event. * The sending status of the event.
* @privateRemarks * @privateRemarks