Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Simplify _locally_reject_invite #8537

Merged
merged 3 commits into from
Oct 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/8537.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Factor out common code between `RoomMemberHandler._locally_reject_invite` and `EventCreationHandler.create_event`.
21 changes: 13 additions & 8 deletions synapse/events/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,32 +97,37 @@ def state_key(self):
def is_state(self):
return self._state_key is not None

async def build(self, prev_event_ids: List[str]) -> EventBase:
async def build(
self, prev_event_ids: List[str], auth_event_ids: Optional[List[str]]
) -> EventBase:
"""Transform into a fully signed and hashed event

Args:
prev_event_ids: The event IDs to use as the prev events
auth_event_ids: The event IDs to use as the auth events.
Should normally be set to None, which will cause them to be calculated
based on the room state at the prev_events.

Returns:
The signed and hashed event.
"""

state_ids = await self._state.get_current_state_ids(
self.room_id, prev_event_ids
)
auth_ids = self._auth.compute_auth_events(self, state_ids)
if auth_event_ids is None:
state_ids = await self._state.get_current_state_ids(
self.room_id, prev_event_ids
)
auth_event_ids = self._auth.compute_auth_events(self, state_ids)

format_version = self.room_version.event_format
if format_version == EventFormatVersions.V1:
# The types of auth/prev events changes between event versions.
auth_events = await self._store.add_event_hashes(
auth_ids
auth_event_ids
) # type: Union[List[str], List[Tuple[str, Dict[str, str]]]]
prev_events = await self._store.add_event_hashes(
prev_event_ids
) # type: Union[List[str], List[Tuple[str, Dict[str, str]]]]
else:
auth_events = auth_ids
auth_events = auth_event_ids
prev_events = prev_event_ids

old_depth = await self._store.get_max_depth_of(prev_event_ids)
Expand Down
30 changes: 23 additions & 7 deletions synapse/handlers/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,9 +437,9 @@ async def create_event(
self,
requester: Requester,
event_dict: dict,
token_id: Optional[str] = None,
txn_id: Optional[str] = None,
prev_event_ids: Optional[List[str]] = None,
auth_event_ids: Optional[List[str]] = None,
require_consent: bool = True,
) -> Tuple[EventBase, EventContext]:
"""
Expand All @@ -453,13 +453,18 @@ async def create_event(
Args:
requester
event_dict: An entire event
token_id
txn_id
prev_event_ids:
the forward extremities to use as the prev_events for the
new event.

If None, they will be requested from the database.

auth_event_ids:
The event ids to use as the auth_events for the new event.
Should normally be left as None, which will cause them to be calculated
based on the room state at the prev_events.

require_consent: Whether to check if the requester has
consented to the privacy policy.
Raises:
Expand Down Expand Up @@ -511,14 +516,17 @@ async def create_event(
if require_consent and not is_exempt:
await self.assert_accepted_privacy_policy(requester)

if token_id is not None:
builder.internal_metadata.token_id = token_id
if requester.access_token_id is not None:
builder.internal_metadata.token_id = requester.access_token_id

if txn_id is not None:
builder.internal_metadata.txn_id = txn_id

event, context = await self.create_new_client_event(
builder=builder, requester=requester, prev_event_ids=prev_event_ids,
builder=builder,
requester=requester,
prev_event_ids=prev_event_ids,
auth_event_ids=auth_event_ids,
)

# In an ideal world we wouldn't need the second part of this condition. However,
Expand Down Expand Up @@ -726,7 +734,7 @@ async def create_and_send_nonmember_event(
return event, event.internal_metadata.stream_ordering

event, context = await self.create_event(
requester, event_dict, token_id=requester.access_token_id, txn_id=txn_id
requester, event_dict, txn_id=txn_id
)

assert self.hs.is_mine_id(event.sender), "User must be our own: %s" % (
Expand Down Expand Up @@ -757,6 +765,7 @@ async def create_new_client_event(
builder: EventBuilder,
requester: Optional[Requester] = None,
prev_event_ids: Optional[List[str]] = None,
auth_event_ids: Optional[List[str]] = None,
) -> Tuple[EventBase, EventContext]:
"""Create a new event for a local client

