Reduce CPU overhead of change password endpoint (#16264)

This commit is contained in:
Erik Johnston 2023-09-08 13:06:00 +01:00 committed by GitHub
parent 1cd410a783
commit d23c394669
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 58 deletions

1
changelog.d/16264.misc Normal file
View file

@ -0,0 +1 @@
Reduce CPU overhead of change password endpoint.

View file

@ -179,53 +179,24 @@ class PasswordRestServlet(RestServlet):
# #
# In the second case, we require a password to confirm their identity. # In the second case, we require a password to confirm their identity.
try:
requester = None requester = None
if self.auth.has_access_token(request): if self.auth.has_access_token(request):
requester = await self.auth.get_user_by_req(request) requester = await self.auth.get_user_by_req(request)
try:
params, session_id = await self.auth_handler.validate_user_via_ui_auth( params, session_id = await self.auth_handler.validate_user_via_ui_auth(
requester, requester,
request, request,
body.dict(exclude_unset=True), body.dict(exclude_unset=True),
"modify your account password", "modify your account password",
) )
except InteractiveAuthIncompleteError as e:
# The user needs to provide more steps to complete auth, but
# they're not required to provide the password again.
#
# If a password is available now, hash the provided password and
# store it for later.
if new_password:
new_password_hash = await self.auth_handler.hash(new_password)
await self.auth_handler.set_session_data(
e.session_id,
UIAuthSessionDataConstants.PASSWORD_HASH,
new_password_hash,
)
raise
user_id = requester.user.to_string() user_id = requester.user.to_string()
else: else:
try:
result, params, session_id = await self.auth_handler.check_ui_auth( result, params, session_id = await self.auth_handler.check_ui_auth(
[[LoginType.EMAIL_IDENTITY]], [[LoginType.EMAIL_IDENTITY]],
request, request,
body.dict(exclude_unset=True), body.dict(exclude_unset=True),
"modify your account password", "modify your account password",
) )
except InteractiveAuthIncompleteError as e:
# The user needs to provide more steps to complete auth, but
# they're not required to provide the password again.
#
# If a password is available now, hash the provided password and
# store it for later.
if new_password:
new_password_hash = await self.auth_handler.hash(new_password)
await self.auth_handler.set_session_data(
e.session_id,
UIAuthSessionDataConstants.PASSWORD_HASH,
new_password_hash,
)
raise
if LoginType.EMAIL_IDENTITY in result: if LoginType.EMAIL_IDENTITY in result:
threepid = result[LoginType.EMAIL_IDENTITY] threepid = result[LoginType.EMAIL_IDENTITY]
@ -244,20 +215,45 @@ class PasswordRestServlet(RestServlet):
threepid["medium"], threepid["address"] threepid["medium"], threepid["address"]
) )
if not threepid_user_id: if not threepid_user_id:
raise SynapseError(404, "Email address not found", Codes.NOT_FOUND) raise SynapseError(
404, "Email address not found", Codes.NOT_FOUND
)
user_id = threepid_user_id user_id = threepid_user_id
else: else:
logger.error("Auth succeeded but no known type! %r", result.keys()) logger.error("Auth succeeded but no known type! %r", result.keys())
raise SynapseError(500, "", Codes.UNKNOWN) raise SynapseError(500, "", Codes.UNKNOWN)
except InteractiveAuthIncompleteError as e:
# The user needs to provide more steps to complete auth, but
# they're not required to provide the password again.
#
# If a password is available now, hash the provided password and
# store it for later. We only do this if we don't already have the
# password hash stored, to avoid repeatedly hashing the password.
if not new_password:
raise
existing_session_password_hash = await self.auth_handler.get_session_data(
e.session_id, UIAuthSessionDataConstants.PASSWORD_HASH, None
)
if existing_session_password_hash:
raise
new_password_hash = await self.auth_handler.hash(new_password)
await self.auth_handler.set_session_data(
e.session_id,
UIAuthSessionDataConstants.PASSWORD_HASH,
new_password_hash,
)
raise
# If we have a password in this request, prefer it. Otherwise, use the # If we have a password in this request, prefer it. Otherwise, use the
# password hash from an earlier request. # password hash from an earlier request.
if new_password: if new_password:
password_hash: Optional[str] = await self.auth_handler.hash(new_password) password_hash: Optional[str] = await self.auth_handler.hash(new_password)
elif session_id is not None: elif session_id is not None:
password_hash = await self.auth_handler.get_session_data( password_hash = existing_session_password_hash
session_id, UIAuthSessionDataConstants.PASSWORD_HASH, None
)
else: else:
# UI validation was skipped, but the request did not include a new # UI validation was skipped, but the request did not include a new
# password. # password.