diff options
Diffstat (limited to 'src/auth')
-rw-r--r-- | src/auth/mod.rs | 106 | ||||
-rw-r--r-- | src/auth/service.rs | 40 |
2 files changed, 0 insertions, 146 deletions
diff --git a/src/auth/mod.rs b/src/auth/mod.rs deleted file mode 100644 index ce550e1..0000000 --- a/src/auth/mod.rs +++ /dev/null @@ -1,106 +0,0 @@ -//! Deezer API authentication. -use std::error::Error; -use std::fmt::Display; -use std::time::Duration; - -use actix_web::web::Data; -use actix_web::{App, HttpServer}; -use serde::Deserialize; -use tokio::sync::mpsc; -use tokio::task::JoinHandle; -use tokio::{select, spawn}; - -use crate::auth::service::retrieve_auth_code; -use crate::errors::auth::AuthPromptHandlerError; - -mod service; - -const AUTH_URL: &str = "https://connect.deezer.com/oauth/auth.php"; - -/// A Deezer authentication code. -#[derive(Debug, Deserialize, Clone)] -pub struct AuthCode(String); - -impl Display for AuthCode -{ - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result - { - self.0.fmt(f) - } -} - -/// A Deezer authentication prompt handler. -pub struct AuthPromptHandler -{ - /// URL to the Deezer authentication prompt. - pub auth_prompt_url: String, - - /// Handle for the running authentication prompt handler. - /// - /// Finishes when a single authentication has occurred. - pub handler: JoinHandle<Result<AuthCode, Box<dyn Error + Send + Sync>>>, -} - -impl AuthPromptHandler -{ - /// Runs a web server that handles a Deezer authentication prompt. - /// - /// The argument `address` must be in the same domain as the domain you defined when - /// you created the application with the ID `app_id`. - /// - /// # Errors - /// Will return Err if the web server created is unable to bind to `address`. - pub async fn run( - app_id: u32, - address: String, - port: u16, - uri_scheme: String, - ) -> Result<Self, AuthPromptHandlerError> - { - let (done_tx, mut done_rx) = mpsc::channel::<AuthCode>(1); - - let done_tx_data = Data::new(done_tx); - - let server = HttpServer::new(move || { - App::new() - .app_data(done_tx_data.clone()) - .service(retrieve_auth_code) - }) - .bind((address.clone(), port)) - .map_err(|_| AuthPromptHandlerError::BindAddressFailed)?; - - let server_future = server.run(); - - let handle = spawn(async move { - let opt_auth_code = select! { - result = server_future => { - result.map(|_| None) - }, - auth_code = async { - done_rx.recv().await - } => Ok(auth_code) - }?; - - Ok(opt_auth_code.map_or_else(|| Err("No auth code was received"), Ok)?) - }); - - Ok(Self { - auth_prompt_url: format!( - "{}?app_id={}&redirect_uri={}://{}:{}&perms=basic_access", - AUTH_URL, app_id, uri_scheme, address, port - ), - handler: handle, - }) - } -} - -/// A Deezer access token. -#[derive(Debug, Clone)] -pub struct AccessToken -{ - /// The access token. - pub access_token: String, - - /// The duration until the access token expires. - pub expires: Duration, -} diff --git a/src/auth/service.rs b/src/auth/service.rs deleted file mode 100644 index b9b44d4..0000000 --- a/src/auth/service.rs +++ /dev/null @@ -1,40 +0,0 @@ -use actix_web::web::{Data, Query}; -use actix_web::{get, HttpResponse}; -use serde::Deserialize; -use tokio::sync::mpsc; - -use crate::auth::AuthCode; - -#[derive(Debug, Deserialize)] -struct AuthCodeQuery -{ - error_reason: Option<String>, - code: Option<AuthCode>, -} - -#[get("/")] -async fn retrieve_auth_code( - query: Query<AuthCodeQuery>, - done_tx: Data<mpsc::Sender<AuthCode>>, -) -> HttpResponse -{ - if let Some(error_reason) = &query.error_reason { - return HttpResponse::Unauthorized().body(format!( - "Error: No authentication code was retrieved. Reason: {}\n\nYou can close this tab", - error_reason - )); - } - - let auth_code = match &query.code { - Some(auth_code) => auth_code, - None => { - return HttpResponse::BadRequest() - .body("Error: No authentication code was retrieved"); - } - }; - - done_tx.send(auth_code.clone()).await.unwrap(); - - HttpResponse::Ok() - .body("Authentication code was successfully retrieved.\n\nYou can close this tab") -} |