Esempio n. 1
0
async def test_register_admin_service(hass, hass_read_only_user,
                                      hass_admin_user):
    """Test the register admin service."""
    calls = []

    async def mock_service(call):
        calls.append(call)

    hass.helpers.service.async_register_admin_service(
        'test', 'test', mock_service, vol.Schema({})
    )

    with pytest.raises(exceptions.UnknownUser):
        await hass.services.async_call(
            'test', 'test', {}, blocking=True, context=ha.Context(
                user_id='non-existing'
            ))
    assert len(calls) == 0

    with pytest.raises(exceptions.Unauthorized):
        await hass.services.async_call(
            'test', 'test', {}, blocking=True, context=ha.Context(
                user_id=hass_read_only_user.id
            ))
    assert len(calls) == 0

    await hass.services.async_call(
        'test', 'test', {}, blocking=True, context=ha.Context(
            user_id=hass_admin_user.id
        ))
    assert len(calls) == 1
    assert calls[0].context.user_id == hass_admin_user.id
Esempio n. 2
0
async def test_require_admin(hass, hass_read_only_user):
    """Test services requiring admin."""
    await async_setup_component(hass, "homeassistant", {})

    for service in (
        SERVICE_HOMEASSISTANT_RESTART,
        SERVICE_HOMEASSISTANT_STOP,
        SERVICE_CHECK_CONFIG,
        SERVICE_RELOAD_CORE_CONFIG,
    ):
        with pytest.raises(Unauthorized):
            await hass.services.async_call(
                ha.DOMAIN,
                service,
                {},
                context=ha.Context(user_id=hass_read_only_user.id),
                blocking=True,
            )
            assert False, f"Should have raises for {service}"

    with pytest.raises(Unauthorized):
        await hass.services.async_call(
            ha.DOMAIN,
            SERVICE_SET_LOCATION,
            {"latitude": 0, "longitude": 0},
            context=ha.Context(user_id=hass_read_only_user.id),
            blocking=True,
        )
Esempio n. 3
0
def test_context():
    """Test context init."""
    c = ha.Context()
    assert c.user_id is None
    assert c.parent_id is None
    assert c.id is not None

    c = ha.Context(23, 100)
    assert c.user_id == 23
    assert c.parent_id == 100
    assert c.id is not None
Esempio n. 4
0
async def test_domain_control_unauthorized(hass, hass_read_only_user):
    """Test domain verification in a service call with an unauthorized user."""
    mock_registry(
        hass,
        {
            "light.kitchen": ent_reg.RegistryEntry(
                entity_id="light.kitchen", unique_id="kitchen", platform="test_domain",
            )
        },
    )

    calls = []

    async def mock_service_log(call):
        """Define a protected service."""
        calls.append(call)

    protected_mock_service = hass.helpers.service.verify_domain_control("test_domain")(
        mock_service_log
    )

    hass.services.async_register(
        "test_domain", "test_service", protected_mock_service, schema=None
    )

    with pytest.raises(exceptions.Unauthorized):
        await hass.services.async_call(
            "test_domain",
            "test_service",
            {},
            blocking=True,
            context=ha.Context(user_id=hass_read_only_user.id),
        )

    assert len(calls) == 0
Esempio n. 5
0
async def test_service_call_event_contains_original_data(hass):
    """Test that service call event contains original data."""
    events = []

    @ha.callback
    def callback(event):
        events.append(event)

    hass.bus.async_listen(EVENT_CALL_SERVICE, callback)

    calls = async_mock_service(hass, 'test', 'service',
                               vol.Schema({'number': vol.Coerce(int)}))

    context = ha.Context()
    await hass.services.async_call('test',
                                   'service', {'number': '23'},
                                   blocking=True,
                                   context=context)
    await hass.async_block_till_done()
    assert len(events) == 1
    assert events[0].data['service_data']['number'] == '23'
    assert events[0].context is context
    assert len(calls) == 1
    assert calls[0].data['number'] == 23
    assert calls[0].context is context
