mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Rename is_owner decorator to is_admin (#19266)
* Rename is_owner decorator to is_admin * Update test_auth.py
This commit is contained in:
parent
a5a896b519
commit
4f98818258
@ -39,7 +39,7 @@ async def async_setup(hass):
|
||||
return True
|
||||
|
||||
|
||||
@websocket_api.require_owner
|
||||
@websocket_api.require_admin
|
||||
@websocket_api.async_response
|
||||
async def websocket_list(hass, connection, msg):
|
||||
"""Return a list of users."""
|
||||
@ -49,7 +49,7 @@ async def websocket_list(hass, connection, msg):
|
||||
websocket_api.result_message(msg['id'], result))
|
||||
|
||||
|
||||
@websocket_api.require_owner
|
||||
@websocket_api.require_admin
|
||||
@websocket_api.async_response
|
||||
async def websocket_delete(hass, connection, msg):
|
||||
"""Delete a user."""
|
||||
@ -72,7 +72,7 @@ async def websocket_delete(hass, connection, msg):
|
||||
websocket_api.result_message(msg['id']))
|
||||
|
||||
|
||||
@websocket_api.require_owner
|
||||
@websocket_api.require_admin
|
||||
@websocket_api.async_response
|
||||
async def websocket_create(hass, connection, msg):
|
||||
"""Create a user."""
|
||||
|
@ -3,7 +3,6 @@ import voluptuous as vol
|
||||
|
||||
from homeassistant.auth.providers import homeassistant as auth_ha
|
||||
from homeassistant.components import websocket_api
|
||||
from homeassistant.components.websocket_api.decorators import require_owner
|
||||
|
||||
|
||||
WS_TYPE_CREATE = 'config/auth_provider/homeassistant/create'
|
||||
@ -54,7 +53,7 @@ def _get_provider(hass):
|
||||
raise RuntimeError('Provider not found')
|
||||
|
||||
|
||||
@require_owner
|
||||
@websocket_api.require_admin
|
||||
@websocket_api.async_response
|
||||
async def websocket_create(hass, connection, msg):
|
||||
"""Create credentials and attach to a user."""
|
||||
@ -91,7 +90,7 @@ async def websocket_create(hass, connection, msg):
|
||||
connection.send_message(websocket_api.result_message(msg['id']))
|
||||
|
||||
|
||||
@require_owner
|
||||
@websocket_api.require_admin
|
||||
@websocket_api.async_response
|
||||
async def websocket_delete(hass, connection, msg):
|
||||
"""Delete username and related credential."""
|
||||
@ -123,6 +122,7 @@ async def websocket_delete(hass, connection, msg):
|
||||
websocket_api.result_message(msg['id']))
|
||||
|
||||
|
||||
@websocket_api.require_admin
|
||||
@websocket_api.async_response
|
||||
async def websocket_change_password(hass, connection, msg):
|
||||
"""Change user password."""
|
||||
|
@ -20,7 +20,7 @@ BASE_COMMAND_MESSAGE_SCHEMA = messages.BASE_COMMAND_MESSAGE_SCHEMA
|
||||
error_message = messages.error_message
|
||||
result_message = messages.result_message
|
||||
async_response = decorators.async_response
|
||||
require_owner = decorators.require_owner
|
||||
require_admin = decorators.require_admin
|
||||
ws_require_user = decorators.ws_require_user
|
||||
# pylint: enable=invalid-name
|
||||
|
||||
|
@ -3,6 +3,7 @@ from functools import wraps
|
||||
import logging
|
||||
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.exceptions import Unauthorized
|
||||
|
||||
from . import messages
|
||||
|
||||
@ -30,21 +31,19 @@ def async_response(func):
|
||||
return schedule_handler
|
||||
|
||||
|
||||
def require_owner(func):
|
||||
"""Websocket decorator to require user to be an owner."""
|
||||
def require_admin(func):
|
||||
"""Websocket decorator to require user to be an admin."""
|
||||
@wraps(func)
|
||||
def with_owner(hass, connection, msg):
|
||||
"""Check owner and call function."""
|
||||
def with_admin(hass, connection, msg):
|
||||
"""Check admin and call function."""
|
||||
user = connection.user
|
||||
|
||||
if user is None or not user.is_owner:
|
||||
connection.send_message(messages.error_message(
|
||||
msg['id'], 'unauthorized', 'This command is for owners only.'))
|
||||
return
|
||||
if user is None or not user.is_admin:
|
||||
raise Unauthorized()
|
||||
|
||||
func(hass, connection, msg)
|
||||
|
||||
return with_owner
|
||||
return with_admin
|
||||
|
||||
|
||||
def ws_require_user(
|
||||
|
@ -13,9 +13,10 @@ def setup_config(hass, aiohttp_client):
|
||||
hass.loop.run_until_complete(auth_config.async_setup(hass))
|
||||
|
||||
|
||||
async def test_list_requires_owner(hass, hass_ws_client, hass_access_token):
|
||||
async def test_list_requires_admin(hass, hass_ws_client,
|
||||
hass_read_only_access_token):
|
||||
"""Test get users requires auth."""
|
||||
client = await hass_ws_client(hass, hass_access_token)
|
||||
client = await hass_ws_client(hass, hass_read_only_access_token)
|
||||
|
||||
await client.send_json({
|
||||
'id': 5,
|
||||
@ -109,9 +110,10 @@ async def test_list(hass, hass_ws_client, hass_admin_user):
|
||||
}
|
||||
|
||||
|
||||
async def test_delete_requires_owner(hass, hass_ws_client, hass_access_token):
|
||||
async def test_delete_requires_admin(hass, hass_ws_client,
|
||||
hass_read_only_access_token):
|
||||
"""Test delete command requires an owner."""
|
||||
client = await hass_ws_client(hass, hass_access_token)
|
||||
client = await hass_ws_client(hass, hass_read_only_access_token)
|
||||
|
||||
await client.send_json({
|
||||
'id': 5,
|
||||
@ -139,15 +141,12 @@ async def test_delete_unable_self_account(hass, hass_ws_client,
|
||||
|
||||
result = await client.receive_json()
|
||||
assert not result['success'], result
|
||||
assert result['error']['code'] == 'unauthorized'
|
||||
assert result['error']['code'] == 'no_delete_self'
|
||||
|
||||
|
||||
async def test_delete_unknown_user(hass, hass_ws_client, hass_access_token):
|
||||
"""Test we cannot delete an unknown user."""
|
||||
client = await hass_ws_client(hass, hass_access_token)
|
||||
refresh_token = await hass.auth.async_validate_access_token(
|
||||
hass_access_token)
|
||||
refresh_token.user.is_owner = True
|
||||
|
||||
await client.send_json({
|
||||
'id': 5,
|
||||
@ -163,9 +162,6 @@ async def test_delete_unknown_user(hass, hass_ws_client, hass_access_token):
|
||||
async def test_delete(hass, hass_ws_client, hass_access_token):
|
||||
"""Test delete command works."""
|
||||
client = await hass_ws_client(hass, hass_access_token)
|
||||
refresh_token = await hass.auth.async_validate_access_token(
|
||||
hass_access_token)
|
||||
refresh_token.user.is_owner = True
|
||||
test_user = MockUser(
|
||||
id='efg',
|
||||
).add_to_hass(hass)
|
||||
@ -186,9 +182,6 @@ async def test_delete(hass, hass_ws_client, hass_access_token):
|
||||
async def test_create(hass, hass_ws_client, hass_access_token):
|
||||
"""Test create command works."""
|
||||
client = await hass_ws_client(hass, hass_access_token)
|
||||
refresh_token = await hass.auth.async_validate_access_token(
|
||||
hass_access_token)
|
||||
refresh_token.user.is_owner = True
|
||||
|
||||
assert len(await hass.auth.async_get_users()) == 1
|
||||
|
||||
@ -210,9 +203,10 @@ async def test_create(hass, hass_ws_client, hass_access_token):
|
||||
assert not user.system_generated
|
||||
|
||||
|
||||
async def test_create_requires_owner(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."""
|
||||
client = await hass_ws_client(hass, hass_access_token)
|
||||
client = await hass_ws_client(hass, hass_read_only_access_token)
|
||||
|
||||
await client.send_json({
|
||||
'id': 5,
|
||||
|
@ -22,9 +22,6 @@ async def test_create_auth_system_generated_user(hass, hass_access_token,
|
||||
"""Test we can't add auth to system generated users."""
|
||||
system_user = MockUser(system_generated=True).add_to_hass(hass)
|
||||
client = await hass_ws_client(hass, hass_access_token)
|
||||
refresh_token = await hass.auth.async_validate_access_token(
|
||||
hass_access_token)
|
||||
refresh_token.user.is_owner = True
|
||||
|
||||
await client.send_json({
|
||||
'id': 5,
|
||||
@ -49,9 +46,6 @@ async def test_create_auth_unknown_user(hass_ws_client, hass,
|
||||
hass_access_token):
|
||||
"""Test create pointing at unknown user."""
|
||||
client = await hass_ws_client(hass, hass_access_token)
|
||||
refresh_token = await hass.auth.async_validate_access_token(
|
||||
hass_access_token)
|
||||
refresh_token.user.is_owner = True
|
||||
|
||||
await client.send_json({
|
||||
'id': 5,
|
||||
@ -67,10 +61,10 @@ async def test_create_auth_unknown_user(hass_ws_client, hass,
|
||||
assert result['error']['code'] == 'not_found'
|
||||
|
||||
|
||||
async def test_create_auth_requires_owner(hass, hass_ws_client,
|
||||
hass_access_token):
|
||||
"""Test create requires owner to call API."""
|
||||
client = await hass_ws_client(hass, hass_access_token)
|
||||
async def test_create_auth_requires_admin(hass, hass_ws_client,
|
||||
hass_read_only_access_token):
|
||||
"""Test create requires admin to call API."""
|
||||
client = await hass_ws_client(hass, hass_read_only_access_token)
|
||||
|
||||
await client.send_json({
|
||||
'id': 5,
|
||||
@ -90,9 +84,6 @@ async def test_create_auth(hass, hass_ws_client, hass_access_token,
|
||||
"""Test create auth command works."""
|
||||
client = await hass_ws_client(hass, hass_access_token)
|
||||
user = MockUser().add_to_hass(hass)
|
||||
refresh_token = await hass.auth.async_validate_access_token(
|
||||
hass_access_token)
|
||||
refresh_token.user.is_owner = True
|
||||
|
||||
assert len(user.credentials) == 0
|
||||
|
||||
@ -123,9 +114,6 @@ async def test_create_auth_duplicate_username(hass, hass_ws_client,
|
||||
"""Test we can't create auth with a duplicate username."""
|
||||
client = await hass_ws_client(hass, hass_access_token)
|
||||
user = MockUser().add_to_hass(hass)
|
||||
refresh_token = await hass.auth.async_validate_access_token(
|
||||
hass_access_token)
|
||||
refresh_token.user.is_owner = True
|
||||
|
||||
hass_storage[prov_ha.STORAGE_KEY] = {
|
||||
'version': 1,
|
||||
@ -153,9 +141,6 @@ async def test_delete_removes_just_auth(hass_ws_client, hass, hass_storage,
|
||||
hass_access_token):
|
||||
"""Test deleting an auth without being connected to a user."""
|
||||
client = await hass_ws_client(hass, hass_access_token)
|
||||
refresh_token = await hass.auth.async_validate_access_token(
|
||||
hass_access_token)
|
||||
refresh_token.user.is_owner = True
|
||||
|
||||
hass_storage[prov_ha.STORAGE_KEY] = {
|
||||
'version': 1,
|
||||
@ -181,9 +166,6 @@ async def test_delete_removes_credential(hass, hass_ws_client,
|
||||
hass_access_token, hass_storage):
|
||||
"""Test deleting auth that is connected to a user."""
|
||||
client = await hass_ws_client(hass, hass_access_token)
|
||||
refresh_token = await hass.auth.async_validate_access_token(
|
||||
hass_access_token)
|
||||
refresh_token.user.is_owner = True
|
||||
|
||||
user = MockUser().add_to_hass(hass)
|
||||
user.credentials.append(
|
||||
@ -210,9 +192,10 @@ async def test_delete_removes_credential(hass, hass_ws_client,
|
||||
assert len(hass_storage[prov_ha.STORAGE_KEY]['data']['users']) == 0
|
||||
|
||||
|
||||
async def test_delete_requires_owner(hass, hass_ws_client, hass_access_token):
|
||||
"""Test delete requires owner."""
|
||||
client = await hass_ws_client(hass, hass_access_token)
|
||||
async def test_delete_requires_admin(hass, hass_ws_client,
|
||||
hass_read_only_access_token):
|
||||
"""Test delete requires admin."""
|
||||
client = await hass_ws_client(hass, hass_read_only_access_token)
|
||||
|
||||
await client.send_json({
|
||||
'id': 5,
|
||||
@ -228,9 +211,6 @@ async def test_delete_requires_owner(hass, hass_ws_client, hass_access_token):
|
||||
async def test_delete_unknown_auth(hass, hass_ws_client, hass_access_token):
|
||||
"""Test trying to delete an unknown auth username."""
|
||||
client = await hass_ws_client(hass, hass_access_token)
|
||||
refresh_token = await hass.auth.async_validate_access_token(
|
||||
hass_access_token)
|
||||
refresh_token.user.is_owner = True
|
||||
|
||||
await client.send_json({
|
||||
'id': 5,
|
||||
|
@ -142,7 +142,7 @@ def hass_access_token(hass, hass_admin_user):
|
||||
"""Return an access token to access Home Assistant."""
|
||||
refresh_token = hass.loop.run_until_complete(
|
||||
hass.auth.async_create_refresh_token(hass_admin_user, CLIENT_ID))
|
||||
yield hass.auth.async_create_access_token(refresh_token)
|
||||
return hass.auth.async_create_access_token(refresh_token)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -167,6 +167,14 @@ def hass_read_only_user(hass, local_auth):
|
||||
return MockUser(groups=[read_only_group]).add_to_hass(hass)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def hass_read_only_access_token(hass, hass_read_only_user):
|
||||
"""Return a Home Assistant read only user."""
|
||||
refresh_token = hass.loop.run_until_complete(
|
||||
hass.auth.async_create_refresh_token(hass_read_only_user, CLIENT_ID))
|
||||
return hass.auth.async_create_access_token(refresh_token)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def legacy_auth(hass):
|
||||
"""Load legacy API password provider."""
|
||||
|
Loading…
x
Reference in New Issue
Block a user