Expand All @@ -769,6 +778,11 @@ async def create_new_client_event(

If None, they will be requested from the database.

auth_event_ids:
The event ids to use as the auth_events for the new event.
Should normally be left as None, which will cause them to be calculated
based on the room state at the prev_events.

Returns:
Tuple of created event, context
"""
Expand All @@ -790,7 +804,9 @@ async def create_new_client_event(
builder.type == EventTypes.Create or len(prev_event_ids) > 0
), "Attempting to create an event with no prev_events"

event = await builder.build(prev_event_ids=prev_event_ids)
event = await builder.build(
prev_event_ids=prev_event_ids, auth_event_ids=auth_event_ids
)
context = await self.state.compute_event_context(event)
if requester:
context.app_service = requester.app_service
Expand Down
1 change: 0 additions & 1 deletion synapse/handlers/room.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,6 @@ async def _upgrade_room(
"replacement_room": new_room_id,
},
},
token_id=requester.access_token_id,
)
old_room_version = await self.store.get_room_version_id(old_room_id)
await self.auth.check_from_context(
Expand Down
59 changes: 15 additions & 44 deletions synapse/handlers/room_member.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,10 @@
import logging
import random
from http import HTTPStatus
from typing import TYPE_CHECKING, Iterable, List, Optional, Tuple, Union

from unpaddedbase64 import encode_base64
from typing import TYPE_CHECKING, Iterable, List, Optional, Tuple

from synapse import types
from synapse.api.constants import MAX_DEPTH, AccountDataTypes, EventTypes, Membership
from synapse.api.constants import AccountDataTypes, EventTypes, Membership
from synapse.api.errors import (
AuthError,
Codes,
Expand All @@ -31,12 +29,8 @@
SynapseError,
)
from synapse.api.ratelimiting import Ratelimiter
from synapse.api.room_versions import EventFormatVersions
from synapse.crypto.event_signing import compute_event_reference_hash
from synapse.events import EventBase
from synapse.events.builder import create_local_event_from_event_dict
from synapse.events.snapshot import EventContext
from synapse.events.validator import EventValidator
from synapse.storage.roommember import RoomsForUser
from synapse.types import JsonDict, Requester, RoomAlias, RoomID, StateMap, UserID
from synapse.util.async_helpers import Linearizer
Expand Down Expand Up @@ -193,7 +187,6 @@ async def _local_membership_update(
# For backwards compatibility:
"membership": membership,
},
token_id=requester.access_token_id,
txn_id=txn_id,
prev_event_ids=prev_event_ids,
require_consent=require_consent,
Expand Down Expand Up @@ -1133,56 +1126,34 @@ async def _locally_reject_invite(

room_id = invite_event.room_id
target_user = invite_event.state_key
room_version = await self.store.get_room_version(room_id)

content["membership"] = Membership.LEAVE

# the auth events for the new event are the same as that of the invite, plus
# the invite itself.
#
# the prev_events are just the invite.
invite_hash = invite_event.event_id # type: Union[str, Tuple]
if room_version.event_format == EventFormatVersions.V1:
alg, h = compute_event_reference_hash(invite_event)
invite_hash = (invite_event.event_id, {alg: encode_base64(h)})

auth_events = tuple(invite_event.auth_events) + (invite_hash,)
prev_events = (invite_hash,)

# we cap depth of generated events, to ensure that they are not
# rejected by other servers (and so that they can be persisted in
# the db)
depth = min(invite_event.depth + 1, MAX_DEPTH)

event_dict = {
"depth": depth,
"auth_events": auth_events,
"prev_events": prev_events,
"type": EventTypes.Member,
"room_id": room_id,
"sender": target_user,
"content": content,
"state_key": target_user,
}

event = create_local_event_from_event_dict(
clock=self.clock,
hostname=self.hs.hostname,
signing_key=self.hs.signing_key,
room_version=room_version,
event_dict=event_dict,
# the auth events for the new event are the same as that of the invite, plus
# the invite itself.
#
# the prev_events are just the invite.
prev_event_ids = [invite_event.event_id]
auth_event_ids = invite_event.auth_event_ids() + prev_event_ids

event, context = await self.event_creation_handler.create_event(
requester,
event_dict,
txn_id=txn_id,
prev_event_ids=prev_event_ids,
auth_event_ids=auth_event_ids,
)
event.internal_metadata.outlier = True
event.internal_metadata.out_of_band_membership = True
if txn_id is not None:
event.internal_metadata.txn_id = txn_id
if requester.access_token_id is not None:
event.internal_metadata.token_id = requester.access_token_id

EventValidator().validate_new(event, self.config)

context = await self.state_handler.compute_event_context(event)
context.app_service = requester.app_service
result_event = await self.event_creation_handler.handle_new_client_event(
requester, event, context, extra_users=[UserID.from_string(target_user)],
)
Expand Down
1 change: 0 additions & 1 deletion tests/handlers/test_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ def _create_duplicate_event(self, txn_id: str) -> Tuple[EventBase, EventContext]
"sender": self.requester.user.to_string(),
"content": {"msgtype": "m.text", "body": random_string(5)},
},
token_id=self.token_id,
txn_id=txn_id,
)
)
Expand Down
2 changes: 1 addition & 1 deletion tests/handlers/test_presence.py
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ def _add_new_user(self, room_id, user_id):
self.store.get_latest_event_ids_in_room(room_id)
)

event = self.get_success(builder.build(prev_event_ids))
event = self.get_success(builder.build(prev_event_ids, None))

self.get_success(self.federation_handler.on_receive_pdu(hostname, event))

Expand Down
2 changes: 1 addition & 1 deletion tests/replication/test_federation_sender_shard.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ def create_room_with_remote_server(self, user, token, remote_server="other_serve
}

builder = factory.for_room_version(room_version, event_dict)
join_event = self.get_success(builder.build(prev_event_ids))
join_event = self.get_success(builder.build(prev_event_ids, None))

self.get_success(federation.on_send_join_request(remote_server, join_event))
self.replicate()
Expand Down
4 changes: 2 additions & 2 deletions tests/storage/test_redaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,9 @@ def __init__(self, base_builder, event_id):
self._event_id = event_id

@defer.inlineCallbacks
def build(self, prev_event_ids):
def build(self, prev_event_ids, auth_event_ids):
built_event = yield defer.ensureDeferred(
self._base_builder.build(prev_event_ids)
self._base_builder.build(prev_event_ids, auth_event_ids)
)

built_event._event_id = self._event_id
Expand Down