From: Jc2k Date: Wed, 8 Jan 2025 13:40:17 +0000 (+0000) Subject: Fix: Jellyfin login should use a stable device id to avoid leaking device records... X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=cbd1c8152758dcf218a23fa6eb60ee15c17c3544;p=music-assistant-server.git Fix: Jellyfin login should use a stable device id to avoid leaking device records in Jellyfin backend (#1840) --- diff --git a/music_assistant/providers/jellyfin/__init__.py b/music_assistant/providers/jellyfin/__init__.py index 1317488f..7a359d3b 100644 --- a/music_assistant/providers/jellyfin/__init__.py +++ b/music_assistant/providers/jellyfin/__init__.py @@ -2,9 +2,9 @@ from __future__ import annotations +import hashlib import mimetypes import socket -import uuid from asyncio import TaskGroup from collections.abc import AsyncGenerator from typing import TYPE_CHECKING @@ -133,6 +133,24 @@ class JellyfinProvider(MusicProvider): async def handle_async_init(self) -> None: """Initialize provider(instance) with given configuration.""" + username = str(self.config.get_value(CONF_USERNAME)) + + # Device ID should be stable between reboots + # Otherwise every time the provider starts we "leak" a new device + # entry in the Jellyfin backend, which creates devices and entities + # in HA if they also use the Jellyfin integration there. + + # We follow a suggestion a Jellyfin dev gave to HA and use an ID + # that is stable even if provider is removed and re-added. + # They said mix in username in case the same device/app has 2 + # connections to the same servers + + # Neither of these are secrets (username is handed over to mint a + # token and server_id is used in zeroconf) but hash them anyway as its meant + # to be an opaque identifier + + device_id = hashlib.sha256(f"{self.mass.server_id}+{username}".encode()).hexdigest() + session_config = SessionConfiguration( session=self.mass.http_session, url=str(self.config.get_value(CONF_URL)), @@ -140,13 +158,13 @@ class JellyfinProvider(MusicProvider): app_name=USER_APP_NAME, app_version=CLIENT_VERSION, device_name=socket.gethostname(), - device_id=str(uuid.uuid4()), + device_id=device_id, ) try: self._client = await authenticate_by_name( session_config, - str(self.config.get_value(CONF_USERNAME)), + username, str(self.config.get_value(CONF_PASSWORD)), ) except Exception as err: diff --git a/tests/conftest.py b/tests/conftest.py index 62c294cd..de17ce16 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -7,7 +7,6 @@ from collections.abc import AsyncGenerator import pytest from music_assistant import MusicAssistant -from tests.common import wait_for_sync_completion @pytest.fixture(name="caplog") @@ -27,8 +26,7 @@ async def mass(tmp_path: pathlib.Path) -> AsyncGenerator[MusicAssistant, None]: mass = MusicAssistant(str(storage_path)) - async with wait_for_sync_completion(mass): - await mass.start() + await mass.start() try: yield mass