mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Quote media_source paths (#49054)
* Quote path in async_sign_path * Address review comments, add tests * Update tests/testing_config/media/Epic Sax Guy 10 Hours.mp4 Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
This commit is contained in:
parent
dbb771e19c
commit
f5545badac
@ -7,6 +7,7 @@ from datetime import timedelta
|
|||||||
import functools as ft
|
import functools as ft
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
from urllib.parse import quote
|
||||||
|
|
||||||
import pychromecast
|
import pychromecast
|
||||||
from pychromecast.controllers.homeassistant import HomeAssistantController
|
from pychromecast.controllers.homeassistant import HomeAssistantController
|
||||||
@ -472,7 +473,7 @@ class CastDevice(MediaPlayerEntity):
|
|||||||
media_id = async_sign_path(
|
media_id = async_sign_path(
|
||||||
self.hass,
|
self.hass,
|
||||||
refresh_token.id,
|
refresh_token.id,
|
||||||
media_id,
|
quote(media_id),
|
||||||
timedelta(seconds=media_source.DEFAULT_EXPIRY_TIME),
|
timedelta(seconds=media_source.DEFAULT_EXPIRY_TIME),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
"""Authentication for HTTP component."""
|
"""Authentication for HTTP component."""
|
||||||
import logging
|
import logging
|
||||||
import secrets
|
import secrets
|
||||||
|
from urllib.parse import unquote
|
||||||
|
|
||||||
from aiohttp import hdrs
|
from aiohttp import hdrs
|
||||||
from aiohttp.web import middleware
|
from aiohttp.web import middleware
|
||||||
@ -30,11 +31,16 @@ def async_sign_path(hass, refresh_token_id, path, expiration):
|
|||||||
|
|
||||||
now = dt_util.utcnow()
|
now = dt_util.utcnow()
|
||||||
encoded = jwt.encode(
|
encoded = jwt.encode(
|
||||||
{"iss": refresh_token_id, "path": path, "iat": now, "exp": now + expiration},
|
{
|
||||||
|
"iss": refresh_token_id,
|
||||||
|
"path": unquote(path),
|
||||||
|
"iat": now,
|
||||||
|
"exp": now + expiration,
|
||||||
|
},
|
||||||
secret,
|
secret,
|
||||||
algorithm="HS256",
|
algorithm="HS256",
|
||||||
)
|
)
|
||||||
return f"{path}?{SIGN_QUERY_PARAM}=" f"{encoded.decode()}"
|
return f"{path}?{SIGN_QUERY_PARAM}={encoded.decode()}"
|
||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
from urllib.parse import quote
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
@ -123,7 +124,7 @@ async def websocket_resolve_media(hass, connection, msg):
|
|||||||
url = async_sign_path(
|
url = async_sign_path(
|
||||||
hass,
|
hass,
|
||||||
connection.refresh_token_id,
|
connection.refresh_token_id,
|
||||||
url,
|
quote(url),
|
||||||
timedelta(seconds=msg["expires"]),
|
timedelta(seconds=msg["expires"]),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
"""Test Media Source initialization."""
|
"""Test Media Source initialization."""
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
from urllib.parse import quote
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@ -45,7 +46,7 @@ async def test_async_browse_media(hass):
|
|||||||
media = await media_source.async_browse_media(hass, "")
|
media = await media_source.async_browse_media(hass, "")
|
||||||
assert isinstance(media, media_source.models.BrowseMediaSource)
|
assert isinstance(media, media_source.models.BrowseMediaSource)
|
||||||
assert media.title == "media/"
|
assert media.title == "media/"
|
||||||
assert len(media.children) == 1
|
assert len(media.children) == 2
|
||||||
|
|
||||||
# Test invalid media content
|
# Test invalid media content
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
@ -133,14 +134,15 @@ async def test_websocket_browse_media(hass, hass_ws_client):
|
|||||||
assert msg["error"]["message"] == "test"
|
assert msg["error"]["message"] == "test"
|
||||||
|
|
||||||
|
|
||||||
async def test_websocket_resolve_media(hass, hass_ws_client):
|
@pytest.mark.parametrize("filename", ["test.mp3", "Epic Sax Guy 10 Hours.mp4"])
|
||||||
|
async def test_websocket_resolve_media(hass, hass_ws_client, filename):
|
||||||
"""Test browse media websocket."""
|
"""Test browse media websocket."""
|
||||||
assert await async_setup_component(hass, const.DOMAIN, {})
|
assert await async_setup_component(hass, const.DOMAIN, {})
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
client = await hass_ws_client(hass)
|
client = await hass_ws_client(hass)
|
||||||
|
|
||||||
media = media_source.models.PlayMedia("/media/local/test.mp3", "audio/mpeg")
|
media = media_source.models.PlayMedia(f"/media/local/{filename}", "audio/mpeg")
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.media_source.async_resolve_media",
|
"homeassistant.components.media_source.async_resolve_media",
|
||||||
@ -150,7 +152,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}/local/test.mp3",
|
"media_content_id": f"{const.URI_SCHEME}{const.DOMAIN}/local/{filename}",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -158,7 +160,7 @@ async def test_websocket_resolve_media(hass, hass_ws_client):
|
|||||||
|
|
||||||
assert msg["success"]
|
assert msg["success"]
|
||||||
assert msg["id"] == 1
|
assert msg["id"] == 1
|
||||||
assert msg["result"]["url"].startswith(media.url)
|
assert msg["result"]["url"].startswith(quote(media.url))
|
||||||
assert msg["result"]["mime_type"] == media.mime_type
|
assert msg["result"]["mime_type"] == media.mime_type
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
|
@ -95,5 +95,8 @@ async def test_media_view(hass, hass_client):
|
|||||||
resp = await client.get("/media/local/test.mp3")
|
resp = await client.get("/media/local/test.mp3")
|
||||||
assert resp.status == 200
|
assert resp.status == 200
|
||||||
|
|
||||||
|
resp = await client.get("/media/local/Epic Sax Guy 10 Hours.mp4")
|
||||||
|
assert resp.status == 200
|
||||||
|
|
||||||
resp = await client.get("/media/recordings/test.mp3")
|
resp = await client.get("/media/recordings/test.mp3")
|
||||||
assert resp.status == 200
|
assert resp.status == 200
|
||||||
|
1
tests/testing_config/media/Epic Sax Guy 10 Hours.mp4
Normal file
1
tests/testing_config/media/Epic Sax Guy 10 Hours.mp4
Normal file
@ -0,0 +1 @@
|
|||||||
|
I play the sax
|
Loading…
x
Reference in New Issue
Block a user