1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-11-28 05:03:59 +03:00

Change how MatrixEvent manages encrypted events

Make `MatrixEvent.event` contain the *encrypted* event, and keep the plaintext
payload in a separate `_clearEvent` property.

This achieves several aims:

* means that we have a record of the actual object which was received over
  the wire, which can be shown by clients for 'view source'.

* makes sent and received encrypted MatrixEvents more consistent (previously
  sent ones had `encryptedType` and `encryptedContent` properties, whereas
  received ones threw away the ciphertext).

* Avoids having to make two MatrixEvents in the receive path, and copying
  fields from one to the other.

*Hopefully* most clients have followed the advice given in the jsdoc of not
relying on MatrixEvent.event to get at events. If they haven't, I guess they'll
break in the face of encrypted events.

(The pushprocessor didn't follow this advice, so needed some tweaks.)
This commit is contained in:
Richard van der Hoff
2016-06-09 16:28:32 +01:00
parent 53b9154fe2
commit 2e4a8f4fa5
5 changed files with 112 additions and 88 deletions

View File

@@ -44,13 +44,17 @@ module.exports.EventStatus = {
/**
* Construct a Matrix Event object
* @constructor
* @param {Object} event The raw event to be wrapped in this DAO
* @param {MatrixEvent} encrypted if the event was encrypted, the original encrypted event
*
* @prop {Object} event The raw event. <b>Do not access this property</b>
* directly unless you absolutely have to. Prefer the getter methods defined on
* this class. Using the getter methods shields your app from
* changes to event JSON between Matrix versions.
* @param {Object} event The raw event to be wrapped in this DAO
*
* @param {Object=} clearEvent For encrypted events, the plaintext payload for
* the event (typically containing <tt>type</tt> and <tt>content</tt> fields).
*
* @prop {Object} event The raw (possibly encrypted) event. <b>Do not access
* this property</b> directly unless you absolutely have to. Prefer the getter
* methods defined on this class. Using the getter methods shields your app
* from changes to event JSON between Matrix versions.
*
* @prop {RoomMember} sender The room member who sent this event, or null e.g.
* this is a presence event.
* @prop {RoomMember} target The room member who is the target of this event, e.g.
@@ -60,20 +64,16 @@ module.exports.EventStatus = {
* that getDirectionalContent() will return event.content and not event.prev_content.
* Default: true. <strong>This property is experimental and may change.</strong>
*/
module.exports.MatrixEvent = function MatrixEvent(event, encryptedEvent) {
module.exports.MatrixEvent = function MatrixEvent(event, clearEvent) {
this.event = event || {};
this.sender = null;
this.target = null;
this.status = null;
this.forwardLooking = true;
this.encryptedEvent = false;
if (encryptedEvent) {
this.encrypted = true;
this.encryptedType = encryptedEvent.getType();
this.encryptedContent = encryptedEvent.getContent();
}
this._clearEvent = clearEvent || {};
};
module.exports.MatrixEvent.prototype = {
/**
@@ -94,19 +94,22 @@ module.exports.MatrixEvent.prototype = {
},
/**
* Get the type of event.
* Get the (decrypted, if necessary) type of event.
*
* @return {string} The event type, e.g. <code>m.room.message</code>
*/
getType: function() {
return this.event.type;
return this._clearEvent.type || this.event.type;
},
/**
* Get the type of the event that will be sent to the homeserver.
* Get the (possibly encrypted) type of the event that will be sent to the
* homeserver.
*
* @return {string} The event type.
*/
getWireType: function() {
return this.encryptedType || this.event.type;
return this.event.type;
},
/**
@@ -128,19 +131,22 @@ module.exports.MatrixEvent.prototype = {
},
/**
* Get the event content JSON.
* Get the (decrypted, if necessary) event content JSON.
*
* @return {Object} The event content JSON, or an empty object.
*/
getContent: function() {
return this.event.content || {};
return this._clearEvent.content || this.event.content || {};
},
/**
* Get the event content JSON that will be sent to the homeserver.
* Get the (possibly encrypted) event content JSON that will be sent to the
* homeserver.
*
* @return {Object} The event content JSON, or an empty object.
*/
getWireContent: function() {
return this.encryptedContent || this.event.content || {};
return this.event.content || {};
},
/**
@@ -193,12 +199,33 @@ module.exports.MatrixEvent.prototype = {
return this.event.state_key !== undefined;
},
/**
* Replace the content of this event with encrypted versions.
* (This is used when sending an event; it should not be used by applications).
*
* @internal
*
* @param {string} crypto_type type of the encrypted event - typically
* <tt>"m.room.encrypted"</tt>
*
* @param {object} crypto_content raw 'content' for the encrypted event.
*/
makeEncrypted: function(crypto_type, crypto_content) {
// keep the plain-text data for 'view source'
this._clearEvent = {
type: this.event.type,
content: this.event.content,
};
this.event.type = crypto_type;
this.event.content = crypto_content;
},
/**
* Check if the event is encrypted.
* @return {boolean} True if this event is encrypted.
*/
isEncrypted: function() {
return this.encrypted;
return Boolean(this._clearEvent.type);
},
getUnsigned: function() {
@@ -226,10 +253,11 @@ module.exports.MatrixEvent.prototype = {
}
var keeps = _REDACT_KEEP_CONTENT_MAP[this.getType()] || {};
for (key in this.event.content) {
if (!this.event.content.hasOwnProperty(key)) { continue; }
var content = this.getContent();
for (key in content) {
if (!content.hasOwnProperty(key)) { continue; }
if (!keeps[key]) {
delete this.event.content[key];
delete content[key];
}
}
},