diff --git a/synapse/handlers/federation_event.py b/synapse/handlers/federation_event.py
index b7136f8d1c..648843cdbe 100644
--- a/synapse/handlers/federation_event.py
+++ b/synapse/handlers/federation_event.py
@@ -583,7 +583,7 @@ class FederationEventHandler:
await self._check_event_auth(origin, event, context)
if context.rejected:
- raise SynapseError(400, "Join event was rejected")
+ raise SynapseError(403, "Join event was rejected")
# the remote server is responsible for sending our join event to the rest
# of the federation. Indeed, attempting to do so will result in problems
diff --git a/synapse/handlers/room_member.py b/synapse/handlers/room_member.py
index 509c557889..1d8b0aee6f 100644
--- a/synapse/handlers/room_member.py
+++ b/synapse/handlers/room_member.py
@@ -850,63 +850,68 @@ class RoomMemberHandler(metaclass=abc.ABCMeta):
# `is_partial_state_room` also indicates whether `partial_state_before_join` is
# partial.
- # TODO: Refactor into dictionary of explicitly allowed transitions
- # between old and new state, with specific error messages for some
- # transitions and generic otherwise
- old_state_id = partial_state_before_join.get(
- (EventTypes.Member, target.to_string())
- )
- if old_state_id:
- old_state = await self.store.get_event(old_state_id, allow_none=True)
- old_membership = old_state.content.get("membership") if old_state else None
- if action == "unban" and old_membership != "ban":
- raise SynapseError(
- 403,
- "Cannot unban user who was not banned"
- " (membership=%s)" % old_membership,
- errcode=Codes.BAD_STATE,
- )
- if old_membership == "ban" and action not in ["ban", "unban", "leave"]:
- raise SynapseError(
- 403,
- "Cannot %s user who was banned" % (action,),
- errcode=Codes.BAD_STATE,
- )
-
- if old_state:
- same_content = content == old_state.content
- same_membership = old_membership == effective_membership_state
- same_sender = requester.user.to_string() == old_state.sender
- if same_sender and same_membership and same_content:
- # duplicate event.
- # we know it was persisted, so must have a stream ordering.
- assert old_state.internal_metadata.stream_ordering
- return (
- old_state.event_id,
- old_state.internal_metadata.stream_ordering,
- )
+ is_host_in_room = await self._is_host_in_room(partial_state_before_join)
- if old_membership in ["ban", "leave"] and action == "kick":
- raise AuthError(403, "The target user is not in the room")
+ # if we are not in the room, we won't have the current state
+ if is_host_in_room:
+ # TODO: Refactor into dictionary of explicitly allowed transitions
+ # between old and new state, with specific error messages for some
+ # transitions and generic otherwise
+ old_state_id = partial_state_before_join.get(
+ (EventTypes.Member, target.to_string())
+ )
- # we don't allow people to reject invites to the server notice
- # room, but they can leave it once they are joined.
- if (
- old_membership == Membership.INVITE
- and effective_membership_state == Membership.LEAVE
- ):
- is_blocked = await self.store.is_server_notice_room(room_id)
- if is_blocked:
+ if old_state_id:
+ old_state = await self.store.get_event(old_state_id, allow_none=True)
+ old_membership = (
+ old_state.content.get("membership") if old_state else None
+ )
+ if action == "unban" and old_membership != "ban":
raise SynapseError(
- HTTPStatus.FORBIDDEN,
- "You cannot reject this invite",
- errcode=Codes.CANNOT_LEAVE_SERVER_NOTICE_ROOM,
+ 403,
+ "Cannot unban user who was not banned"
+ " (membership=%s)" % old_membership,
+ errcode=Codes.BAD_STATE,
+ )
+ if old_membership == "ban" and action not in ["ban", "unban", "leave"]:
+ raise SynapseError(
+ 403,
+ "Cannot %s user who was banned" % (action,),
+ errcode=Codes.BAD_STATE,
)
- else:
- if action == "kick":
- raise AuthError(403, "The target user is not in the room")
- is_host_in_room = await self._is_host_in_room(partial_state_before_join)
+ if old_state:
+ same_content = content == old_state.content
+ same_membership = old_membership == effective_membership_state
+ same_sender = requester.user.to_string() == old_state.sender
+ if same_sender and same_membership and same_content:
+ # duplicate event.
+ # we know it was persisted, so must have a stream ordering.
+ assert old_state.internal_metadata.stream_ordering
+ return (
+ old_state.event_id,
+ old_state.internal_metadata.stream_ordering,
+ )
+
+ if old_membership in ["ban", "leave"] and action == "kick":
+ raise AuthError(403, "The target user is not in the room")
+
+ # we don't allow people to reject invites to the server notice
+ # room, but they can leave it once they are joined.
+ if (
+ old_membership == Membership.INVITE
+ and effective_membership_state == Membership.LEAVE
+ ):
+ is_blocked = await self.store.is_server_notice_room(room_id)
+ if is_blocked:
+ raise SynapseError(
+ HTTPStatus.FORBIDDEN,
+ "You cannot reject this invite",
+ errcode=Codes.CANNOT_LEAVE_SERVER_NOTICE_ROOM,
+ )
+ else:
+ if action == "kick":
+ raise AuthError(403, "The target user is not in the room")
if effective_membership_state == Membership.JOIN:
if requester.is_guest:
|