Decrypt relations before applying them to target event (#1696)
This commit is contained in:
+21
-1
@@ -5566,7 +5566,7 @@ function _PojoToMatrixEventMapper(client, options = {}) {
|
||||
]);
|
||||
}
|
||||
if (decrypt) {
|
||||
event.attemptDecryption(client._crypto);
|
||||
client.decryptEventIfNeeded(event);
|
||||
}
|
||||
}
|
||||
if (!preventReEmit) {
|
||||
@@ -5608,6 +5608,26 @@ MatrixClient.prototype.generateClientSecret = function() {
|
||||
return randomString(32);
|
||||
};
|
||||
|
||||
/**
|
||||
* Attempts to decrypt an event
|
||||
* @param {MatrixEvent} event The event to decrypt
|
||||
* @returns {Promise<void>} A decryption promise
|
||||
* @param {object} options
|
||||
* @param {bool} options.isRetry True if this is a retry (enables more logging)
|
||||
* @param {bool} options.emit Emits "event.decrypted" if set to true
|
||||
*/
|
||||
MatrixClient.prototype.decryptEventIfNeeded = function(event, options) {
|
||||
if (event.shouldAttemptDecryption()) {
|
||||
event.attemptDecryption(this._crypto, options);
|
||||
}
|
||||
|
||||
if (event.isBeingDecrypted()) {
|
||||
return event._decryptionPromise;
|
||||
} else {
|
||||
return Promise.resolve();
|
||||
}
|
||||
};
|
||||
|
||||
// MatrixClient Event JSDocs
|
||||
|
||||
/**
|
||||
|
||||
+4
-1
@@ -3322,7 +3322,10 @@ Crypto.prototype._onToDeviceEvent = function(event) {
|
||||
this._onKeyVerificationMessage(event);
|
||||
} else if (event.getContent().msgtype === "m.bad.encrypted") {
|
||||
this._onToDeviceBadEncrypted(event);
|
||||
} else if (event.isBeingDecrypted()) {
|
||||
} else if (event.isBeingDecrypted() || event.shouldAttemptDecryption()) {
|
||||
if (!event.isBeingDecrypted()) {
|
||||
event.attemptDecryption(this);
|
||||
}
|
||||
// once the event has been decrypted, try again
|
||||
event.once('Event.decrypted', (ev) => {
|
||||
this._onToDeviceEvent(ev);
|
||||
|
||||
@@ -769,7 +769,7 @@ EventTimelineSet.prototype.aggregateRelations = function(event) {
|
||||
}
|
||||
|
||||
// If the event is currently encrypted, wait until it has been decrypted.
|
||||
if (event.isBeingDecrypted()) {
|
||||
if (event.isBeingDecrypted() || event.shouldAttemptDecryption()) {
|
||||
event.once("Event.decrypted", () => {
|
||||
this.aggregateRelations(event);
|
||||
});
|
||||
|
||||
+22
-10
@@ -46,6 +46,7 @@ export class Relations extends EventEmitter {
|
||||
this._annotationsBySender = {};
|
||||
this._sortedAnnotationsByKey = [];
|
||||
this._targetEvent = null;
|
||||
this._room = room;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,7 +55,7 @@ export class Relations extends EventEmitter {
|
||||
* @param {MatrixEvent} event
|
||||
* The new relation event to be added.
|
||||
*/
|
||||
addEvent(event) {
|
||||
async addEvent(event) {
|
||||
if (this._relations.has(event)) {
|
||||
return;
|
||||
}
|
||||
@@ -84,7 +85,8 @@ export class Relations extends EventEmitter {
|
||||
if (this.relationType === "m.annotation") {
|
||||
this._addAnnotationToAggregation(event);
|
||||
} else if (this.relationType === "m.replace" && this._targetEvent) {
|
||||
this._targetEvent.makeReplaced(this.getLastReplacement());
|
||||
const lastReplacement = await this.getLastReplacement();
|
||||
this._targetEvent.makeReplaced(lastReplacement);
|
||||
}
|
||||
|
||||
event.on("Event.beforeRedaction", this._onBeforeRedaction);
|
||||
@@ -98,7 +100,7 @@ export class Relations extends EventEmitter {
|
||||
* @param {MatrixEvent} event
|
||||
* The relation event to remove.
|
||||
*/
|
||||
_removeEvent(event) {
|
||||
async _removeEvent(event) {
|
||||
if (!this._relations.has(event)) {
|
||||
return;
|
||||
}
|
||||
@@ -122,7 +124,8 @@ export class Relations extends EventEmitter {
|
||||
if (this.relationType === "m.annotation") {
|
||||
this._removeAnnotationFromAggregation(event);
|
||||
} else if (this.relationType === "m.replace" && this._targetEvent) {
|
||||
this._targetEvent.makeReplaced(this.getLastReplacement());
|
||||
const lastReplacement = await this.getLastReplacement();
|
||||
this._targetEvent.makeReplaced(lastReplacement);
|
||||
}
|
||||
|
||||
this.emit("Relations.remove", event);
|
||||
@@ -227,7 +230,7 @@ export class Relations extends EventEmitter {
|
||||
* @param {MatrixEvent} redactedEvent
|
||||
* The original relation event that is about to be redacted.
|
||||
*/
|
||||
_onBeforeRedaction = (redactedEvent) => {
|
||||
_onBeforeRedaction = async (redactedEvent) => {
|
||||
if (!this._relations.has(redactedEvent)) {
|
||||
return;
|
||||
}
|
||||
@@ -238,7 +241,8 @@ export class Relations extends EventEmitter {
|
||||
// Remove the redacted annotation from aggregation by key
|
||||
this._removeAnnotationFromAggregation(redactedEvent);
|
||||
} else if (this.relationType === "m.replace" && this._targetEvent) {
|
||||
this._targetEvent.makeReplaced(this.getLastReplacement());
|
||||
const lastReplacement = await this.getLastReplacement();
|
||||
this._targetEvent.makeReplaced(lastReplacement);
|
||||
}
|
||||
|
||||
redactedEvent.removeListener("Event.beforeRedaction", this._onBeforeRedaction);
|
||||
@@ -291,7 +295,7 @@ export class Relations extends EventEmitter {
|
||||
*
|
||||
* @return {MatrixEvent?}
|
||||
*/
|
||||
getLastReplacement() {
|
||||
async getLastReplacement() {
|
||||
if (this.relationType !== "m.replace") {
|
||||
// Aggregating on last only makes sense for this relation type
|
||||
return null;
|
||||
@@ -309,7 +313,7 @@ export class Relations extends EventEmitter {
|
||||
this._targetEvent.getServerAggregatedRelation("m.replace");
|
||||
const minTs = replaceRelation && replaceRelation.origin_server_ts;
|
||||
|
||||
return this.getRelations().reduce((last, event) => {
|
||||
const lastReplacement = this.getRelations().reduce((last, event) => {
|
||||
if (event.getSender() !== this._targetEvent.getSender()) {
|
||||
return last;
|
||||
}
|
||||
@@ -321,18 +325,26 @@ export class Relations extends EventEmitter {
|
||||
}
|
||||
return event;
|
||||
}, null);
|
||||
|
||||
if (lastReplacement?.shouldAttemptDecryption()) {
|
||||
await lastReplacement.attemptDecryption(this._room._client._crypto);
|
||||
} else if (lastReplacement?.isBeingDecrypted()) {
|
||||
await lastReplacement._decryptionPromise;
|
||||
}
|
||||
|
||||
return lastReplacement;
|
||||
}
|
||||
|
||||
/*
|
||||
* @param {MatrixEvent} targetEvent the event the relations are related to.
|
||||
*/
|
||||
setTargetEvent(event) {
|
||||
async setTargetEvent(event) {
|
||||
if (this._targetEvent) {
|
||||
return;
|
||||
}
|
||||
this._targetEvent = event;
|
||||
if (this.relationType === "m.replace") {
|
||||
const replacement = this.getLastReplacement();
|
||||
const replacement = await this.getLastReplacement();
|
||||
// this is the initial update, so only call it if we already have something
|
||||
// to not emit Event.replaced needlessly
|
||||
if (replacement) {
|
||||
|
||||
@@ -55,7 +55,9 @@ export class CallEventHandler {
|
||||
private evaluateEventBuffer = () => {
|
||||
if (this.client.getSyncState() === "SYNCING") {
|
||||
// don't process any events until they are all decrypted
|
||||
if (this.callEventBuffer.some((e) => e.isBeingDecrypted())) return;
|
||||
if (this.callEventBuffer.some((e) => {
|
||||
return e.isBeingDecrypted() || e.shouldAttemptDecryption()
|
||||
})) return;
|
||||
|
||||
const ignoreCallIds = new Set<String>();
|
||||
// inspect the buffer and mark all calls which have been answered
|
||||
@@ -87,17 +89,19 @@ export class CallEventHandler {
|
||||
|
||||
private onEvent = (event: MatrixEvent) => {
|
||||
// any call events or ones that might be once they're decrypted
|
||||
const isBeingDecrypted = event.isBeingDecrypted();
|
||||
const shouldAttemptDecryption = event.shouldAttemptDecryption();
|
||||
if (
|
||||
event.getType().indexOf("m.call.") === 0 ||
|
||||
event.getType().indexOf("org.matrix.call.") === 0
|
||||
|| event.isBeingDecrypted()
|
||||
|| isBeingDecrypted || shouldAttemptDecryption
|
||||
) {
|
||||
// queue up for processing once all events from this sync have been
|
||||
// processed (see above).
|
||||
this.callEventBuffer.push(event);
|
||||
}
|
||||
|
||||
if (event.isBeingDecrypted() || event.isDecryptionFailure()) {
|
||||
if (event.isDecryptionFailure() || isBeingDecrypted || shouldAttemptDecryption) {
|
||||
// add an event listener for once the event is decrypted.
|
||||
event.once("Event.decrypted", () => {
|
||||
if (event.getType().indexOf("m.call.") === -1) return;
|
||||
|
||||
Reference in New Issue
Block a user