diff --git a/homeassistant/components/hassio/addon_panel.py b/homeassistant/components/hassio/addon_panel.py index 2a88788a2b5bc8..92dcc6435f91e2 100644 --- a/homeassistant/components/hassio/addon_panel.py +++ b/homeassistant/components/hassio/addon_panel.py @@ -8,7 +8,7 @@ from aiohttp import web from homeassistant.components import frontend -from homeassistant.components.http import HomeAssistantView +from homeassistant.components.http import HomeAssistantView, require_admin from homeassistant.core import HomeAssistant from .handler import get_supervisor_client @@ -43,6 +43,7 @@ def __init__(self, hass: HomeAssistant) -> None: self.hass = hass self.client = get_supervisor_client(hass) + @require_admin async def post(self, request: web.Request, addon: str) -> web.Response: """Handle new add-on panel requests.""" panels = await self.get_panels() @@ -56,6 +57,7 @@ async def post(self, request: web.Request, addon: str) -> web.Response: _register_panel(self.hass, addon, panels[addon]) return web.Response() + @require_admin async def delete(self, request: web.Request, addon: str) -> web.Response: """Handle remove add-on panel requests.""" frontend.async_remove_panel(self.hass, addon) diff --git a/tests/components/hassio/test_addon_panel.py b/tests/components/hassio/test_addon_panel.py index e199ad66a7e23e..5f8a6aead4d1ad 100644 --- a/tests/components/hassio/test_addon_panel.py +++ b/tests/components/hassio/test_addon_panel.py @@ -9,6 +9,7 @@ from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component +from tests.common import MockUser from tests.typing import ClientSessionGenerator @@ -90,6 +91,42 @@ async def test_hassio_addon_panel_api( ) +@pytest.mark.usefixtures("hassio_env") +async def test_hassio_addon_panel_api_non_admin( + hass: HomeAssistant, + hass_client: ClientSessionGenerator, + ingress_panels: AsyncMock, + hass_admin_user: MockUser, +) -> None: + """Test register panel api fails with non admin user.""" + ingress_panels.return_value = { + "test1": IngressPanel(enable=True, title="Test", icon="mdi:test", admin=False), + } + + with patch( + "homeassistant.components.hassio.addon_panel._register_panel", + ) as mock_panel: + await async_setup_component(hass, "hassio", {}) + await hass.async_block_till_done() + + ingress_panels.assert_called_once() + mock_panel.assert_called_once() + + mock_panel.reset_mock() + hass_admin_user.groups = [] + hass_client = await hass_client() + + # Both should return unauthorized regardless of enabled as the endpoint requires + # admin and the user is not admin + resp = await hass_client.post("/api/hassio_push/panel/test2") + assert resp.status == HTTPStatus.UNAUTHORIZED + + resp = await hass_client.post("/api/hassio_push/panel/test1") + assert resp.status == HTTPStatus.UNAUTHORIZED + + mock_panel.assert_not_called() + + @pytest.mark.usefixtures("hassio_env") async def test_hassio_addon_panel_registration( hass: HomeAssistant, ingress_panels: AsyncMock @@ -118,3 +155,49 @@ async def test_hassio_addon_panel_registration( require_admin=True, config={"addon": "test_addon"}, ) + + +@pytest.mark.usefixtures("hassio_env") +async def test_hassio_addon_panel_api_delete( + hass: HomeAssistant, hass_client: ClientSessionGenerator, ingress_panels: AsyncMock +) -> None: + """Test panel api delete.""" + ingress_panels.return_value = { + "test1": IngressPanel(enable=True, title="Test", icon="mdi:test", admin=False), + } + await async_setup_component(hass, "hassio", {}) + await hass.async_block_till_done() + + hass_client = await hass_client() + + with patch( + "homeassistant.components.hassio.addon_panel.frontend.async_remove_panel" + ) as mock_remove: + resp = await hass_client.delete("/api/hassio_push/panel/test1") + assert resp.status == HTTPStatus.OK + mock_remove.assert_called_once_with(hass, "test1") + + +@pytest.mark.usefixtures("hassio_env") +async def test_hassio_addon_panel_api_delete_non_admin( + hass: HomeAssistant, + hass_client: ClientSessionGenerator, + ingress_panels: AsyncMock, + hass_admin_user: MockUser, +) -> None: + """Test panel api delete fails with non admin user.""" + ingress_panels.return_value = { + "test1": IngressPanel(enable=True, title="Test", icon="mdi:test", admin=False), + } + await async_setup_component(hass, "hassio", {}) + await hass.async_block_till_done() + + hass_admin_user.groups = [] + hass_client = await hass_client() + + with patch( + "homeassistant.components.hassio.addon_panel.frontend.async_remove_panel" + ) as mock_remove: + resp = await hass_client.delete("/api/hassio_push/panel/test1") + assert resp.status == HTTPStatus.UNAUTHORIZED + mock_remove.assert_not_called()