Add an option to the set password API to choose whether to logout other devices. (#7085)

This commit is contained in:
Patrick Cloke 2020-03-18 07:50:00 -04:00 committed by GitHub
parent 6d110ddea4
commit 88b41986db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 38 additions and 19 deletions

1
changelog.d/7085.feature Normal file
View File

@ -0,0 +1 @@
Add an optional parameter to control whether other sessions are logged out when a user's password is modified.

View File

@ -38,6 +38,7 @@ The parameter ``threepids`` is optional.
The parameter ``avatar_url`` is optional. The parameter ``avatar_url`` is optional.
The parameter ``admin`` is optional and defaults to 'false'. The parameter ``admin`` is optional and defaults to 'false'.
The parameter ``deactivated`` is optional and defaults to 'false'. The parameter ``deactivated`` is optional and defaults to 'false'.
The parameter ``password`` is optional. If provided the user's password is updated and all devices are logged out.
If the user already exists then optional parameters default to the current value. If the user already exists then optional parameters default to the current value.
List Accounts List Accounts
@ -168,11 +169,14 @@ with a body of:
.. code:: json .. code:: json
{ {
"new_password": "<secret>" "new_password": "<secret>",
"logout_devices": true,
} }
including an ``access_token`` of a server admin. including an ``access_token`` of a server admin.
The parameter ``new_password`` is required.
The parameter ``logout_devices`` is optional and defaults to ``true``.
Get whether a user is a server administrator or not Get whether a user is a server administrator or not
=================================================== ===================================================

View File

@ -13,10 +13,12 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import logging import logging
from typing import Optional
from twisted.internet import defer from twisted.internet import defer
from synapse.api.errors import Codes, StoreError, SynapseError from synapse.api.errors import Codes, StoreError, SynapseError
from synapse.types import Requester
from ._base import BaseHandler from ._base import BaseHandler
@ -32,14 +34,17 @@ class SetPasswordHandler(BaseHandler):
self._device_handler = hs.get_device_handler() self._device_handler = hs.get_device_handler()
@defer.inlineCallbacks @defer.inlineCallbacks
def set_password(self, user_id, newpassword, requester=None): def set_password(
self,
user_id: str,
new_password: str,
logout_devices: bool,
requester: Optional[Requester] = None,
):
if not self.hs.config.password_localdb_enabled: if not self.hs.config.password_localdb_enabled:
raise SynapseError(403, "Password change disabled", errcode=Codes.FORBIDDEN) raise SynapseError(403, "Password change disabled", errcode=Codes.FORBIDDEN)
password_hash = yield self._auth_handler.hash(newpassword) password_hash = yield self._auth_handler.hash(new_password)
except_device_id = requester.device_id if requester else None
except_access_token_id = requester.access_token_id if requester else None
try: try:
yield self.store.user_set_password_hash(user_id, password_hash) yield self.store.user_set_password_hash(user_id, password_hash)
@ -48,14 +53,18 @@ class SetPasswordHandler(BaseHandler):
raise SynapseError(404, "Unknown user", Codes.NOT_FOUND) raise SynapseError(404, "Unknown user", Codes.NOT_FOUND)
raise e raise e
# we want to log out all of the user's other sessions. First delete # Optionally, log out all of the user's other sessions.
# all his other devices. if logout_devices:
yield self._device_handler.delete_all_devices_for_user( except_device_id = requester.device_id if requester else None
user_id, except_device_id=except_device_id except_access_token_id = requester.access_token_id if requester else None
)
# and now delete any access tokens which weren't associated with # First delete all of their other devices.
# devices (or were associated with this device). yield self._device_handler.delete_all_devices_for_user(
yield self._auth_handler.delete_access_tokens_for_user( user_id, except_device_id=except_device_id
user_id, except_token_id=except_access_token_id )
)
# and now delete any access tokens which weren't associated with
# devices (or were associated with this device).
yield self._auth_handler.delete_access_tokens_for_user(
user_id, except_token_id=except_access_token_id
)

View File

@ -221,8 +221,9 @@ class UserRestServletV2(RestServlet):
raise SynapseError(400, "Invalid password") raise SynapseError(400, "Invalid password")
else: else:
new_password = body["password"] new_password = body["password"]
logout_devices = True
await self.set_password_handler.set_password( await self.set_password_handler.set_password(
target_user.to_string(), new_password, requester target_user.to_string(), new_password, logout_devices, requester
) )
if "deactivated" in body: if "deactivated" in body:
@ -536,9 +537,10 @@ class ResetPasswordRestServlet(RestServlet):
params = parse_json_object_from_request(request) params = parse_json_object_from_request(request)
assert_params_in_dict(params, ["new_password"]) assert_params_in_dict(params, ["new_password"])
new_password = params["new_password"] new_password = params["new_password"]
logout_devices = params.get("logout_devices", True)
await self._set_password_handler.set_password( await self._set_password_handler.set_password(
target_user_id, new_password, requester target_user_id, new_password, logout_devices, requester
) )
return 200, {} return 200, {}

View File

@ -265,8 +265,11 @@ class PasswordRestServlet(RestServlet):
assert_params_in_dict(params, ["new_password"]) assert_params_in_dict(params, ["new_password"])
new_password = params["new_password"] new_password = params["new_password"]
logout_devices = params.get("logout_devices", True)
await self._set_password_handler.set_password(user_id, new_password, requester) await self._set_password_handler.set_password(
user_id, new_password, logout_devices, requester
)
return 200, {} return 200, {}