Add option to connect to plex server over https (#1127)
authortenfire <nil_erik@hotmail.com>
Sat, 16 Mar 2024 01:11:29 +0000 (02:11 +0100)
committerGitHub <noreply@github.com>
Sat, 16 Mar 2024 01:11:29 +0000 (02:11 +0100)
music_assistant/server/providers/plex/__init__.py
music_assistant/server/providers/plex/helpers.py

index 664bd09959fa52ae5dd6a2e710b04e5a6504deac..430e4716f04ba21d45fc9ff85ecb6cc2c78d62f4 100644 (file)
@@ -8,6 +8,7 @@ from asyncio import TaskGroup
 from typing import TYPE_CHECKING, Any
 
 import plexapi.exceptions
+import requests
 from aiohttp import ClientTimeout
 from plexapi.audio import Album as PlexAlbum
 from plexapi.audio import Artist as PlexArtist
@@ -69,6 +70,8 @@ CONF_AUTH_TOKEN = "token"
 CONF_LIBRARY_ID = "library_id"
 CONF_LOCAL_SERVER_IP = "local_server_ip"
 CONF_LOCAL_SERVER_PORT = "local_server_port"
+CONF_LOCAL_SERVER_SSL = "local_server_ssl"
+CONF_LOCAL_SERVER_VERIFY_CERT = "local_server_verify_cert"
 CONF_USE_GDM = "use_gdm"
 CONF_ACTION_GDM = "gdm"
 FAKE_ARTIST_PREFIX = "_fake://"
@@ -113,9 +116,15 @@ async def get_config_entries(
         if server_details[0] is None and server_details[1] is None:
             values[CONF_LOCAL_SERVER_IP] = "Discovery failed, please add IP manually"
             values[CONF_LOCAL_SERVER_PORT] = "Discovery failed, please add Port manually"
+            values[CONF_LOCAL_SERVER_SSL] = "Discovery failed, please set SSL manually"
+            values[CONF_LOCAL_SERVER_VERIFY_CERT] = (
+                "Discovery failed, please set " "Verify certificate manually"
+            )
         else:
             values[CONF_LOCAL_SERVER_IP] = server_details[0]
             values[CONF_LOCAL_SERVER_PORT] = server_details[1]
+            values[CONF_LOCAL_SERVER_SSL] = False
+            values[CONF_LOCAL_SERVER_VERIFY_CERT] = False
     # config flow auth action/step (authenticate button clicked)
     if action == CONF_ACTION_AUTH:
         async with AuthenticationHelper(mass, values["session_id"]) as auth_helper:
@@ -145,7 +154,18 @@ async def get_config_entries(
         token = mass.config.decrypt_string(values.get(CONF_AUTH_TOKEN))
         server_http_ip = values.get(CONF_LOCAL_SERVER_IP)
         server_http_port = values.get(CONF_LOCAL_SERVER_PORT)
-        if not (libraries := await get_libraries(mass, token, server_http_ip, server_http_port)):
+        server_http_ssl = values.get(CONF_LOCAL_SERVER_SSL)
+        server_http_verify_cert = values.get(CONF_LOCAL_SERVER_VERIFY_CERT)
+        if not (
+            libraries := await get_libraries(
+                mass,
+                token,
+                server_http_ssl,
+                server_http_ip,
+                server_http_port,
+                server_http_verify_cert,
+            )
+        ):
             msg = "Unable to retrieve Servers and/or Music Libraries"
             raise LoginFailed(msg)
         conf_libraries.options = tuple(
@@ -179,6 +199,22 @@ async def get_config_entries(
             required=True,
             value=values.get(CONF_LOCAL_SERVER_PORT) if values else None,
         ),
+        ConfigEntry(
+            key=CONF_LOCAL_SERVER_SSL,
+            type=ConfigEntryType.BOOLEAN,
+            label="SSL (HTTPS)",
+            description="Connect to the local server using SSL (HTTPS)",
+            required=True,
+            default_value=False,
+        ),
+        ConfigEntry(
+            key=CONF_LOCAL_SERVER_VERIFY_CERT,
+            type=ConfigEntryType.BOOLEAN,
+            label="Verify certificate",
+            description="Verify local server SSL certificate",
+            required=True,
+            default_value=True,
+        ),
         ConfigEntry(
             key=CONF_AUTH_TOKEN,
             type=ConfigEntryType.SECURE_STRING,
@@ -208,9 +244,19 @@ class PlexProvider(MusicProvider):
 
         def connect() -> PlexServer:
             try:
+                session = requests.Session()
+                session.verify = (
+                    self.config.get_value(CONF_LOCAL_SERVER_VERIFY_CERT)
+                    if self.config.get_value(CONF_LOCAL_SERVER_SSL)
+                    else False
+                )
+                local_server_protocol = (
+                    "https" if self.config.get_value(CONF_LOCAL_SERVER_SSL) else "http"
+                )
                 plex_server = PlexServer(
-                    f"http://{self.config.get_value(CONF_LOCAL_SERVER_IP)}:{self.config.get_value(CONF_LOCAL_SERVER_PORT)}",
+                    f"{local_server_protocol}://{self.config.get_value(CONF_LOCAL_SERVER_IP)}:{self.config.get_value(CONF_LOCAL_SERVER_PORT)}",
                     token=self.config.get_value(CONF_AUTH_TOKEN),
+                    session=session,
                 )
             except plexapi.exceptions.BadRequest as err:
                 if "Invalid token" in str(err):
index 21e3d4e0927ec87589358454141260d8d8d4bca7..527773880318b6220219f961c837f08af635ef91 100644 (file)
@@ -5,6 +5,7 @@ from __future__ import annotations
 import asyncio
 from typing import TYPE_CHECKING
 
+import requests
 from plexapi.gdm import GDM
 from plexapi.library import LibrarySection as PlexLibrarySection
 from plexapi.library import MusicSection as PlexMusicSection
@@ -15,7 +16,12 @@ if TYPE_CHECKING:
 
 
 async def get_libraries(
-    mass: MusicAssistant, auth_token: str, local_server_ip: str, local_server_port: str
+    mass: MusicAssistant,
+    auth_token: str,
+    local_server_ssl: bool,
+    local_server_ip: str,
+    local_server_port: str,
+    local_server_verify_cert: bool,
 ) -> list[str]:
     """
     Get all music libraries for all plex servers.
@@ -27,8 +33,13 @@ async def get_libraries(
     def _get_libraries():
         # create a listing of available music libraries on all servers
         all_libraries: list[str] = []
+        session = requests.Session()
+        session.verify = local_server_verify_cert
+        local_server_protocol = "https" if local_server_ssl else "http"
         plex_server: PlexServer = PlexServer(
-            f"http://{local_server_ip}:{local_server_port}", auth_token
+            f"{local_server_protocol}://{local_server_ip}:{local_server_port}",
+            auth_token,
+            session=session,
         )
         for media_section in plex_server.library.sections():
             media_section: PlexLibrarySection