diff --git a/homeassistant/components/auth/__init__.py b/homeassistant/components/auth/__init__.py index 8c0c17844f9..19edfe5a618 100644 --- a/homeassistant/components/auth/__init__.py +++ b/homeassistant/components/auth/__init__.py @@ -459,6 +459,7 @@ async def websocket_current_user( 'id': user.id, 'name': user.name, 'is_owner': user.is_owner, + 'is_admin': user.is_admin, 'credentials': [{'auth_provider_type': c.auth_provider_type, 'auth_provider_id': c.auth_provider_id} for c in user.credentials], diff --git a/homeassistant/components/config/auth.py b/homeassistant/components/config/auth.py index 625dbefbbb3..e6451e09a98 100644 --- a/homeassistant/components/config/auth.py +++ b/homeassistant/components/config/auth.py @@ -36,6 +36,7 @@ async def async_setup(hass): WS_TYPE_CREATE, websocket_create, SCHEMA_WS_CREATE ) + hass.components.websocket_api.async_register_command(websocket_update) return True @@ -84,6 +85,40 @@ async def websocket_create(hass, connection, msg): })) +@websocket_api.require_admin +@websocket_api.async_response +@websocket_api.websocket_command({ + vol.Required('type'): 'config/auth/update', + vol.Required('user_id'): str, + vol.Optional('name'): str, + vol.Optional('group_ids'): [str] +}) +async def websocket_update(hass, connection, msg): + """Update a user.""" + user = await hass.auth.async_get_user(msg.pop('user_id')) + + if not user: + connection.send_message(websocket_api.error_message( + msg['id'], websocket_api.const.ERR_NOT_FOUND, 'User not found')) + return + + if user.system_generated: + connection.send_message(websocket_api.error_message( + msg['id'], 'cannot_modify_system_generated', + 'Unable to update system generated users.')) + return + + msg.pop('type') + msg_id = msg.pop('id') + + await hass.auth.async_update_user(user, **msg) + + connection.send_message( + websocket_api.result_message(msg_id, { + 'user': _user_info(user), + })) + + def _user_info(user): """Format a user.""" return { diff --git a/tests/components/config/test_auth.py b/tests/components/config/test_auth.py index 5cc7b4bd82e..316740488e3 100644 --- a/tests/components/config/test_auth.py +++ b/tests/components/config/test_auth.py @@ -112,7 +112,7 @@ async def test_list(hass, hass_ws_client, hass_admin_user): async def test_delete_requires_admin(hass, hass_ws_client, hass_read_only_access_token): - """Test delete command requires an owner.""" + """Test delete command requires an admin.""" client = await hass_ws_client(hass, hass_read_only_access_token) await client.send_json({ @@ -205,7 +205,7 @@ async def test_create(hass, hass_ws_client, hass_access_token): async def test_create_requires_admin(hass, hass_ws_client, hass_read_only_access_token): - """Test create command requires an owner.""" + """Test create command requires an admin.""" client = await hass_ws_client(hass, hass_read_only_access_token) await client.send_json({ @@ -217,3 +217,67 @@ async def test_create_requires_admin(hass, hass_ws_client, result = await client.receive_json() assert not result['success'], result assert result['error']['code'] == 'unauthorized' + + +async def test_update(hass, hass_ws_client): + """Test update command works.""" + client = await hass_ws_client(hass) + + user = await hass.auth.async_create_user("Test user") + + await client.send_json({ + 'id': 5, + 'type': 'config/auth/update', + 'user_id': user.id, + 'name': 'Updated name', + 'group_ids': ['system-read-only'], + }) + + result = await client.receive_json() + assert result['success'], result + data_user = result['result']['user'] + + assert user.name == "Updated name" + assert data_user['name'] == "Updated name" + assert len(user.groups) == 1 + assert user.groups[0].id == "system-read-only" + assert data_user['group_ids'] == ["system-read-only"] + + +async def test_update_requires_admin(hass, hass_ws_client, + hass_read_only_access_token): + """Test update command requires an admin.""" + client = await hass_ws_client(hass, hass_read_only_access_token) + + user = await hass.auth.async_create_user("Test user") + + await client.send_json({ + 'id': 5, + 'type': 'config/auth/update', + 'user_id': user.id, + 'name': 'Updated name', + }) + + result = await client.receive_json() + assert not result['success'], result + assert result['error']['code'] == 'unauthorized' + assert user.name == "Test user" + + +async def test_update_system_generated(hass, hass_ws_client): + """Test update command cannot update a system generated.""" + client = await hass_ws_client(hass) + + user = await hass.auth.async_create_system_user("Test user") + + await client.send_json({ + 'id': 5, + 'type': 'config/auth/update', + 'user_id': user.id, + 'name': 'Updated name', + }) + + result = await client.receive_json() + assert not result['success'], result + assert result['error']['code'] == 'cannot_modify_system_generated' + assert user.name == "Test user"