summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam T. Carpenter <atc@53hor.net>2021-04-02 18:23:45 -0400
committerAdam T. Carpenter <atc@53hor.net>2021-04-02 18:23:45 -0400
commitb1c45640a72300433800c8370657335616f8c541 (patch)
treead7df1bfa6f59390ad227183364b308ab2137ed0
parent7633bf5855ae5359d0fe280970e5c5c210c536b3 (diff)
downloadtwinh-b1c45640a72300433800c8370657335616f8c541.tar.xz
twinh-b1c45640a72300433800c8370657335616f8c541.zip
replaced mongo with sled, added some basic functional google oauth2 code
-rw-r--r--Cargo.toml7
-rw-r--r--src/handlers/mod.rs115
-rw-r--r--src/main.rs13
-rw-r--r--src/models/mod.rs7
-rw-r--r--src/templates/mod.rs8
5 files changed, 126 insertions, 24 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 4fc3f0c..72dff12 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,13 +7,14 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+bincode = "1.3"
env_logger = "0.8"
handlebars = "3.5"
hyper = { version = "0.14", default-features = false, features = ["full"] }
+hyper-rustls = "0.22"
log = "0.4"
-mongodb = "1.2"
once_cell = "1.7"
-serde = "1.0"
-serde_json = "1.0"
+serde = { version = "1.0", features = ["derive"]}
serde_urlencoded = "0.7"
+sled = "0.34"
tokio = { version = "1.2", default-features = false, features = ["full"] }
diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs
index efd99f5..1aba908 100644
--- a/src/handlers/mod.rs
+++ b/src/handlers/mod.rs
@@ -1,18 +1,18 @@
use crate::templates;
use handlebars::Handlebars;
+use hyper::body::HttpBody as _;
use hyper::Method;
use hyper::StatusCode;
use hyper::{Body, Request, Response};
use serde::{Deserialize, Serialize};
use std::convert::Infallible; // TODO:
-pub async fn router(
- req: Request<Body>,
- _client: mongodb::Client,
-) -> Result<Response<Body>, Infallible> {
+pub async fn router(req: Request<Body>) -> Result<Response<Body>, Infallible> {
match (req.method(), req.uri().path()) {
- (&Method::GET, "/") | (&Method::GET, "/index.html") => Ok(Response::new("Welcome!".into())),
- (&Method::GET, "/parts") | (&Method::GET, "/parts/index.html") => get_parts(req).await,
+ (&Method::GET, "/") | (&Method::GET, "/index.html") => index(req).await,
+ (&Method::GET, "/login") | (&Method::GET, "/login/index.html") => login().await,
+ (&Method::GET, "/login/google") => login_google().await,
+ (&Method::GET, "/login/google/code") => login_google_code(req).await,
_ => Ok(Response::builder()
.status(StatusCode::NOT_FOUND)
.body("Not found.".into())
@@ -20,7 +20,102 @@ pub async fn router(
}
}
-async fn get_parts(req: Request<Body>) -> Result<Response<Body>, Infallible> {
+async fn login() -> Result<Response<Body>, Infallible> {
+ Ok(Response::new(templates::LOGIN_T.into()))
+}
+
+async fn login_google() -> Result<Response<Body>, Infallible> {
+ let uri = hyper::Uri::builder()
+ .scheme("https")
+ .authority("accounts.google.com")
+ .path_and_query(format!(
+ "{}?client_id={}&redirect_uri={}&response_type={}&scope={}&state={}",
+ "/o/oauth2/v2/auth",
+ "???",
+ "http://localhost:3000/login/google/code",
+ "code",
+ "openid%20profile%20email",
+ "BLARGH"
+ ))
+ .build()
+ .unwrap();
+ let resp = Response::builder()
+ .header(hyper::header::LOCATION, uri.to_string())
+ .status(StatusCode::TEMPORARY_REDIRECT)
+ .body("".into())
+ .unwrap();
+ Ok(resp)
+}
+
+#[derive(Serialize)]
+struct AuthRequest {
+ client_id: String,
+ client_secret: String,
+ grant_type: &'static str,
+ redirect_uri: String,
+ code: String,
+}
+
+impl Default for AuthRequest {
+ fn default() -> Self {
+ Self {
+ client_id: "???".into(),
+ client_secret: "???".into(),
+ grant_type: "authorization_code",
+ redirect_uri: String::new(),
+ code: String::new(),
+ }
+ }
+}
+
+async fn login_google_code(req: Request<Body>) -> Result<Response<Body>, Infallible> {
+ let query = req.uri().query().unwrap_or_default();
+ let query = serde_urlencoded::de::from_str::<GoogleOAuthQuery>(query).unwrap();
+ if query.state != "BLARGH" {
+ dbg!("tampering?");
+ }
+
+ // get access token
+ let auth_body = AuthRequest {
+ code: query.code,
+ redirect_uri: "http://localhost:3000/login/google/code".to_owned(),
+ ..Default::default()
+ };
+
+ let https = hyper_rustls::HttpsConnector::with_native_roots();
+ let client: hyper::Client<_, hyper::Body> = hyper::Client::builder().build(https);
+
+ let req = Request::builder()
+ .method(Method::POST)
+ .uri("https://oauth2.googleapis.com/token")
+ .header(
+ hyper::header::CONTENT_TYPE,
+ "application/x-www-form-urlencoded",
+ )
+ .body(serde_urlencoded::ser::to_string(auth_body).unwrap().into())
+ .unwrap();
+ let mut resp = client.request(req).await.unwrap();
+ use std::io::prelude::*;
+ while let Some(chunk) = resp.body_mut().data().await {
+ std::io::stdout().write_all(&chunk.unwrap()).unwrap();
+ }
+
+ let resp = Response::builder()
+ .header(hyper::header::LOCATION, "/".to_string())
+ .status(StatusCode::TEMPORARY_REDIRECT)
+ .body("Successful login, redirecting...".into())
+ .unwrap();
+ Ok(resp)
+}
+
+pub struct AccessToken {
+ access_token: String,
+ expires_in: String,
+ scope: String,
+ token_type: String,
+}
+
+async fn index(req: Request<Body>) -> Result<Response<Body>, Infallible> {
let query = req.uri().query().unwrap_or_default();
let filter = serde_urlencoded::de::from_str::<PartsQuery>(query).unwrap();
let mut reg = Handlebars::new();
@@ -49,6 +144,12 @@ async fn get_parts(req: Request<Body>) -> Result<Response<Body>, Infallible> {
}
#[derive(Debug, Deserialize)]
+struct GoogleOAuthQuery {
+ code: String,
+ state: String,
+}
+
+#[derive(Debug, Deserialize)]
struct PartsQuery {
make: Option<String>,
year: Option<String>,
diff --git a/src/main.rs b/src/main.rs
index a2af455..168a5f5 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -13,17 +13,8 @@ mod templates;
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let addr = config::INSTANCE.addr;
- let client = mongodb::Client::with_uri_str(&config::INSTANCE.db_uri).await?;
-
- let make_svc = make_service_fn(move |_conn| {
- let client = client.clone();
-
- async {
- Ok::<_, Infallible>(service_fn(move |req| {
- handlers::router(req, client.to_owned())
- }))
- }
- });
+ let make_svc =
+ make_service_fn(move |_conn| async { Ok::<_, Infallible>(service_fn(handlers::router)) });
let server = Server::bind(&addr).serve(make_svc);
let graceful = server.with_graceful_shutdown(shutdown_signal());
diff --git a/src/models/mod.rs b/src/models/mod.rs
index 1a4d1df..5830a1b 100644
--- a/src/models/mod.rs
+++ b/src/models/mod.rs
@@ -2,12 +2,13 @@ use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub struct Car {
- year: u16, // I'll worry about this in 65534 AD.
+ doors: u8,
+ engine: Engine,
make: String,
model: String,
- engine: Engine,
- doors: u8,
transmission: Transmission,
+ trim: String,
+ year: u16, // I'll worry about this in 65534 AD.
}
#[derive(Serialize, Deserialize)]
diff --git a/src/templates/mod.rs b/src/templates/mod.rs
index 1a594fb..3a6eb2b 100644
--- a/src/templates/mod.rs
+++ b/src/templates/mod.rs
@@ -1 +1,9 @@
pub static INDEX_T: &str = include_str!("index.html");
+pub static LOGIN_T: &str = include_str!("login.html");
+pub const CATALOG_L: &str = "/#menu";
+pub const PARTS_L: &str = "/parts";
+pub const PARTS_CSV_L: &str = "/parts.csv";
+pub const CARS_L: &str = "/cars";
+pub const CARS_CSV_L: &str = "/cars.csv";
+pub const SUGGESTIONS_L: &str = "/suggestions";
+pub const LOGIN_L: &str = "/login";