1
mirror of https://github.com/home-assistant/core synced 2024-08-28 03:36:46 +02:00

Add is_admin checks to scene/script/automation APIs (#98025)

This commit is contained in:
Franck Nijhof 2023-08-08 12:11:52 +02:00 committed by GitHub
parent 55619e7d6d
commit 40e256847c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 113 additions and 1 deletions

View File

@ -7,7 +7,7 @@ import os
import voluptuous as vol
from homeassistant.components import frontend
from homeassistant.components.http import HomeAssistantView
from homeassistant.components.http import HomeAssistantView, require_admin
from homeassistant.const import CONF_ID, EVENT_COMPONENT_LOADED
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
@ -103,6 +103,7 @@ class BaseEditConfigView(HomeAssistantView):
"""Delete value."""
raise NotImplementedError
@require_admin
async def get(self, request, config_key):
"""Fetch device specific config."""
hass = request.app["hass"]
@ -115,6 +116,7 @@ class BaseEditConfigView(HomeAssistantView):
return self.json(value)
@require_admin
async def post(self, request, config_key):
"""Validate config and return results."""
try:
@ -156,6 +158,7 @@ class BaseEditConfigView(HomeAssistantView):
return self.json({"result": "ok"})
@require_admin
async def delete(self, request, config_key):
"""Remove an entry."""
hass = request.app["hass"]

View File

@ -372,3 +372,35 @@ async def test_delete_automation(
assert hass_config_store["automations.yaml"] == [{"id": "moon"}]
assert len(ent_reg.entities) == 1
@pytest.mark.parametrize("automation_config", ({},))
async def test_api_calls_require_admin(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
hass_read_only_access_token: str,
hass_config_store,
setup_automation,
) -> None:
"""Test cloud APIs endpoints do not work as a normal user."""
with patch.object(config, "SECTIONS", ["automation"]):
await async_setup_component(hass, "config", {})
hass_config_store["automations.yaml"] = [{"id": "sun"}, {"id": "moon"}]
client = await hass_client(hass_read_only_access_token)
# Get
resp = await client.get("/api/config/automation/config/moon")
assert resp.status == HTTPStatus.UNAUTHORIZED
# Update
resp = await client.post(
"/api/config/automation/config/moon",
data=json.dumps({"trigger": [], "action": [], "condition": []}),
)
assert resp.status == HTTPStatus.UNAUTHORIZED
# Delete
resp = await client.delete("/api/config/automation/config/sun")
assert resp.status == HTTPStatus.UNAUTHORIZED

View File

@ -221,3 +221,47 @@ async def test_delete_scene(
]
assert len(ent_reg.entities) == 1
@pytest.mark.parametrize("scene_config", ({},))
async def test_api_calls_require_admin(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
hass_read_only_access_token: str,
hass_config_store,
setup_scene,
) -> None:
"""Test scene APIs endpoints do not work as a normal user."""
with patch.object(config, "SECTIONS", ["scene"]):
await async_setup_component(hass, "config", {})
hass_config_store["scenes.yaml"] = [
{
"id": "light_off",
"name": "Lights off",
"entities": {"light.bedroom": {"state": "off"}},
}
]
client = await hass_client(hass_read_only_access_token)
# Get
resp = await client.get("/api/config/scene/config/light_off")
assert resp.status == HTTPStatus.UNAUTHORIZED
# Update
resp = await client.post(
"/api/config/scene/config/light_off",
data=json.dumps(
{
"id": "light_off",
"name": "Lights off",
"entities": {"light.bedroom": {"state": "off"}},
}
),
)
assert resp.status == HTTPStatus.UNAUTHORIZED
# Delete
resp = await client.delete("/api/config/scene/config/light_on")
assert resp.status == HTTPStatus.UNAUTHORIZED

View File

@ -314,3 +314,36 @@ async def test_delete_script(
assert hass_config_store["scripts.yaml"] == {"one": {}}
assert len(ent_reg.entities) == 1
@pytest.mark.parametrize("script_config", ({},))
async def test_api_calls_require_admin(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
hass_read_only_access_token: str,
hass_config_store,
) -> None:
"""Test script APIs endpoints do not work as a normal user."""
with patch.object(config, "SECTIONS", ["script"]):
await async_setup_component(hass, "config", {})
hass_config_store["scripts.yaml"] = {
"moon": {"alias": "Moon"},
}
client = await hass_client(hass_read_only_access_token)
# Get
resp = await client.get("/api/config/script/config/moon")
assert resp.status == HTTPStatus.UNAUTHORIZED
# Update
resp = await client.post(
"/api/config/script/config/moon",
data=json.dumps({"sequence": []}),
)
assert resp.status == HTTPStatus.UNAUTHORIZED
# Delete
resp = await client.delete("/api/config/script/config/moon")
assert resp.status == HTTPStatus.UNAUTHORIZED