use reqwest::{Client, Url};
use serde::{Deserialize, Serialize};
#[cfg(test)]
mod test {
use crate::auth::auth_url;
#[test]
fn auth_url_test() {
let url = auth_url("my_client_id", "code", None, Some("me vote"), None);
assert_eq!("https://api.genius.com/oauth/authorize?client_id=my_client_id&response_type=code&scope=me+vote", url.as_str());
}
}
pub mod login;
#[derive(Serialize)]
struct AuthRequest {
code: String,
client_secret: String,
client_id: String,
redirect_uri: String,
response_type: String,
grant_type: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct AuthResponse {
pub access_token: Option<String>,
pub token_type: Option<String>,
pub error: Option<String>,
pub error_description: Option<String>,
}
#[must_use]
pub fn auth_url(
client_id: &str,
response_type: &str,
redirect_uri: Option<&str>,
scope: Option<&str>,
state: Option<&str>,
) -> Url {
let mut params = vec![("client_id", client_id), ("response_type", response_type)];
if let Some(redirect_uri) = redirect_uri {
params.push(("redirect_uri", redirect_uri));
}
if let Some(scope) = scope {
params.push(("scope", scope));
}
if let Some(state) = state {
params.push(("state", state));
}
Url::parse_with_params("https://api.genius.com/oauth/authorize", params)
.expect("Can't parse authentication URL.")
}
pub async fn authenticate(
code: String,
client_secret: String,
client_id: String,
redirect_uri: String,
) -> Result<AuthResponse, reqwest::Error> {
let auth_req = AuthRequest {
code,
client_secret,
client_id,
redirect_uri,
response_type: "code".to_owned(),
grant_type: "authorization_code".to_owned(),
};
let url = Url::parse("https://api.genius.com/oauth/token")
.expect("Could not parse valid URL from login_with_username input.");
let client = Client::new();
let request = client.post(url).json(&auth_req).send().await?;
let result = request.json::<AuthResponse>().await?;
Ok(result)
}