Esempio n. 6
0
async def test_call_context_target_all(hass, mock_handle_entity_call,
                                       mock_entities):
    """Check we only target allowed entities if targeting all."""
    with patch(
            "homeassistant.auth.AuthManager.async_get_user",
            return_value=Mock(permissions=PolicyPermissions(
                {"entities": {
                    "entity_ids": {
                        "light.kitchen": True
                    }
                }}, None)),
    ):
        await service.entity_service_call(
            hass,
            [Mock(entities=mock_entities)],
            Mock(),
            ha.ServiceCall(
                "test_domain",
                "test_service",
                data={"entity_id": ENTITY_MATCH_ALL},
                context=ha.Context(user_id="mock-id"),
            ),
        )

    assert len(mock_handle_entity_call.mock_calls) == 1
    assert mock_handle_entity_call.mock_calls[0][1][
        1].entity_id == "light.kitchen"
Esempio n. 7
0
async def test_domain_control_unknown(hass, mock_entities):
    """Test domain verification in a service call with an unknown user."""
    calls = []

    async def mock_service_log(call):
        """Define a protected service."""
        calls.append(call)

    with patch(
            "homeassistant.helpers.entity_registry.async_get_registry",
            return_value=Mock(entities=mock_entities),
    ):
        protected_mock_service = hass.helpers.service.verify_domain_control(
            "test_domain")(mock_service_log)

        hass.services.async_register("test_domain",
                                     "test_service",
                                     protected_mock_service,
                                     schema=None)

        with pytest.raises(exceptions.UnknownUser):
            await hass.services.async_call(
                "test_domain",
                "test_service",
                {},
                blocking=True,
                context=ha.Context(user_id="fake_user_id"),
            )
        assert len(calls) == 0
Esempio n. 8
0
async def test_service_executed_with_subservices(hass):
    """Test we block correctly till all services done."""
    calls = async_mock_service(hass, "test", "inner")
    context = ha.Context()

    async def handle_outer(call):
        """Handle outer service call."""
        calls.append(call)
        call1 = hass.services.async_call("test",
                                         "inner",
                                         blocking=True,
                                         context=call.context)
        call2 = hass.services.async_call("test",
                                         "inner",
                                         blocking=True,
                                         context=call.context)
        await asyncio.wait([call1, call2])
        calls.append(call)

    hass.services.async_register("test", "outer", handle_outer)

    await hass.services.async_call("test",
                                   "outer",
                                   blocking=True,
                                   context=context)

    assert len(calls) == 4
    assert [call.service
            for call in calls] == ["outer", "inner", "inner", "outer"]
    assert all(call.context is context for call in calls)
Esempio n. 9
0
async def test_service_call_event_contains_original_data(hass):
    """Test that service call event contains original data."""
    events = []

    @ha.callback
    def callback(event):
        events.append(event)

    hass.bus.async_listen(EVENT_CALL_SERVICE, callback)

    calls = async_mock_service(hass, "test", "service",
                               vol.Schema({"number": vol.Coerce(int)}))

    context = ha.Context()
    await hass.services.async_call("test",
                                   "service", {"number": "23"},
                                   blocking=True,
                                   context=context)
    await hass.async_block_till_done()
    assert len(events) == 1
    assert events[0].data["service_data"]["number"] == "23"
    assert events[0].context is context
    assert len(calls) == 1
    assert calls[0].data["number"] == 23
    assert calls[0].context is context
Esempio n. 10
0
async def test_call_context_target_specific(
    hass, mock_service_platform_call, mock_entities
):
    """Check targeting specific entities."""
    with patch(
        "homeassistant.auth.AuthManager.async_get_user",
        return_value=mock_coro(
            Mock(
                permissions=PolicyPermissions(
                    {"entities": {"entity_ids": {"light.kitchen": True}}}, None
                )
            )
        ),
    ):
        await service.entity_service_call(
            hass,
            [Mock(entities=mock_entities)],
            Mock(),
            ha.ServiceCall(
                "test_domain",
                "test_service",
                {"entity_id": "light.kitchen"},
                context=ha.Context(user_id="mock-id"),
            ),
        )

    assert len(mock_service_platform_call.mock_calls) == 1
    entities = mock_service_platform_call.mock_calls[0][1][2]
    assert entities == [mock_entities["light.kitchen"]]
Esempio n. 11
0
async def test_light_context(hass, hass_admin_user):
    """Test that light context works."""
    platform = getattr(hass.components, "test.light")
    platform.init()
    assert await async_setup_component(hass, "light",
                                       {"light": {
                                           "platform": "test"
                                       }})
    await hass.async_block_till_done()

    state = hass.states.get("light.ceiling")
    assert state is not None

    await hass.services.async_call(
        "light",
        "toggle",
        {"entity_id": state.entity_id},
        blocking=True,
        context=core.Context(user_id=hass_admin_user.id),
    )

    state2 = hass.states.get("light.ceiling")
    assert state2 is not None
    assert state.state != state2.state
    assert state2.context.user_id == hass_admin_user.id
Esempio n. 12
0
async def test_domain_control_unauthorized(hass, hass_read_only_user, mock_entities):
    """Test domain verification in a service call with an unauthorized user."""
    calls = []

    async def mock_service_log(call):
        """Define a protected service."""
        calls.append(call)

    with patch(
        "homeassistant.helpers.entity_registry.async_get_registry",
        return_value=mock_coro(Mock(entities=mock_entities)),
    ):
        protected_mock_service = hass.helpers.service.verify_domain_control(
            "test_domain"
        )(mock_service_log)

        hass.services.async_register(
            "test_domain", "test_service", protected_mock_service, schema=None
        )

        with pytest.raises(exceptions.Unauthorized):
            await hass.services.async_call(
                "test_domain",
                "test_service",
                {},
                blocking=True,
                context=ha.Context(user_id=hass_read_only_user.id),
            )
Esempio n. 13
0
async def test_domain_control_admin(hass, hass_admin_user, mock_entities):
    """Test domain verification in a service call with an admin user."""
    calls = []

    async def mock_service_log(call):
        """Define a protected service."""
        calls.append(call)

    with patch('homeassistant.helpers.entity_registry.async_get_registry',
               return_value=mock_coro(Mock(entities=mock_entities))):
        protected_mock_service = hass.helpers.service.verify_domain_control(
            'test_domain')(mock_service_log)

        hass.services.async_register('test_domain',
                                     'test_service',
                                     protected_mock_service,
                                     schema=None)

        await hass.services.async_call(
            'test_domain',
            'test_service', {},
            blocking=True,
            context=ha.Context(user_id=hass_admin_user.id))

        assert len(calls) == 1
Esempio n. 14
0
async def test_domain_control_no_user(hass):
    """Test domain verification in a service call with no user."""
    mock_registry(
        hass,
        {
            "light.kitchen": ent_reg.RegistryEntry(
                entity_id="light.kitchen", unique_id="kitchen", platform="test_domain",
            )
        },
    )

    calls = []

    async def mock_service_log(call):
        """Define a protected service."""
        calls.append(call)

    protected_mock_service = hass.helpers.service.verify_domain_control("test_domain")(
        mock_service_log
    )

    hass.services.async_register(
        "test_domain", "test_service", protected_mock_service, schema=None
    )

    await hass.services.async_call(
        "test_domain",
        "test_service",
        {},
        blocking=True,
        context=ha.Context(user_id=None),
    )

    assert len(calls) == 1
Esempio n. 15
0
async def test_domain_control_no_user(hass, mock_entities):
    """Test domain verification in a service call with no user."""
    calls = []

    async def mock_service_log(call):
        """Define a protected service."""
        calls.append(call)

    with patch(
        "homeassistant.helpers.entity_registry.async_get_registry",
        return_value=mock_coro(Mock(entities=mock_entities)),
    ):
        protected_mock_service = hass.helpers.service.verify_domain_control(
            "test_domain"
        )(mock_service_log)

        hass.services.async_register(
            "test_domain", "test_service", protected_mock_service, schema=None
        )

        await hass.services.async_call(
            "test_domain",
            "test_service",
            {},
            blocking=True,
            context=ha.Context(user_id=None),
        )

        assert len(calls) == 1
Esempio n. 16
0
async def test_call_context_user_not_exist(hass):
    """Check we don't allow deleted users to do things."""
    with pytest.raises(exceptions.UnknownUser) as err:
        await service.entity_service_call(hass, [], Mock(), ha.ServiceCall(
            'test_domain', 'test_service', context=ha.Context(
                user_id='non-existing')))

    assert err.value.context.user_id == 'non-existing'
Esempio n. 17
0
async def async_handle_message(hass,
                               config,
                               request,
                               context=None,
                               enabled=True):
    """Handle incoming API messages.

    If enabled is False, the response to all messagess will be a
    BRIDGE_UNREACHABLE error. This can be used if the API has been disabled in
    configuration.
    """
    assert request[API_DIRECTIVE][API_HEADER]["payloadVersion"] == "3"

    if context is None:
        context = ha.Context()

    directive = AlexaDirective(request)

    try:
        if not enabled:
            raise AlexaBridgeUnreachableError(
                "Alexa API not enabled in Safegate Pro configuration")

        if directive.has_endpoint:
            directive.load_entity(hass, config)

        funct_ref = HANDLERS.get((directive.namespace, directive.name))
        if funct_ref:
            response = await funct_ref(hass, config, directive, context)
            if directive.has_endpoint:
                response.merge_context_properties(directive.endpoint)
        else:
            _LOGGER.warning("Unsupported API request %s/%s",
                            directive.namespace, directive.name)
            response = directive.error()
    except AlexaError as err:
        response = directive.error(error_type=err.error_type,
                                   error_message=err.error_message)

    request_info = {"namespace": directive.namespace, "name": directive.name}

    if directive.has_endpoint:
        request_info["entity_id"] = directive.entity_id

    hass.bus.async_fire(
        EVENT_ALEXA_SMART_HOME,
        {
            "request": request_info,
            "response": {
                "namespace": response.namespace,
                "name": response.name
            },
        },
        context=context,
    )

    return response.serialize()
Esempio n. 18
0
def test_event_eq():
    """Test events."""
    now = dt_util.utcnow()
    data = {"some": "attr"}
    context = ha.Context()
    event1, event2 = [
        ha.Event("some_type", data, time_fired=now, context=context) for _ in range(2)
    ]

    assert event1 == event2
Esempio n. 19
0
    def test_eq(self):
        """Test events."""
        now = dt_util.utcnow()
        data = {'some': 'attr'}
        context = ha.Context()
        event1, event2 = [
            ha.Event('some_type', data, time_fired=now, context=context)
            for _ in range(2)
        ]

        assert event1 == event2
Esempio n. 20
0
async def test_turn_on_off_toggle_schema(hass, hass_read_only_user):
    """Test the schemas for the turn on/off/toggle services."""
    await async_setup_component(hass, "homeassistant", {})

    for service in SERVICE_TURN_ON, SERVICE_TURN_OFF, SERVICE_TOGGLE:
        for invalid in None, "nothing", ENTITY_MATCH_ALL, ENTITY_MATCH_NONE:
            with pytest.raises(vol.Invalid):
                await hass.services.async_call(
                    ha.DOMAIN,
                    service,
                    {"entity_id": invalid},
                    context=ha.Context(user_id=hass_read_only_user.id),
                    blocking=True,
                )
Esempio n. 21
0
async def test_call_context_target_specific_no_auth(
        hass, mock_service_platform_call, mock_entities):
    """Check targeting specific entities without auth."""
    with pytest.raises(exceptions.Unauthorized) as err:
        with patch('homeassistant.auth.AuthManager.async_get_user',
                   return_value=mock_coro(Mock(
                       permissions=PolicyPermissions({})))):
            await service.entity_service_call(hass, [
                Mock(entities=mock_entities)
            ], Mock(), ha.ServiceCall('test_domain', 'test_service', {
                'entity_id': 'light.kitchen'
            }, context=ha.Context(user_id='mock-id')))

    assert err.value.context.user_id == 'mock-id'
    assert err.value.entity_id == 'light.kitchen'
Esempio n. 22
0
def test_from_event_to_db_state():
    """Test converting event to db state."""
    state = ha.State("sensor.temperature", "18")
    event = ha.Event(
        EVENT_STATE_CHANGED,
        {
            "entity_id": "sensor.temperature",
            "old_state": None,
            "new_state": state
        },
        context=state.context,
    )
    # We don't restore context unless we need it by joining the
    # events table on the event_id for state_changed events
    state.context = ha.Context(id=None)
    assert state == States.from_event(event).to_native()
