1use reqwest::{Client, Url};
2use serde::{Deserialize, Serialize};
3
4#[cfg(test)]
5mod test {
6 use crate::auth::auth_url;
7 #[test]
8 fn auth_url_test() {
9 let url = auth_url("my_client_id", "code", None, Some("me vote"), None);
10 assert_eq!("https://api.genius.com/oauth/authorize?client_id=my_client_id&response_type=code&scope=me+vote", url.as_str());
11 }
12}
13
14pub mod login;
16
17#[derive(Serialize)]
18struct AuthRequest {
19 code: String,
20 client_secret: String,
21 client_id: String,
22 redirect_uri: String,
23 response_type: String,
24 grant_type: String,
25}
26
27#[derive(Serialize, Deserialize, Debug)]
29pub struct AuthResponse {
30 pub access_token: Option<String>,
31 pub token_type: Option<String>,
32 pub error: Option<String>,
33 pub error_description: Option<String>,
34}
35
36#[must_use]
54pub fn auth_url(
55 client_id: &str,
56 response_type: &str,
57 redirect_uri: Option<&str>,
58 scope: Option<&str>,
59 state: Option<&str>,
60) -> Url {
61 let mut params = vec![("client_id", client_id), ("response_type", response_type)];
62 if let Some(redirect_uri) = redirect_uri {
63 params.push(("redirect_uri", redirect_uri));
64 }
65 if let Some(scope) = scope {
66 params.push(("scope", scope));
67 }
68 if let Some(state) = state {
69 params.push(("state", state));
70 }
71 Url::parse_with_params("https://api.genius.com/oauth/authorize", params)
72 .expect("Can't parse authentication URL.")
73}
74
75pub async fn authenticate(
83 code: String,
84 client_secret: String,
85 client_id: String,
86 redirect_uri: String,
87) -> Result<AuthResponse, reqwest::Error> {
88 let auth_req = AuthRequest {
89 code,
90 client_secret,
91 client_id,
92 redirect_uri,
93 response_type: "code".to_owned(),
94 grant_type: "authorization_code".to_owned(),
95 };
96 let url = Url::parse("https://api.genius.com/oauth/token")
97 .expect("Could not parse valid URL from login_with_username input.");
98 let client = Client::new();
99 let request = client.post(url).json(&auth_req).send().await?;
100 let result = request.json::<AuthResponse>().await?;
101 Ok(result)
102}