Fix setting a user's external_id via the admin API returns 500 and deletes users existing external mappings if that external ID is already mapped (#11051)

Fixes #10846
This commit is contained in:
Dirk Klimpel 2021-10-21 10:52:32 +02:00 committed by GitHub
parent 57501d9194
commit ef7fe09778
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 321 additions and 37 deletions

View file

@ -35,6 +35,7 @@ from synapse.rest.admin._base import (
assert_user_is_admin,
)
from synapse.rest.client._base import client_patterns
from synapse.storage.databases.main.registration import ExternalIDReuseException
from synapse.storage.databases.main.stats import UserSortOrder
from synapse.types import JsonDict, UserID
@ -228,12 +229,12 @@ class UserRestServletV2(RestServlet):
if not isinstance(deactivate, bool):
raise SynapseError(400, "'deactivated' parameter is not of type boolean")
# convert List[Dict[str, str]] into Set[Tuple[str, str]]
# convert List[Dict[str, str]] into List[Tuple[str, str]]
if external_ids is not None:
new_external_ids = {
new_external_ids = [
(external_id["auth_provider"], external_id["external_id"])
for external_id in external_ids
}
]
# convert List[Dict[str, str]] into Set[Tuple[str, str]]
if threepids is not None:
@ -275,28 +276,13 @@ class UserRestServletV2(RestServlet):
)
if external_ids is not None:
# get changed external_ids (added and removed)
cur_external_ids = set(
await self.store.get_external_ids_by_user(user_id)
)
add_external_ids = new_external_ids - cur_external_ids
del_external_ids = cur_external_ids - new_external_ids
# remove old external_ids
for auth_provider, external_id in del_external_ids:
await self.store.remove_user_external_id(
auth_provider,
external_id,
user_id,
)
# add new external_ids
for auth_provider, external_id in add_external_ids:
await self.store.record_user_external_id(
auth_provider,
external_id,
try:
await self.store.replace_user_external_id(
new_external_ids,
user_id,
)
except ExternalIDReuseException:
raise SynapseError(409, "External id is already in use.")
if "avatar_url" in body and isinstance(body["avatar_url"], str):
await self.profile_handler.set_avatar_url(
@ -384,12 +370,15 @@ class UserRestServletV2(RestServlet):
)
if external_ids is not None:
for auth_provider, external_id in new_external_ids:
await self.store.record_user_external_id(
auth_provider,
external_id,
user_id,
)
try:
for auth_provider, external_id in new_external_ids:
await self.store.record_user_external_id(
auth_provider,
external_id,
user_id,
)
except ExternalIDReuseException:
raise SynapseError(409, "External id is already in use.")
if "avatar_url" in body and isinstance(body["avatar_url"], str):
await self.profile_handler.set_avatar_url(