From b48090656bb7be77d1b3f300255a3fe1c3b3ff7e Mon Sep 17 00:00:00 2001 From: Chris Jean-Marie Date: Thu, 10 Mar 2022 19:43:54 +0000 Subject: [PATCH] refactor code to separate files --- Cargo.lock | 8 ++++++ Cargo.toml | 3 ++- src/discord_oauth.rs | 9 +++++++ src/google_oauth.rs | 9 +++++++ src/main.rs | 63 ++++++++++++-------------------------------- src/oauth.rs | 31 ++++++++++++++++++++++ 6 files changed, 76 insertions(+), 47 deletions(-) create mode 100644 src/discord_oauth.rs create mode 100644 src/google_oauth.rs create mode 100644 src/oauth.rs diff --git a/Cargo.lock b/Cargo.lock index 869883f..a5b12e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -631,6 +631,7 @@ dependencies = [ "serde", "serde_json", "tokio", + "tower-http", "tracing", "tracing-subscriber", "uuid", @@ -1369,10 +1370,17 @@ dependencies = [ "http", "http-body", "http-range-header", + "httpdate", + "mime", + "mime_guess", + "percent-encoding", "pin-project-lite", + "tokio", + "tokio-util 0.7.0", "tower", "tower-layer", "tower-service", + "tracing", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 22e34a3..952025c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,4 +18,5 @@ askama = "0.11" oauth2 = "4.1" reqwest = { version = "0.11", default-features = false, features = ["rustls-tls", "json"] } headers = "0.3" -http = "0.2" \ No newline at end of file +http = "0.2" +tower-http = { version = "0.2.0", features = ["fs", "trace"] } \ No newline at end of file diff --git a/src/discord_oauth.rs b/src/discord_oauth.rs new file mode 100644 index 0000000..6cc4fb8 --- /dev/null +++ b/src/discord_oauth.rs @@ -0,0 +1,9 @@ +async fn discord_auth(Extension(client): Extension) -> impl IntoResponse { + let (auth_url, _csrf_token) = client + .authorize_url(CsrfToken::new_random) + .add_scope(Scope::new("identify".to_string())) + .url(); + + // Redirect to Discord's oauth service + Redirect::to(auth_url.to_string().parse().unwrap()) +} \ No newline at end of file diff --git a/src/google_oauth.rs b/src/google_oauth.rs new file mode 100644 index 0000000..ec061bb --- /dev/null +++ b/src/google_oauth.rs @@ -0,0 +1,9 @@ +async fn google_auth(Extension(client): Extension) -> impl IntoResponse { + let (auth_url, _csrf_token) = client + .authorize_url(CsrfToken::new_random) + .add_scope(Scope::new("identify".to_string())) + .url(); + + // Redirect to Discord's oauth service + Redirect::to(auth_url.to_string().parse().unwrap()) +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 1b0fb52..452673a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ use async_session::{MemoryStore, Session, SessionStore as _}; use axum::{ async_trait, extract::{ - self, rejection::TypedHeaderRejectionReason, Extension, FromRequest, Query, RequestParts, + rejection::TypedHeaderRejectionReason, Extension, FromRequest, Query, RequestParts, TypedHeader, }, headers::Cookie, @@ -14,18 +14,19 @@ use axum::{ StatusCode, }, response::{Html, IntoResponse, Redirect, Response}, - routing::get, + routing::{get, get_service}, Router, }; use http::header; -use oauth2::{ - basic::BasicClient, reqwest::async_http_client, AuthUrl, AuthorizationCode, ClientId, - ClientSecret, CsrfToken, RedirectUrl, Scope, TokenResponse, TokenUrl, -}; +use oauth2::{basic::BasicClient, reqwest::async_http_client, AuthorizationCode, TokenResponse}; use serde::{Deserialize, Serialize}; -use std::{env, net::SocketAddr}; +use std::net::SocketAddr; +use tower_http::{services::ServeDir, trace::TraceLayer}; use uuid::Uuid; +mod oauth; +use oauth::oauth_client; + const COOKIE_NAME: &str = "SESSION"; // The user data we'll get back from Discord. @@ -54,6 +55,15 @@ async fn main() { // build our application with a route let app = Router::new() // `GET /` goes to `root` + .nest( + "/assets", + get_service(ServeDir::new(".")).handle_error(|error: std::io::Error| async move { + ( + StatusCode::INTERNAL_SERVER_ERROR, + format!("Unhandled internal error: {}", error), + ) + }), + ) .route("/", get(index)) .layer(Extension(store)) .layer(Extension(oauth_client)); @@ -188,45 +198,6 @@ where } } -fn oauth_client() -> BasicClient { - // Environment variables (* = required): - // *"CLIENT_ID" "REPLACE_ME"; - // *"CLIENT_SECRET" "REPLACE_ME"; - // "REDIRECT_URL" "http://127.0.0.1:3000/auth/authorized"; - // "AUTH_URL" "https://discord.com/api/oauth2/authorize?response_type=code"; - // "TOKEN_URL" "https://discord.com/api/oauth2/token"; - - let client_id = env::var("GOOGLE_CLIENT_ID").expect("Missing CLIENT_ID!"); - let client_secret = env::var("GOOGLE_CLIENT_SECRET").expect("Missing CLIENT_SECRET!"); - let redirect_url = env::var("REDIRECT_URL") - .unwrap_or_else(|_| "http://127.0.0.1:3000/auth/authorized".to_string()); - - let auth_url = env::var("AUTH_URL").unwrap_or_else(|_| { - "https://discord.com/api/oauth2/authorize?response_type=code".to_string() - }); - - let token_url = env::var("TOKEN_URL") - .unwrap_or_else(|_| "https://discord.com/api/oauth2/token".to_string()); - - BasicClient::new( - ClientId::new(client_id), - Some(ClientSecret::new(client_secret)), - AuthUrl::new(auth_url).unwrap(), - Some(TokenUrl::new(token_url).unwrap()), - ) - .set_redirect_uri(RedirectUrl::new(redirect_url).unwrap()) -} - -async fn discord_auth(Extension(client): Extension) -> impl IntoResponse { - let (auth_url, _csrf_token) = client - .authorize_url(CsrfToken::new_random) - .add_scope(Scope::new("identify".to_string())) - .url(); - - // Redirect to Discord's oauth service - Redirect::to(auth_url.to_string().parse().unwrap()) -} - // Valid user session required. If there is none, redirect to the auth page async fn protected(user: User) -> impl IntoResponse { format!( diff --git a/src/oauth.rs b/src/oauth.rs new file mode 100644 index 0000000..9d461cd --- /dev/null +++ b/src/oauth.rs @@ -0,0 +1,31 @@ +use oauth2::{basic::BasicClient, AuthUrl, ClientId, ClientSecret, RedirectUrl, TokenUrl}; +use std::env; + +pub fn oauth_client() -> BasicClient { + // Environment variables (* = required): + // *"CLIENT_ID" "REPLACE_ME"; + // *"CLIENT_SECRET" "REPLACE_ME"; + // "REDIRECT_URL" "http://127.0.0.1:3000/auth/authorized"; + // "AUTH_URL" "https://discord.com/api/oauth2/authorize?response_type=code"; + // "TOKEN_URL" "https://discord.com/api/oauth2/token"; + + let client_id = env::var("GOOGLE_CLIENT_ID").expect("Missing CLIENT_ID!"); + let client_secret = env::var("GOOGLE_CLIENT_SECRET").expect("Missing CLIENT_SECRET!"); + let redirect_url = env::var("REDIRECT_URL") + .unwrap_or_else(|_| "http://127.0.0.1:3000/auth/authorized".to_string()); + + let auth_url = env::var("AUTH_URL").unwrap_or_else(|_| { + "https://discord.com/api/oauth2/authorize?response_type=code".to_string() + }); + + let token_url = env::var("TOKEN_URL") + .unwrap_or_else(|_| "https://discord.com/api/oauth2/token".to_string()); + + BasicClient::new( + ClientId::new(client_id), + Some(ClientSecret::new(client_secret)), + AuthUrl::new(auth_url).unwrap(), + Some(TokenUrl::new(token_url).unwrap()), + ) + .set_redirect_uri(RedirectUrl::new(redirect_url).unwrap()) +}