core/homeassistant/components/mobile_app/websocket_api.py

112 lines
4.2 KiB
Python
Raw Normal View History

mobile_app improvements (#21607) * First webhook commands for getting and deleting single registrations * Keep a list of deleted webhook IDs so we can 410 if the webhook receives traffic in the future * Return a empty JSON object instead of None * Split up mobile_app bits into individual files * Add typing * Sort keys * Remove unused async_setup_entry * New decorator method of registering webhooks * Add tests for cloud hook forwarding and improve error handling for cloud hooks * Initial implementation of platform specific logic * Add get registrations by user ID websocket call, minor style fixes * Stop using resp dictionary during registration * Move mobile_app/ios.py to ios/mobile_app.py * Log any errors encountered during webhook * Improve update registration call * Split up mobile_app tests to match split up component * Fix tests * Remove integration_map in favor of component name in registration * Add a few helper functions for custom logic components to use * Load the app_component platform at device registration or component setup time * Remove extraneous function * Use guard function for checking if component is in device * Inline websocket schemas * Rename ATTR_s used in storage to DATA_ prefix * squash flake8 and pylint issues * Remove ios.mobile_app platform * Dont mark websocket_api as a dependency * Return standard empty_okay_response with 400 if no JSON sent * Ensure deleted webhook IDs are registered at launch * Remove the creation of cloudhooks during handle_webhook * Rename device to registration everywhere applicable * Dont check if cloud is logged in, just check if cloud is in components * Dont ever use cloudhook_id * Remove component loading logic for a later PR * Cast exception to string * Remove unused functions
2019-03-09 07:44:56 +00:00
"""Websocket API for mobile_app."""
import voluptuous as vol
from homeassistant.components.cloud import async_delete_cloudhook
from homeassistant.components.websocket_api import (ActiveConnection,
async_register_command,
async_response,
error_message,
result_message,
websocket_command,
ws_require_user)
from homeassistant.components.websocket_api.const import (ERR_INVALID_FORMAT,
ERR_NOT_FOUND,
ERR_UNAUTHORIZED)
from homeassistant.const import CONF_WEBHOOK_ID
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.typing import HomeAssistantType
from .const import (CONF_CLOUDHOOK_URL, CONF_USER_ID, DATA_CONFIG_ENTRIES,
DATA_DELETED_IDS, DATA_STORE, DOMAIN)
mobile_app improvements (#21607) * First webhook commands for getting and deleting single registrations * Keep a list of deleted webhook IDs so we can 410 if the webhook receives traffic in the future * Return a empty JSON object instead of None * Split up mobile_app bits into individual files * Add typing * Sort keys * Remove unused async_setup_entry * New decorator method of registering webhooks * Add tests for cloud hook forwarding and improve error handling for cloud hooks * Initial implementation of platform specific logic * Add get registrations by user ID websocket call, minor style fixes * Stop using resp dictionary during registration * Move mobile_app/ios.py to ios/mobile_app.py * Log any errors encountered during webhook * Improve update registration call * Split up mobile_app tests to match split up component * Fix tests * Remove integration_map in favor of component name in registration * Add a few helper functions for custom logic components to use * Load the app_component platform at device registration or component setup time * Remove extraneous function * Use guard function for checking if component is in device * Inline websocket schemas * Rename ATTR_s used in storage to DATA_ prefix * squash flake8 and pylint issues * Remove ios.mobile_app platform * Dont mark websocket_api as a dependency * Return standard empty_okay_response with 400 if no JSON sent * Ensure deleted webhook IDs are registered at launch * Remove the creation of cloudhooks during handle_webhook * Rename device to registration everywhere applicable * Dont check if cloud is logged in, just check if cloud is in components * Dont ever use cloudhook_id * Remove component loading logic for a later PR * Cast exception to string * Remove unused functions
2019-03-09 07:44:56 +00:00
from .helpers import safe_registration, savable_state
def register_websocket_handlers(hass: HomeAssistantType) -> bool:
"""Register the websocket handlers."""
async_register_command(hass, websocket_get_user_registrations)
async_register_command(hass, websocket_delete_registration)
return True
@ws_require_user()
@async_response
@websocket_command({
vol.Required('type'): 'mobile_app/get_user_registrations',
vol.Optional(CONF_USER_ID): cv.string,
})
async def websocket_get_user_registrations(
hass: HomeAssistantType, connection: ActiveConnection,
msg: dict) -> None:
"""Return all registrations or just registrations for given user ID."""
user_id = msg.get(CONF_USER_ID, connection.user.id)
if user_id != connection.user.id and not connection.user.is_admin:
# If user ID is provided and is not current user ID and current user
# isn't an admin user
connection.send_error(msg['id'], ERR_UNAUTHORIZED, "Unauthorized")
return
user_registrations = []
for config_entry in hass.config_entries.async_entries(domain=DOMAIN):
registration = config_entry.data
mobile_app improvements (#21607) * First webhook commands for getting and deleting single registrations * Keep a list of deleted webhook IDs so we can 410 if the webhook receives traffic in the future * Return a empty JSON object instead of None * Split up mobile_app bits into individual files * Add typing * Sort keys * Remove unused async_setup_entry * New decorator method of registering webhooks * Add tests for cloud hook forwarding and improve error handling for cloud hooks * Initial implementation of platform specific logic * Add get registrations by user ID websocket call, minor style fixes * Stop using resp dictionary during registration * Move mobile_app/ios.py to ios/mobile_app.py * Log any errors encountered during webhook * Improve update registration call * Split up mobile_app tests to match split up component * Fix tests * Remove integration_map in favor of component name in registration * Add a few helper functions for custom logic components to use * Load the app_component platform at device registration or component setup time * Remove extraneous function * Use guard function for checking if component is in device * Inline websocket schemas * Rename ATTR_s used in storage to DATA_ prefix * squash flake8 and pylint issues * Remove ios.mobile_app platform * Dont mark websocket_api as a dependency * Return standard empty_okay_response with 400 if no JSON sent * Ensure deleted webhook IDs are registered at launch * Remove the creation of cloudhooks during handle_webhook * Rename device to registration everywhere applicable * Dont check if cloud is logged in, just check if cloud is in components * Dont ever use cloudhook_id * Remove component loading logic for a later PR * Cast exception to string * Remove unused functions
2019-03-09 07:44:56 +00:00
if connection.user.is_admin or registration[CONF_USER_ID] is user_id:
user_registrations.append(safe_registration(registration))
connection.send_message(
result_message(msg['id'], user_registrations))
@ws_require_user()
@async_response
@websocket_command({
vol.Required('type'): 'mobile_app/delete_registration',
vol.Required(CONF_WEBHOOK_ID): cv.string,
})
async def websocket_delete_registration(hass: HomeAssistantType,
connection: ActiveConnection,
msg: dict) -> None:
"""Delete the registration for the given webhook_id."""
user = connection.user
webhook_id = msg.get(CONF_WEBHOOK_ID)
if webhook_id is None:
connection.send_error(msg['id'], ERR_INVALID_FORMAT,
"Webhook ID not provided")
return
config_entry = hass.data[DOMAIN][DATA_CONFIG_ENTRIES][webhook_id]
registration = config_entry.data
mobile_app improvements (#21607) * First webhook commands for getting and deleting single registrations * Keep a list of deleted webhook IDs so we can 410 if the webhook receives traffic in the future * Return a empty JSON object instead of None * Split up mobile_app bits into individual files * Add typing * Sort keys * Remove unused async_setup_entry * New decorator method of registering webhooks * Add tests for cloud hook forwarding and improve error handling for cloud hooks * Initial implementation of platform specific logic * Add get registrations by user ID websocket call, minor style fixes * Stop using resp dictionary during registration * Move mobile_app/ios.py to ios/mobile_app.py * Log any errors encountered during webhook * Improve update registration call * Split up mobile_app tests to match split up component * Fix tests * Remove integration_map in favor of component name in registration * Add a few helper functions for custom logic components to use * Load the app_component platform at device registration or component setup time * Remove extraneous function * Use guard function for checking if component is in device * Inline websocket schemas * Rename ATTR_s used in storage to DATA_ prefix * squash flake8 and pylint issues * Remove ios.mobile_app platform * Dont mark websocket_api as a dependency * Return standard empty_okay_response with 400 if no JSON sent * Ensure deleted webhook IDs are registered at launch * Remove the creation of cloudhooks during handle_webhook * Rename device to registration everywhere applicable * Dont check if cloud is logged in, just check if cloud is in components * Dont ever use cloudhook_id * Remove component loading logic for a later PR * Cast exception to string * Remove unused functions
2019-03-09 07:44:56 +00:00
if registration is None:
connection.send_error(msg['id'], ERR_NOT_FOUND,
"Webhook ID not found in storage")
return
if registration[CONF_USER_ID] != user.id and not user.is_admin:
return error_message(
msg['id'], ERR_UNAUTHORIZED, 'User is not registration owner')
await hass.config_entries.async_remove(config_entry.entry_id)
mobile_app improvements (#21607) * First webhook commands for getting and deleting single registrations * Keep a list of deleted webhook IDs so we can 410 if the webhook receives traffic in the future * Return a empty JSON object instead of None * Split up mobile_app bits into individual files * Add typing * Sort keys * Remove unused async_setup_entry * New decorator method of registering webhooks * Add tests for cloud hook forwarding and improve error handling for cloud hooks * Initial implementation of platform specific logic * Add get registrations by user ID websocket call, minor style fixes * Stop using resp dictionary during registration * Move mobile_app/ios.py to ios/mobile_app.py * Log any errors encountered during webhook * Improve update registration call * Split up mobile_app tests to match split up component * Fix tests * Remove integration_map in favor of component name in registration * Add a few helper functions for custom logic components to use * Load the app_component platform at device registration or component setup time * Remove extraneous function * Use guard function for checking if component is in device * Inline websocket schemas * Rename ATTR_s used in storage to DATA_ prefix * squash flake8 and pylint issues * Remove ios.mobile_app platform * Dont mark websocket_api as a dependency * Return standard empty_okay_response with 400 if no JSON sent * Ensure deleted webhook IDs are registered at launch * Remove the creation of cloudhooks during handle_webhook * Rename device to registration everywhere applicable * Dont check if cloud is logged in, just check if cloud is in components * Dont ever use cloudhook_id * Remove component loading logic for a later PR * Cast exception to string * Remove unused functions
2019-03-09 07:44:56 +00:00
hass.data[DOMAIN][DATA_DELETED_IDS].append(webhook_id)
store = hass.data[DOMAIN][DATA_STORE]
try:
await store.async_save(savable_state(hass))
except HomeAssistantError:
return error_message(
msg['id'], 'internal_error', 'Error deleting registration')
if (CONF_CLOUDHOOK_URL in registration and
"cloud" in hass.config.components):
await async_delete_cloudhook(hass, webhook_id)
connection.send_message(result_message(msg['id'], 'ok'))