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

Commit d23c394

Browse files
authored
Reduce CPU overhead of change password endpoint (#16264)
1 parent 1cd410a commit d23c394

File tree

2 files changed

+55
-58
lines changed

2 files changed

+55
-58
lines changed

changelog.d/16264.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Reduce CPU overhead of change password endpoint.

synapse/rest/client/account.py

Lines changed: 54 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -179,85 +179,81 @@ async def on_POST(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
179179
#
180180
# In the second case, we require a password to confirm their identity.
181181

182-
requester = None
183-
if self.auth.has_access_token(request):
184-
requester = await self.auth.get_user_by_req(request)
185-
try:
182+
try:
183+
requester = None
184+
if self.auth.has_access_token(request):
185+
requester = await self.auth.get_user_by_req(request)
186186
params, session_id = await self.auth_handler.validate_user_via_ui_auth(
187187
requester,
188188
request,
189189
body.dict(exclude_unset=True),
190190
"modify your account password",
191191
)
192-
except InteractiveAuthIncompleteError as e:
193-
# The user needs to provide more steps to complete auth, but
194-
# they're not required to provide the password again.
195-
#
196-
# If a password is available now, hash the provided password and
197-
# store it for later.
198-
if new_password:
199-
new_password_hash = await self.auth_handler.hash(new_password)
200-
await self.auth_handler.set_session_data(
201-
e.session_id,
202-
UIAuthSessionDataConstants.PASSWORD_HASH,
203-
new_password_hash,
204-
)
205-
raise
206-
user_id = requester.user.to_string()
207-
else:
208-
try:
192+
user_id = requester.user.to_string()
193+
else:
209194
result, params, session_id = await self.auth_handler.check_ui_auth(
210195
[[LoginType.EMAIL_IDENTITY]],
211196
request,
212197
body.dict(exclude_unset=True),
213198
"modify your account password",
214199
)
215-
except InteractiveAuthIncompleteError as e:
216-
# The user needs to provide more steps to complete auth, but
217-
# they're not required to provide the password again.
218-
#
219-
# If a password is available now, hash the provided password and
220-
# store it for later.
221-
if new_password:
222-
new_password_hash = await self.auth_handler.hash(new_password)
223-
await self.auth_handler.set_session_data(
224-
e.session_id,
225-
UIAuthSessionDataConstants.PASSWORD_HASH,
226-
new_password_hash,
200+
201+
if LoginType.EMAIL_IDENTITY in result:
202+
threepid = result[LoginType.EMAIL_IDENTITY]
203+
if "medium" not in threepid or "address" not in threepid:
204+
raise SynapseError(500, "Malformed threepid")
205+
if threepid["medium"] == "email":
206+
# For emails, canonicalise the address.
207+
# We store all email addresses canonicalised in the DB.
208+
# (See add_threepid in synapse/handlers/auth.py)
209+
try:
210+
threepid["address"] = validate_email(threepid["address"])
211+
except ValueError as e:
212+
raise SynapseError(400, str(e))
213+
# if using email, we must know about the email they're authing with!
214+
threepid_user_id = await self.datastore.get_user_id_by_threepid(
215+
threepid["medium"], threepid["address"]
227216
)
217+
if not threepid_user_id:
218+
raise SynapseError(
219+
404, "Email address not found", Codes.NOT_FOUND
220+
)
221+
user_id = threepid_user_id
222+
else:
223+
logger.error("Auth succeeded but no known type! %r", result.keys())
224+
raise SynapseError(500, "", Codes.UNKNOWN)
225+
226+
except InteractiveAuthIncompleteError as e:
227+
# The user needs to provide more steps to complete auth, but
228+
# they're not required to provide the password again.
229+
#
230+
# If a password is available now, hash the provided password and
231+
# store it for later. We only do this if we don't already have the
232+
# password hash stored, to avoid repeatedly hashing the password.
233+
234+
if not new_password:
228235
raise
229236

230-
if LoginType.EMAIL_IDENTITY in result:
231-
threepid = result[LoginType.EMAIL_IDENTITY]
232-
if "medium" not in threepid or "address" not in threepid:
233-
raise SynapseError(500, "Malformed threepid")
234-
if threepid["medium"] == "email":
235-
# For emails, canonicalise the address.
236-
# We store all email addresses canonicalised in the DB.
237-
# (See add_threepid in synapse/handlers/auth.py)
238-
try:
239-
threepid["address"] = validate_email(threepid["address"])
240-
except ValueError as e:
241-
raise SynapseError(400, str(e))
242-
# if using email, we must know about the email they're authing with!
243-
threepid_user_id = await self.datastore.get_user_id_by_threepid(
244-
threepid["medium"], threepid["address"]
245-
)
246-
if not threepid_user_id:
247-
raise SynapseError(404, "Email address not found", Codes.NOT_FOUND)
248-
user_id = threepid_user_id
249-
else:
250-
logger.error("Auth succeeded but no known type! %r", result.keys())
251-
raise SynapseError(500, "", Codes.UNKNOWN)
237+
existing_session_password_hash = await self.auth_handler.get_session_data(
238+
e.session_id, UIAuthSessionDataConstants.PASSWORD_HASH, None
239+
)
240+
if existing_session_password_hash:
241+
raise
242+
243+
new_password_hash = await self.auth_handler.hash(new_password)
244+
await self.auth_handler.set_session_data(
245+
e.session_id,
246+
UIAuthSessionDataConstants.PASSWORD_HASH,
247+
new_password_hash,
248+
)
249+
raise
252250

253251
# If we have a password in this request, prefer it. Otherwise, use the
254252
# password hash from an earlier request.
255253
if new_password:
256254
password_hash: Optional[str] = await self.auth_handler.hash(new_password)
257255
elif session_id is not None:
258-
password_hash = await self.auth_handler.get_session_data(
259-
session_id, UIAuthSessionDataConstants.PASSWORD_HASH, None
260-
)
256+
password_hash = existing_session_password_hash
261257
else:
262258
# UI validation was skipped, but the request did not include a new
263259
# password.

0 commit comments

Comments
 (0)