From 5a5ecfad260a682500ebd89ef914782624fd5291 Mon Sep 17 00:00:00 2001 From: shockrah Date: Sun, 20 Dec 2020 19:43:27 -0800 Subject: [PATCH] Optimizations for buidling memcacache for our tokens --- server-api/src/auth.rs | 90 ++++++++++++++++++++++----------------- server-api/src/invites.rs | 6 ++- server-api/src/main.rs | 7 ++- server-api/src/routes.rs | 2 + 4 files changed, 64 insertions(+), 41 deletions(-) diff --git a/server-api/src/auth.rs b/server-api/src/auth.rs index e953a1f..1dd2fa2 100644 --- a/server-api/src/auth.rs +++ b/server-api/src/auth.rs @@ -2,6 +2,9 @@ use bcrypt::{self, BcryptResult}; use mysql_async::Pool; use mysql_async::error::Error as SqlError; +use hyper::{ + HeaderMap, header::HeaderValue +}; use crate::routes; @@ -65,64 +68,75 @@ fn get_jwt(params: &serde_json::Value) -> Option<&str> { } fn valid_jwt(token: &str) -> AuthReason { - // TODO - return AuthReason::Good; + // TODO : take the token string and check if we have the jwt somewhere + return AuthReason::Good; // Good|Bad } -pub async fn wall_entry(path: &str, pool: &Pool, params: &serde_json::Value) -> Result { +fn get_login(params: &serde_json::Value) -> Option<(db::UBigInt, &str)> { + let id_v = params.get("id"); + let secret_v = params.get("secret"); + return match (id_v, secret_v) { + (Some(id_v), Some(secret_v)) => { + match (id_v.as_u64(), secret_v.as_str()) { + (Some(id), Some(secret)) => Some((id, secret)), + _ => None + } + }, + _ => None + } +} + + +pub async fn wall_entry<'path, 'pool, 'params>( + headers: HeaderMap, + path: &'path str, + pool: &'pool Pool, + params: &'params serde_json::Value) + -> Result { use std::borrow::Cow; // Dont need to auth if it's not required let open_path = routes::is_open(path); let jwt = get_jwt(params); + let head = headers.get("Authorization"); + println!("Auth header: {:?}", head); + if open_path { // ignore the parameters since they're irelevant return Ok(AuthReason::OpenAuth); } - else if let Some(jwt) = jwt { - // if we have a jwt then verify its validity - return Ok(valid_jwt(jwt)); // Good|BadKey + if let Some(jwt) = jwt { + // get the headers here + return Ok(valid_jwt(jwt)); } - else { - + if let Some((id, secret)) = get_login(params) { // Last chance we might be hitting the /login route so we have to do the heavy auth flow - match (params.get("id"), params.get("secret")) { - /* - * If we apparantly have user data then check for validity in credentials - */ - (Some(id_v), Some(secret_v)) => { - /* unwrapping because i couldn't care less about poorly formatted request data */ - if path != "/login" { - return Ok(AuthReason::BadKey); - } - let id = id_v.as_u64().unwrap_or(0); // basically nobody is allowed to have 0 as its supposed to be reserved - let secret = secret_v.as_str().unwrap_or(""); - return match Member::get(pool, id).await { - Response::Row(user) => { - if valid_secret(secret, &user.secret) && valid_perms(user, path){ - Ok(AuthReason::Good) - } - else { - Ok(AuthReason::BadKey) - } - }, - Response::Empty => Ok(AuthReason::BadKey), - Response::Other(err) => Err(SqlError::Other(Cow::from(err))), - _ => Err(SqlError::Other(Cow::from("Undefined result"))) - } - }, - _ => { - Ok(AuthReason::NoKey) + + if path != routes::AUTH_LOGIN { + return Ok(AuthReason::BadKey); + } + else { + return match Member::get(pool, id).await { + Response::Row(user) => { + if valid_secret(secret, &user.secret) && valid_perms(user, path){ + Ok(AuthReason::Good) + } + else { + Ok(AuthReason::BadKey) + } + }, + Response::Empty => Ok(AuthReason::BadKey), + Response::Other(err) => Err(SqlError::Other(Cow::from(err))), + _ => Err(SqlError::Other(Cow::from("Undefined result"))) } } } + return Ok(AuthReason::BadKey); } -pub async fn login_get_jwt(pool: &Pool, params: &serde_json::Value) -> Result { +pub async fn login_get_jwt(response: &mut hyper::Response, params: serde_json::Value) { let (id_v, secret_v) = (params.get("id"), params.get("secret")); - - return Ok(AuthReason::Good); } diff --git a/server-api/src/invites.rs b/server-api/src/invites.rs index 4fc2da6..a0374e4 100644 --- a/server-api/src/invites.rs +++ b/server-api/src/invites.rs @@ -153,7 +153,11 @@ pub async fn create(pool: &Pool, response: &mut Response, params: Value) { * Creates a new invite */ - let id = params.get("id").unwrap().as_u64().unwrap(); + // no user can actually have an id of 0 this won't find anyone on the backend + let id = match params.get("id") { + Some(val) => val.as_u64().unwrap_or(0), + None => 0 + }; let use_count = match params.get("uses") { Some(val) => val.as_i64(), diff --git a/server-api/src/main.rs b/server-api/src/main.rs index 5b11d7b..4609f4e 100644 --- a/server-api/src/main.rs +++ b/server-api/src/main.rs @@ -48,6 +48,8 @@ async fn route_dispatcher(pool: &Pool, resp: &mut Response, meth: &Method, const POST: &Method = &Method::POST; const DELETE: &Method = &Method::DELETE; match (meth, path) { + /* AUTHENTICATION */ + (POST, routes::AUTH_LOGIN) => auth::login_get_jwt(resp, params).await, /* INVITES */ (GET, routes::INVITE_CREATE) => invites::create(pool, resp, params).await, (GET, routes::INVITE_JOIN) => invites::join(pool, resp, params).await, @@ -77,13 +79,14 @@ async fn main_responder(request: Request) -> Result, hyper: let (parts, mut body) = request.into_parts(); let method = parts.method; let path = parts.uri.path(); + let headers = parts.headers; println!("{}: {}", method, path); let params_res = http_params::parse_params(&mut body).await; - if let Ok(mut params) = params_res { + if let Ok(params) = params_res { let pool = Pool::new(&env::var("DATABASE_URL").unwrap()); - if let Ok(auth_result) = auth::wall_entry(path, &pool, &mut params).await { + if let Ok(auth_result) = auth::wall_entry(headers, path, &pool, ¶ms).await { // Deal with permissions errors at this point match auth_result { OpenAuth | Good => route_dispatcher(&pool, &mut response, &method, path, params).await, diff --git a/server-api/src/routes.rs b/server-api/src/routes.rs index ce50e59..4742ae5 100644 --- a/server-api/src/routes.rs +++ b/server-api/src/routes.rs @@ -1,6 +1,8 @@ // TODO: this whole ass module bro i mean c'mon.... just just clean it type Rstr = &'static str; +pub const AUTH_LOGIN: Rstr = "/login"; // requires @id @secret + pub const INVITE_CREATE: Rstr = "/invite/create"; // @ perms::CREATE_INVITE pub const INVITE_JOIN: Rstr = "/join"; // @ none for new accounts