From 99fcb20f50f349322135204bd0093fa2407d25b4 Mon Sep 17 00:00:00 2001 From: Thang Pham Date: Thu, 31 Oct 2024 11:56:02 -0400 Subject: [PATCH] ignore cache when authenticating the application using `authenticate` CLI command (#592) resolves #590 This PR also allows `login_redirect_uri` to be configurable --- docs/config.md | 1 + examples/app.toml | 1 + spotify_player/src/auth.rs | 25 +++++++++++++++++++++---- spotify_player/src/cli/handlers.rs | 4 ++-- spotify_player/src/client/mod.rs | 2 +- spotify_player/src/config/mod.rs | 4 ++++ 6 files changed, 30 insertions(+), 7 deletions(-) diff --git a/docs/config.md b/docs/config.md index 70aa7bd3..0aaeec09 100644 --- a/docs/config.md +++ b/docs/config.md @@ -26,6 +26,7 @@ All configuration files should be placed inside the application's configuration | --------------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------- | | `client_id` | the Spotify client's ID | `65b708073fc0480ea92a077233ca87bd` | | `client_id_command` | a shell command that prints the Spotify client ID to stdout (overrides `client_id`) | `None` | +| `login_redirect_uri` | the redirect URI for authenticating the application | `http://127.0.0.1:8989/login` | | `client_port` | the port that the application's client is running on to handle CLI commands | `8080` | | `tracks_playback_limit` | the limit for the number of tracks played in a **tracks** playback | `50` | | `playback_format` | the format of the text in the playback's window | `{status} {track} • {artists}\n{album}\n{metadata}` | diff --git a/examples/app.toml b/examples/app.toml index 7c055ae7..2818b38f 100644 --- a/examples/app.toml +++ b/examples/app.toml @@ -1,5 +1,6 @@ theme = "default" client_id = "65b708073fc0480ea92a077233ca87bd" +login_redirect_uri = "http://127.0.0.1:8989/login" client_port = 8080 tracks_playback_limit = 50 playback_format = "{status} {track} • {artists}\n{album}\n{metadata}" diff --git a/spotify_player/src/auth.rs b/spotify_player/src/auth.rs index 53c7c5a4..b7598f00 100644 --- a/spotify_player/src/auth.rs +++ b/spotify_player/src/auth.rs @@ -5,7 +5,6 @@ use librespot_oauth::get_access_token; use crate::config; pub const SPOTIFY_CLIENT_ID: &str = "65b708073fc0480ea92a077233ca87bd"; -const CLIENT_REDIRECT_URI: &str = "http://127.0.0.1:8989/login"; // based on https://github.com/librespot-org/librespot/blob/f96f36c064795011f9fee912291eecb1aa46fff6/src/main.rs#L173 const OAUTH_SCOPES: &[&str] = &[ "app-remote-control", @@ -40,6 +39,7 @@ const OAUTH_SCOPES: &[&str] = &[ pub struct AuthConfig { pub cache: Cache, pub session_config: SessionConfig, + pub login_redirect_uri: String, } impl Default for AuthConfig { @@ -47,6 +47,7 @@ impl Default for AuthConfig { AuthConfig { cache: Cache::new(None::, None, None, None).unwrap(), session_config: SessionConfig::default(), + login_redirect_uri: "http://127.0.0.1:8989/login".to_string(), } } } @@ -74,20 +75,36 @@ impl AuthConfig { Ok(AuthConfig { cache, session_config: configs.app_config.session_config()?, + login_redirect_uri: configs.app_config.login_redirect_uri.clone(), }) } } /// Get Spotify credentials to authenticate the application -pub async fn get_creds(auth_config: &AuthConfig, reauth: bool) -> Result { - Ok(match auth_config.cache.credentials() { +/// +/// # Args +/// - `auth_config`: authentication configuration +/// - `reauth`: whether to re-authenticate the application if no cached credentials are found +// - `use_cached`: whether to use cached credentials if available +pub async fn get_creds( + auth_config: &AuthConfig, + reauth: bool, + use_cached: bool, +) -> Result { + let creds = if use_cached { + auth_config.cache.credentials() + } else { + None + }; + + Ok(match creds { None => { let msg = "No cached credentials found, please authenticate the application first."; if reauth { eprintln!("{msg}"); get_access_token( SPOTIFY_CLIENT_ID, - CLIENT_REDIRECT_URI, + &auth_config.login_redirect_uri, OAUTH_SCOPES.to_vec(), ) .map(|t| Credentials::with_access_token(t.access_token))? diff --git a/spotify_player/src/cli/handlers.rs b/spotify_player/src/cli/handlers.rs index 43e3a43e..da311fb0 100644 --- a/spotify_player/src/cli/handlers.rs +++ b/spotify_player/src/cli/handlers.rs @@ -171,7 +171,6 @@ fn try_connect_to_client(socket: &UdpSocket, configs: &config::Configs) -> Resul } pub fn handle_cli_subcommand(cmd: &str, args: &ArgMatches) -> Result<()> { - let socket = UdpSocket::bind("127.0.0.1:0")?; let configs = config::get_config(); // handle commands that don't require a client separately @@ -179,7 +178,7 @@ pub fn handle_cli_subcommand(cmd: &str, args: &ArgMatches) -> Result<()> { "authenticate" => { let auth_config = AuthConfig::new(configs)?; let rt = tokio::runtime::Runtime::new()?; - rt.block_on(crate::auth::get_creds(&auth_config, true))?; + rt.block_on(crate::auth::get_creds(&auth_config, true, false))?; std::process::exit(0); } "generate" => { @@ -194,6 +193,7 @@ pub fn handle_cli_subcommand(cmd: &str, args: &ArgMatches) -> Result<()> { _ => {} } + let socket = UdpSocket::bind("127.0.0.1:0")?; try_connect_to_client(&socket, configs).context("try to connect to a client")?; // construct a socket request based on the CLI command and its arguments diff --git a/spotify_player/src/client/mod.rs b/spotify_player/src/client/mod.rs index 34e7edf5..f21373b3 100644 --- a/spotify_player/src/client/mod.rs +++ b/spotify_player/src/client/mod.rs @@ -114,7 +114,7 @@ impl Client { /// Create a new client session pub async fn new_session(&self, state: Option<&SharedState>, reauth: bool) -> Result<()> { let session = self.auth_config.session(); - let creds = auth::get_creds(&self.auth_config, reauth) + let creds = auth::get_creds(&self.auth_config, reauth, true) .await .context("get credentials")?; *self.session.lock().await = Some(session.clone()); diff --git a/spotify_player/src/config/mod.rs b/spotify_player/src/config/mod.rs index e2e98750..66e007d5 100644 --- a/spotify_player/src/config/mod.rs +++ b/spotify_player/src/config/mod.rs @@ -54,6 +54,8 @@ pub struct AppConfig { pub client_port: u16, + pub login_redirect_uri: String, + pub player_event_hook_command: Option, pub playback_format: String, @@ -256,6 +258,8 @@ impl Default for AppConfig { client_port: 8080, + login_redirect_uri: "http://127.0.0.1:8989/login".to_string(), + tracks_playback_limit: 50, playback_format: String::from("{status} {track} • {artists}\n{album}\n{metadata}"),