mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-05-03 04:44:52 -04:00
Allow ThirdPartyRules modules to replace event content
Support returning a new event dict from `check_event_allowed`.
This commit is contained in:
parent
123711ed19
commit
617e8a4653
3 changed files with 75 additions and 9 deletions
|
@ -795,16 +795,22 @@ class EventCreationHandler:
|
|||
if requester:
|
||||
context.app_service = requester.app_service
|
||||
|
||||
event_allowed = await self.third_party_event_rules.check_event_allowed(
|
||||
third_party_result = await self.third_party_event_rules.check_event_allowed(
|
||||
event, context
|
||||
)
|
||||
if not event_allowed:
|
||||
if not third_party_result:
|
||||
logger.info(
|
||||
"Event %s forbidden by third-party rules", event,
|
||||
)
|
||||
raise SynapseError(
|
||||
403, "This event is not allowed in this context", Codes.FORBIDDEN
|
||||
)
|
||||
elif isinstance(third_party_result, dict):
|
||||
# the third-party rules want to replace the event. We'll need to build a new
|
||||
# event.
|
||||
event, context = await self._rebuild_event_after_third_party_rules(
|
||||
third_party_result, event
|
||||
)
|
||||
|
||||
self.validator.validate_new(event, self.config)
|
||||
|
||||
|
@ -1294,3 +1300,57 @@ class EventCreationHandler:
|
|||
room_id,
|
||||
)
|
||||
del self._rooms_to_exclude_from_dummy_event_insertion[room_id]
|
||||
|
||||
async def _rebuild_event_after_third_party_rules(
|
||||
self, third_party_result: dict, original_event: EventBase
|
||||
) -> Tuple[EventBase, EventContext]:
|
||||
# the third_party_event_rules want to replace the event.
|
||||
# we do some basic checks, and then return the replacement event and context.
|
||||
|
||||
# Construct a new EventBuilder and validate it, which helps with the
|
||||
# rest of these checks.
|
||||
try:
|
||||
builder = self.event_builder_factory.for_room_version(
|
||||
original_event.room_version, third_party_result
|
||||
)
|
||||
self.validator.validate_builder(builder)
|
||||
except SynapseError as e:
|
||||
raise Exception(
|
||||
"Third party rules module created an invalid event: " + e.msg,
|
||||
)
|
||||
|
||||
immutable_fields = [
|
||||
# changing the room is going to break things: we've already checked that the
|
||||
# room exists, and are holding a concurrency limiter token for that room.
|
||||
# Also, we might need to use a different room version.
|
||||
"room_id",
|
||||
# changing the type or state key might work, but we'd need to check that the
|
||||
# calling functions aren't making assumptions about them.
|
||||
"type",
|
||||
"state_key",
|
||||
]
|
||||
|
||||
for k in immutable_fields:
|
||||
if getattr(builder, k, None) != original_event.get(k):
|
||||
raise Exception(
|
||||
"Third party rules module created an invalid event: "
|
||||
"cannot change field " + k
|
||||
)
|
||||
|
||||
# check that the new sender belongs to this HS
|
||||
if not self.hs.is_mine_id(builder.sender):
|
||||
raise Exception(
|
||||
"Third party rules module created an invalid event: "
|
||||
"invalid sender " + builder.sender
|
||||
)
|
||||
|
||||
# copy over the original internal metadata
|
||||
for k, v in original_event.internal_metadata.get_dict().items():
|
||||
setattr(builder.internal_metadata, k, v)
|
||||
|
||||
event = await builder.build(prev_event_ids=original_event.prev_event_ids())
|
||||
|
||||
# we rebuild the event context, to be on the safe side. If nothing else,
|
||||
# delta_ids might need an update.
|
||||
context = await self.state.compute_event_context(event)
|
||||
return event, context
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue