Strip trailing slash from Jellyfin server URL (#173049)
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.const import CONF_URL
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
|
||||
from homeassistant.helpers import config_validation as cv, device_registry as dr
|
||||
@@ -65,6 +66,15 @@ async def async_setup_entry(hass: HomeAssistant, entry: JellyfinConfigEntry) ->
|
||||
return True
|
||||
|
||||
|
||||
async def async_migrate_entry(hass: HomeAssistant, entry: JellyfinConfigEntry) -> bool:
|
||||
"""Migrate an old config entry."""
|
||||
if entry.version == 1 and entry.minor_version < 2:
|
||||
new_data = {**entry.data, CONF_URL: entry.data[CONF_URL].rstrip("/")}
|
||||
hass.config_entries.async_update_entry(entry, data=new_data, minor_version=2)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: JellyfinConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||
|
||||
@@ -46,6 +46,7 @@ class JellyfinConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
"""Handle a config flow for Jellyfin."""
|
||||
|
||||
VERSION = 1
|
||||
MINOR_VERSION = 2
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Initialize the Jellyfin config flow."""
|
||||
@@ -58,6 +59,8 @@ class JellyfinConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
errors: dict[str, str] = {}
|
||||
|
||||
if user_input is not None:
|
||||
user_input[CONF_URL] = user_input[CONF_URL].rstrip("/")
|
||||
|
||||
if self.client_device_id is None:
|
||||
self.client_device_id = _generate_client_device_id()
|
||||
|
||||
|
||||
@@ -59,6 +59,35 @@ async def test_form(
|
||||
assert len(mock_client.jellyfin.get_user_settings.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_form_strips_trailing_slash_from_url(
|
||||
hass: HomeAssistant,
|
||||
mock_jellyfin: MagicMock,
|
||||
mock_client: MagicMock,
|
||||
mock_client_device_id: MagicMock,
|
||||
mock_setup_entry: MagicMock,
|
||||
) -> None:
|
||||
"""Test a trailing slash is stripped from the configured URL.
|
||||
|
||||
A trailing slash would otherwise be joined into a double-slashed request
|
||||
path (e.g. //system/info/public) that some Jellyfin versions reject.
|
||||
"""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={**USER_INPUT, CONF_URL: f"{TEST_URL}/"},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result2["type"] is FlowResultType.CREATE_ENTRY
|
||||
# The persisted URL has no trailing slash...
|
||||
assert result2["data"][CONF_URL] == TEST_URL
|
||||
# ...and the connection was attempted against the normalized URL.
|
||||
mock_client.auth.connect_to_address.assert_called_once_with(TEST_URL)
|
||||
|
||||
|
||||
async def test_form_cannot_connect(
|
||||
hass: HomeAssistant,
|
||||
mock_jellyfin: MagicMock,
|
||||
|
||||
@@ -4,11 +4,13 @@ from unittest.mock import MagicMock
|
||||
|
||||
from homeassistant.components.jellyfin.const import DOMAIN
|
||||
from homeassistant.config_entries import SOURCE_REAUTH, ConfigEntryState
|
||||
from homeassistant.const import CONF_PASSWORD, CONF_URL, CONF_USERNAME
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from . import async_load_json_fixture
|
||||
from .const import TEST_PASSWORD, TEST_URL, TEST_USERNAME
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
from tests.typing import WebSocketGenerator
|
||||
@@ -75,6 +77,33 @@ async def test_load_unload_config_entry(
|
||||
assert mock_config_entry.state is ConfigEntryState.NOT_LOADED
|
||||
|
||||
|
||||
async def test_migrate_strips_trailing_slash_from_url(
|
||||
hass: HomeAssistant,
|
||||
mock_jellyfin: MagicMock,
|
||||
mock_client: MagicMock,
|
||||
) -> None:
|
||||
"""Test migrating an entry strips a trailing slash from the stored URL."""
|
||||
config_entry = MockConfigEntry(
|
||||
title="Jellyfin",
|
||||
domain=DOMAIN,
|
||||
data={
|
||||
CONF_URL: f"{TEST_URL}/",
|
||||
CONF_USERNAME: TEST_USERNAME,
|
||||
CONF_PASSWORD: TEST_PASSWORD,
|
||||
},
|
||||
unique_id="USER-UUID",
|
||||
version=1,
|
||||
minor_version=1,
|
||||
)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert config_entry.minor_version == 2
|
||||
assert config_entry.data[CONF_URL] == TEST_URL
|
||||
|
||||
|
||||
async def test_device_remove_devices(
|
||||
hass: HomeAssistant,
|
||||
hass_ws_client: WebSocketGenerator,
|
||||
|
||||
Reference in New Issue
Block a user