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

Commit

Permalink
Add an option to the set password API to choose whether to logout oth…
Browse files Browse the repository at this point in the history
…er devices. (#7085)

* commit '88b41986d':
  Add an option to the set password API to choose whether to logout other devices. (#7085)
  • Loading branch information
anoadragon453 committed Mar 24, 2020
2 parents 82bf3bd + 88b4198 commit 6ed566e
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 20 deletions.
1 change: 1 addition & 0 deletions changelog.d/7085.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add an optional parameter to control whether other sessions are logged out when a user's password is modified.
6 changes: 5 additions & 1 deletion docs/admin_api/user_admin_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ The parameter ``threepids`` is optional.
The parameter ``avatar_url`` is optional.
The parameter ``admin`` 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.

List Accounts
Expand Down Expand Up @@ -168,11 +169,14 @@ with a body of:
.. code:: json
{
"new_password": "<secret>"
"new_password": "<secret>",
"logout_devices": true,
}
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
===================================================
Expand Down
41 changes: 25 additions & 16 deletions synapse/handlers/set_password.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
from typing import Optional

from twisted.internet import defer

from synapse.api.errors import Codes, StoreError, SynapseError
from synapse.types import Requester

from ._base import BaseHandler

Expand All @@ -34,16 +36,19 @@ def __init__(self, hs):
self._password_policy_handler = hs.get_password_policy_handler()

@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:
raise SynapseError(403, "Password change disabled", errcode=Codes.FORBIDDEN)

self._password_policy_handler.validate_password(newpassword)
self._password_policy_handler.validate_password(new_password)

password_hash = yield self._auth_handler.hash(newpassword)

except_device_id = requester.device_id if requester else None
except_access_token_id = requester.access_token_id if requester else None
password_hash = yield self._auth_handler.hash(new_password)

try:
yield self.store.user_set_password_hash(user_id, password_hash)
Expand All @@ -52,14 +57,18 @@ def set_password(self, user_id, newpassword, requester=None):
raise SynapseError(404, "Unknown user", Codes.NOT_FOUND)
raise e

# we want to log out all of the user's other sessions. First delete
# all his other devices.
yield self._device_handler.delete_all_devices_for_user(
user_id, except_device_id=except_device_id
)
# Optionally, log out all of the user's other sessions.
if logout_devices:
except_device_id = requester.device_id if requester else None
except_access_token_id = requester.access_token_id if requester else None

# First delete all of their other devices.
yield self._device_handler.delete_all_devices_for_user(
user_id, except_device_id=except_device_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
)
# 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
)
6 changes: 4 additions & 2 deletions synapse/rest/admin/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,9 @@ async def on_PUT(self, request, user_id):
raise SynapseError(400, "Invalid password")
else:
new_password = body["password"]
logout_devices = True
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:
Expand Down Expand Up @@ -536,9 +537,10 @@ async def on_POST(self, request, target_user_id):
params = parse_json_object_from_request(request)
assert_params_in_dict(params, ["new_password"])
new_password = params["new_password"]
logout_devices = params.get("logout_devices", True)

await self._set_password_handler.set_password(
target_user_id, new_password, requester
target_user_id, new_password, logout_devices, requester
)
return 200, {}

Expand Down
5 changes: 4 additions & 1 deletion synapse/rest/client/v2_alpha/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,11 @@ async def on_POST(self, request):

assert_params_in_dict(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
)

if self.hs.config.shadow_server:
shadow_user = UserID(
Expand Down

0 comments on commit 6ed566e

Please sign in to comment.