mirror of
https://github.com/home-assistant/core.git
synced 2025-07-14 16:57:10 +00:00
Added WS endpoint for changing homeassistant password. (#15527)
* Added WS endpoint for changing homeassistant password. * Remove change password helper. Don't require current password. * Restore current password verification. * Added tests. * Use correct send method
This commit is contained in:
parent
8b04d48ffd
commit
396895d077
@ -20,6 +20,13 @@ SCHEMA_WS_DELETE = websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend({
|
|||||||
vol.Required('username'): str,
|
vol.Required('username'): str,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
WS_TYPE_CHANGE_PASSWORD = 'config/auth_provider/homeassistant/change_password'
|
||||||
|
SCHEMA_WS_CHANGE_PASSWORD = websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend({
|
||||||
|
vol.Required('type'): WS_TYPE_CHANGE_PASSWORD,
|
||||||
|
vol.Required('current_password'): str,
|
||||||
|
vol.Required('new_password'): str
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
async def async_setup(hass):
|
async def async_setup(hass):
|
||||||
"""Enable the Home Assistant views."""
|
"""Enable the Home Assistant views."""
|
||||||
@ -31,6 +38,10 @@ async def async_setup(hass):
|
|||||||
WS_TYPE_DELETE, websocket_delete,
|
WS_TYPE_DELETE, websocket_delete,
|
||||||
SCHEMA_WS_DELETE
|
SCHEMA_WS_DELETE
|
||||||
)
|
)
|
||||||
|
hass.components.websocket_api.async_register_command(
|
||||||
|
WS_TYPE_CHANGE_PASSWORD, websocket_change_password,
|
||||||
|
SCHEMA_WS_CHANGE_PASSWORD
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@ -118,3 +129,46 @@ def websocket_delete(hass, connection, msg):
|
|||||||
websocket_api.result_message(msg['id']))
|
websocket_api.result_message(msg['id']))
|
||||||
|
|
||||||
hass.async_add_job(delete_creds())
|
hass.async_add_job(delete_creds())
|
||||||
|
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def websocket_change_password(hass, connection, msg):
|
||||||
|
"""Change user password."""
|
||||||
|
async def change_password():
|
||||||
|
"""Change user password."""
|
||||||
|
user = connection.request.get('hass_user')
|
||||||
|
if user is None:
|
||||||
|
connection.send_message_outside(websocket_api.error_message(
|
||||||
|
msg['id'], 'user_not_found', 'User not found'))
|
||||||
|
return
|
||||||
|
|
||||||
|
provider = _get_provider(hass)
|
||||||
|
await provider.async_initialize()
|
||||||
|
|
||||||
|
username = None
|
||||||
|
for credential in user.credentials:
|
||||||
|
if credential.auth_provider_type == provider.type:
|
||||||
|
username = credential.data['username']
|
||||||
|
break
|
||||||
|
|
||||||
|
if username is None:
|
||||||
|
connection.send_message_outside(websocket_api.error_message(
|
||||||
|
msg['id'], 'credentials_not_found', 'Credentials not found'))
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
await provider.async_validate_login(
|
||||||
|
username, msg['current_password'])
|
||||||
|
except auth_ha.InvalidAuth:
|
||||||
|
connection.send_message_outside(websocket_api.error_message(
|
||||||
|
msg['id'], 'invalid_password', 'Invalid password'))
|
||||||
|
return
|
||||||
|
|
||||||
|
await hass.async_add_executor_job(
|
||||||
|
provider.data.change_password, username, msg['new_password'])
|
||||||
|
await provider.data.async_save()
|
||||||
|
|
||||||
|
connection.send_message_outside(
|
||||||
|
websocket_api.result_message(msg['id']))
|
||||||
|
|
||||||
|
hass.async_add_job(change_password())
|
||||||
|
@ -227,3 +227,77 @@ async def test_delete_unknown_auth(hass, hass_ws_client, hass_access_token):
|
|||||||
result = await client.receive_json()
|
result = await client.receive_json()
|
||||||
assert not result['success'], result
|
assert not result['success'], result
|
||||||
assert result['error']['code'] == 'auth_not_found'
|
assert result['error']['code'] == 'auth_not_found'
|
||||||
|
|
||||||
|
|
||||||
|
async def test_change_password(hass, hass_ws_client, hass_access_token):
|
||||||
|
"""Test that change password succeeds with valid password."""
|
||||||
|
provider = hass.auth.auth_providers[0]
|
||||||
|
await provider.async_initialize()
|
||||||
|
await hass.async_add_executor_job(
|
||||||
|
provider.data.add_auth, 'test-user', 'test-pass')
|
||||||
|
|
||||||
|
credentials = await provider.async_get_or_create_credentials({
|
||||||
|
'username': 'test-user'
|
||||||
|
})
|
||||||
|
|
||||||
|
user = hass_access_token.refresh_token.user
|
||||||
|
await hass.auth.async_link_user(user, credentials)
|
||||||
|
|
||||||
|
client = await hass_ws_client(hass, hass_access_token)
|
||||||
|
await client.send_json({
|
||||||
|
'id': 6,
|
||||||
|
'type': auth_ha.WS_TYPE_CHANGE_PASSWORD,
|
||||||
|
'current_password': 'test-pass',
|
||||||
|
'new_password': 'new-pass'
|
||||||
|
})
|
||||||
|
|
||||||
|
result = await client.receive_json()
|
||||||
|
assert result['success'], result
|
||||||
|
await provider.async_validate_login('test-user', 'new-pass')
|
||||||
|
|
||||||
|
|
||||||
|
async def test_change_password_wrong_pw(hass, hass_ws_client,
|
||||||
|
hass_access_token):
|
||||||
|
"""Test that change password fails with invalid password."""
|
||||||
|
provider = hass.auth.auth_providers[0]
|
||||||
|
await provider.async_initialize()
|
||||||
|
await hass.async_add_executor_job(
|
||||||
|
provider.data.add_auth, 'test-user', 'test-pass')
|
||||||
|
|
||||||
|
credentials = await provider.async_get_or_create_credentials({
|
||||||
|
'username': 'test-user'
|
||||||
|
})
|
||||||
|
|
||||||
|
user = hass_access_token.refresh_token.user
|
||||||
|
await hass.auth.async_link_user(user, credentials)
|
||||||
|
|
||||||
|
client = await hass_ws_client(hass, hass_access_token)
|
||||||
|
await client.send_json({
|
||||||
|
'id': 6,
|
||||||
|
'type': auth_ha.WS_TYPE_CHANGE_PASSWORD,
|
||||||
|
'current_password': 'wrong-pass',
|
||||||
|
'new_password': 'new-pass'
|
||||||
|
})
|
||||||
|
|
||||||
|
result = await client.receive_json()
|
||||||
|
assert not result['success'], result
|
||||||
|
assert result['error']['code'] == 'invalid_password'
|
||||||
|
with pytest.raises(prov_ha.InvalidAuth):
|
||||||
|
await provider.async_validate_login('test-user', 'new-pass')
|
||||||
|
|
||||||
|
|
||||||
|
async def test_change_password_no_creds(hass, hass_ws_client,
|
||||||
|
hass_access_token):
|
||||||
|
"""Test that change password fails with no credentials."""
|
||||||
|
client = await hass_ws_client(hass, hass_access_token)
|
||||||
|
|
||||||
|
await client.send_json({
|
||||||
|
'id': 6,
|
||||||
|
'type': auth_ha.WS_TYPE_CHANGE_PASSWORD,
|
||||||
|
'current_password': 'test-pass',
|
||||||
|
'new_password': 'new-pass'
|
||||||
|
})
|
||||||
|
|
||||||
|
result = await client.receive_json()
|
||||||
|
assert not result['success'], result
|
||||||
|
assert result['error']['code'] == 'credentials_not_found'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user