mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-09-19 17:14:34 -04:00
Prevent redacted events from appearing in message search (#6377)
This commit is contained in:
parent
6676ee9c4a
commit
fc316a4894
6 changed files with 78 additions and 43 deletions
|
@ -19,8 +19,10 @@ import itertools
|
|||
import logging
|
||||
import threading
|
||||
from collections import namedtuple
|
||||
from typing import List, Optional
|
||||
|
||||
from canonicaljson import json
|
||||
from constantly import NamedConstant, Names
|
||||
|
||||
from twisted.internet import defer
|
||||
|
||||
|
@ -55,6 +57,16 @@ EVENT_QUEUE_TIMEOUT_S = 0.1 # Timeout when waiting for requests for events
|
|||
_EventCacheEntry = namedtuple("_EventCacheEntry", ("event", "redacted_event"))
|
||||
|
||||
|
||||
class EventRedactBehaviour(Names):
|
||||
"""
|
||||
What to do when retrieving a redacted event from the database.
|
||||
"""
|
||||
|
||||
AS_IS = NamedConstant()
|
||||
REDACT = NamedConstant()
|
||||
BLOCK = NamedConstant()
|
||||
|
||||
|
||||
class EventsWorkerStore(SQLBaseStore):
|
||||
def __init__(self, database: Database, db_conn, hs):
|
||||
super(EventsWorkerStore, self).__init__(database, db_conn, hs)
|
||||
|
@ -125,25 +137,27 @@ class EventsWorkerStore(SQLBaseStore):
|
|||
@defer.inlineCallbacks
|
||||
def get_event(
|
||||
self,
|
||||
event_id,
|
||||
check_redacted=True,
|
||||
get_prev_content=False,
|
||||
allow_rejected=False,
|
||||
allow_none=False,
|
||||
check_room_id=None,
|
||||
event_id: List[str],
|
||||
redact_behaviour: EventRedactBehaviour = EventRedactBehaviour.REDACT,
|
||||
get_prev_content: bool = False,
|
||||
allow_rejected: bool = False,
|
||||
allow_none: bool = False,
|
||||
check_room_id: Optional[str] = None,
|
||||
):
|
||||
"""Get an event from the database by event_id.
|
||||
|
||||
Args:
|
||||
event_id (str): The event_id of the event to fetch
|
||||
check_redacted (bool): If True, check if event has been redacted
|
||||
and redact it.
|
||||
get_prev_content (bool): If True and event is a state event,
|
||||
event_id: The event_id of the event to fetch
|
||||
redact_behaviour: Determine what to do with a redacted event. Possible values:
|
||||
* AS_IS - Return the full event body with no redacted content
|
||||
* REDACT - Return the event but with a redacted body
|
||||
* DISALLOW - Do not return redacted events
|
||||
get_prev_content: If True and event is a state event,
|
||||
include the previous states content in the unsigned field.
|
||||
allow_rejected (bool): If True return rejected events.
|
||||
allow_none (bool): If True, return None if no event found, if
|
||||
allow_rejected: If True return rejected events.
|
||||
allow_none: If True, return None if no event found, if
|
||||
False throw a NotFoundError
|
||||
check_room_id (str|None): if not None, check the room of the found event.
|
||||
check_room_id: if not None, check the room of the found event.
|
||||
If there is a mismatch, behave as per allow_none.
|
||||
|
||||
Returns:
|
||||
|
@ -154,7 +168,7 @@ class EventsWorkerStore(SQLBaseStore):
|
|||
|
||||
events = yield self.get_events_as_list(
|
||||
[event_id],
|
||||
check_redacted=check_redacted,
|
||||
redact_behaviour=redact_behaviour,
|
||||
get_prev_content=get_prev_content,
|
||||
allow_rejected=allow_rejected,
|
||||
)
|
||||
|
@ -173,27 +187,30 @@ class EventsWorkerStore(SQLBaseStore):
|
|||
@defer.inlineCallbacks
|
||||
def get_events(
|
||||
self,
|
||||
event_ids,
|
||||
check_redacted=True,
|
||||
get_prev_content=False,
|
||||
allow_rejected=False,
|
||||
event_ids: List[str],
|
||||
redact_behaviour: EventRedactBehaviour = EventRedactBehaviour.REDACT,
|
||||
get_prev_content: bool = False,
|
||||
allow_rejected: bool = False,
|
||||
):
|
||||
"""Get events from the database
|
||||
|
||||
Args:
|
||||
event_ids (list): The event_ids of the events to fetch
|
||||
check_redacted (bool): If True, check if event has been redacted
|
||||
and redact it.
|
||||
get_prev_content (bool): If True and event is a state event,
|
||||
event_ids: The event_ids of the events to fetch
|
||||
redact_behaviour: Determine what to do with a redacted event. Possible
|
||||
values:
|
||||
* AS_IS - Return the full event body with no redacted content
|
||||
* REDACT - Return the event but with a redacted body
|
||||
* DISALLOW - Do not return redacted events
|
||||
get_prev_content: If True and event is a state event,
|
||||
include the previous states content in the unsigned field.
|
||||
allow_rejected (bool): If True return rejected events.
|
||||
allow_rejected: If True return rejected events.
|
||||
|
||||
Returns:
|
||||
Deferred : Dict from event_id to event.
|
||||
"""
|
||||
events = yield self.get_events_as_list(
|
||||
event_ids,
|
||||
check_redacted=check_redacted,
|
||||
redact_behaviour=redact_behaviour,
|
||||
get_prev_content=get_prev_content,
|
||||
allow_rejected=allow_rejected,
|
||||
)
|
||||
|
@ -203,21 +220,23 @@ class EventsWorkerStore(SQLBaseStore):
|
|||
@defer.inlineCallbacks
|
||||
def get_events_as_list(
|
||||
self,
|
||||
event_ids,
|
||||
check_redacted=True,
|
||||
get_prev_content=False,
|
||||
allow_rejected=False,
|
||||
event_ids: List[str],
|
||||
redact_behaviour: EventRedactBehaviour = EventRedactBehaviour.REDACT,
|
||||
get_prev_content: bool = False,
|
||||
allow_rejected: bool = False,
|
||||
):
|
||||
"""Get events from the database and return in a list in the same order
|
||||
as given by `event_ids` arg.
|
||||
|
||||
Args:
|
||||
event_ids (list): The event_ids of the events to fetch
|
||||
check_redacted (bool): If True, check if event has been redacted
|
||||
and redact it.
|
||||
get_prev_content (bool): If True and event is a state event,
|
||||
event_ids: The event_ids of the events to fetch
|
||||
redact_behaviour: Determine what to do with a redacted event. Possible values:
|
||||
* AS_IS - Return the full event body with no redacted content
|
||||
* REDACT - Return the event but with a redacted body
|
||||
* DISALLOW - Do not return redacted events
|
||||
get_prev_content: If True and event is a state event,
|
||||
include the previous states content in the unsigned field.
|
||||
allow_rejected (bool): If True return rejected events.
|
||||
allow_rejected: If True, return rejected events.
|
||||
|
||||
Returns:
|
||||
Deferred[list[EventBase]]: List of events fetched from the database. The
|
||||
|
@ -319,10 +338,14 @@ class EventsWorkerStore(SQLBaseStore):
|
|||
# Update the cache to save doing the checks again.
|
||||
entry.event.internal_metadata.recheck_redaction = False
|
||||
|
||||
if check_redacted and entry.redacted_event:
|
||||
event = entry.redacted_event
|
||||
else:
|
||||
event = entry.event
|
||||
event = entry.event
|
||||
|
||||
if entry.redacted_event:
|
||||
if redact_behaviour == EventRedactBehaviour.BLOCK:
|
||||
# Skip this event
|
||||
continue
|
||||
elif redact_behaviour == EventRedactBehaviour.REDACT:
|
||||
event = entry.redacted_event
|
||||
|
||||
events.append(event)
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ from twisted.internet import defer
|
|||
|
||||
from synapse.api.errors import SynapseError
|
||||
from synapse.storage._base import SQLBaseStore, make_in_list_sql_clause
|
||||
from synapse.storage.data_stores.main.events_worker import EventRedactBehaviour
|
||||
from synapse.storage.database import Database
|
||||
from synapse.storage.engines import PostgresEngine, Sqlite3Engine
|
||||
|
||||
|
@ -453,7 +454,12 @@ class SearchStore(SearchBackgroundUpdateStore):
|
|||
|
||||
results = list(filter(lambda row: row["room_id"] in room_ids, results))
|
||||
|
||||
events = yield self.get_events_as_list([r["event_id"] for r in results])
|
||||
# We set redact_behaviour to BLOCK here to prevent redacted events being returned in
|
||||
# search results (which is a data leak)
|
||||
events = yield self.get_events_as_list(
|
||||
[r["event_id"] for r in results],
|
||||
redact_behaviour=EventRedactBehaviour.BLOCK,
|
||||
)
|
||||
|
||||
event_map = {ev.event_id: ev for ev in events}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue