diff --git a/homeassistant/components/mobile_app/const.py b/homeassistant/components/mobile_app/const.py index 11b6f3e9865..3f1a6bc988c 100644 --- a/homeassistant/components/mobile_app/const.py +++ b/homeassistant/components/mobile_app/const.py @@ -43,7 +43,6 @@ ATTR_WEBHOOK_TYPE = 'type' ERR_ENCRYPTION_REQUIRED = 'encryption_required' ERR_INVALID_COMPONENT = 'invalid_component' -ERR_RENDER_FAILURE = 'render_failure' ERR_SAVE_FAILURE = 'save_failure' WEBHOOK_TYPE_CALL_SERVICE = 'call_service' @@ -99,8 +98,10 @@ FIRE_EVENT_SCHEMA = vol.Schema({ }) RENDER_TEMPLATE_SCHEMA = vol.Schema({ - vol.Required(ATTR_TEMPLATE): cv.string, - vol.Optional(ATTR_TEMPLATE_VARIABLES, default={}): dict, + str: { + vol.Required(ATTR_TEMPLATE): cv.template, + vol.Optional(ATTR_TEMPLATE_VARIABLES, default={}): dict, + } }) WEBHOOK_SCHEMAS = { diff --git a/homeassistant/components/mobile_app/webhook.py b/homeassistant/components/mobile_app/webhook.py index 9efd1fcd9f8..e8372c8648d 100644 --- a/homeassistant/components/mobile_app/webhook.py +++ b/homeassistant/components/mobile_app/webhook.py @@ -15,7 +15,7 @@ from homeassistant.const import (ATTR_DOMAIN, ATTR_SERVICE, ATTR_SERVICE_DATA, from homeassistant.core import EventOrigin from homeassistant.exceptions import (HomeAssistantError, ServiceNotFound, TemplateError) -from homeassistant.helpers import template +from homeassistant.helpers.template import attach from homeassistant.helpers.discovery import load_platform from homeassistant.helpers.storage import Store from homeassistant.helpers.typing import HomeAssistantType @@ -26,10 +26,9 @@ from .const import (ATTR_APP_COMPONENT, ATTR_DEVICE_NAME, ATTR_EVENT_DATA, ATTR_WEBHOOK_ENCRYPTED, ATTR_WEBHOOK_ENCRYPTED_DATA, ATTR_WEBHOOK_TYPE, CONF_SECRET, DATA_DELETED_IDS, DATA_REGISTRATIONS, DOMAIN, ERR_ENCRYPTION_REQUIRED, - ERR_RENDER_FAILURE, WEBHOOK_PAYLOAD_SCHEMA, - WEBHOOK_SCHEMAS, WEBHOOK_TYPE_CALL_SERVICE, - WEBHOOK_TYPE_FIRE_EVENT, WEBHOOK_TYPE_RENDER_TEMPLATE, - WEBHOOK_TYPE_UPDATE_LOCATION, + WEBHOOK_PAYLOAD_SCHEMA, WEBHOOK_SCHEMAS, + WEBHOOK_TYPE_CALL_SERVICE, WEBHOOK_TYPE_FIRE_EVENT, + WEBHOOK_TYPE_RENDER_TEMPLATE, WEBHOOK_TYPE_UPDATE_LOCATION, WEBHOOK_TYPE_UPDATE_REGISTRATION) from .helpers import (_decrypt_payload, empty_okay_response, error_response, @@ -132,17 +131,18 @@ async def handle_webhook(store: Store, hass: HomeAssistantType, return empty_okay_response(headers=headers) if webhook_type == WEBHOOK_TYPE_RENDER_TEMPLATE: - try: - tpl = template.Template(data[ATTR_TEMPLATE], hass) - rendered = tpl.async_render(data.get(ATTR_TEMPLATE_VARIABLES)) - return webhook_response({"rendered": rendered}, - registration=registration, headers=headers) - # noqa: E722 pylint: disable=broad-except - except (ValueError, TemplateError, Exception) as ex: - _LOGGER.error("Error when rendering template during mobile_app " - "webhook (device name: %s): %s", - registration[ATTR_DEVICE_NAME], ex) - return error_response(ERR_RENDER_FAILURE, str(ex), headers=headers) + resp = {} + for key, item in data.items(): + try: + tpl = item[ATTR_TEMPLATE] + attach(hass, tpl) + resp[key] = tpl.async_render(item.get(ATTR_TEMPLATE_VARIABLES)) + # noqa: E722 pylint: disable=broad-except + except TemplateError as ex: + resp[key] = {"error": str(ex)} + + return webhook_response(resp, registration=registration, + headers=headers) if webhook_type == WEBHOOK_TYPE_UPDATE_LOCATION: try: diff --git a/tests/components/mobile_app/const.py b/tests/components/mobile_app/const.py index 919a2a6e1fb..6dfe050191b 100644 --- a/tests/components/mobile_app/const.py +++ b/tests/components/mobile_app/const.py @@ -49,7 +49,9 @@ REGISTER_CLEARTEXT = { RENDER_TEMPLATE = { 'type': 'render_template', 'data': { - 'template': 'Hello world' + 'one': { + 'template': 'Hello world' + } } } diff --git a/tests/components/mobile_app/test_http_api.py b/tests/components/mobile_app/test_http_api.py index 195d33e15b2..7861e63459a 100644 --- a/tests/components/mobile_app/test_http_api.py +++ b/tests/components/mobile_app/test_http_api.py @@ -5,7 +5,7 @@ import pytest from homeassistant.components.mobile_app.const import CONF_SECRET from homeassistant.const import CONF_WEBHOOK_ID -from .const import REGISTER +from .const import REGISTER, RENDER_TEMPLATE from . import authed_api_client # noqa: F401 @@ -35,7 +35,7 @@ async def test_registration(hass_client, authed_api_client): # noqa: F811 key = key[:keylen] key = key.ljust(keylen, b'\0') - payload = json.dumps({'template': 'Hello world'}).encode("utf-8") + payload = json.dumps(RENDER_TEMPLATE['data']).encode("utf-8") data = SecretBox(key).encrypt(payload, encoder=Base64Encoder).decode("utf-8") @@ -62,7 +62,7 @@ async def test_registration(hass_client, authed_api_client): # noqa: F811 encoder=Base64Encoder) decrypted_data = decrypted_data.decode("utf-8") - assert json.loads(decrypted_data) == {'rendered': 'Hello world'} + assert json.loads(decrypted_data) == {'one': 'Hello world'} async def test_register_invalid_component(authed_api_client): # noqa: F811 diff --git a/tests/components/mobile_app/test_webhook.py b/tests/components/mobile_app/test_webhook.py index bbdfcde93e7..75e8903c494 100644 --- a/tests/components/mobile_app/test_webhook.py +++ b/tests/components/mobile_app/test_webhook.py @@ -24,7 +24,7 @@ async def test_webhook_handle_render_template(webhook_client): # noqa: F811 assert resp.status == 200 json = await resp.json() - assert json == {'rendered': 'Hello world'} + assert json == {'one': 'Hello world'} async def test_webhook_handle_call_services(hass, webhook_client): # noqa: E501 F811 @@ -123,7 +123,7 @@ async def test_webhook_handle_decryption(webhook_client): # noqa: F811 key = key[:keylen] key = key.ljust(keylen, b'\0') - payload = json.dumps({'template': 'Hello world'}).encode("utf-8") + payload = json.dumps(RENDER_TEMPLATE['data']).encode("utf-8") data = SecretBox(key).encrypt(payload, encoder=Base64Encoder).decode("utf-8") @@ -148,7 +148,7 @@ async def test_webhook_handle_decryption(webhook_client): # noqa: F811 encoder=Base64Encoder) decrypted_data = decrypted_data.decode("utf-8") - assert json.loads(decrypted_data) == {'rendered': 'Hello world'} + assert json.loads(decrypted_data) == {'one': 'Hello world'} async def test_webhook_requires_encryption(webhook_client): # noqa: F811