Add permission checks to Rest API (#18639)
* Add permission checks to Rest API * Clean up unnecessary method * Remove all the tuple stuff from entity check * Simplify perms * Correct param name for owner permission * Hass.io make/update user to be admin * Types
This commit is contained in:
parent
f387cdec59
commit
8b8629a5f4
15 changed files with 282 additions and 145 deletions
|
@ -16,10 +16,12 @@ from tests.common import async_mock_service
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_api_client(hass, aiohttp_client):
|
||||
"""Start the Hass HTTP component."""
|
||||
def mock_api_client(hass, aiohttp_client, hass_access_token):
|
||||
"""Start the Hass HTTP component and return admin API client."""
|
||||
hass.loop.run_until_complete(async_setup_component(hass, 'api', {}))
|
||||
return hass.loop.run_until_complete(aiohttp_client(hass.http.app))
|
||||
return hass.loop.run_until_complete(aiohttp_client(hass.http.app, headers={
|
||||
'Authorization': 'Bearer {}'.format(hass_access_token)
|
||||
}))
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
|
@ -405,7 +407,8 @@ def _listen_count(hass):
|
|||
return sum(hass.bus.async_listeners().values())
|
||||
|
||||
|
||||
async def test_api_error_log(hass, aiohttp_client):
|
||||
async def test_api_error_log(hass, aiohttp_client, hass_access_token,
|
||||
hass_admin_user):
|
||||
"""Test if we can fetch the error log."""
|
||||
hass.data[DATA_LOGGING] = '/some/path'
|
||||
await async_setup_component(hass, 'api', {
|
||||
|
@ -416,7 +419,7 @@ async def test_api_error_log(hass, aiohttp_client):
|
|||
client = await aiohttp_client(hass.http.app)
|
||||
|
||||
resp = await client.get(const.URL_API_ERROR_LOG)
|
||||
# Verufy auth required
|
||||
# Verify auth required
|
||||
assert resp.status == 401
|
||||
|
||||
with patch(
|
||||
|
@ -424,7 +427,7 @@ async def test_api_error_log(hass, aiohttp_client):
|
|||
return_value=web.Response(status=200, text='Hello')
|
||||
) as mock_file:
|
||||
resp = await client.get(const.URL_API_ERROR_LOG, headers={
|
||||
'x-ha-access': 'yolo'
|
||||
'Authorization': 'Bearer {}'.format(hass_access_token)
|
||||
})
|
||||
|
||||
assert len(mock_file.mock_calls) == 1
|
||||
|
@ -432,6 +435,13 @@ async def test_api_error_log(hass, aiohttp_client):
|
|||
assert resp.status == 200
|
||||
assert await resp.text() == 'Hello'
|
||||
|
||||
# Verify we require admin user
|
||||
hass_admin_user.groups = []
|
||||
resp = await client.get(const.URL_API_ERROR_LOG, headers={
|
||||
'Authorization': 'Bearer {}'.format(hass_access_token)
|
||||
})
|
||||
assert resp.status == 401
|
||||
|
||||
|
||||
async def test_api_fire_event_context(hass, mock_api_client,
|
||||
hass_access_token):
|
||||
|
@ -494,3 +504,67 @@ async def test_api_set_state_context(hass, mock_api_client, hass_access_token):
|
|||
|
||||
state = hass.states.get('light.kitchen')
|
||||
assert state.context.user_id == refresh_token.user.id
|
||||
|
||||
|
||||
async def test_event_stream_requires_admin(hass, mock_api_client,
|
||||
hass_admin_user):
|
||||
"""Test user needs to be admin to access event stream."""
|
||||
hass_admin_user.groups = []
|
||||
resp = await mock_api_client.get('/api/stream')
|
||||
assert resp.status == 401
|
||||
|
||||
|
||||
async def test_states_view_filters(hass, mock_api_client, hass_admin_user):
|
||||
"""Test filtering only visible states."""
|
||||
hass_admin_user.mock_policy({
|
||||
'entities': {
|
||||
'entity_ids': {
|
||||
'test.entity': True
|
||||
}
|
||||
}
|
||||
})
|
||||
hass.states.async_set('test.entity', 'hello')
|
||||
hass.states.async_set('test.not_visible_entity', 'invisible')
|
||||
resp = await mock_api_client.get(const.URL_API_STATES)
|
||||
assert resp.status == 200
|
||||
json = await resp.json()
|
||||
assert len(json) == 1
|
||||
assert json[0]['entity_id'] == 'test.entity'
|
||||
|
||||
|
||||
async def test_get_entity_state_read_perm(hass, mock_api_client,
|
||||
hass_admin_user):
|
||||
"""Test getting a state requires read permission."""
|
||||
hass_admin_user.mock_policy({})
|
||||
resp = await mock_api_client.get('/api/states/light.test')
|
||||
assert resp.status == 401
|
||||
|
||||
|
||||
async def test_post_entity_state_admin(hass, mock_api_client, hass_admin_user):
|
||||
"""Test updating state requires admin."""
|
||||
hass_admin_user.groups = []
|
||||
resp = await mock_api_client.post('/api/states/light.test')
|
||||
assert resp.status == 401
|
||||
|
||||
|
||||
async def test_delete_entity_state_admin(hass, mock_api_client,
|
||||
hass_admin_user):
|
||||
"""Test deleting entity requires admin."""
|
||||
hass_admin_user.groups = []
|
||||
resp = await mock_api_client.delete('/api/states/light.test')
|
||||
assert resp.status == 401
|
||||
|
||||
|
||||
async def test_post_event_admin(hass, mock_api_client, hass_admin_user):
|
||||
"""Test sending event requires admin."""
|
||||
hass_admin_user.groups = []
|
||||
resp = await mock_api_client.post('/api/events/state_changed')
|
||||
assert resp.status == 401
|
||||
|
||||
|
||||
async def test_rendering_template_admin(hass, mock_api_client,
|
||||
hass_admin_user):
|
||||
"""Test rendering a template requires admin."""
|
||||
hass_admin_user.groups = []
|
||||
resp = await mock_api_client.post('/api/template')
|
||||
assert resp.status == 401
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue