mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 18:57:06 +00:00
Add missing application credential to Tesla Fleet (#123271)
Co-authored-by: Franck Nijhof <frenck@frenck.nl>
This commit is contained in:
parent
45ce0fed0a
commit
764166342e
@ -13,6 +13,7 @@ from tesla_fleet_api.exceptions import (
|
|||||||
TeslaFleetError,
|
TeslaFleetError,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from homeassistant.components.application_credentials import ClientCredential
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_TOKEN, Platform
|
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_TOKEN, Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
@ -26,7 +27,9 @@ from homeassistant.helpers.config_entry_oauth2_flow import (
|
|||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.device_registry import DeviceInfo
|
from homeassistant.helpers.device_registry import DeviceInfo
|
||||||
|
|
||||||
from .const import DOMAIN, LOGGER, MODELS
|
from .application_credentials import TeslaOAuth2Implementation
|
||||||
|
from .config_flow import OAuth2FlowHandler
|
||||||
|
from .const import CLIENT_ID, DOMAIN, LOGGER, MODELS, NAME
|
||||||
from .coordinator import (
|
from .coordinator import (
|
||||||
TeslaFleetEnergySiteInfoCoordinator,
|
TeslaFleetEnergySiteInfoCoordinator,
|
||||||
TeslaFleetEnergySiteLiveCoordinator,
|
TeslaFleetEnergySiteLiveCoordinator,
|
||||||
@ -51,6 +54,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: TeslaFleetConfigEntry) -
|
|||||||
scopes = token["scp"]
|
scopes = token["scp"]
|
||||||
region = token["ou_code"].lower()
|
region = token["ou_code"].lower()
|
||||||
|
|
||||||
|
OAuth2FlowHandler.async_register_implementation(
|
||||||
|
hass,
|
||||||
|
TeslaOAuth2Implementation(hass, DOMAIN, ClientCredential(CLIENT_ID, "", NAME)),
|
||||||
|
)
|
||||||
|
|
||||||
implementation = await async_get_config_entry_implementation(hass, entry)
|
implementation = await async_get_config_entry_implementation(hass, entry)
|
||||||
oauth_session = OAuth2Session(hass, entry, implementation)
|
oauth_session = OAuth2Session(hass, entry, implementation)
|
||||||
refresh_lock = asyncio.Lock()
|
refresh_lock = asyncio.Lock()
|
||||||
|
@ -5,15 +5,17 @@ import hashlib
|
|||||||
import secrets
|
import secrets
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from homeassistant.components.application_credentials import ClientCredential
|
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 import config_entry_oauth2_flow
|
||||||
|
|
||||||
from .const import DOMAIN, SCOPES
|
from .const import AUTHORIZE_URL, DOMAIN, SCOPES, TOKEN_URL
|
||||||
|
|
||||||
CLIENT_ID = "71b813eb-4a2e-483a-b831-4dec5cb9bf0d"
|
AUTH_SERVER = AuthorizationServer(AUTHORIZE_URL, TOKEN_URL)
|
||||||
AUTHORIZE_URL = "https://auth.tesla.com/oauth2/v3/authorize"
|
|
||||||
TOKEN_URL = "https://auth.tesla.com/oauth2/v3/token"
|
|
||||||
|
|
||||||
|
|
||||||
async def async_get_auth_implementation(
|
async def async_get_auth_implementation(
|
||||||
@ -23,15 +25,16 @@ async def async_get_auth_implementation(
|
|||||||
return TeslaOAuth2Implementation(
|
return TeslaOAuth2Implementation(
|
||||||
hass,
|
hass,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
credential,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TeslaOAuth2Implementation(config_entry_oauth2_flow.LocalOAuth2Implementation):
|
class TeslaOAuth2Implementation(AuthImplementation):
|
||||||
"""Tesla Fleet API Open Source Oauth2 implementation."""
|
"""Tesla Fleet API Open Source Oauth2 implementation."""
|
||||||
|
|
||||||
_name = "Tesla Fleet API"
|
def __init__(
|
||||||
|
self, hass: HomeAssistant, domain: str, credential: ClientCredential
|
||||||
def __init__(self, hass: HomeAssistant, domain: str) -> None:
|
) -> None:
|
||||||
"""Initialize local auth implementation."""
|
"""Initialize local auth implementation."""
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self._domain = domain
|
self._domain = domain
|
||||||
@ -45,10 +48,8 @@ class TeslaOAuth2Implementation(config_entry_oauth2_flow.LocalOAuth2Implementati
|
|||||||
super().__init__(
|
super().__init__(
|
||||||
hass,
|
hass,
|
||||||
domain,
|
domain,
|
||||||
CLIENT_ID,
|
credential,
|
||||||
"", # Implementation has no client secret
|
AUTH_SERVER,
|
||||||
AUTHORIZE_URL,
|
|
||||||
TOKEN_URL,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -8,10 +8,12 @@ from typing import Any
|
|||||||
|
|
||||||
import jwt
|
import jwt
|
||||||
|
|
||||||
|
from homeassistant.components.application_credentials import ClientCredential
|
||||||
from homeassistant.config_entries import ConfigEntry, ConfigFlowResult
|
from homeassistant.config_entries import ConfigEntry, ConfigFlowResult
|
||||||
from homeassistant.helpers import config_entry_oauth2_flow
|
from homeassistant.helpers import config_entry_oauth2_flow
|
||||||
|
|
||||||
from .const import DOMAIN, LOGGER
|
from .application_credentials import TeslaOAuth2Implementation
|
||||||
|
from .const import CLIENT_ID, DOMAIN, LOGGER, NAME
|
||||||
|
|
||||||
|
|
||||||
class OAuth2FlowHandler(
|
class OAuth2FlowHandler(
|
||||||
@ -27,6 +29,19 @@ class OAuth2FlowHandler(
|
|||||||
"""Return logger."""
|
"""Return logger."""
|
||||||
return LOGGER
|
return LOGGER
|
||||||
|
|
||||||
|
async def async_step_user(
|
||||||
|
self, user_input: dict[str, Any] | None = None
|
||||||
|
) -> ConfigFlowResult:
|
||||||
|
"""Handle a flow start."""
|
||||||
|
self.async_register_implementation(
|
||||||
|
self.hass,
|
||||||
|
TeslaOAuth2Implementation(
|
||||||
|
self.hass, DOMAIN, ClientCredential(CLIENT_ID, "", NAME)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
return await super().async_step_user()
|
||||||
|
|
||||||
async def async_oauth_create_entry(
|
async def async_oauth_create_entry(
|
||||||
self,
|
self,
|
||||||
data: dict[str, Any],
|
data: dict[str, Any],
|
||||||
|
@ -13,6 +13,11 @@ CONF_REFRESH_TOKEN = "refresh_token"
|
|||||||
|
|
||||||
LOGGER = logging.getLogger(__package__)
|
LOGGER = logging.getLogger(__package__)
|
||||||
|
|
||||||
|
NAME = "Home Assistant"
|
||||||
|
CLIENT_ID = "71b813eb-4a2e-483a-b831-4dec5cb9bf0d"
|
||||||
|
AUTHORIZE_URL = "https://auth.tesla.com/oauth2/v3/authorize"
|
||||||
|
TOKEN_URL = "https://auth.tesla.com/oauth2/v3/token"
|
||||||
|
|
||||||
SCOPES = [
|
SCOPES = [
|
||||||
Scope.OPENID,
|
Scope.OPENID,
|
||||||
Scope.OFFLINE_ACCESS,
|
Scope.OFFLINE_ACCESS,
|
||||||
|
@ -4,9 +4,15 @@ from unittest.mock import patch
|
|||||||
|
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy import SnapshotAssertion
|
||||||
|
|
||||||
|
from homeassistant.components.application_credentials import (
|
||||||
|
ClientCredential,
|
||||||
|
async_import_client_credential,
|
||||||
|
)
|
||||||
|
from homeassistant.components.tesla_fleet.const import CLIENT_ID, DOMAIN
|
||||||
from homeassistant.const import Platform
|
from homeassistant.const import Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import entity_registry as er
|
from homeassistant.helpers import entity_registry as er
|
||||||
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
@ -18,6 +24,14 @@ async def setup_platform(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Set up the Tesla Fleet platform."""
|
"""Set up the Tesla Fleet platform."""
|
||||||
|
|
||||||
|
assert await async_setup_component(hass, "application_credentials", {})
|
||||||
|
await async_import_client_credential(
|
||||||
|
hass,
|
||||||
|
DOMAIN,
|
||||||
|
ClientCredential(CLIENT_ID, "", "Home Assistant"),
|
||||||
|
DOMAIN,
|
||||||
|
)
|
||||||
|
|
||||||
config_entry.add_to_hass(hass)
|
config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
if platforms is None:
|
if platforms is None:
|
||||||
|
@ -10,14 +10,7 @@ from unittest.mock import AsyncMock, patch
|
|||||||
import jwt
|
import jwt
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.application_credentials import (
|
|
||||||
ClientCredential,
|
|
||||||
async_import_client_credential,
|
|
||||||
)
|
|
||||||
from homeassistant.components.tesla_fleet.application_credentials import CLIENT_ID
|
|
||||||
from homeassistant.components.tesla_fleet.const import DOMAIN, SCOPES
|
from homeassistant.components.tesla_fleet.const import DOMAIN, SCOPES
|
||||||
from homeassistant.core import HomeAssistant
|
|
||||||
from homeassistant.setup import async_setup_component
|
|
||||||
|
|
||||||
from .const import LIVE_STATUS, PRODUCTS, SITE_INFO, VEHICLE_DATA, VEHICLE_ONLINE
|
from .const import LIVE_STATUS, PRODUCTS, SITE_INFO, VEHICLE_DATA, VEHICLE_ONLINE
|
||||||
|
|
||||||
@ -71,18 +64,6 @@ def normal_config_entry(expires_at: int, scopes: list[str]) -> MockConfigEntry:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@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,
|
|
||||||
ClientCredential(CLIENT_ID, ""),
|
|
||||||
DOMAIN,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
def mock_products() -> Generator[AsyncMock]:
|
def mock_products() -> Generator[AsyncMock]:
|
||||||
"""Mock Tesla Fleet Api products method."""
|
"""Mock Tesla Fleet Api products method."""
|
||||||
|
@ -5,12 +5,13 @@ from urllib.parse import parse_qs, urlparse
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.tesla_fleet.application_credentials import (
|
from homeassistant.components.tesla_fleet.const import (
|
||||||
AUTHORIZE_URL,
|
AUTHORIZE_URL,
|
||||||
CLIENT_ID,
|
CLIENT_ID,
|
||||||
|
DOMAIN,
|
||||||
|
SCOPES,
|
||||||
TOKEN_URL,
|
TOKEN_URL,
|
||||||
)
|
)
|
||||||
from homeassistant.components.tesla_fleet.const import DOMAIN, SCOPES
|
|
||||||
from homeassistant.config_entries import SOURCE_REAUTH, SOURCE_USER
|
from homeassistant.config_entries import SOURCE_REAUTH, SOURCE_USER
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.data_entry_flow import FlowResultType
|
from homeassistant.data_entry_flow import FlowResultType
|
||||||
|
Loading…
x
Reference in New Issue
Block a user