Optimizations for buidling memcacache for our tokens

This commit is contained in:
shockrah 2020-12-20 19:43:27 -08:00
parent 88f6e5b532
commit 5a5ecfad26
4 changed files with 64 additions and 41 deletions

View File

@ -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<AuthReason, SqlError> {
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<HeaderValue>,
path: &'path str,
pool: &'pool Pool,
params: &'params serde_json::Value)
-> Result<AuthReason, SqlError> {
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<AuthReason, SqlError> {
pub async fn login_get_jwt(response: &mut hyper::Response<hyper::Body>, params: serde_json::Value) {
let (id_v, secret_v) = (params.get("id"), params.get("secret"));
return Ok(AuthReason::Good);
}

View File

@ -153,7 +153,11 @@ pub async fn create(pool: &Pool, response: &mut Response<Body>, 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(),

View File

@ -48,6 +48,8 @@ async fn route_dispatcher(pool: &Pool, resp: &mut Response<Body>, 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<Body>) -> Result<Response<Body>, 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, &params).await {
// Deal with permissions errors at this point
match auth_result {
OpenAuth | Good => route_dispatcher(&pool, &mut response, &method, path, params).await,

View File

@ -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