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

Commit 3dd175b

Browse files
authored
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.
1 parent 94375f7 commit 3dd175b

File tree

26 files changed

+203
-208
lines changed

26 files changed

+203
-208
lines changed

changelog.d/13024.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Refactor methods in `synapse.api.auth.Auth` to use `Requester` objects everywhere instead of user IDs.

synapse/api/auth.py

Lines changed: 95 additions & 107 deletions
Large diffs are not rendered by default.

synapse/handlers/auth.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ async def validate_user_via_ui_auth(
280280
that it isn't stolen by re-authenticating them.
281281
282282
Args:
283-
requester: The user, as given by the access token
283+
requester: The user making the request, according to the access token.
284284
285285
request: The request sent by the client.
286286
@@ -1435,20 +1435,25 @@ async def delete_access_token(self, access_token: str) -> None:
14351435
access_token: access token to be deleted
14361436
14371437
"""
1438-
user_info = await self.auth.get_user_by_access_token(access_token)
1438+
token = await self.store.get_user_by_access_token(access_token)
1439+
if not token:
1440+
# At this point, the token should already have been fetched once by
1441+
# the caller, so this should not happen, unless of a race condition
1442+
# between two delete requests
1443+
raise SynapseError(HTTPStatus.UNAUTHORIZED, "Unrecognised access token")
14391444
await self.store.delete_access_token(access_token)
14401445

14411446
# see if any modules want to know about this
14421447
await self.password_auth_provider.on_logged_out(
1443-
user_id=user_info.user_id,
1444-
device_id=user_info.device_id,
1448+
user_id=token.user_id,
1449+
device_id=token.device_id,
14451450
access_token=access_token,
14461451
)
14471452

14481453
# delete pushers associated with this access token
1449-
if user_info.token_id is not None:
1454+
if token.token_id is not None:
14501455
await self.hs.get_pusherpool().remove_pushers_by_access_token(
1451-
user_info.user_id, (user_info.token_id,)
1456+
token.user_id, (token.token_id,)
14521457
)
14531458

14541459
async def delete_access_tokens_for_user(

synapse/handlers/directory.py

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
from synapse.appservice import ApplicationService
3131
from synapse.module_api import NOT_SPAM
3232
from synapse.storage.databases.main.directory import RoomAliasMapping
33-
from synapse.types import JsonDict, Requester, RoomAlias, UserID, get_domain_from_id
33+
from synapse.types import JsonDict, Requester, RoomAlias, get_domain_from_id
3434

3535
if TYPE_CHECKING:
3636
from synapse.server import HomeServer
@@ -133,7 +133,7 @@ async def create_association(
133133
else:
134134
# Server admins are not subject to the same constraints as normal
135135
# users when creating an alias (e.g. being in the room).
136-
is_admin = await self.auth.is_server_admin(requester.user)
136+
is_admin = await self.auth.is_server_admin(requester)
137137

138138
if (self.require_membership and check_membership) and not is_admin:
139139
rooms_for_user = await self.store.get_rooms_for_user(user_id)
@@ -197,7 +197,7 @@ async def delete_association(
197197
user_id = requester.user.to_string()
198198

199199
try:
200-
can_delete = await self._user_can_delete_alias(room_alias, user_id)
200+
can_delete = await self._user_can_delete_alias(room_alias, requester)
201201
except StoreError as e:
202202
if e.code == 404:
203203
raise NotFoundError("Unknown room alias")
@@ -400,7 +400,9 @@ def can_modify_alias(self, alias: RoomAlias, user_id: Optional[str] = None) -> b
400400
# either no interested services, or no service with an exclusive lock
401401
return True
402402

403-
async def _user_can_delete_alias(self, alias: RoomAlias, user_id: str) -> bool:
403+
async def _user_can_delete_alias(
404+
self, alias: RoomAlias, requester: Requester
405+
) -> bool:
404406
"""Determine whether a user can delete an alias.
405407
406408
One of the following must be true:
@@ -413,7 +415,7 @@ async def _user_can_delete_alias(self, alias: RoomAlias, user_id: str) -> bool:
413415
"""
414416
creator = await self.store.get_room_alias_creator(alias.to_string())
415417

416-
if creator == user_id:
418+
if creator == requester.user.to_string():
417419
return True
418420

419421
# Resolve the alias to the corresponding room.
@@ -422,9 +424,7 @@ async def _user_can_delete_alias(self, alias: RoomAlias, user_id: str) -> bool:
422424
if not room_id:
423425
return False
424426

425-
return await self.auth.check_can_change_room_list(
426-
room_id, UserID.from_string(user_id)
427-
)
427+
return await self.auth.check_can_change_room_list(room_id, requester)
428428

429429
async def edit_published_room_list(
430430
self, requester: Requester, room_id: str, visibility: str
@@ -463,7 +463,7 @@ async def edit_published_room_list(
463463
raise SynapseError(400, "Unknown room")
464464

465465
can_change_room_list = await self.auth.check_can_change_room_list(
466-
room_id, requester.user
466+
room_id, requester
467467
)
468468
if not can_change_room_list:
469469
raise AuthError(
@@ -528,10 +528,8 @@ async def get_aliases_for_room(
528528
Get a list of the aliases that currently point to this room on this server
529529
"""
530530
# allow access to server admins and current members of the room
531-
is_admin = await self.auth.is_server_admin(requester.user)
531+
is_admin = await self.auth.is_server_admin(requester)
532532
if not is_admin:
533-
await self.auth.check_user_in_room_or_world_readable(
534-
room_id, requester.user.to_string()
535-
)
533+
await self.auth.check_user_in_room_or_world_readable(room_id, requester)
536534

537535
return await self.store.get_aliases_for_room(room_id)

synapse/handlers/initial_sync.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -309,18 +309,18 @@ async def room_initial_sync(
309309
if blocked:
310310
raise SynapseError(403, "This room has been blocked on this server")
311311

312-
user_id = requester.user.to_string()
313-
314312
(
315313
membership,
316314
member_event_id,
317315
) = await self.auth.check_user_in_room_or_world_readable(
318316
room_id,
319-
user_id,
317+
requester,
320318
allow_departed_users=True,
321319
)
322320
is_peeking = member_event_id is None
323321

322+
user_id = requester.user.to_string()
323+
324324
if membership == Membership.JOIN:
325325
result = await self._room_initial_sync_joined(
326326
user_id, room_id, pagin_config, membership, is_peeking

synapse/handlers/message.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,15 @@ def __init__(self, hs: "HomeServer"):
104104

105105
async def get_room_data(
106106
self,
107-
user_id: str,
107+
requester: Requester,
108108
room_id: str,
109109
event_type: str,
110110
state_key: str,
111111
) -> Optional[EventBase]:
112112
"""Get data from a room.
113113
114114
Args:
115-
user_id
115+
requester: The user who did the request.
116116
room_id
117117
event_type
118118
state_key
@@ -125,7 +125,7 @@ async def get_room_data(
125125
membership,
126126
membership_event_id,
127127
) = await self.auth.check_user_in_room_or_world_readable(
128-
room_id, user_id, allow_departed_users=True
128+
room_id, requester, allow_departed_users=True
129129
)
130130

131131
if membership == Membership.JOIN:
@@ -161,11 +161,10 @@ async def get_room_data(
161161

162162
async def get_state_events(
163163
self,
164-
user_id: str,
164+
requester: Requester,
165165
room_id: str,
166166
state_filter: Optional[StateFilter] = None,
167167
at_token: Optional[StreamToken] = None,
168-
is_guest: bool = False,
169168
) -> List[dict]:
170169
"""Retrieve all state events for a given room. If the user is
171170
joined to the room then return the current state. If the user has
@@ -174,14 +173,13 @@ async def get_state_events(
174173
visible.
175174
176175
Args:
177-
user_id: The user requesting state events.
176+
requester: The user requesting state events.
178177
room_id: The room ID to get all state events from.
179178
state_filter: The state filter used to fetch state from the database.
180179
at_token: the stream token of the at which we are requesting
181180
the stats. If the user is not allowed to view the state as of that
182181
stream token, we raise a 403 SynapseError. If None, returns the current
183182
state based on the current_state_events table.
184-
is_guest: whether this user is a guest
185183
Returns:
186184
A list of dicts representing state events. [{}, {}, {}]
187185
Raises:
@@ -191,6 +189,7 @@ async def get_state_events(
191189
members of this room.
192190
"""
193191
state_filter = state_filter or StateFilter.all()
192+
user_id = requester.user.to_string()
194193

195194
if at_token:
196195
last_event_id = (
@@ -223,7 +222,7 @@ async def get_state_events(
223222
membership,
224223
membership_event_id,
225224
) = await self.auth.check_user_in_room_or_world_readable(
226-
room_id, user_id, allow_departed_users=True
225+
room_id, requester, allow_departed_users=True
227226
)
228227

229228
if membership == Membership.JOIN:
@@ -317,12 +316,11 @@ async def get_joined_members(self, requester: Requester, room_id: str) -> dict:
317316
Returns:
318317
A dict of user_id to profile info
319318
"""
320-
user_id = requester.user.to_string()
321319
if not requester.app_service:
322320
# We check AS auth after fetching the room membership, as it
323321
# requires us to pull out all joined members anyway.
324322
membership, _ = await self.auth.check_user_in_room_or_world_readable(
325-
room_id, user_id, allow_departed_users=True
323+
room_id, requester, allow_departed_users=True
326324
)
327325
if membership != Membership.JOIN:
328326
raise SynapseError(
@@ -340,7 +338,10 @@ async def get_joined_members(self, requester: Requester, room_id: str) -> dict:
340338
# If this is an AS, double check that they are allowed to see the members.
341339
# This can either be because the AS user is in the room or because there
342340
# is a user in the room that the AS is "interested in"
343-
if requester.app_service and user_id not in users_with_profile:
341+
if (
342+
requester.app_service
343+
and requester.user.to_string() not in users_with_profile
344+
):
344345
for uid in users_with_profile:
345346
if requester.app_service.is_interested_in_user(uid):
346347
break

synapse/handlers/pagination.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ async def get_messages(
464464
membership,
465465
member_event_id,
466466
) = await self.auth.check_user_in_room_or_world_readable(
467-
room_id, user_id, allow_departed_users=True
467+
room_id, requester, allow_departed_users=True
468468
)
469469

470470
if pagin_config.direction == "b":

synapse/handlers/register.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,13 @@
2929
JoinRules,
3030
LoginType,
3131
)
32-
from synapse.api.errors import AuthError, Codes, ConsentNotGivenError, SynapseError
32+
from synapse.api.errors import (
33+
AuthError,
34+
Codes,
35+
ConsentNotGivenError,
36+
InvalidClientTokenError,
37+
SynapseError,
38+
)
3339
from synapse.appservice import ApplicationService
3440
from synapse.config.server import is_threepid_reserved
3541
from synapse.http.servlet import assert_params_in_dict
@@ -180,10 +186,7 @@ async def check_username(
180186
)
181187
if guest_access_token:
182188
user_data = await self.auth.get_user_by_access_token(guest_access_token)
183-
if (
184-
not user_data.is_guest
185-
or UserID.from_string(user_data.user_id).localpart != localpart
186-
):
189+
if not user_data.is_guest or user_data.user.localpart != localpart:
187190
raise AuthError(
188191
403,
189192
"Cannot register taken user ID without valid guest "
@@ -618,7 +621,7 @@ async def appservice_register(self, user_localpart: str, as_token: str) -> str:
618621
user_id = user.to_string()
619622
service = self.store.get_app_service_by_token(as_token)
620623
if not service:
621-
raise AuthError(403, "Invalid application service token.")
624+
raise InvalidClientTokenError()
622625
if not service.is_interested_in_user(user_id):
623626
raise SynapseError(
624627
400,

synapse/handlers/relations.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ async def get_relations(
103103

104104
# TODO Properly handle a user leaving a room.
105105
(_, member_event_id) = await self._auth.check_user_in_room_or_world_readable(
106-
room_id, user_id, allow_departed_users=True
106+
room_id, requester, allow_departed_users=True
107107
)
108108

109109
# This gets the original event and checks that a) the event exists and

synapse/handlers/room.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,7 @@ async def create_room(
721721
# allow the server notices mxid to create rooms
722722
is_requester_admin = True
723723
else:
724-
is_requester_admin = await self.auth.is_server_admin(requester.user)
724+
is_requester_admin = await self.auth.is_server_admin(requester)
725725

726726
# Let the third party rules modify the room creation config if needed, or abort
727727
# the room creation entirely with an exception.
@@ -1279,7 +1279,7 @@ async def get_event_context(
12791279
"""
12801280
user = requester.user
12811281
if use_admin_priviledge:
1282-
await assert_user_is_admin(self.auth, requester.user)
1282+
await assert_user_is_admin(self.auth, requester)
12831283

12841284
before_limit = math.floor(limit / 2.0)
12851285
after_limit = limit - before_limit

0 commit comments

Comments
 (0)