From f17ecba5191027147e9199717ebf61c144f1f65a Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Wed, 15 May 2019 13:42:06 +0100 Subject: [PATCH] Add `getRelation` helper This adds a `getRelation` helper to ensure we always read relation info from the wire content as required in E2E rooms. --- src/models/event-timeline-set.js | 5 ++--- src/models/event.js | 30 ++++++++++++++++++++---------- src/models/relations.js | 8 +++----- src/models/room.js | 2 +- 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/models/event-timeline-set.js b/src/models/event-timeline-set.js index d9cc15ce4..3295359f7 100644 --- a/src/models/event-timeline-set.js +++ b/src/models/event-timeline-set.js @@ -719,9 +719,8 @@ EventTimelineSet.prototype._aggregateRelations = function(event) { return; } - const content = event.getContent(); - const relation = content && content["m.relates_to"]; - if (!relation || !relation.rel_type || !relation.event_id) { + const relation = event.getRelation(); + if (!relation) { return; } diff --git a/src/models/event.js b/src/models/event.js index 41ddbc12c..c6829cfac 100644 --- a/src/models/event.js +++ b/src/models/event.js @@ -735,20 +735,34 @@ utils.extend(module.exports.MatrixEvent.prototype, { }, /** - * Get whether the event is a relation event, and of a given type if `relType` is passed in. + * Get whether the event is a relation event, and of a given type if + * `relType` is passed in. * - * @param {string?} relType if given, checks that the relation is of the given type + * @param {string?} relType if given, checks that the relation is of the + * given type * @return {boolean} */ isRelation(relType = undefined) { - // must use event.content as m.relates_to is not encrypted - // and _clearEvent doesn't have it. - const content = this.event.content; + // Relation info is lifted out of the encrypted content when sent to + // encrypted rooms, so we have to check `getWireContent` for this. + const content = this.getWireContent(); const relation = content && content["m.relates_to"]; return relation && relation.rel_type && relation.event_id && ((relType && relation.rel_type === relType) || !relType); }, + /** + * Get relation info for the event, if any. + * + * @return {Object} + */ + getRelation() { + if (!this.isRelation()) { + return null; + } + return this.getWireContent()["m.relates_to"]; + }, + /** * Set an event that replaces the content of this event, through an m.replace relation. * @@ -768,11 +782,7 @@ utils.extend(module.exports.MatrixEvent.prototype, { } const oldContent = this.getContent(); const newContent = newEvent.getContent()["m.new_content"]; - // need to always replace m.relates_to with the old one, - // even if there is none, as the m.replace relation should - // not be exposed on the target event m.relates_to (that's what the server does). - Object.assign(oldContent, newContent, - {"m.relates_to": oldContent["m.relates_to"]}); + Object.assign(oldContent, newContent); this._replacingEvent = newEvent; }, diff --git a/src/models/relations.js b/src/models/relations.js index 52193b028..a74e65bf8 100644 --- a/src/models/relations.js +++ b/src/models/relations.js @@ -52,9 +52,8 @@ export default class Relations extends EventEmitter { * The new relation event to be aggregated. */ addEvent(event) { - const content = event.getContent(); - const relation = content && content["m.relates_to"]; - if (!relation || !relation.rel_type || !relation.event_id) { + const relation = event.getRelation(); + if (!relation) { console.error("Event must have relation info"); return; } @@ -139,8 +138,7 @@ export default class Relations extends EventEmitter { if (this.relationType === "m.annotation") { // Remove the redacted annotation from aggregation by key - const content = redactedEvent.getContent(); - const relation = content && content["m.relates_to"]; + const relation = redactedEvent.getRelation(); if (!relation) { return; } diff --git a/src/models/room.js b/src/models/room.js index 471967549..b09e34944 100644 --- a/src/models/room.js +++ b/src/models/room.js @@ -1034,7 +1034,7 @@ Room.prototype._addLiveEvent = function(event, duplicateStrategy) { if (this._opts.unstableClientRelationReplacements && event.isRelation("m.replace")) { - const relatesTo = event.getContent()["m.relates_to"]; + const relatesTo = event.getRelation(); const replacedId = relatesTo && relatesTo.event_id; const replacedEvent = this.getUnfilteredTimelineSet().findEventById(replacedId); if (replacedEvent) {