Add application_credentials platform to geocaching integration (#71880)

This commit is contained in:
Allen Porter 2022-05-16 00:57:25 -07:00 committed by GitHub
parent aa35b87884
commit 7c68278482
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 48 additions and 90 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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"
}

View File

@ -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."""

View File

@ -6,6 +6,7 @@ To update, run python3 -m script.hassfest
# fmt: off
APPLICATION_CREDENTIALS = [
"geocaching",
"google",
"spotify",
"xbox"

View File

@ -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}