diff --git a/homeassistant/components/light/__init__.py b/homeassistant/components/light/__init__.py index aa12e562515..a16d1aaf87e 100644 --- a/homeassistant/components/light/__init__.py +++ b/homeassistant/components/light/__init__.py @@ -12,11 +12,13 @@ import os import voluptuous as vol +from homeassistant.auth.permissions.const import POLICY_CONTROL from homeassistant.components.group import \ ENTITY_ID_FORMAT as GROUP_ENTITY_ID_FORMAT from homeassistant.const import ( ATTR_ENTITY_ID, SERVICE_TOGGLE, SERVICE_TURN_OFF, SERVICE_TURN_ON, STATE_ON) +from homeassistant.exceptions import UnknownUser, Unauthorized import homeassistant.helpers.config_validation as cv from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa from homeassistant.helpers.entity import ToggleEntity @@ -256,6 +258,21 @@ async def async_setup(hass, config): target_lights = component.async_extract_from_service(service) params.pop(ATTR_ENTITY_ID, None) + if service.context.user_id: + user = await hass.auth.async_get_user(service.context.user_id) + if user is None: + raise UnknownUser(context=service.context) + + entity_perms = user.permissions.check_entity + + for light in target_lights: + if not entity_perms(light, POLICY_CONTROL): + raise Unauthorized( + context=service.context, + entity_id=light, + permission=POLICY_CONTROL + ) + preprocess_turn_on_alternatives(params) update_tasks = [] diff --git a/tests/components/light/test_init.py b/tests/components/light/test_init.py index 09474a5ad06..28d688b2080 100644 --- a/tests/components/light/test_init.py +++ b/tests/components/light/test_init.py @@ -5,7 +5,10 @@ import unittest.mock as mock import os from io import StringIO +import pytest + from homeassistant import core, loader +from homeassistant.exceptions import Unauthorized from homeassistant.setup import setup_component, async_setup_component from homeassistant.const import ( ATTR_ENTITY_ID, STATE_ON, STATE_OFF, CONF_PLATFORM, @@ -495,3 +498,22 @@ async def test_light_context(hass, hass_admin_user): assert state2 is not None assert state.state != state2.state assert state2.context.user_id == hass_admin_user.id + + +async def test_light_turn_on_auth(hass, hass_admin_user): + """Test that light context works.""" + assert await async_setup_component(hass, 'light', { + 'light': { + 'platform': 'test' + } + }) + + state = hass.states.get('light.ceiling') + assert state is not None + + hass_admin_user.mock_policy({}) + + with pytest.raises(Unauthorized): + await hass.services.async_call('light', 'turn_on', { + 'entity_id': state.entity_id, + }, True, core.Context(user_id=hass_admin_user.id))