mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-09-20 03:14:35 -04:00
synapse.api.auth.Auth
cleanup: make permission-related methods use Requester
instead of the UserID
(#13024)
Part of #13019 This changes all the permission-related methods to rely on the Requester instead of the UserID. This is a first step towards enabling scoped access tokens at some point, since I expect the Requester to have scope-related informations in it. It also changes methods which figure out the user/device/appservice out of the access token to return a Requester instead of something else. This avoids having store-related objects in the methods signatures.
This commit is contained in:
parent
94375f7a91
commit
3dd175b628
26 changed files with 202 additions and 207 deletions
|
@ -280,7 +280,7 @@ class AuthHandler:
|
|||
that it isn't stolen by re-authenticating them.
|
||||
|
||||
Args:
|
||||
requester: The user, as given by the access token
|
||||
requester: The user making the request, according to the access token.
|
||||
|
||||
request: The request sent by the client.
|
||||
|
||||
|
@ -1435,20 +1435,25 @@ class AuthHandler:
|
|||
access_token: access token to be deleted
|
||||
|
||||
"""
|
||||
user_info = await self.auth.get_user_by_access_token(access_token)
|
||||
token = await self.store.get_user_by_access_token(access_token)
|
||||
if not token:
|
||||
# At this point, the token should already have been fetched once by
|
||||
# the caller, so this should not happen, unless of a race condition
|
||||
# between two delete requests
|
||||
raise SynapseError(HTTPStatus.UNAUTHORIZED, "Unrecognised access token")
|
||||
await self.store.delete_access_token(access_token)
|
||||
|
||||
# see if any modules want to know about this
|
||||
await self.password_auth_provider.on_logged_out(
|
||||
user_id=user_info.user_id,
|
||||
device_id=user_info.device_id,
|
||||
user_id=token.user_id,
|
||||
device_id=token.device_id,
|
||||
access_token=access_token,
|
||||
)
|
||||
|
||||
# delete pushers associated with this access token
|
||||
if user_info.token_id is not None:
|
||||
if token.token_id is not None:
|
||||
await self.hs.get_pusherpool().remove_pushers_by_access_token(
|
||||
user_info.user_id, (user_info.token_id,)
|
||||
token.user_id, (token.token_id,)
|
||||
)
|
||||
|
||||
async def delete_access_tokens_for_user(
|
||||
|
|
|
@ -30,7 +30,7 @@ from synapse.api.errors import (
|
|||
from synapse.appservice import ApplicationService
|
||||
from synapse.module_api import NOT_SPAM
|
||||
from synapse.storage.databases.main.directory import RoomAliasMapping
|
||||
from synapse.types import JsonDict, Requester, RoomAlias, UserID, get_domain_from_id
|
||||
from synapse.types import JsonDict, Requester, RoomAlias, get_domain_from_id
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from synapse.server import HomeServer
|
||||
|
@ -133,7 +133,7 @@ class DirectoryHandler:
|
|||
else:
|
||||
# Server admins are not subject to the same constraints as normal
|
||||
# users when creating an alias (e.g. being in the room).
|
||||
is_admin = await self.auth.is_server_admin(requester.user)
|
||||
is_admin = await self.auth.is_server_admin(requester)
|
||||
|
||||
if (self.require_membership and check_membership) and not is_admin:
|
||||
rooms_for_user = await self.store.get_rooms_for_user(user_id)
|
||||
|
@ -197,7 +197,7 @@ class DirectoryHandler:
|
|||
user_id = requester.user.to_string()
|
||||
|
||||
try:
|
||||
can_delete = await self._user_can_delete_alias(room_alias, user_id)
|
||||
can_delete = await self._user_can_delete_alias(room_alias, requester)
|
||||
except StoreError as e:
|
||||
if e.code == 404:
|
||||
raise NotFoundError("Unknown room alias")
|
||||
|
@ -400,7 +400,9 @@ class DirectoryHandler:
|
|||
# either no interested services, or no service with an exclusive lock
|
||||
return True
|
||||
|
||||
async def _user_can_delete_alias(self, alias: RoomAlias, user_id: str) -> bool:
|
||||
async def _user_can_delete_alias(
|
||||
self, alias: RoomAlias, requester: Requester
|
||||
) -> bool:
|
||||
"""Determine whether a user can delete an alias.
|
||||
|
||||
One of the following must be true:
|
||||
|
@ -413,7 +415,7 @@ class DirectoryHandler:
|
|||
"""
|
||||
creator = await self.store.get_room_alias_creator(alias.to_string())
|
||||
|
||||
if creator == user_id:
|
||||
if creator == requester.user.to_string():
|
||||
return True
|
||||
|
||||
# Resolve the alias to the corresponding room.
|
||||
|
@ -422,9 +424,7 @@ class DirectoryHandler:
|
|||
if not room_id:
|
||||
return False
|
||||
|
||||
return await self.auth.check_can_change_room_list(
|
||||
room_id, UserID.from_string(user_id)
|
||||
)
|
||||
return await self.auth.check_can_change_room_list(room_id, requester)
|
||||
|
||||
async def edit_published_room_list(
|
||||
self, requester: Requester, room_id: str, visibility: str
|
||||
|
@ -463,7 +463,7 @@ class DirectoryHandler:
|
|||
raise SynapseError(400, "Unknown room")
|
||||
|
||||
can_change_room_list = await self.auth.check_can_change_room_list(
|
||||
room_id, requester.user
|
||||
room_id, requester
|
||||
)
|
||||
if not can_change_room_list:
|
||||
raise AuthError(
|
||||
|
@ -528,10 +528,8 @@ class DirectoryHandler:
|
|||
Get a list of the aliases that currently point to this room on this server
|
||||
"""
|
||||
# allow access to server admins and current members of the room
|
||||
is_admin = await self.auth.is_server_admin(requester.user)
|
||||
is_admin = await self.auth.is_server_admin(requester)
|
||||
if not is_admin:
|
||||
await self.auth.check_user_in_room_or_world_readable(
|
||||
room_id, requester.user.to_string()
|
||||
)
|
||||
await self.auth.check_user_in_room_or_world_readable(room_id, requester)
|
||||
|
||||
return await self.store.get_aliases_for_room(room_id)
|
||||
|
|
|
@ -309,18 +309,18 @@ class InitialSyncHandler:
|
|||
if blocked:
|
||||
raise SynapseError(403, "This room has been blocked on this server")
|
||||
|
||||
user_id = requester.user.to_string()
|
||||
|
||||
(
|
||||
membership,
|
||||
member_event_id,
|
||||
) = await self.auth.check_user_in_room_or_world_readable(
|
||||
room_id,
|
||||
user_id,
|
||||
requester,
|
||||
allow_departed_users=True,
|
||||
)
|
||||
is_peeking = member_event_id is None
|
||||
|
||||
user_id = requester.user.to_string()
|
||||
|
||||
if membership == Membership.JOIN:
|
||||
result = await self._room_initial_sync_joined(
|
||||
user_id, room_id, pagin_config, membership, is_peeking
|
||||
|
|
|
@ -104,7 +104,7 @@ class MessageHandler:
|
|||
|
||||
async def get_room_data(
|
||||
self,
|
||||
user_id: str,
|
||||
requester: Requester,
|
||||
room_id: str,
|
||||
event_type: str,
|
||||
state_key: str,
|
||||
|
@ -112,7 +112,7 @@ class MessageHandler:
|
|||
"""Get data from a room.
|
||||
|
||||
Args:
|
||||
user_id
|
||||
requester: The user who did the request.
|
||||
room_id
|
||||
event_type
|
||||
state_key
|
||||
|
@ -125,7 +125,7 @@ class MessageHandler:
|
|||
membership,
|
||||
membership_event_id,
|
||||
) = await self.auth.check_user_in_room_or_world_readable(
|
||||
room_id, user_id, allow_departed_users=True
|
||||
room_id, requester, allow_departed_users=True
|
||||
)
|
||||
|
||||
if membership == Membership.JOIN:
|
||||
|
@ -161,11 +161,10 @@ class MessageHandler:
|
|||
|
||||
async def get_state_events(
|
||||
self,
|
||||
user_id: str,
|
||||
requester: Requester,
|
||||
room_id: str,
|
||||
state_filter: Optional[StateFilter] = None,
|
||||
at_token: Optional[StreamToken] = None,
|
||||
is_guest: bool = False,
|
||||
) -> List[dict]:
|
||||
"""Retrieve all state events for a given room. If the user is
|
||||
joined to the room then return the current state. If the user has
|
||||
|
@ -174,14 +173,13 @@ class MessageHandler:
|
|||
visible.
|
||||
|
||||
Args:
|
||||
user_id: The user requesting state events.
|
||||
requester: The user requesting state events.
|
||||
room_id: The room ID to get all state events from.
|
||||
state_filter: The state filter used to fetch state from the database.
|
||||
at_token: the stream token of the at which we are requesting
|
||||
the stats. If the user is not allowed to view the state as of that
|
||||
stream token, we raise a 403 SynapseError. If None, returns the current
|
||||
state based on the current_state_events table.
|
||||
is_guest: whether this user is a guest
|
||||
Returns:
|
||||
A list of dicts representing state events. [{}, {}, {}]
|
||||
Raises:
|
||||
|
@ -191,6 +189,7 @@ class MessageHandler:
|
|||
members of this room.
|
||||
"""
|
||||
state_filter = state_filter or StateFilter.all()
|
||||
user_id = requester.user.to_string()
|
||||
|
||||
if at_token:
|
||||
last_event_id = (
|
||||
|
@ -223,7 +222,7 @@ class MessageHandler:
|
|||
membership,
|
||||
membership_event_id,
|
||||
) = await self.auth.check_user_in_room_or_world_readable(
|
||||
room_id, user_id, allow_departed_users=True
|
||||
room_id, requester, allow_departed_users=True
|
||||
)
|
||||
|
||||
if membership == Membership.JOIN:
|
||||
|
@ -317,12 +316,11 @@ class MessageHandler:
|
|||
Returns:
|
||||
A dict of user_id to profile info
|
||||
"""
|
||||
user_id = requester.user.to_string()
|
||||
if not requester.app_service:
|
||||
# We check AS auth after fetching the room membership, as it
|
||||
# requires us to pull out all joined members anyway.
|
||||
membership, _ = await self.auth.check_user_in_room_or_world_readable(
|
||||
room_id, user_id, allow_departed_users=True
|
||||
room_id, requester, allow_departed_users=True
|
||||
)
|
||||
if membership != Membership.JOIN:
|
||||
raise SynapseError(
|
||||
|
@ -340,7 +338,10 @@ class MessageHandler:
|
|||
# If this is an AS, double check that they are allowed to see the members.
|
||||
# This can either be because the AS user is in the room or because there
|
||||
# is a user in the room that the AS is "interested in"
|
||||
if requester.app_service and user_id not in users_with_profile:
|
||||
if (
|
||||
requester.app_service
|
||||
and requester.user.to_string() not in users_with_profile
|
||||
):
|
||||
for uid in users_with_profile:
|
||||
if requester.app_service.is_interested_in_user(uid):
|
||||
break
|
||||
|
|
|
@ -464,7 +464,7 @@ class PaginationHandler:
|
|||
membership,
|
||||
member_event_id,
|
||||
) = await self.auth.check_user_in_room_or_world_readable(
|
||||
room_id, user_id, allow_departed_users=True
|
||||
room_id, requester, allow_departed_users=True
|
||||
)
|
||||
|
||||
if pagin_config.direction == "b":
|
||||
|
|
|
@ -29,7 +29,13 @@ from synapse.api.constants import (
|
|||
JoinRules,
|
||||
LoginType,
|
||||
)
|
||||
from synapse.api.errors import AuthError, Codes, ConsentNotGivenError, SynapseError
|
||||
from synapse.api.errors import (
|
||||
AuthError,
|
||||
Codes,
|
||||
ConsentNotGivenError,
|
||||
InvalidClientTokenError,
|
||||
SynapseError,
|
||||
)
|
||||
from synapse.appservice import ApplicationService
|
||||
from synapse.config.server import is_threepid_reserved
|
||||
from synapse.http.servlet import assert_params_in_dict
|
||||
|
@ -180,10 +186,7 @@ class RegistrationHandler:
|
|||
)
|
||||
if guest_access_token:
|
||||
user_data = await self.auth.get_user_by_access_token(guest_access_token)
|
||||
if (
|
||||
not user_data.is_guest
|
||||
or UserID.from_string(user_data.user_id).localpart != localpart
|
||||
):
|
||||
if not user_data.is_guest or user_data.user.localpart != localpart:
|
||||
raise AuthError(
|
||||
403,
|
||||
"Cannot register taken user ID without valid guest "
|
||||
|
@ -618,7 +621,7 @@ class RegistrationHandler:
|
|||
user_id = user.to_string()
|
||||
service = self.store.get_app_service_by_token(as_token)
|
||||
if not service:
|
||||
raise AuthError(403, "Invalid application service token.")
|
||||
raise InvalidClientTokenError()
|
||||
if not service.is_interested_in_user(user_id):
|
||||
raise SynapseError(
|
||||
400,
|
||||
|
|
|
@ -103,7 +103,7 @@ class RelationsHandler:
|
|||
|
||||
# TODO Properly handle a user leaving a room.
|
||||
(_, member_event_id) = await self._auth.check_user_in_room_or_world_readable(
|
||||
room_id, user_id, allow_departed_users=True
|
||||
room_id, requester, allow_departed_users=True
|
||||
)
|
||||
|
||||
# This gets the original event and checks that a) the event exists and
|
||||
|
|
|
@ -721,7 +721,7 @@ class RoomCreationHandler:
|
|||
# allow the server notices mxid to create rooms
|
||||
is_requester_admin = True
|
||||
else:
|
||||
is_requester_admin = await self.auth.is_server_admin(requester.user)
|
||||
is_requester_admin = await self.auth.is_server_admin(requester)
|
||||
|
||||
# Let the third party rules modify the room creation config if needed, or abort
|
||||
# the room creation entirely with an exception.
|
||||
|
@ -1279,7 +1279,7 @@ class RoomContextHandler:
|
|||
"""
|
||||
user = requester.user
|
||||
if use_admin_priviledge:
|
||||
await assert_user_is_admin(self.auth, requester.user)
|
||||
await assert_user_is_admin(self.auth, requester)
|
||||
|
||||
before_limit = math.floor(limit / 2.0)
|
||||
after_limit = limit - before_limit
|
||||
|
|
|
@ -179,7 +179,7 @@ class RoomMemberHandler(metaclass=abc.ABCMeta):
|
|||
"""Try and join a room that this server is not in
|
||||
|
||||
Args:
|
||||
requester
|
||||
requester: The user making the request, according to the access token.
|
||||
remote_room_hosts: List of servers that can be used to join via.
|
||||
room_id: Room that we are trying to join
|
||||
user: User who is trying to join
|
||||
|
@ -744,7 +744,7 @@ class RoomMemberHandler(metaclass=abc.ABCMeta):
|
|||
is_requester_admin = True
|
||||
|
||||
else:
|
||||
is_requester_admin = await self.auth.is_server_admin(requester.user)
|
||||
is_requester_admin = await self.auth.is_server_admin(requester)
|
||||
|
||||
if not is_requester_admin:
|
||||
if self.config.server.block_non_admin_invites:
|
||||
|
@ -868,7 +868,7 @@ class RoomMemberHandler(metaclass=abc.ABCMeta):
|
|||
bypass_spam_checker = True
|
||||
|
||||
else:
|
||||
bypass_spam_checker = await self.auth.is_server_admin(requester.user)
|
||||
bypass_spam_checker = await self.auth.is_server_admin(requester)
|
||||
|
||||
inviter = await self._get_inviter(target.to_string(), room_id)
|
||||
if (
|
||||
|
@ -1410,7 +1410,7 @@ class RoomMemberHandler(metaclass=abc.ABCMeta):
|
|||
ShadowBanError if the requester has been shadow-banned.
|
||||
"""
|
||||
if self.config.server.block_non_admin_invites:
|
||||
is_requester_admin = await self.auth.is_server_admin(requester.user)
|
||||
is_requester_admin = await self.auth.is_server_admin(requester)
|
||||
if not is_requester_admin:
|
||||
raise SynapseError(
|
||||
403, "Invites have been disabled on this server", Codes.FORBIDDEN
|
||||
|
@ -1693,7 +1693,7 @@ class RoomMemberMasterHandler(RoomMemberHandler):
|
|||
check_complexity
|
||||
and self.hs.config.server.limit_remote_rooms.admins_can_join
|
||||
):
|
||||
check_complexity = not await self.auth.is_server_admin(user)
|
||||
check_complexity = not await self.store.is_server_admin(user)
|
||||
|
||||
if check_complexity:
|
||||
# Fetch the room complexity
|
||||
|
|
|
@ -253,12 +253,11 @@ class TypingWriterHandler(FollowerTypingHandler):
|
|||
self, target_user: UserID, requester: Requester, room_id: str, timeout: int
|
||||
) -> None:
|
||||
target_user_id = target_user.to_string()
|
||||
auth_user_id = requester.user.to_string()
|
||||
|
||||
if not self.is_mine_id(target_user_id):
|
||||
raise SynapseError(400, "User is not hosted on this homeserver")
|
||||
|
||||
if target_user_id != auth_user_id:
|
||||
if target_user != requester.user:
|
||||
raise AuthError(400, "Cannot set another user's typing state")
|
||||
|
||||
if requester.shadow_banned:
|
||||
|
@ -266,7 +265,7 @@ class TypingWriterHandler(FollowerTypingHandler):
|
|||
await self.clock.sleep(random.randint(1, 10))
|
||||
raise ShadowBanError()
|
||||
|
||||
await self.auth.check_user_in_room(room_id, target_user_id)
|
||||
await self.auth.check_user_in_room(room_id, requester)
|
||||
|
||||
logger.debug("%s has started typing in %s", target_user_id, room_id)
|
||||
|
||||
|
@ -289,12 +288,11 @@ class TypingWriterHandler(FollowerTypingHandler):
|
|||
self, target_user: UserID, requester: Requester, room_id: str
|
||||
) -> None:
|
||||
target_user_id = target_user.to_string()
|
||||
auth_user_id = requester.user.to_string()
|
||||
|
||||
if not self.is_mine_id(target_user_id):
|
||||
raise SynapseError(400, "User is not hosted on this homeserver")
|
||||
|
||||
if target_user_id != auth_user_id:
|
||||
if target_user != requester.user:
|
||||
raise AuthError(400, "Cannot set another user's typing state")
|
||||
|
||||
if requester.shadow_banned:
|
||||
|
@ -302,7 +300,7 @@ class TypingWriterHandler(FollowerTypingHandler):
|
|||
await self.clock.sleep(random.randint(1, 10))
|
||||
raise ShadowBanError()
|
||||
|
||||
await self.auth.check_user_in_room(room_id, target_user_id)
|
||||
await self.auth.check_user_in_room(room_id, requester)
|
||||
|
||||
logger.debug("%s has stopped typing in %s", target_user_id, room_id)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue