Skip to content

Commit

Permalink
Login workflow improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
quodrum-glas committed Feb 23, 2024
1 parent a07910e commit 0e7c98c
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 24 deletions.
8 changes: 5 additions & 3 deletions mopidy_tidal/auth_http_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from mopidy_tidal.session import PersistentSession

from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import unquote
from urllib.parse import unquote, urlparse

HTML_BODY = """<!DOCTYPE html>
<html>
Expand Down Expand Up @@ -51,10 +51,12 @@ def __init__(self, session: PersistentSession, login_result_holder, *args, **kwa
super().__init__(*args, **kwargs)

def do_GET(self):
url = urlparse(self.path)
self.send_response(200)
self.end_headers()
interactive = INTERACTIVE_HTML_BODY if self.login_handler.is_pkce else ''
self.wfile.write(HTML_BODY(authurl=self.login_handler.get_login_url(), interactive=interactive).encode())
if url.path == '/' and url.query == '' and url.params == '':
interactive = INTERACTIVE_HTML_BODY if self.login_handler.is_pkce else ''
self.wfile.write(HTML_BODY(authurl=self.login_handler.get_login_url(), interactive=interactive).encode())

def do_POST(self):
content_length = int(self.headers.get("Content-Length"), 0)
Expand Down
53 changes: 34 additions & 19 deletions mopidy_tidal/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
logger = logging.getLogger(__name__)

OAUTH_JSON = "tidal.oauth.{}.json".format
MAX_LOGIN_WAIT_MINS = 5


class TidalBackend(ThreadingActor, backend.Backend):
Expand Down Expand Up @@ -44,44 +45,58 @@ def get_dir(self, folder):
return method(self._config)

def on_start(self):
login_pkce = self.get_config("login_pkce") or True
client_id = self.get_config("client_id")
client_secret = self.get_config("client_secret")
quality = self.get_config("quality")
config = Config(quality=Quality(quality))
config = Config(quality=Quality(self.get_config("quality")))
is_hires_quality = config.quality in [Quality.hi_res.value, Quality.hi_res_lossless.value]
login_pkce = is_hires_quality or self.get_config("login_pkce")
if client_id:
config.client_id = client_id
config.client_secret = client_secret
if login_pkce:
config.client_id_pkce = client_id
config.client_secret_pkce = client_secret
oauth_file_location = os.path.join(self.get_dir("data"), OAUTH_JSON(
client_id or config.client_id_pkce if login_pkce else config.client_id))
else:
config.client_id = client_id
config.client_secret = client_secret
client_id_in_use = config.client_id_pkce if login_pkce else config.client_id
oauth_file_location = os.path.join(self.get_dir("data"), OAUTH_JSON(client_id_in_use))
self.session = PersistentSession(config, login_pkce=login_pkce, authentication_local_storage=oauth_file_location)
logger.info("Connecting to TIDAL... Requested Quality = %s" % quality)
logger.info(f"{client_id_in_use} connecting to TIDAL. Requested Quality: {config.quality}")
if is_hires_quality:
logger.info("Enabling TIDAL HI-RES")
self.session.client_enable_hires()
self.connect()

def connect(self):
success = False
try:
self.session.load_oauth_session_from_file()
logger.info(f"Session loaded from {oauth_file_location}")
except FileNotFoundError:
if self.session.check_login():
logger.info("TIDAL Login OK")
success = True
else:
logger.info("TIDAL Login KO")
raise PermissionError("Saved session failed to authenticate")
except (FileNotFoundError, PermissionError, ) as e:
logger.info(e)
try:
self.new_login()
success = True
except TimeoutError as e:
logger.error(e)
except Exception as e:
logger.exception(e)
if self.session.check_login():
logger.info("TIDAL Login OK")
subscription = self.session.request.basic_request('GET', f'users/{self.session.user.id}/subscription').json()
logger.info("HighestSoundQuality: {highestSoundQuality}".format(**subscription))
else:
logger.info("TIDAL Login KO")

if not success:
raise RuntimeError("Failed connection to TIDAL Service")
subscription = self.session.request.basic_request('GET', f'users/{self.session.user.id}/subscription').json()
logger.info("Connected to TIDAL. HighestSoundQuality: {highestSoundQuality}".format(**subscription))

def new_login(self):
login_web_port = self.get_config("login_web_port")
login_result_holder = Queue(maxsize=1)
terminate = start_oauth_deamon(self.session, login_web_port, login_result_holder)
logger.info(f"No saved session found. Please visit http://{get_ip()}:{login_web_port} to authenticate")
logger.info(f"Please visit http://{get_ip()}:{login_web_port} to authenticate")
try:
exception = login_result_holder.get(timeout=300)
exception = login_result_holder.get(timeout=MAX_LOGIN_WAIT_MINS * 60)
if exception:
raise exception
except Empty:
Expand Down
5 changes: 3 additions & 2 deletions mopidy_tidal/session.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import datetime
import json
import logging
from os.path import basename

from tidalapi import Session

Expand All @@ -20,7 +21,7 @@ def load_oauth_session_from_file(self):
data = json.load(f)
data["expiry_time"] = datetime.datetime.fromisoformat(data["expiry_time"])
self.load_oauth_session(**data)
logger.info(f"Session Loaded. Expires at {self.expiry_time.isoformat()}")
logger.info(f"Session loaded from {basename(self._authentication_local_storage)} - Expires at {self.expiry_time.isoformat()}")

def save_oauth_session_to_file(self):
with open(self._authentication_local_storage, 'w') as f:
Expand All @@ -30,7 +31,7 @@ def save_oauth_session_to_file(self):
"refresh_token": self.refresh_token,
"expiry_time": self.expiry_time.isoformat(),
}, f)
logger.info(f"Session Saved. Expires at {self.expiry_time.isoformat()}")
logger.info(f"Session saved to {basename(self._authentication_local_storage)} - Expires at {self.expiry_time.isoformat()}")

def token_refresh(self, *args, **kwargs):
logger.info(f"Authentication expired at {self.expiry_time.isoformat()} ...Refreshing")
Expand Down

0 comments on commit 0e7c98c

Please sign in to comment.