mirror of
https://github.com/element-hq/synapse.git
synced 2024-11-23 01:55:53 +03:00
Reduce CPU overhead of change password endpoint (#16264)
This commit is contained in:
parent
1cd410a783
commit
d23c394669
2 changed files with 55 additions and 58 deletions
1
changelog.d/16264.misc
Normal file
1
changelog.d/16264.misc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Reduce CPU overhead of change password endpoint.
|
|
@ -179,85 +179,81 @@ 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.
|
||||||
|
|
||||||
requester = None
|
try:
|
||||||
if self.auth.has_access_token(request):
|
requester = None
|
||||||
requester = await self.auth.get_user_by_req(request)
|
if self.auth.has_access_token(request):
|
||||||
try:
|
requester = await self.auth.get_user_by_req(request)
|
||||||
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:
|
user_id = requester.user.to_string()
|
||||||
# The user needs to provide more steps to complete auth, but
|
else:
|
||||||
# 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()
|
|
||||||
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
|
if LoginType.EMAIL_IDENTITY in result:
|
||||||
# they're not required to provide the password again.
|
threepid = result[LoginType.EMAIL_IDENTITY]
|
||||||
#
|
if "medium" not in threepid or "address" not in threepid:
|
||||||
# If a password is available now, hash the provided password and
|
raise SynapseError(500, "Malformed threepid")
|
||||||
# store it for later.
|
if threepid["medium"] == "email":
|
||||||
if new_password:
|
# For emails, canonicalise the address.
|
||||||
new_password_hash = await self.auth_handler.hash(new_password)
|
# We store all email addresses canonicalised in the DB.
|
||||||
await self.auth_handler.set_session_data(
|
# (See add_threepid in synapse/handlers/auth.py)
|
||||||
e.session_id,
|
try:
|
||||||
UIAuthSessionDataConstants.PASSWORD_HASH,
|
threepid["address"] = validate_email(threepid["address"])
|
||||||
new_password_hash,
|
except ValueError as e:
|
||||||
|
raise SynapseError(400, str(e))
|
||||||
|
# if using email, we must know about the email they're authing with!
|
||||||
|
threepid_user_id = await self.datastore.get_user_id_by_threepid(
|
||||||
|
threepid["medium"], threepid["address"]
|
||||||
)
|
)
|
||||||
|
if not threepid_user_id:
|
||||||
|
raise SynapseError(
|
||||||
|
404, "Email address not found", Codes.NOT_FOUND
|
||||||
|
)
|
||||||
|
user_id = threepid_user_id
|
||||||
|
else:
|
||||||
|
logger.error("Auth succeeded but no known type! %r", result.keys())
|
||||||
|
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
|
raise
|
||||||
|
|
||||||
if LoginType.EMAIL_IDENTITY in result:
|
existing_session_password_hash = await self.auth_handler.get_session_data(
|
||||||
threepid = result[LoginType.EMAIL_IDENTITY]
|
e.session_id, UIAuthSessionDataConstants.PASSWORD_HASH, None
|
||||||
if "medium" not in threepid or "address" not in threepid:
|
)
|
||||||
raise SynapseError(500, "Malformed threepid")
|
if existing_session_password_hash:
|
||||||
if threepid["medium"] == "email":
|
raise
|
||||||
# For emails, canonicalise the address.
|
|
||||||
# We store all email addresses canonicalised in the DB.
|
new_password_hash = await self.auth_handler.hash(new_password)
|
||||||
# (See add_threepid in synapse/handlers/auth.py)
|
await self.auth_handler.set_session_data(
|
||||||
try:
|
e.session_id,
|
||||||
threepid["address"] = validate_email(threepid["address"])
|
UIAuthSessionDataConstants.PASSWORD_HASH,
|
||||||
except ValueError as e:
|
new_password_hash,
|
||||||
raise SynapseError(400, str(e))
|
)
|
||||||
# if using email, we must know about the email they're authing with!
|
raise
|
||||||
threepid_user_id = await self.datastore.get_user_id_by_threepid(
|
|
||||||
threepid["medium"], threepid["address"]
|
|
||||||
)
|
|
||||||
if not threepid_user_id:
|
|
||||||
raise SynapseError(404, "Email address not found", Codes.NOT_FOUND)
|
|
||||||
user_id = threepid_user_id
|
|
||||||
else:
|
|
||||||
logger.error("Auth succeeded but no known type! %r", result.keys())
|
|
||||||
raise SynapseError(500, "", Codes.UNKNOWN)
|
|
||||||
|
|
||||||
# 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.
|
||||||
|
|
Loading…
Reference in a new issue