Handle invalid auth in Overseerr (#136243)

This commit is contained in:
Joost Lekkerkerker 2025-01-22 13:47:13 +01:00 committed by GitHub
parent 0b7ed7dcbd
commit 5e63e02ebc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 62 additions and 7 deletions

View File

@ -2,8 +2,11 @@
from typing import Any from typing import Any
from python_overseerr import OverseerrClient from python_overseerr import (
from python_overseerr.exceptions import OverseerrError OverseerrAuthenticationError,
OverseerrClient,
OverseerrError,
)
import voluptuous as vol import voluptuous as vol
from yarl import URL from yarl import URL
@ -47,6 +50,8 @@ class OverseerrConfigFlow(ConfigFlow, domain=DOMAIN):
) )
try: try:
await client.get_request_count() await client.get_request_count()
except OverseerrAuthenticationError:
errors["base"] = "invalid_auth"
except OverseerrError: except OverseerrError:
errors["base"] = "cannot_connect" errors["base"] = "cannot_connect"
else: else:

View File

@ -2,13 +2,18 @@
from datetime import timedelta from datetime import timedelta
from python_overseerr import OverseerrClient, RequestCount from python_overseerr import (
from python_overseerr.exceptions import OverseerrConnectionError OverseerrAuthenticationError,
OverseerrClient,
OverseerrConnectionError,
RequestCount,
)
from yarl import URL from yarl import URL
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_API_KEY, CONF_HOST, CONF_PORT, CONF_SSL from homeassistant.const import CONF_API_KEY, CONF_HOST, CONF_PORT, CONF_SSL
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryError
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
@ -47,6 +52,11 @@ class OverseerrCoordinator(DataUpdateCoordinator[RequestCount]):
"""Fetch data from API endpoint.""" """Fetch data from API endpoint."""
try: try:
return await self.client.get_request_count() return await self.client.get_request_count()
except OverseerrAuthenticationError as err:
raise ConfigEntryError(
translation_domain=DOMAIN,
translation_key="auth_error",
) from err
except OverseerrConnectionError as err: except OverseerrConnectionError as err:
raise UpdateFailed( raise UpdateFailed(
translation_domain=DOMAIN, translation_domain=DOMAIN,

View File

@ -17,6 +17,7 @@
}, },
"error": { "error": {
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
"invalid_host": "The provided URL is not a valid host." "invalid_host": "The provided URL is not a valid host."
} }
}, },
@ -66,6 +67,9 @@
"connection_error": { "connection_error": {
"message": "Error connecting to the Overseerr instance: {error}" "message": "Error connecting to the Overseerr instance: {error}"
}, },
"auth_error": {
"message": "Invalid API key."
},
"not_loaded": { "not_loaded": {
"message": "{target} is not loaded." "message": "{target} is not loaded."
}, },

View File

@ -3,7 +3,10 @@
from unittest.mock import AsyncMock, patch from unittest.mock import AsyncMock, patch
import pytest import pytest
from python_overseerr.exceptions import OverseerrConnectionError from python_overseerr.exceptions import (
OverseerrAuthenticationError,
OverseerrConnectionError,
)
from homeassistant.components.overseerr.const import DOMAIN from homeassistant.components.overseerr.const import DOMAIN
from homeassistant.config_entries import SOURCE_USER from homeassistant.config_entries import SOURCE_USER
@ -61,13 +64,22 @@ async def test_full_flow(
} }
@pytest.mark.parametrize(
("exception", "error"),
[
(OverseerrAuthenticationError, "invalid_auth"),
(OverseerrConnectionError, "cannot_connect"),
],
)
async def test_flow_errors( async def test_flow_errors(
hass: HomeAssistant, hass: HomeAssistant,
mock_overseerr_client: AsyncMock, mock_overseerr_client: AsyncMock,
mock_setup_entry: AsyncMock, mock_setup_entry: AsyncMock,
exception: Exception,
error: str,
) -> None: ) -> None:
"""Test flow errors.""" """Test flow errors."""
mock_overseerr_client.get_request_count.side_effect = OverseerrConnectionError() mock_overseerr_client.get_request_count.side_effect = exception
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
DOMAIN, DOMAIN,
@ -82,7 +94,7 @@ async def test_flow_errors(
) )
assert result["type"] is FlowResultType.FORM assert result["type"] is FlowResultType.FORM
assert result["errors"] == {"base": "cannot_connect"} assert result["errors"] == {"base": error}
mock_overseerr_client.get_request_count.side_effect = None mock_overseerr_client.get_request_count.side_effect = None

View File

@ -4,6 +4,7 @@ from typing import Any
from unittest.mock import AsyncMock, patch from unittest.mock import AsyncMock, patch
import pytest import pytest
from python_overseerr import OverseerrAuthenticationError, OverseerrConnectionError
from python_overseerr.models import WebhookNotificationOptions from python_overseerr.models import WebhookNotificationOptions
from syrupy import SnapshotAssertion from syrupy import SnapshotAssertion
@ -14,6 +15,7 @@ from homeassistant.components.overseerr import (
REGISTERED_NOTIFICATIONS, REGISTERED_NOTIFICATIONS,
) )
from homeassistant.components.overseerr.const import DOMAIN from homeassistant.components.overseerr.const import DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr from homeassistant.helpers import device_registry as dr
@ -23,6 +25,28 @@ from tests.common import MockConfigEntry
from tests.components.cloud import mock_cloud from tests.components.cloud import mock_cloud
@pytest.mark.parametrize(
("exception", "config_entry_state"),
[
(OverseerrAuthenticationError, ConfigEntryState.SETUP_ERROR),
(OverseerrConnectionError, ConfigEntryState.SETUP_RETRY),
],
)
async def test_initialization_errors(
hass: HomeAssistant,
mock_overseerr_client: AsyncMock,
mock_config_entry: MockConfigEntry,
exception: Exception,
config_entry_state: ConfigEntryState,
) -> None:
"""Test the Overseerr integration initialization errors."""
mock_overseerr_client.get_request_count.side_effect = exception
await setup_integration(hass, mock_config_entry)
assert mock_config_entry.state == config_entry_state
async def test_device_info( async def test_device_info(
hass: HomeAssistant, hass: HomeAssistant,
snapshot: SnapshotAssertion, snapshot: SnapshotAssertion,