1
mirror of https://github.com/home-assistant/core synced 2024-08-02 23:40:32 +02:00

Import cloud (#64116)

* Add type hints to cloud

* Import cloud

* Adjust smartthings tests

Co-authored-by: epenet <epenet@users.noreply.github.com>
This commit is contained in:
epenet 2022-01-14 16:35:35 +01:00 committed by GitHub
parent 9f61aecd5e
commit 2c0033254b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 46 additions and 52 deletions

View File

@ -116,20 +116,20 @@ class CloudNotAvailable(HomeAssistantError):
@bind_hass
@callback
def async_is_logged_in(hass) -> bool:
def async_is_logged_in(hass: HomeAssistant) -> bool:
"""Test if user is logged in."""
return DOMAIN in hass.data and hass.data[DOMAIN].is_logged_in
@bind_hass
@callback
def async_active_subscription(hass) -> bool:
def async_active_subscription(hass: HomeAssistant) -> bool:
"""Test if user has an active subscription."""
return async_is_logged_in(hass) and not hass.data[DOMAIN].subscription_expired
@bind_hass
async def async_create_cloudhook(hass, webhook_id: str) -> str:
async def async_create_cloudhook(hass: HomeAssistant, webhook_id: str) -> str:
"""Create a cloudhook."""
if not async_is_logged_in(hass):
raise CloudNotAvailable
@ -139,7 +139,7 @@ async def async_create_cloudhook(hass, webhook_id: str) -> str:
@bind_hass
async def async_delete_cloudhook(hass, webhook_id: str) -> None:
async def async_delete_cloudhook(hass: HomeAssistant, webhook_id: str) -> None:
"""Delete a cloudhook."""
if DOMAIN not in hass.data:
raise CloudNotAvailable
@ -149,7 +149,7 @@ async def async_delete_cloudhook(hass, webhook_id: str) -> None:
@bind_hass
@callback
def async_remote_ui_url(hass) -> str:
def async_remote_ui_url(hass: HomeAssistant) -> str:
"""Get the remote UI URL."""
if not async_is_logged_in(hass):
raise CloudNotAvailable

View File

@ -10,6 +10,7 @@ import emoji
from nacl.secret import SecretBox
import voluptuous as vol
from homeassistant.components import cloud
from homeassistant.components.http import HomeAssistantView
from homeassistant.components.http.data_validator import RequestDataValidator
from homeassistant.const import ATTR_DEVICE_ID, CONF_WEBHOOK_ID
@ -68,10 +69,10 @@ class RegistrationsView(HomeAssistantView):
webhook_id = secrets.token_hex()
if hass.components.cloud.async_active_subscription():
data[
CONF_CLOUDHOOK_URL
] = await hass.components.cloud.async_create_cloudhook(webhook_id)
if cloud.async_active_subscription(hass):
data[CONF_CLOUDHOOK_URL] = await cloud.async_create_cloudhook(
hass, webhook_id
)
data[CONF_WEBHOOK_ID] = webhook_id
@ -102,7 +103,7 @@ class RegistrationsView(HomeAssistantView):
remote_ui_url = None
with suppress(hass.components.cloud.CloudNotAvailable):
remote_ui_url = hass.components.cloud.async_remote_ui_url()
remote_ui_url = cloud.async_remote_ui_url(hass)
return self.json(
{

View File

@ -10,7 +10,7 @@ from aiohttp.web import HTTPBadRequest, Request, Response, json_response
from nacl.secret import SecretBox
import voluptuous as vol
from homeassistant.components import notify as hass_notify, tag
from homeassistant.components import cloud, notify as hass_notify, tag
from homeassistant.components.binary_sensor import (
DEVICE_CLASSES as BINARY_SENSOR_CLASSES,
)
@ -593,7 +593,7 @@ async def webhook_get_config(hass, config_entry, data):
resp[CONF_CLOUDHOOK_URL] = config_entry.data[CONF_CLOUDHOOK_URL]
with suppress(hass.components.cloud.CloudNotAvailable):
resp[CONF_REMOTE_UI_URL] = hass.components.cloud.async_remote_ui_url()
resp[CONF_REMOTE_UI_URL] = cloud.async_remote_ui_url(hass)
return webhook_response(resp, registration=config_entry.data)

View File

@ -183,10 +183,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
data = {**entry.data, CONF_WEBHOOK_ID: secrets.token_hex()}
hass.config_entries.async_update_entry(entry, data=data)
if hass.components.cloud.async_active_subscription():
if cloud.async_active_subscription(hass):
if CONF_CLOUDHOOK_URL not in entry.data:
webhook_url = await hass.components.cloud.async_create_cloudhook(
entry.data[CONF_WEBHOOK_ID]
webhook_url = await cloud.async_create_cloudhook(
hass, entry.data[CONF_WEBHOOK_ID]
)
data = {**entry.data, CONF_CLOUDHOOK_URL: webhook_url}
hass.config_entries.async_update_entry(entry, data=data)
@ -276,10 +276,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Cleanup when entry is removed."""
if (
CONF_WEBHOOK_ID in entry.data
and hass.components.cloud.async_active_subscription()
):
if CONF_WEBHOOK_ID in entry.data and cloud.async_active_subscription(hass):
try:
_LOGGER.debug(
"Removing Netatmo cloudhook (%s)", entry.data[CONF_WEBHOOK_ID]

View File

@ -8,7 +8,7 @@ from aiohttp.web import json_response
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.components import mqtt, webhook
from homeassistant.components import cloud, mqtt, webhook
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_GPS_ACCURACY,
@ -126,7 +126,7 @@ async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
if not entry.data.get("cloudhook"):
return
await hass.components.cloud.async_delete_cloudhook(entry.data[CONF_WEBHOOK_ID])
await cloud.async_delete_cloudhook(hass, entry.data[CONF_WEBHOOK_ID])
async def async_connect_mqtt(hass, component):

View File

@ -2,7 +2,7 @@
import secrets
from homeassistant import config_entries
from homeassistant.components import webhook
from homeassistant.components import cloud, webhook
from homeassistant.const import CONF_WEBHOOK_ID
from .const import DOMAIN
@ -68,10 +68,8 @@ class OwnTracksFlow(config_entries.ConfigFlow, domain=DOMAIN):
async def _get_webhook_id(self):
"""Generate webhook ID."""
webhook_id = webhook.async_generate_id()
if self.hass.components.cloud.async_active_subscription():
webhook_url = await self.hass.components.cloud.async_create_cloudhook(
webhook_id
)
if cloud.async_active_subscription(self.hass):
webhook_url = await cloud.async_create_cloudhook(self.hass, webhook_id)
cloudhook = True
else:
webhook_url = webhook.async_generate_url(self.hass, webhook_id)

View File

@ -3,7 +3,7 @@ from pyplaato.plaato import PlaatoDeviceType
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.components import webhook
from homeassistant.components import cloud, webhook
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_SCAN_INTERVAL, CONF_TOKEN, CONF_WEBHOOK_ID
from homeassistant.core import callback
@ -141,10 +141,8 @@ class PlaatoConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
async def _get_webhook_id(self):
"""Generate webhook ID."""
webhook_id = webhook.async_generate_id()
if self.hass.components.cloud.async_active_subscription():
webhook_url = await self.hass.components.cloud.async_create_cloudhook(
webhook_id
)
if cloud.async_active_subscription(self.hass):
webhook_url = await cloud.async_create_cloudhook(self.hass, webhook_id)
cloudhook = True
else:
webhook_url = webhook.async_generate_url(self.hass, webhook_id)

View File

@ -5,6 +5,7 @@ import secrets
from rachiopy import Rachio
from requests.exceptions import ConnectTimeout
from homeassistant.components import cloud
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_API_KEY, Platform
from homeassistant.core import HomeAssistant
@ -36,7 +37,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Remove a rachio config entry."""
if CONF_CLOUDHOOK_URL in entry.data:
await hass.components.cloud.async_delete_cloudhook(entry.data[CONF_WEBHOOK_ID])
await cloud.async_delete_cloudhook(hass, entry.data[CONF_WEBHOOK_ID])
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:

View File

@ -1,7 +1,7 @@
"""Webhooks used by rachio."""
from aiohttp import web
from homeassistant.components import webhook
from homeassistant.components import cloud, webhook
from homeassistant.const import URL_API
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_send
@ -115,11 +115,9 @@ async def async_get_or_create_registered_webhook_id_and_url(hass, entry):
config[CONF_WEBHOOK_ID] = webhook_id
updated_config = True
if hass.components.cloud.async_active_subscription():
if cloud.async_active_subscription(hass):
if not (cloudhook_url := config.get(CONF_CLOUDHOOK_URL)):
cloudhook_url = await hass.components.cloud.async_create_cloudhook(
webhook_id
)
cloudhook_url = await cloud.async_create_cloudhook(hass, webhook_id)
config[CONF_CLOUDHOOK_URL] = cloudhook_url
updated_config = True
webhook_url = cloudhook_url

View File

@ -23,7 +23,7 @@ from pysmartthings import (
SubscriptionEntity,
)
from homeassistant.components import webhook
from homeassistant.components import cloud, webhook
from homeassistant.const import CONF_WEBHOOK_ID
from homeassistant.core import HomeAssistant
from homeassistant.helpers.aiohttp_client import async_get_clientsession
@ -94,7 +94,7 @@ async def validate_installed_app(api, installed_app_id: str):
def validate_webhook_requirements(hass: HomeAssistant) -> bool:
"""Ensure Home Assistant is setup properly to receive webhooks."""
if hass.components.cloud.async_active_subscription():
if cloud.async_active_subscription(hass):
return True
if hass.data[DOMAIN][CONF_CLOUDHOOK_URL] is not None:
return True
@ -108,7 +108,7 @@ def get_webhook_url(hass: HomeAssistant) -> str:
Return the cloudhook if available, otherwise local webhook.
"""
cloudhook_url = hass.data[DOMAIN][CONF_CLOUDHOOK_URL]
if hass.components.cloud.async_active_subscription() and cloudhook_url is not None:
if cloud.async_active_subscription(hass) and cloudhook_url is not None:
return cloudhook_url
return webhook.async_generate_url(hass, hass.data[DOMAIN][CONF_WEBHOOK_ID])
@ -229,11 +229,11 @@ async def setup_smartapp_endpoint(hass: HomeAssistant):
cloudhook_url = config.get(CONF_CLOUDHOOK_URL)
if (
cloudhook_url is None
and hass.components.cloud.async_active_subscription()
and cloud.async_active_subscription(hass)
and not hass.config_entries.async_entries(DOMAIN)
):
cloudhook_url = await hass.components.cloud.async_create_cloudhook(
config[CONF_WEBHOOK_ID]
cloudhook_url = await cloud.async_create_cloudhook(
hass, config[CONF_WEBHOOK_ID]
)
config[CONF_CLOUDHOOK_URL] = cloudhook_url
await store.async_save(config)
@ -279,10 +279,8 @@ async def unload_smartapp_endpoint(hass: HomeAssistant):
return
# Remove the cloudhook if it was created
cloudhook_url = hass.data[DOMAIN][CONF_CLOUDHOOK_URL]
if cloudhook_url and hass.components.cloud.async_is_logged_in():
await hass.components.cloud.async_delete_cloudhook(
hass.data[DOMAIN][CONF_WEBHOOK_ID]
)
if cloudhook_url and cloud.async_is_logged_in(hass):
await cloud.async_delete_cloudhook(hass, hass.data[DOMAIN][CONF_WEBHOOK_ID])
# Remove cloudhook from storage
store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY)
await store.async_save(

View File

@ -6,6 +6,7 @@ import secrets
from toonapi import Status, Toon, ToonError
from homeassistant.components import cloud
from homeassistant.components.webhook import (
async_register as webhook_register,
async_unregister as webhook_unregister,
@ -57,11 +58,11 @@ class ToonDataUpdateCoordinator(DataUpdateCoordinator[Status]):
data = {**self.entry.data, CONF_WEBHOOK_ID: secrets.token_hex()}
self.hass.config_entries.async_update_entry(self.entry, data=data)
if self.hass.components.cloud.async_active_subscription():
if cloud.async_active_subscription(self.hass):
if CONF_CLOUDHOOK_URL not in self.entry.data:
webhook_url = await self.hass.components.cloud.async_create_cloudhook(
self.entry.data[CONF_WEBHOOK_ID]
webhook_url = await cloud.async_create_cloudhook(
self.hass, self.entry.data[CONF_WEBHOOK_ID]
)
data = {**self.entry.data, CONF_CLOUDHOOK_URL: webhook_url}
self.hass.config_entries.async_update_entry(self.entry, data=data)

View File

@ -355,9 +355,11 @@ async def test_entry_created_with_cloudhook(
request.refresh_token = refresh_token
with patch.object(
hass.components.cloud, "async_active_subscription", Mock(return_value=True)
smartapp.cloud,
"async_active_subscription",
Mock(return_value=True),
), patch.object(
hass.components.cloud,
smartapp.cloud,
"async_create_cloudhook",
AsyncMock(return_value="http://cloud.test"),
) as mock_create_cloudhook: