async def async_play_media(self, media_type, media_id, **kwargs): """Play a piece of media.""" # Handle media_source if media_source.is_media_source_id(media_id): sourced_media = await media_source.async_resolve_media( self.opp, media_id) media_type = sourced_media.mime_type media_id = sourced_media.url # If media ID is a relative URL, we serve it from HA. # Create a signed path. if media_id[0] == "/": # Sign URL with Open Peer Power Cast User config_entry_id = self.registry_entry.config_entry_id config_entry = self.opp.config_entries.async_get_entry( config_entry_id) user_id = config_entry.data["user_id"] user = await self.opp.auth.async_get_user(user_id) if user.refresh_tokens: refresh_token: RefreshToken = list( user.refresh_tokens.values())[0] media_id = async_sign_path( self.opp, refresh_token.id, quote(media_id), timedelta(seconds=media_source.DEFAULT_EXPIRY_TIME), ) # prepend external URL hass_url = get_url(self.opp, prefer_external=True) media_id = f"{hass_url}{media_id}" await self.opp.async_add_executor_job( ft.partial(self.play_media, media_type, media_id, **kwargs))
async def test_auth_access_signed_path(opp, app, aiohttp_client, opp_access_token): """Test access with signed url.""" app.router.add_post("/", mock_handler) app.router.add_get("/another_path", mock_handler) setup_auth(opp, app) client = await aiohttp_client(app) refresh_token = await opp.auth.async_validate_access_token(opp_access_token ) signed_path = async_sign_path(opp, refresh_token.id, "/", timedelta(seconds=5)) req = await client.get(signed_path) assert req.status == 200 data = await req.json() assert data["user_id"] == refresh_token.user.id # Use signature on other path req = await client.get("/another_path?{}".format( signed_path.split("?")[1])) assert req.status == 401 # We only allow GET req = await client.post(signed_path) assert req.status == 401 # Never valid as expired in the past. expired_signed_path = async_sign_path(opp, refresh_token.id, "/", timedelta(seconds=-5)) req = await client.get(expired_signed_path) assert req.status == 401 # refresh token gone should also invalidate signature await opp.auth.async_remove_refresh_token(refresh_token) req = await client.get(signed_path) assert req.status == 401
def websocket_sign_path(opp: OpenPeerPower, connection: websocket_api.ActiveConnection, msg): """Handle a sign path request.""" connection.send_message( websocket_api.result_message( msg["id"], { "path": async_sign_path( opp, connection.refresh_token_id, msg["path"], timedelta(seconds=msg["expires"]), ) }, ))
async def websocket_resolve_media(opp, connection, msg): """Resolve media.""" try: media = await async_resolve_media(opp, msg["media_content_id"]) url = media.url except Unresolvable as err: connection.send_error(msg["id"], "resolve_media_failed", str(err)) else: if url[0] == "/": url = async_sign_path( opp, connection.refresh_token_id, quote(url), timedelta(seconds=msg["expires"]), ) connection.send_result(msg["id"], { "url": url, "mime_type": media.mime_type })