Refactor + put redaction in NonPersistedEventEntry
This commit is contained in:
parent
8cc04e4c25
commit
9d161a0bcf
5 changed files with 78 additions and 56 deletions
|
@ -254,7 +254,7 @@ export class Timeline {
|
|||
/** @package */
|
||||
addEntries(newEntries) {
|
||||
this._addLocalRelationsToNewRemoteEntries(newEntries);
|
||||
this._updateEntriesNotInTimeline(newEntries);
|
||||
this._updateEntriesFetchedFromHomeserver(newEntries);
|
||||
this._moveEntryToRemoteEntries(newEntries);
|
||||
this._remoteEntries.setManySorted(newEntries);
|
||||
this._loadContextEntriesWhereNeeded(newEntries);
|
||||
|
@ -262,13 +262,17 @@ export class Timeline {
|
|||
|
||||
/**
|
||||
* Update entries based on newly received events.
|
||||
* eg: a newly received redaction event may mark an existing event in contextEntriesNotInTimeline as being redacted
|
||||
* This is only for the events that are not in the timeline but had to fetched from elsewhere to render reply previews.
|
||||
* This is specific to events that are not in the timeline but had to be fetched from the homeserver.
|
||||
*/
|
||||
_updateEntriesNotInTimeline(entries) {
|
||||
_updateEntriesFetchedFromHomeserver(entries) {
|
||||
for (const entry of entries) {
|
||||
const relatedEntry = this._contextEntriesNotInTimeline.get(entry.relatedEventId);
|
||||
if (!relatedEntry) {
|
||||
if (!relatedEntry || !relatedEntry.isNonPersisted) {
|
||||
/**
|
||||
* Updates for entries in timeline is handled by remoteEntries observable collection
|
||||
* Updates for entries not in timeline but fetched from storage is handled in this.replaceEntries()
|
||||
* This code is specific to entries fetched from HomeServer i.e NonPersistedEventEntry
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
const newEntry = this._createEntryFromRelatedEntries(entry, relatedEntry);
|
||||
|
@ -292,7 +296,7 @@ export class Timeline {
|
|||
_createEntryFromRelatedEntries(entry, relatedEntry) {
|
||||
if (entry.isRedaction) {
|
||||
const newEntry = relatedEntry.clone();
|
||||
newEntry.setAsRedacted();
|
||||
newEntry.redact(entry);
|
||||
return newEntry;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,3 +17,50 @@ limitations under the License.
|
|||
export function isValidFragmentId(id) {
|
||||
return typeof id === "number";
|
||||
}
|
||||
|
||||
// copied over from matrix-js-sdk, copyright 2016 OpenMarket Ltd
|
||||
/* _REDACT_KEEP_KEY_MAP gives the keys we keep when an event is redacted
|
||||
*
|
||||
* This is specified here:
|
||||
* http://matrix.org/speculator/spec/HEAD/client_server/latest.html#redactions
|
||||
*
|
||||
* Also:
|
||||
* - We keep 'unsigned' since that is created by the local server
|
||||
* - We keep user_id for backwards-compat with v1
|
||||
*/
|
||||
const _REDACT_KEEP_KEY_MAP = [
|
||||
'event_id', 'type', 'room_id', 'user_id', 'sender', 'state_key', 'prev_state',
|
||||
'content', 'unsigned', 'origin_server_ts',
|
||||
].reduce(function(ret, val) {
|
||||
ret[val] = 1; return ret;
|
||||
}, {});
|
||||
|
||||
// a map from event type to the .content keys we keep when an event is redacted
|
||||
const _REDACT_KEEP_CONTENT_MAP = {
|
||||
'm.room.member': {'membership': 1},
|
||||
'm.room.create': {'creator': 1},
|
||||
'm.room.join_rules': {'join_rule': 1},
|
||||
'm.room.power_levels': {'ban': 1, 'events': 1, 'events_default': 1,
|
||||
'kick': 1, 'redact': 1, 'state_default': 1,
|
||||
'users': 1, 'users_default': 1,
|
||||
},
|
||||
'm.room.aliases': {'aliases': 1},
|
||||
};
|
||||
// end of matrix-js-sdk code
|
||||
|
||||
export function redactEvent(redactionEvent, redactedEvent) {
|
||||
for (const key of Object.keys(redactedEvent)) {
|
||||
if (!_REDACT_KEEP_KEY_MAP[key]) {
|
||||
delete redactedEvent[key];
|
||||
}
|
||||
}
|
||||
const { content } = redactedEvent;
|
||||
const keepMap = _REDACT_KEEP_CONTENT_MAP[redactedEvent.type];
|
||||
for (const key of Object.keys(content)) {
|
||||
if (!keepMap?.[key]) {
|
||||
delete content[key];
|
||||
}
|
||||
}
|
||||
redactedEvent.unsigned = redactedEvent.unsigned || {};
|
||||
redactedEvent.unsigned.redacted_because = redactionEvent;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ export class EventEntry extends BaseEventEntry {
|
|||
this._decryptionResult = null;
|
||||
this._contextEntry = null;
|
||||
this._contextForEntries = null;
|
||||
this._markedAsRedacted = false;
|
||||
}
|
||||
|
||||
clone() {
|
||||
|
@ -58,10 +57,6 @@ export class EventEntry extends BaseEventEntry {
|
|||
this._contextForEntries.push(entry);
|
||||
}
|
||||
|
||||
setAsRedacted() {
|
||||
this._markedAsRedacted = true;
|
||||
}
|
||||
|
||||
get contextForEntries() {
|
||||
return this._contextForEntries;
|
||||
}
|
||||
|
@ -160,7 +155,7 @@ export class EventEntry extends BaseEventEntry {
|
|||
}
|
||||
|
||||
get isRedacted() {
|
||||
return this._markedAsRedacted || super.isRedacted || isRedacted(this._eventEntry.event);
|
||||
return super.isRedacted || isRedacted(this._eventEntry.event);
|
||||
}
|
||||
|
||||
get redactionReason() {
|
||||
|
|
|
@ -15,6 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import {EventEntry} from "./EventEntry.js";
|
||||
import {redactEvent} from "../common.js";
|
||||
|
||||
// EventEntry but without the two properties that are populated via SyncWriter
|
||||
// Useful if you want to create an EventEntry that is ephemeral
|
||||
|
@ -27,4 +28,21 @@ export class NonPersistedEventEntry extends EventEntry {
|
|||
get entryIndex() {
|
||||
throw new Error("Cannot access entryIndex for non-persisted EventEntry");
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is needed because NonPersistedEventEntry cannot rely on RelationWriter to handle redactions
|
||||
*/
|
||||
redact(redactionEvent) {
|
||||
redactEvent(redactionEvent.event, this.event);
|
||||
}
|
||||
|
||||
clone() {
|
||||
const clone = new NonPersistedEventEntry(this._eventEntry, this._fragmentIdComparer);
|
||||
clone.updateFrom(this);
|
||||
return clone;
|
||||
}
|
||||
|
||||
get isNonPersisted() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
import {EventEntry} from "../entries/EventEntry.js";
|
||||
import {REDACTION_TYPE, isRedacted} from "../../common.js";
|
||||
import {ANNOTATION_RELATION_TYPE, getRelation} from "../relations.js";
|
||||
import {redactEvent} from "../common.js";
|
||||
|
||||
export class RelationWriter {
|
||||
constructor({roomId, ownUserId, fragmentIdComparer}) {
|
||||
|
@ -127,21 +128,7 @@ export class RelationWriter {
|
|||
// check if we're the target of a relation and remove all relations then as well
|
||||
txn.timelineRelations.removeAllForTarget(this._roomId, redactedEvent.event_id);
|
||||
|
||||
for (const key of Object.keys(redactedEvent)) {
|
||||
if (!_REDACT_KEEP_KEY_MAP[key]) {
|
||||
delete redactedEvent[key];
|
||||
}
|
||||
}
|
||||
const {content} = redactedEvent;
|
||||
const keepMap = _REDACT_KEEP_CONTENT_MAP[redactedEvent.type];
|
||||
for (const key of Object.keys(content)) {
|
||||
if (!keepMap?.[key]) {
|
||||
delete content[key];
|
||||
}
|
||||
}
|
||||
redactedEvent.unsigned = redactedEvent.unsigned || {};
|
||||
redactedEvent.unsigned.redacted_because = redactionEvent;
|
||||
|
||||
redactEvent(redactionEvent, redactedEvent);
|
||||
delete redactedStorageEntry.annotations;
|
||||
|
||||
return true;
|
||||
|
@ -223,35 +210,6 @@ function isObjectEmpty(obj) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// copied over from matrix-js-sdk, copyright 2016 OpenMarket Ltd
|
||||
/* _REDACT_KEEP_KEY_MAP gives the keys we keep when an event is redacted
|
||||
*
|
||||
* This is specified here:
|
||||
* http://matrix.org/speculator/spec/HEAD/client_server/latest.html#redactions
|
||||
*
|
||||
* Also:
|
||||
* - We keep 'unsigned' since that is created by the local server
|
||||
* - We keep user_id for backwards-compat with v1
|
||||
*/
|
||||
const _REDACT_KEEP_KEY_MAP = [
|
||||
'event_id', 'type', 'room_id', 'user_id', 'sender', 'state_key', 'prev_state',
|
||||
'content', 'unsigned', 'origin_server_ts',
|
||||
].reduce(function(ret, val) {
|
||||
ret[val] = 1; return ret;
|
||||
}, {});
|
||||
|
||||
// a map from event type to the .content keys we keep when an event is redacted
|
||||
const _REDACT_KEEP_CONTENT_MAP = {
|
||||
'm.room.member': {'membership': 1},
|
||||
'm.room.create': {'creator': 1},
|
||||
'm.room.join_rules': {'join_rule': 1},
|
||||
'm.room.power_levels': {'ban': 1, 'events': 1, 'events_default': 1,
|
||||
'kick': 1, 'redact': 1, 'state_default': 1,
|
||||
'users': 1, 'users_default': 1,
|
||||
},
|
||||
'm.room.aliases': {'aliases': 1},
|
||||
};
|
||||
// end of matrix-js-sdk code
|
||||
|
||||
import {createMockStorage} from "../../../../mocks/Storage";
|
||||
import {createEvent, withTextBody, withRedacts, withContent} from "../../../../mocks/event.js";
|
||||
|
|
Reference in a new issue