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
This commit is contained in:
parent
49eaa34e03
commit
9ab0753cf7
12 changed files with 1022 additions and 613 deletions
78
homeassistant/components/mobile_app/http_api.py
Normal file
78
homeassistant/components/mobile_app/http_api.py
Normal file
|
@ -0,0 +1,78 @@
|
|||
"""Provides an HTTP API for mobile_app."""
|
||||
from typing import Dict
|
||||
|
||||
from aiohttp.web import Response, Request
|
||||
|
||||
from homeassistant.auth.util import generate_secret
|
||||
from homeassistant.components.cloud import async_create_cloudhook
|
||||
from homeassistant.components.http import HomeAssistantView
|
||||
from homeassistant.components.http.data_validator import RequestDataValidator
|
||||
from homeassistant.const import (HTTP_CREATED, HTTP_INTERNAL_SERVER_ERROR,
|
||||
CONF_WEBHOOK_ID)
|
||||
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.storage import Store
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
|
||||
from .const import (DATA_REGISTRATIONS, ATTR_SUPPORTS_ENCRYPTION,
|
||||
CONF_CLOUDHOOK_URL, CONF_SECRET, CONF_USER_ID,
|
||||
DOMAIN, REGISTRATION_SCHEMA)
|
||||
|
||||
from .helpers import supports_encryption, savable_state
|
||||
|
||||
from .webhook import setup_registration
|
||||
|
||||
|
||||
def register_http_handlers(hass: HomeAssistantType, store: Store) -> bool:
|
||||
"""Register the HTTP handlers/views."""
|
||||
hass.http.register_view(RegistrationsView(store))
|
||||
return True
|
||||
|
||||
|
||||
class RegistrationsView(HomeAssistantView):
|
||||
"""A view that accepts registration requests."""
|
||||
|
||||
url = '/api/mobile_app/registrations'
|
||||
name = 'api:mobile_app:register'
|
||||
|
||||
def __init__(self, store: Store) -> None:
|
||||
"""Initialize the view."""
|
||||
self._store = store
|
||||
|
||||
@RequestDataValidator(REGISTRATION_SCHEMA)
|
||||
async def post(self, request: Request, data: Dict) -> Response:
|
||||
"""Handle the POST request for registration."""
|
||||
hass = request.app['hass']
|
||||
|
||||
webhook_id = generate_secret()
|
||||
|
||||
if "cloud" in hass.config.components:
|
||||
cloudhook = await async_create_cloudhook(hass, webhook_id)
|
||||
|
||||
if cloudhook is not None:
|
||||
data[CONF_CLOUDHOOK_URL] = cloudhook[CONF_CLOUDHOOK_URL]
|
||||
|
||||
data[CONF_WEBHOOK_ID] = webhook_id
|
||||
|
||||
if data[ATTR_SUPPORTS_ENCRYPTION] and supports_encryption():
|
||||
secret = generate_secret(16)
|
||||
|
||||
data[CONF_SECRET] = secret
|
||||
|
||||
data[CONF_USER_ID] = request['hass_user'].id
|
||||
|
||||
hass.data[DOMAIN][DATA_REGISTRATIONS][webhook_id] = data
|
||||
|
||||
try:
|
||||
await self._store.async_save(savable_state(hass))
|
||||
except HomeAssistantError:
|
||||
return self.json_message("Error saving registration.",
|
||||
HTTP_INTERNAL_SERVER_ERROR)
|
||||
|
||||
setup_registration(hass, self._store, data)
|
||||
|
||||
return self.json({
|
||||
CONF_CLOUDHOOK_URL: data.get(CONF_CLOUDHOOK_URL),
|
||||
CONF_SECRET: data.get(CONF_SECRET),
|
||||
CONF_WEBHOOK_ID: data[CONF_WEBHOOK_ID],
|
||||
}, status_code=HTTP_CREATED)
|
Loading…
Add table
Add a link
Reference in a new issue