From 7c68278482aa79817012af78f6cd49fd7fc51ffd Mon Sep 17 00:00:00 2001 From: Allen Porter Date: Mon, 16 May 2022 00:57:25 -0700 Subject: [PATCH] Add application_credentials platform to geocaching integration (#71880) --- .../components/geocaching/__init__.py | 46 +------------------ .../geocaching/application_credentials.py | 14 ++++++ .../components/geocaching/manifest.json | 2 +- homeassistant/components/geocaching/oauth.py | 34 +++++++------- .../generated/application_credentials.py | 1 + .../components/geocaching/test_config_flow.py | 41 ++++++----------- 6 files changed, 48 insertions(+), 90 deletions(-) create mode 100644 homeassistant/components/geocaching/application_credentials.py diff --git a/homeassistant/components/geocaching/__init__.py b/homeassistant/components/geocaching/__init__.py index f04fbbd608f..430cbc9a8d0 100644 --- a/homeassistant/components/geocaching/__init__.py +++ b/homeassistant/components/geocaching/__init__.py @@ -1,61 +1,19 @@ """The Geocaching integration.""" -import voluptuous as vol -from homeassistant.config_entries import SOURCE_INTEGRATION_DISCOVERY, ConfigEntry -from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET, Platform +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import Platform from homeassistant.core import HomeAssistant -from homeassistant.helpers import config_validation as cv from homeassistant.helpers.config_entry_oauth2_flow import ( OAuth2Session, async_get_config_entry_implementation, ) -from homeassistant.helpers.typing import ConfigType -from .config_flow import GeocachingFlowHandler from .const import DOMAIN 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] -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: """Set up Geocaching from a config entry.""" implementation = await async_get_config_entry_implementation(hass, entry) diff --git a/homeassistant/components/geocaching/application_credentials.py b/homeassistant/components/geocaching/application_credentials.py new file mode 100644 index 00000000000..e3d35f57a81 --- /dev/null +++ b/homeassistant/components/geocaching/application_credentials.py @@ -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) diff --git a/homeassistant/components/geocaching/manifest.json b/homeassistant/components/geocaching/manifest.json index 683a23d474a..59c3da45cf5 100644 --- a/homeassistant/components/geocaching/manifest.json +++ b/homeassistant/components/geocaching/manifest.json @@ -4,7 +4,7 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/geocaching", "requirements": ["geocachingapi==0.2.1"], - "dependencies": ["auth"], + "dependencies": ["application_credentials"], "codeowners": ["@Sholofly", "@reinder83"], "iot_class": "cloud_polling" } diff --git a/homeassistant/components/geocaching/oauth.py b/homeassistant/components/geocaching/oauth.py index 29371eb793c..e0120344cdb 100644 --- a/homeassistant/components/geocaching/oauth.py +++ b/homeassistant/components/geocaching/oauth.py @@ -3,37 +3,37 @@ from __future__ import annotations from typing import Any, cast +from homeassistant.components.application_credentials import ( + AuthImplementation, + AuthorizationServer, + ClientCredential, +) from homeassistant.core import HomeAssistant -from homeassistant.helpers import config_entry_oauth2_flow from homeassistant.helpers.aiohttp_client import async_get_clientsession -from .const import DOMAIN, ENVIRONMENT, ENVIRONMENT_URLS +from .const import ENVIRONMENT, ENVIRONMENT_URLS -class GeocachingOAuth2Implementation( - config_entry_oauth2_flow.LocalOAuth2Implementation -): +class GeocachingOAuth2Implementation(AuthImplementation): """Local OAuth2 implementation for Geocaching.""" def __init__( - self, hass: HomeAssistant, client_id: str, client_secret: str, name: str + self, + hass: HomeAssistant, + auth_domain: str, + credential: ClientCredential, ) -> None: """Local Geocaching Oauth Implementation.""" - self._name = name super().__init__( hass=hass, - client_id=client_id, - client_secret=client_secret, - domain=DOMAIN, - authorize_url=ENVIRONMENT_URLS[ENVIRONMENT]["authorize_url"], - token_url=ENVIRONMENT_URLS[ENVIRONMENT]["token_url"], + auth_domain=auth_domain, + credential=credential, + authorization_server=AuthorizationServer( + authorize_url=ENVIRONMENT_URLS[ENVIRONMENT]["authorize_url"], + token_url=ENVIRONMENT_URLS[ENVIRONMENT]["token_url"], + ), ) - @property - def name(self) -> str: - """Name of the implementation.""" - return f"{self._name}" - @property def extra_authorize_data(self) -> dict: """Extra data that needs to be appended to the authorize url.""" diff --git a/homeassistant/generated/application_credentials.py b/homeassistant/generated/application_credentials.py index 3e283dcfeee..56340ccc44e 100644 --- a/homeassistant/generated/application_credentials.py +++ b/homeassistant/generated/application_credentials.py @@ -6,6 +6,7 @@ To update, run python3 -m script.hassfest # fmt: off APPLICATION_CREDENTIALS = [ + "geocaching", "google", "spotify", "xbox" diff --git a/tests/components/geocaching/test_config_flow.py b/tests/components/geocaching/test_config_flow.py index 0f5d182b2db..56a301e2f3c 100644 --- a/tests/components/geocaching/test_config_flow.py +++ b/tests/components/geocaching/test_config_flow.py @@ -4,19 +4,18 @@ from http import HTTPStatus from unittest.mock import MagicMock 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 ( DOMAIN, ENVIRONMENT, ENVIRONMENT_URLS, ) -from homeassistant.config_entries import ( - DEFAULT_DISCOVERY_UNIQUE_ID, - SOURCE_INTEGRATION_DISCOVERY, - SOURCE_REAUTH, - SOURCE_USER, -) -from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET +from homeassistant.config_entries import SOURCE_REAUTH, SOURCE_USER from homeassistant.core import HomeAssistant from homeassistant.data_entry_flow import RESULT_TYPE_ABORT, RESULT_TYPE_EXTERNAL_STEP 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] -async def setup_geocaching_component(hass: HomeAssistant) -> bool: - """Set up the Geocaching component.""" - return await async_setup_component( +@pytest.fixture(autouse=True) +async def setup_credentials(hass: HomeAssistant) -> None: + """Fixture to setup credentials.""" + assert await async_setup_component(hass, "application_credentials", {}) + await async_import_client_credential( hass, DOMAIN, - { - DOMAIN: { - CONF_CLIENT_ID: CLIENT_ID, - CONF_CLIENT_SECRET: CLIENT_SECRET, - }, - }, + ClientCredential(CLIENT_ID, CLIENT_SECRET), ) @@ -53,15 +49,6 @@ async def test_full_flow( mock_setup_entry: MagicMock, ) -> None: """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( DOMAIN, context={"source": SOURCE_USER} ) @@ -113,9 +100,9 @@ async def test_existing_entry( mock_geocaching_config_flow: MagicMock, mock_setup_entry: MagicMock, mock_config_entry: MockConfigEntry, + setup_credentials: None, ) -> None: """Check existing entry.""" - assert await setup_geocaching_component(hass) mock_config_entry.add_to_hass(hass) assert len(hass.config_entries.async_entries(DOMAIN)) == 1 @@ -161,7 +148,6 @@ async def test_oauth_error( mock_setup_entry: MagicMock, ) -> None: """Check if aborted when oauth error occurs.""" - assert await setup_geocaching_component(hass) result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_USER} ) @@ -213,7 +199,6 @@ async def test_reauthentication( ) -> None: """Test Geocaching reauthentication.""" mock_config_entry.add_to_hass(hass) - assert await setup_geocaching_component(hass) result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_REAUTH}