diff --git a/synapse/rest/client/devices.py b/synapse/rest/client/devices.py
index 690d2ec406..51f17f80da 100644
--- a/synapse/rest/client/devices.py
+++ b/synapse/rest/client/devices.py
@@ -232,7 +232,7 @@ class DehydratedDeviceDataModel(RequestBodyModel):
class DehydratedDeviceServlet(RestServlet):
"""Retrieve or store a dehydrated device.
- Implements either MSC2697 or MSC3814.
+ Implements MSC2697.
GET /org.matrix.msc2697.v2/dehydrated_device
@@ -266,7 +266,12 @@ class DehydratedDeviceServlet(RestServlet):
"""
- def __init__(self, hs: "HomeServer", msc2697: bool = True):
+ PATTERNS = client_patterns(
+ "/org.matrix.msc2697.v2/dehydrated_device$",
+ releases=(),
+ )
+
+ def __init__(self, hs: "HomeServer"):
super().__init__()
self.hs = hs
self.auth = hs.get_auth()
@@ -274,13 +279,6 @@ class DehydratedDeviceServlet(RestServlet):
assert isinstance(handler, DeviceHandler)
self.device_handler = handler
- self.PATTERNS = client_patterns(
- "/org.matrix.msc2697.v2/dehydrated_device$"
- if msc2697
- else "/org.matrix.msc3814.v1/dehydrated_device$",
- releases=(),
- )
-
async def on_GET(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
requester = await self.auth.get_user_by_req(request)
dehydrated_device = await self.device_handler.get_dehydrated_device(
@@ -513,10 +511,8 @@ class DehydratedDeviceV2Servlet(RestServlet):
if dehydrated_device is not None:
(device_id, device_data) = dehydrated_device
- result = await self.device_handler.rehydrate_device(
- requester.user.to_string(),
- self.auth.get_access_token_from_request(request),
- device_id,
+ await self.device_handler.delete_dehydrated_device(
+ requester.user.to_string(), device_id
)
result = {"device_id": device_id}
@@ -538,6 +534,14 @@ class DehydratedDeviceV2Servlet(RestServlet):
requester = await self.auth.get_user_by_req(request)
user_id = requester.user.to_string()
+ old_dehydrated_device = await self.device_handler.get_dehydrated_device(user_id)
+
+ # if an old device exists, delete it before creating a new one
+ if old_dehydrated_device:
+ await self.device_handler.delete_dehydrated_device(
+ user_id, old_dehydrated_device[0]
+ )
+
device_info = submission.dict()
if "device_keys" not in device_info.keys():
raise SynapseError(
@@ -573,7 +577,7 @@ def register_servlets(hs: "HomeServer", http_server: HttpServer) -> None:
if hs.config.worker.worker_app is None:
DeviceRestServlet(hs).register(http_server)
if hs.config.experimental.msc2697_enabled:
- DehydratedDeviceServlet(hs, msc2697=True).register(http_server)
+ DehydratedDeviceServlet(hs).register(http_server)
ClaimDehydratedDeviceServlet(hs).register(http_server)
if hs.config.experimental.msc3814_enabled:
DehydratedDeviceV2Servlet(hs).register(http_server)
diff --git a/synapse/rest/client/room_upgrade_rest_servlet.py b/synapse/rest/client/room_upgrade_rest_servlet.py
index 6a7792e18b..4a5d9e13e7 100644
--- a/synapse/rest/client/room_upgrade_rest_servlet.py
+++ b/synapse/rest/client/room_upgrade_rest_servlet.py
@@ -17,6 +17,7 @@ from typing import TYPE_CHECKING, Tuple
from synapse.api.errors import Codes, ShadowBanError, SynapseError
from synapse.api.room_versions import KNOWN_ROOM_VERSIONS
+from synapse.handlers.worker_lock import DELETE_ROOM_LOCK_NAME
from synapse.http.server import HttpServer
from synapse.http.servlet import (
RestServlet,
@@ -60,6 +61,7 @@ class RoomUpgradeRestServlet(RestServlet):
self._hs = hs
self._room_creation_handler = hs.get_room_creation_handler()
self._auth = hs.get_auth()
+ self._worker_lock_handler = hs.get_worker_locks_handler()
async def on_POST(
self, request: SynapseRequest, room_id: str
@@ -78,9 +80,12 @@ class RoomUpgradeRestServlet(RestServlet):
)
try:
- new_room_id = await self._room_creation_handler.upgrade_room(
- requester, room_id, new_version
- )
+ async with self._worker_lock_handler.acquire_read_write_lock(
+ DELETE_ROOM_LOCK_NAME, room_id, write=False
+ ):
+ new_room_id = await self._room_creation_handler.upgrade_room(
+ requester, room_id, new_version
+ )
except ShadowBanError:
# Generate a random room ID.
new_room_id = stringutils.random_string(18)
diff --git a/synapse/rest/client/transactions.py b/synapse/rest/client/transactions.py
index 0d8a63d8be..3d814c404d 100644
--- a/synapse/rest/client/transactions.py
+++ b/synapse/rest/client/transactions.py
@@ -50,8 +50,6 @@ class HttpTransactionCache:
# for at *LEAST* 30 mins, and at *MOST* 60 mins.
self.cleaner = self.clock.looping_call(self._cleanup, CLEANUP_PERIOD_MS)
- self._msc3970_enabled = hs.config.experimental.msc3970_enabled
-
def _get_transaction_key(self, request: IRequest, requester: Requester) -> Hashable:
"""A helper function which returns a transaction key that can be used
with TransactionCache for idempotent requests.
@@ -78,18 +76,20 @@ class HttpTransactionCache:
elif requester.app_service is not None:
return (path, "appservice", requester.app_service.id)
- # With MSC3970, we use the user ID and device ID as the transaction key
- elif self._msc3970_enabled:
+ # Use the user ID and device ID as the transaction key.
+ elif requester.device_id:
assert requester.user, "Requester must have a user"
assert requester.device_id, "Requester must have a device_id"
return (path, "user", requester.user, requester.device_id)
- # Otherwise, the pre-MSC3970 behaviour is to use the access token ID
+ # Some requsters don't have device IDs, these are mostly handled above
+ # (appservice and guest users), but does not cover access tokens minted
+ # by the admin API. Use the access token ID instead.
else:
assert (
requester.access_token_id is not None
), "Requester must have an access_token_id"
- return (path, "user", requester.access_token_id)
+ return (path, "user_admin", requester.access_token_id)
def fetch_or_execute_request(
self,
|