Esempio n. 23
0
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))
Esempio n. 24
0
    async def post(self, request):
        """Handle Alexa Smart Home requests.

        The Smart Home API requires the endpoint to be implemented in AWS
        Lambda, which will need to forward the requests to here and pass back
        the response.
        """
        hass = request.app["hass"]
        user = request["hass_user"]
        message = await request.json()

        _LOGGER.debug("Received Alexa Smart Home request: %s", message)

        response = await async_handle_message(
            hass, self.smart_home_config, message, context=core.Context(user_id=user.id)
        )
        _LOGGER.debug("Sending Alexa Smart Home response: %s", response)
        return b"" if response is None else self.json(response)
Esempio n. 25
0
async def test_light_context(hass):
    """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

    await hass.services.async_call('light', 'toggle', {
        'entity_id': state.entity_id,
    }, True, core.Context(user_id='abcd'))

    state2 = hass.states.get('light.ceiling')
    assert state2 is not None
    assert state.state != state2.state
    assert state2.context.user_id == 'abcd'
Esempio n. 26
0
async def test_switch_context(hass, hass_admin_user):
    """Test that switch context works."""
    assert await async_setup_component(hass, 'switch',
                                       {'switch': {
                                           'platform': 'test'
                                       }})

    state = hass.states.get('switch.ac')
    assert state is not None

    await hass.services.async_call('switch', 'toggle', {
        'entity_id': state.entity_id,
    }, True, core.Context(user_id=hass_admin_user.id))

    state2 = hass.states.get('switch.ac')
    assert state2 is not None
    assert state.state != state2.state
    assert state2.context.user_id == hass_admin_user.id
Esempio n. 27
0
async def test_call_context_target_all(hass, mock_service_platform_call,
                                       mock_entities):
    """Check we only target allowed entities if targetting all."""
    with patch('homeassistant.auth.AuthManager.async_get_user',
               return_value=mock_coro(Mock(permissions=PolicyPermissions({
                   'entities': {
                       'entity_ids': {
                           'light.kitchen': True
                       }
                   }
               })))):
        await service.entity_service_call(hass, [
            Mock(entities=mock_entities)
        ], Mock(), ha.ServiceCall('test_domain', 'test_service',
                                  context=ha.Context(user_id='mock-id')))

    assert len(mock_service_platform_call.mock_calls) == 1
    entities = mock_service_platform_call.mock_calls[0][1][2]
    assert entities == [mock_entities['light.kitchen']]
Esempio n. 28
0
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),
        )
Esempio n. 29
0
async def test_switch_context(hass, hass_admin_user):
    """Test that switch context works."""
    assert await async_setup_component(hass, "switch", {"switch": {"platform": "test"}})

    await hass.async_block_till_done()

    state = hass.states.get("switch.ac")
    assert state is not None

    await hass.services.async_call(
        "switch",
        "toggle",
        {"entity_id": state.entity_id},
        True,
        core.Context(user_id=hass_admin_user.id),
    )

    state2 = hass.states.get("switch.ac")
    assert state2 is not None
    assert state.state != state2.state
    assert state2.context.user_id == hass_admin_user.id
Esempio n. 30
0
async def test_call_context_target_specific_no_auth(hass,
                                                    mock_handle_entity_call,
                                                    mock_entities):
    """Check targeting specific entities without auth."""
    with pytest.raises(exceptions.Unauthorized) as err, patch(
            "homeassistant.auth.AuthManager.async_get_user",
            return_value=Mock(permissions=PolicyPermissions({}, None)),
    ):
        await service.entity_service_call(
            hass,
            [Mock(entities=mock_entities)],
            Mock(),
            ha.ServiceCall(
                "test_domain",
                "test_service",
                {"entity_id": "light.kitchen"},
                context=ha.Context(user_id="mock-id"),
            ),
        )

    assert err.value.context.user_id == "mock-id"
    assert err.value.entity_id == "light.kitchen"