Fix local media browser source conflicting with local www folder (#40151)
parent
d3a59652bb
commit
9ffcf35b23
|
@ -64,7 +64,7 @@ class LocalSource(MediaSource):
|
||||||
mime_type, _ = mimetypes.guess_type(
|
mime_type, _ = mimetypes.guess_type(
|
||||||
str(self.async_full_path(source_dir_id, location))
|
str(self.async_full_path(source_dir_id, location))
|
||||||
)
|
)
|
||||||
return PlayMedia(f"/local_source/{item.identifier}", mime_type)
|
return PlayMedia(f"/media/{item.identifier}", mime_type)
|
||||||
|
|
||||||
async def async_browse_media(
|
async def async_browse_media(
|
||||||
self, item: MediaSourceItem, media_types: Tuple[str] = MEDIA_MIME_TYPES
|
self, item: MediaSourceItem, media_types: Tuple[str] = MEDIA_MIME_TYPES
|
||||||
|
@ -177,7 +177,7 @@ class LocalMediaView(HomeAssistantView):
|
||||||
Returns media files in config/media.
|
Returns media files in config/media.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
url = "/local_source/{source_dir_id}/{location:.*}"
|
url = "/media/{source_dir_id}/{location:.*}"
|
||||||
name = "media"
|
name = "media"
|
||||||
|
|
||||||
def __init__(self, hass: HomeAssistant, source: LocalSource):
|
def __init__(self, hass: HomeAssistant, source: LocalSource):
|
||||||
|
@ -190,10 +190,10 @@ class LocalMediaView(HomeAssistantView):
|
||||||
) -> web.FileResponse:
|
) -> web.FileResponse:
|
||||||
"""Start a GET request."""
|
"""Start a GET request."""
|
||||||
if location != sanitize_path(location):
|
if location != sanitize_path(location):
|
||||||
return web.HTTPNotFound()
|
raise web.HTTPNotFound()
|
||||||
|
|
||||||
if source_dir_id not in self.hass.config.media_dirs:
|
if source_dir_id not in self.hass.config.media_dirs:
|
||||||
return web.HTTPNotFound()
|
raise web.HTTPNotFound()
|
||||||
|
|
||||||
media_path = self.source.async_full_path(source_dir_id, location)
|
media_path = self.source.async_full_path(source_dir_id, location)
|
||||||
|
|
||||||
|
|
|
@ -510,9 +510,9 @@ async def async_process_ha_core_config(hass: HomeAssistant, config: Dict) -> Non
|
||||||
|
|
||||||
if CONF_MEDIA_DIRS not in config:
|
if CONF_MEDIA_DIRS not in config:
|
||||||
if is_docker_env():
|
if is_docker_env():
|
||||||
hac.media_dirs = {"media": "/media"}
|
hac.media_dirs = {"local": "/media"}
|
||||||
else:
|
else:
|
||||||
hac.media_dirs = {"media": hass.config.path("media")}
|
hac.media_dirs = {"local": hass.config.path("media")}
|
||||||
|
|
||||||
# Init whitelist external dir
|
# Init whitelist external dir
|
||||||
hac.allowlist_external_dirs = {hass.config.path("www"), *hac.media_dirs.values()}
|
hac.allowlist_external_dirs = {hass.config.path("www"), *hac.media_dirs.values()}
|
||||||
|
|
|
@ -205,7 +205,7 @@ async def async_test_home_assistant(loop):
|
||||||
hass.config.elevation = 0
|
hass.config.elevation = 0
|
||||||
hass.config.time_zone = date_util.get_time_zone("US/Pacific")
|
hass.config.time_zone = date_util.get_time_zone("US/Pacific")
|
||||||
hass.config.units = METRIC_SYSTEM
|
hass.config.units = METRIC_SYSTEM
|
||||||
hass.config.media_dirs = {"media": get_test_config_dir("media")}
|
hass.config.media_dirs = {"local": get_test_config_dir("media")}
|
||||||
hass.config.skip_pip = True
|
hass.config.skip_pip = True
|
||||||
|
|
||||||
hass.config_entries = config_entries.ConfigEntries(hass, {})
|
hass.config_entries = config_entries.ConfigEntries(hass, {})
|
||||||
|
|
|
@ -65,7 +65,7 @@ async def test_async_resolve_media(hass):
|
||||||
|
|
||||||
media = await media_source.async_resolve_media(
|
media = await media_source.async_resolve_media(
|
||||||
hass,
|
hass,
|
||||||
media_source.generate_media_source_id(const.DOMAIN, "media/test.mp3"),
|
media_source.generate_media_source_id(const.DOMAIN, "local/test.mp3"),
|
||||||
)
|
)
|
||||||
assert isinstance(media, media_source.models.PlayMedia)
|
assert isinstance(media, media_source.models.PlayMedia)
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ async def test_websocket_resolve_media(hass, hass_ws_client):
|
||||||
|
|
||||||
client = await hass_ws_client(hass)
|
client = await hass_ws_client(hass)
|
||||||
|
|
||||||
media = media_source.models.PlayMedia("/local_source/media/test.mp3", "audio/mpeg")
|
media = media_source.models.PlayMedia("/media/local/test.mp3", "audio/mpeg")
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.media_source.async_resolve_media",
|
"homeassistant.components.media_source.async_resolve_media",
|
||||||
|
@ -150,7 +150,7 @@ async def test_websocket_resolve_media(hass, hass_ws_client):
|
||||||
{
|
{
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"type": "media_source/resolve_media",
|
"type": "media_source/resolve_media",
|
||||||
"media_content_id": f"{const.URI_SCHEME}{const.DOMAIN}/media/test.mp3",
|
"media_content_id": f"{const.URI_SCHEME}{const.DOMAIN}/local/test.mp3",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ async def test_async_browse_media(hass):
|
||||||
"""Test browse media."""
|
"""Test browse media."""
|
||||||
local_media = hass.config.path("media")
|
local_media = hass.config.path("media")
|
||||||
await async_process_ha_core_config(
|
await async_process_ha_core_config(
|
||||||
hass, {"media_dirs": {"media": local_media, "recordings": local_media}}
|
hass, {"media_dirs": {"local": local_media, "recordings": local_media}}
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
@ -21,14 +21,14 @@ async def test_async_browse_media(hass):
|
||||||
# Test path not exists
|
# Test path not exists
|
||||||
with pytest.raises(media_source.BrowseError) as excinfo:
|
with pytest.raises(media_source.BrowseError) as excinfo:
|
||||||
await media_source.async_browse_media(
|
await media_source.async_browse_media(
|
||||||
hass, f"{const.URI_SCHEME}{const.DOMAIN}/media/test/not/exist"
|
hass, f"{const.URI_SCHEME}{const.DOMAIN}/local/test/not/exist"
|
||||||
)
|
)
|
||||||
assert str(excinfo.value) == "Path does not exist."
|
assert str(excinfo.value) == "Path does not exist."
|
||||||
|
|
||||||
# Test browse file
|
# Test browse file
|
||||||
with pytest.raises(media_source.BrowseError) as excinfo:
|
with pytest.raises(media_source.BrowseError) as excinfo:
|
||||||
await media_source.async_browse_media(
|
await media_source.async_browse_media(
|
||||||
hass, f"{const.URI_SCHEME}{const.DOMAIN}/media/test.mp3"
|
hass, f"{const.URI_SCHEME}{const.DOMAIN}/local/test.mp3"
|
||||||
)
|
)
|
||||||
assert str(excinfo.value) == "Path is not a directory."
|
assert str(excinfo.value) == "Path is not a directory."
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ async def test_async_browse_media(hass):
|
||||||
# Test directory traversal
|
# Test directory traversal
|
||||||
with pytest.raises(media_source.BrowseError) as excinfo:
|
with pytest.raises(media_source.BrowseError) as excinfo:
|
||||||
await media_source.async_browse_media(
|
await media_source.async_browse_media(
|
||||||
hass, f"{const.URI_SCHEME}{const.DOMAIN}/media/../configuration.yaml"
|
hass, f"{const.URI_SCHEME}{const.DOMAIN}/local/../configuration.yaml"
|
||||||
)
|
)
|
||||||
assert str(excinfo.value) == "Invalid path."
|
assert str(excinfo.value) == "Invalid path."
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ async def test_async_browse_media(hass):
|
||||||
assert media
|
assert media
|
||||||
|
|
||||||
media = await media_source.async_browse_media(
|
media = await media_source.async_browse_media(
|
||||||
hass, f"{const.URI_SCHEME}{const.DOMAIN}/media/."
|
hass, f"{const.URI_SCHEME}{const.DOMAIN}/local/."
|
||||||
)
|
)
|
||||||
assert media
|
assert media
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ async def test_media_view(hass, hass_client):
|
||||||
"""Test media view."""
|
"""Test media view."""
|
||||||
local_media = hass.config.path("media")
|
local_media = hass.config.path("media")
|
||||||
await async_process_ha_core_config(
|
await async_process_ha_core_config(
|
||||||
hass, {"media_dirs": {"media": local_media, "recordings": local_media}}
|
hass, {"media_dirs": {"local": local_media, "recordings": local_media}}
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
@ -77,23 +77,23 @@ async def test_media_view(hass, hass_client):
|
||||||
client = await hass_client()
|
client = await hass_client()
|
||||||
|
|
||||||
# Protects against non-existent files
|
# Protects against non-existent files
|
||||||
resp = await client.get("/local_source/media/invalid.txt")
|
resp = await client.get("/media/local/invalid.txt")
|
||||||
assert resp.status == 404
|
assert resp.status == 404
|
||||||
|
|
||||||
resp = await client.get("/local_source/recordings/invalid.txt")
|
resp = await client.get("/media/recordings/invalid.txt")
|
||||||
assert resp.status == 404
|
assert resp.status == 404
|
||||||
|
|
||||||
# Protects against non-media files
|
# Protects against non-media files
|
||||||
resp = await client.get("/local_source/media/not_media.txt")
|
resp = await client.get("/media/local/not_media.txt")
|
||||||
assert resp.status == 404
|
assert resp.status == 404
|
||||||
|
|
||||||
# Protects against unknown local media sources
|
# Protects against unknown local media sources
|
||||||
resp = await client.get("/local_source/unknown_source/not_media.txt")
|
resp = await client.get("/media/unknown_source/not_media.txt")
|
||||||
assert resp.status == 404
|
assert resp.status == 404
|
||||||
|
|
||||||
# Fetch available media
|
# Fetch available media
|
||||||
resp = await client.get("/local_source/media/test.mp3")
|
resp = await client.get("/media/local/test.mp3")
|
||||||
assert resp.status == 200
|
assert resp.status == 200
|
||||||
|
|
||||||
resp = await client.get("/local_source/recordings/test.mp3")
|
resp = await client.get("/media/recordings/test.mp3")
|
||||||
assert resp.status == 200
|
assert resp.status == 200
|
||||||
|
|
|
@ -499,7 +499,7 @@ async def test_loading_configuration_default_media_dirs_docker(hass):
|
||||||
assert hass.config.location_name == "Huis"
|
assert hass.config.location_name == "Huis"
|
||||||
assert len(hass.config.allowlist_external_dirs) == 2
|
assert len(hass.config.allowlist_external_dirs) == 2
|
||||||
assert "/media" in hass.config.allowlist_external_dirs
|
assert "/media" in hass.config.allowlist_external_dirs
|
||||||
assert hass.config.media_dirs == {"media": "/media"}
|
assert hass.config.media_dirs == {"local": "/media"}
|
||||||
|
|
||||||
|
|
||||||
async def test_loading_configuration_from_packages(hass):
|
async def test_loading_configuration_from_packages(hass):
|
||||||
|
|
Loading…
Reference in New Issue