mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Add application_credentials platform to geocaching integration (#71880)
This commit is contained in:
parent
aa35b87884
commit
7c68278482
@ -1,61 +1,19 @@
|
|||||||
"""The Geocaching integration."""
|
"""The Geocaching integration."""
|
||||||
import voluptuous as vol
|
|
||||||
|
|
||||||
from homeassistant.config_entries import SOURCE_INTEGRATION_DISCOVERY, ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET, Platform
|
from homeassistant.const import Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import config_validation as cv
|
|
||||||
from homeassistant.helpers.config_entry_oauth2_flow import (
|
from homeassistant.helpers.config_entry_oauth2_flow import (
|
||||||
OAuth2Session,
|
OAuth2Session,
|
||||||
async_get_config_entry_implementation,
|
async_get_config_entry_implementation,
|
||||||
)
|
)
|
||||||
from homeassistant.helpers.typing import ConfigType
|
|
||||||
|
|
||||||
from .config_flow import GeocachingFlowHandler
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
from .coordinator import GeocachingDataUpdateCoordinator
|
from .coordinator import GeocachingDataUpdateCoordinator
|
||||||
from .oauth import GeocachingOAuth2Implementation
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema(
|
|
||||||
{
|
|
||||||
DOMAIN: vol.Schema(
|
|
||||||
{
|
|
||||||
vol.Required(CONF_CLIENT_ID): cv.string,
|
|
||||||
vol.Required(CONF_CLIENT_SECRET): cv.string,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
extra=vol.ALLOW_EXTRA,
|
|
||||||
)
|
|
||||||
|
|
||||||
PLATFORMS = [Platform.SENSOR]
|
PLATFORMS = [Platform.SENSOR]
|
||||||
|
|
||||||
|
|
||||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|
||||||
"""Set up the Geocaching component."""
|
|
||||||
if DOMAIN not in config:
|
|
||||||
return True
|
|
||||||
|
|
||||||
GeocachingFlowHandler.async_register_implementation(
|
|
||||||
hass,
|
|
||||||
GeocachingOAuth2Implementation(
|
|
||||||
hass,
|
|
||||||
client_id=config[DOMAIN][CONF_CLIENT_ID],
|
|
||||||
client_secret=config[DOMAIN][CONF_CLIENT_SECRET],
|
|
||||||
name="Geocaching",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
# When manual configuration is done, discover the integration.
|
|
||||||
hass.async_create_task(
|
|
||||||
hass.config_entries.flow.async_init(
|
|
||||||
DOMAIN, context={"source": SOURCE_INTEGRATION_DISCOVERY}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
"""Set up Geocaching from a config entry."""
|
"""Set up Geocaching from a config entry."""
|
||||||
implementation = await async_get_config_entry_implementation(hass, entry)
|
implementation = await async_get_config_entry_implementation(hass, entry)
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
"""application_credentials platform for Geocaching."""
|
||||||
|
|
||||||
|
from homeassistant.components.application_credentials import ClientCredential
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers import config_entry_oauth2_flow
|
||||||
|
|
||||||
|
from .oauth import GeocachingOAuth2Implementation
|
||||||
|
|
||||||
|
|
||||||
|
async def async_get_auth_implementation(
|
||||||
|
hass: HomeAssistant, auth_domain: str, credential: ClientCredential
|
||||||
|
) -> config_entry_oauth2_flow.AbstractOAuth2Implementation:
|
||||||
|
"""Return auth implementation."""
|
||||||
|
return GeocachingOAuth2Implementation(hass, auth_domain, credential)
|
@ -4,7 +4,7 @@
|
|||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/geocaching",
|
"documentation": "https://www.home-assistant.io/integrations/geocaching",
|
||||||
"requirements": ["geocachingapi==0.2.1"],
|
"requirements": ["geocachingapi==0.2.1"],
|
||||||
"dependencies": ["auth"],
|
"dependencies": ["application_credentials"],
|
||||||
"codeowners": ["@Sholofly", "@reinder83"],
|
"codeowners": ["@Sholofly", "@reinder83"],
|
||||||
"iot_class": "cloud_polling"
|
"iot_class": "cloud_polling"
|
||||||
}
|
}
|
||||||
|
@ -3,37 +3,37 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from typing import Any, cast
|
from typing import Any, cast
|
||||||
|
|
||||||
|
from homeassistant.components.application_credentials import (
|
||||||
|
AuthImplementation,
|
||||||
|
AuthorizationServer,
|
||||||
|
ClientCredential,
|
||||||
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import config_entry_oauth2_flow
|
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
|
|
||||||
from .const import DOMAIN, ENVIRONMENT, ENVIRONMENT_URLS
|
from .const import ENVIRONMENT, ENVIRONMENT_URLS
|
||||||
|
|
||||||
|
|
||||||
class GeocachingOAuth2Implementation(
|
class GeocachingOAuth2Implementation(AuthImplementation):
|
||||||
config_entry_oauth2_flow.LocalOAuth2Implementation
|
|
||||||
):
|
|
||||||
"""Local OAuth2 implementation for Geocaching."""
|
"""Local OAuth2 implementation for Geocaching."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, hass: HomeAssistant, client_id: str, client_secret: str, name: str
|
self,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
auth_domain: str,
|
||||||
|
credential: ClientCredential,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Local Geocaching Oauth Implementation."""
|
"""Local Geocaching Oauth Implementation."""
|
||||||
self._name = name
|
|
||||||
super().__init__(
|
super().__init__(
|
||||||
hass=hass,
|
hass=hass,
|
||||||
client_id=client_id,
|
auth_domain=auth_domain,
|
||||||
client_secret=client_secret,
|
credential=credential,
|
||||||
domain=DOMAIN,
|
authorization_server=AuthorizationServer(
|
||||||
authorize_url=ENVIRONMENT_URLS[ENVIRONMENT]["authorize_url"],
|
authorize_url=ENVIRONMENT_URLS[ENVIRONMENT]["authorize_url"],
|
||||||
token_url=ENVIRONMENT_URLS[ENVIRONMENT]["token_url"],
|
token_url=ENVIRONMENT_URLS[ENVIRONMENT]["token_url"],
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self) -> str:
|
|
||||||
"""Name of the implementation."""
|
|
||||||
return f"{self._name}"
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_authorize_data(self) -> dict:
|
def extra_authorize_data(self) -> dict:
|
||||||
"""Extra data that needs to be appended to the authorize url."""
|
"""Extra data that needs to be appended to the authorize url."""
|
||||||
|
@ -6,6 +6,7 @@ To update, run python3 -m script.hassfest
|
|||||||
# fmt: off
|
# fmt: off
|
||||||
|
|
||||||
APPLICATION_CREDENTIALS = [
|
APPLICATION_CREDENTIALS = [
|
||||||
|
"geocaching",
|
||||||
"google",
|
"google",
|
||||||
"spotify",
|
"spotify",
|
||||||
"xbox"
|
"xbox"
|
||||||
|
@ -4,19 +4,18 @@ from http import HTTPStatus
|
|||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
from aiohttp.test_utils import TestClient
|
from aiohttp.test_utils import TestClient
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant.components.application_credentials import (
|
||||||
|
ClientCredential,
|
||||||
|
async_import_client_credential,
|
||||||
|
)
|
||||||
from homeassistant.components.geocaching.const import (
|
from homeassistant.components.geocaching.const import (
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
ENVIRONMENT,
|
ENVIRONMENT,
|
||||||
ENVIRONMENT_URLS,
|
ENVIRONMENT_URLS,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import (
|
from homeassistant.config_entries import SOURCE_REAUTH, SOURCE_USER
|
||||||
DEFAULT_DISCOVERY_UNIQUE_ID,
|
|
||||||
SOURCE_INTEGRATION_DISCOVERY,
|
|
||||||
SOURCE_REAUTH,
|
|
||||||
SOURCE_USER,
|
|
||||||
)
|
|
||||||
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET
|
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.data_entry_flow import RESULT_TYPE_ABORT, RESULT_TYPE_EXTERNAL_STEP
|
from homeassistant.data_entry_flow import RESULT_TYPE_ABORT, RESULT_TYPE_EXTERNAL_STEP
|
||||||
from homeassistant.helpers import config_entry_oauth2_flow
|
from homeassistant.helpers import config_entry_oauth2_flow
|
||||||
@ -30,17 +29,14 @@ from tests.test_util.aiohttp import AiohttpClientMocker
|
|||||||
CURRENT_ENVIRONMENT_URLS = ENVIRONMENT_URLS[ENVIRONMENT]
|
CURRENT_ENVIRONMENT_URLS = ENVIRONMENT_URLS[ENVIRONMENT]
|
||||||
|
|
||||||
|
|
||||||
async def setup_geocaching_component(hass: HomeAssistant) -> bool:
|
@pytest.fixture(autouse=True)
|
||||||
"""Set up the Geocaching component."""
|
async def setup_credentials(hass: HomeAssistant) -> None:
|
||||||
return await async_setup_component(
|
"""Fixture to setup credentials."""
|
||||||
|
assert await async_setup_component(hass, "application_credentials", {})
|
||||||
|
await async_import_client_credential(
|
||||||
hass,
|
hass,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
{
|
ClientCredential(CLIENT_ID, CLIENT_SECRET),
|
||||||
DOMAIN: {
|
|
||||||
CONF_CLIENT_ID: CLIENT_ID,
|
|
||||||
CONF_CLIENT_SECRET: CLIENT_SECRET,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -53,15 +49,6 @@ async def test_full_flow(
|
|||||||
mock_setup_entry: MagicMock,
|
mock_setup_entry: MagicMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Check full flow."""
|
"""Check full flow."""
|
||||||
assert await setup_geocaching_component(hass)
|
|
||||||
|
|
||||||
# Ensure integration is discovered when manual implementation is configured
|
|
||||||
flows = hass.config_entries.flow.async_progress()
|
|
||||||
assert len(flows) == 1
|
|
||||||
assert "context" in flows[0]
|
|
||||||
assert flows[0]["context"]["source"] == SOURCE_INTEGRATION_DISCOVERY
|
|
||||||
assert flows[0]["context"]["unique_id"] == DEFAULT_DISCOVERY_UNIQUE_ID
|
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN, context={"source": SOURCE_USER}
|
DOMAIN, context={"source": SOURCE_USER}
|
||||||
)
|
)
|
||||||
@ -113,9 +100,9 @@ async def test_existing_entry(
|
|||||||
mock_geocaching_config_flow: MagicMock,
|
mock_geocaching_config_flow: MagicMock,
|
||||||
mock_setup_entry: MagicMock,
|
mock_setup_entry: MagicMock,
|
||||||
mock_config_entry: MockConfigEntry,
|
mock_config_entry: MockConfigEntry,
|
||||||
|
setup_credentials: None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Check existing entry."""
|
"""Check existing entry."""
|
||||||
assert await setup_geocaching_component(hass)
|
|
||||||
mock_config_entry.add_to_hass(hass)
|
mock_config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
|
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
|
||||||
@ -161,7 +148,6 @@ async def test_oauth_error(
|
|||||||
mock_setup_entry: MagicMock,
|
mock_setup_entry: MagicMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Check if aborted when oauth error occurs."""
|
"""Check if aborted when oauth error occurs."""
|
||||||
assert await setup_geocaching_component(hass)
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN, context={"source": SOURCE_USER}
|
DOMAIN, context={"source": SOURCE_USER}
|
||||||
)
|
)
|
||||||
@ -213,7 +199,6 @@ async def test_reauthentication(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Test Geocaching reauthentication."""
|
"""Test Geocaching reauthentication."""
|
||||||
mock_config_entry.add_to_hass(hass)
|
mock_config_entry.add_to_hass(hass)
|
||||||
assert await setup_geocaching_component(hass)
|
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN, context={"source": SOURCE_REAUTH}
|
DOMAIN, context={"source": SOURCE_REAUTH}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user