pub mod db; use axum::{ body::Body, Json, response::Response, Router, routing::{get, post} }; use crate::AppError; use db::{get_users, User}; use http::{header::HeaderMap, StatusCode}; use mongodb::bson::{doc, oid::ObjectId}; type ApiResult = Result; pub fn router() -> Router { Router::new() .route("/sign-in", get(get_sign_in) .post(post_sign_in) ) .route("/sign-up", post(post_sign_up)) .route("/sign-out", post(post_sign_out)) .route("/backup", post(post_backup) ) .route("/restore", get(get_restore) ) } pub async fn get_sign_in(Json(body): Json) -> ApiResult { let db = get_users().await?; let query = doc! { "$expr": { "$eq": ["$username", body.username] } }; match db.find_one(query, None).await? { Some(user) => { Ok(Response::builder() .status(StatusCode::CREATED) .body(Body::from(user.auth.unwrap().salt.unwrap()))?) }, None => { Ok(Response::builder() .status(StatusCode::NOT_FOUND) .body(Body::from("User does not exist"))?) } } } pub async fn post_sign_in(Json(body): Json) -> ApiResult { let db = get_users().await?; let api = ObjectId::new(); let query = doc! { "$expr": { "$and": [ { "$eq": ["$username", body.username]}, { "$eq": ["$_auth._hash", body.auth.unwrap_or_default().hash]} ] } }; let update = doc! { "$set": { "_auth._api": api } }; match db.find_one(query.clone(), None).await? { Some(_user) => { db.update_one(query, update, None).await?; Ok(Response::builder() .status(StatusCode::OK) .body(Body::from(api.to_string()))?) }, None => { Ok(Response::builder() .status(StatusCode::UNAUTHORIZED) .body(Body::from("Username or password is incorrect"))?) }, } } pub async fn post_sign_up(Json(body): Json) -> ApiResult { let db = get_users().await?; let auth = body.clone().auth.unwrap_or_default(); let query = doc! { "$expr": { "$and": [ { "$eq": ["$username", &body.username] }, { "$eq": ["$_auth._hash", &auth.hash]}, { "$eq": ["$_auth._salt", &auth.salt]} ] } }; match db.find_one(query, None).await? { Some(_user) => { Ok(Response::builder() .status(StatusCode::NOT_ACCEPTABLE) .body(Body::from("Username is already taken"))?) }, None => { db.insert_one(body, None).await?; Ok(Response::builder() .status(StatusCode::CREATED) .body(Body::from("Account created successfully"))?) } } } pub async fn post_sign_out(headers: HeaderMap) -> ApiResult { let db = get_users().await?; let api = headers["api_key"].to_str()?; let query = doc! { "$expr": { "$eq": ["$_auth._api", ObjectId::parse_str(api)?] } }; let update = doc! { "$unset": { "_auth._api": ObjectId::new() } }; match db.find_one(query.clone(), None).await? { Some(_user) => { db.update_one(query, update, None).await?; Ok(Response::builder() .status(StatusCode::OK) .body(Body::from("Sign out successful"))?) }, None => { Ok(Response::builder() .status(StatusCode::NOT_ACCEPTABLE) .body(Body::from("User does not exist"))?) }, } } pub async fn post_backup() {} //TODO: Backup pub async fn get_restore() {} //TODO: restore