mirror of
https://github.com/home-assistant/core.git
synced 2025-07-17 18:27:09 +00:00
Fix double space quoting in WebDAV (#140364)
This commit is contained in:
parent
bc6d342919
commit
d2124db3ec
@ -13,7 +13,11 @@ from homeassistant.core import HomeAssistant
|
|||||||
from homeassistant.exceptions import ConfigEntryError, ConfigEntryNotReady
|
from homeassistant.exceptions import ConfigEntryError, ConfigEntryNotReady
|
||||||
|
|
||||||
from .const import CONF_BACKUP_PATH, DATA_BACKUP_AGENT_LISTENERS, DOMAIN
|
from .const import CONF_BACKUP_PATH, DATA_BACKUP_AGENT_LISTENERS, DOMAIN
|
||||||
from .helpers import async_create_client, async_ensure_path_exists
|
from .helpers import (
|
||||||
|
async_create_client,
|
||||||
|
async_ensure_path_exists,
|
||||||
|
async_migrate_wrong_folder_path,
|
||||||
|
)
|
||||||
|
|
||||||
type WebDavConfigEntry = ConfigEntry[Client]
|
type WebDavConfigEntry = ConfigEntry[Client]
|
||||||
|
|
||||||
@ -46,10 +50,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: WebDavConfigEntry) -> bo
|
|||||||
translation_key="cannot_connect",
|
translation_key="cannot_connect",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
path = entry.data.get(CONF_BACKUP_PATH, "/")
|
||||||
|
await async_migrate_wrong_folder_path(client, path)
|
||||||
|
|
||||||
# Ensure the backup directory exists
|
# Ensure the backup directory exists
|
||||||
if not await async_ensure_path_exists(
|
if not await async_ensure_path_exists(client, path):
|
||||||
client, entry.data.get(CONF_BACKUP_PATH, "/")
|
|
||||||
):
|
|
||||||
raise ConfigEntryNotReady(
|
raise ConfigEntryNotReady(
|
||||||
translation_domain=DOMAIN,
|
translation_domain=DOMAIN,
|
||||||
translation_key="cannot_access_or_create_backup_path",
|
translation_key="cannot_access_or_create_backup_path",
|
||||||
|
@ -1,10 +1,18 @@
|
|||||||
"""Helper functions for the WebDAV component."""
|
"""Helper functions for the WebDAV component."""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
from aiowebdav2.client import Client, ClientOptions
|
from aiowebdav2.client import Client, ClientOptions
|
||||||
|
from aiowebdav2.exceptions import WebDavError
|
||||||
|
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
from homeassistant.exceptions import ConfigEntryNotReady
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
|
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_create_client(
|
def async_create_client(
|
||||||
@ -36,3 +44,24 @@ async def async_ensure_path_exists(client: Client, path: str) -> bool:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def async_migrate_wrong_folder_path(client: Client, path: str) -> None:
|
||||||
|
"""Migrate the wrong encoded folder path to the correct one."""
|
||||||
|
wrong_path = path.replace(" ", "%20")
|
||||||
|
if await client.check(wrong_path):
|
||||||
|
try:
|
||||||
|
await client.move(wrong_path, path)
|
||||||
|
except WebDavError as err:
|
||||||
|
raise ConfigEntryNotReady(
|
||||||
|
translation_domain=DOMAIN,
|
||||||
|
translation_key="failed_to_migrate_folder",
|
||||||
|
translation_placeholders={
|
||||||
|
"wrong_path": wrong_path,
|
||||||
|
"correct_path": path,
|
||||||
|
},
|
||||||
|
) from err
|
||||||
|
|
||||||
|
_LOGGER.debug(
|
||||||
|
"Migrated wrong encoded folder path from %s to %s", wrong_path, path
|
||||||
|
)
|
||||||
|
@ -8,5 +8,5 @@
|
|||||||
"iot_class": "cloud_polling",
|
"iot_class": "cloud_polling",
|
||||||
"loggers": ["aiowebdav2"],
|
"loggers": ["aiowebdav2"],
|
||||||
"quality_scale": "bronze",
|
"quality_scale": "bronze",
|
||||||
"requirements": ["aiowebdav2==0.4.1"]
|
"requirements": ["aiowebdav2==0.4.2"]
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,9 @@
|
|||||||
},
|
},
|
||||||
"cannot_access_or_create_backup_path": {
|
"cannot_access_or_create_backup_path": {
|
||||||
"message": "Cannot access or create backup path. Please check the path and permissions."
|
"message": "Cannot access or create backup path. Please check the path and permissions."
|
||||||
|
},
|
||||||
|
"failed_to_migrate_folder": {
|
||||||
|
"message": "Failed to migrate wrong encoded folder \"{wrong_path}\" to \"{correct_path}\"."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
requirements_all.txt
generated
2
requirements_all.txt
generated
@ -422,7 +422,7 @@ aiowaqi==3.1.0
|
|||||||
aiowatttime==0.1.1
|
aiowatttime==0.1.1
|
||||||
|
|
||||||
# homeassistant.components.webdav
|
# homeassistant.components.webdav
|
||||||
aiowebdav2==0.4.1
|
aiowebdav2==0.4.2
|
||||||
|
|
||||||
# homeassistant.components.webostv
|
# homeassistant.components.webostv
|
||||||
aiowebostv==0.7.3
|
aiowebostv==0.7.3
|
||||||
|
2
requirements_test_all.txt
generated
2
requirements_test_all.txt
generated
@ -404,7 +404,7 @@ aiowaqi==3.1.0
|
|||||||
aiowatttime==0.1.1
|
aiowatttime==0.1.1
|
||||||
|
|
||||||
# homeassistant.components.webdav
|
# homeassistant.components.webdav
|
||||||
aiowebdav2==0.4.1
|
aiowebdav2==0.4.2
|
||||||
|
|
||||||
# homeassistant.components.webostv
|
# homeassistant.components.webostv
|
||||||
aiowebostv==0.7.3
|
aiowebostv==0.7.3
|
||||||
|
@ -1 +1,14 @@
|
|||||||
"""Tests for the WebDAV integration."""
|
"""Tests for the WebDAV integration."""
|
||||||
|
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
|
||||||
|
async def setup_integration(
|
||||||
|
hass: HomeAssistant, mock_config_entry: MockConfigEntry
|
||||||
|
) -> None:
|
||||||
|
"""Set up the WebDAV integration for testing."""
|
||||||
|
mock_config_entry.add_to_hass(hass)
|
||||||
|
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
@ -62,4 +62,5 @@ def mock_webdav_client() -> Generator[AsyncMock]:
|
|||||||
mock.download_iter.side_effect = _download_mock
|
mock.download_iter.side_effect = _download_mock
|
||||||
mock.upload_iter.return_value = None
|
mock.upload_iter.return_value = None
|
||||||
mock.clean.return_value = None
|
mock.clean.return_value = None
|
||||||
|
mock.move.return_value = None
|
||||||
yield mock
|
yield mock
|
||||||
|
96
tests/components/webdav/test_init.py
Normal file
96
tests/components/webdav/test_init.py
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
"""Test WebDAV component setup."""
|
||||||
|
|
||||||
|
from unittest.mock import AsyncMock
|
||||||
|
|
||||||
|
from aiowebdav2.exceptions import WebDavError
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant.components.webdav.const import CONF_BACKUP_PATH, DOMAIN
|
||||||
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
|
from homeassistant.const import CONF_PASSWORD, CONF_URL, CONF_USERNAME
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
from . import setup_integration
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
|
||||||
|
async def test_migrate_wrong_path(
|
||||||
|
hass: HomeAssistant, webdav_client: AsyncMock
|
||||||
|
) -> None:
|
||||||
|
"""Test migration of wrong encoded folder path."""
|
||||||
|
webdav_client.list_with_properties.return_value = [
|
||||||
|
{"/wrong%20path": []},
|
||||||
|
]
|
||||||
|
|
||||||
|
config_entry = MockConfigEntry(
|
||||||
|
title="user@webdav.demo",
|
||||||
|
domain=DOMAIN,
|
||||||
|
data={
|
||||||
|
CONF_URL: "https://webdav.demo",
|
||||||
|
CONF_USERNAME: "user",
|
||||||
|
CONF_PASSWORD: "supersecretpassword",
|
||||||
|
CONF_BACKUP_PATH: "/wrong path",
|
||||||
|
},
|
||||||
|
entry_id="01JKXV07ASC62D620DGYNG2R8H",
|
||||||
|
)
|
||||||
|
await setup_integration(hass, config_entry)
|
||||||
|
|
||||||
|
webdav_client.move.assert_called_once_with("/wrong%20path", "/wrong path")
|
||||||
|
|
||||||
|
|
||||||
|
async def test_migrate_non_wrong_path(
|
||||||
|
hass: HomeAssistant, webdav_client: AsyncMock
|
||||||
|
) -> None:
|
||||||
|
"""Test no migration of correct folder path."""
|
||||||
|
webdav_client.list_with_properties.return_value = [
|
||||||
|
{"/correct path": []},
|
||||||
|
]
|
||||||
|
webdav_client.check.side_effect = lambda path: path == "/correct path"
|
||||||
|
|
||||||
|
config_entry = MockConfigEntry(
|
||||||
|
title="user@webdav.demo",
|
||||||
|
domain=DOMAIN,
|
||||||
|
data={
|
||||||
|
CONF_URL: "https://webdav.demo",
|
||||||
|
CONF_USERNAME: "user",
|
||||||
|
CONF_PASSWORD: "supersecretpassword",
|
||||||
|
CONF_BACKUP_PATH: "/correct path",
|
||||||
|
},
|
||||||
|
entry_id="01JKXV07ASC62D620DGYNG2R8H",
|
||||||
|
)
|
||||||
|
|
||||||
|
await setup_integration(hass, config_entry)
|
||||||
|
|
||||||
|
webdav_client.move.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
async def test_migrate_error(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
webdav_client: AsyncMock,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
) -> None:
|
||||||
|
"""Test migration of wrong encoded folder path with error."""
|
||||||
|
webdav_client.list_with_properties.return_value = [
|
||||||
|
{"/wrong%20path": []},
|
||||||
|
]
|
||||||
|
webdav_client.move.side_effect = WebDavError("Failed to move")
|
||||||
|
|
||||||
|
config_entry = MockConfigEntry(
|
||||||
|
title="user@webdav.demo",
|
||||||
|
domain=DOMAIN,
|
||||||
|
data={
|
||||||
|
CONF_URL: "https://webdav.demo",
|
||||||
|
CONF_USERNAME: "user",
|
||||||
|
CONF_PASSWORD: "supersecretpassword",
|
||||||
|
CONF_BACKUP_PATH: "/wrong path",
|
||||||
|
},
|
||||||
|
entry_id="01JKXV07ASC62D620DGYNG2R8H",
|
||||||
|
)
|
||||||
|
await setup_integration(hass, config_entry)
|
||||||
|
|
||||||
|
assert config_entry.state is ConfigEntryState.SETUP_RETRY
|
||||||
|
assert (
|
||||||
|
'Failed to migrate wrong encoded folder "/wrong%20path" to "/wrong path"'
|
||||||
|
in caplog.text
|
||||||
|
)
|
Loading…
x
Reference in New Issue
Block a user