pub mod db; use axum::{ body::Body, extract::Path, Json, response::Response, Router, routing::{get, post} }; use axum_session_auth::AuthSession; use axum_session_mongo::SessionMongoPool; use chrono::Utc; use crate::AppError; use db::{get_users, User}; use http::StatusCode; use mongodb::{ bson::{doc, oid::ObjectId, to_document}, Client }; use rlg::macro_info_log; type AuthenticationSession = AuthSession; type ApiResult = Result; pub fn router() -> Router { Router::new() .nest("/:user_id", user_router()) .route("/sign-up", post(post_sign_up) ) } fn user_router() -> Router { Router::new() .route("/sign-in", get(get_sign_in) .post(post_sign_in) ) .route("/sign-out", post(post_sign_out)) .route("/backup", post(post_backup) ) .route("/restore", get(get_restore) ) } pub async fn get_sign_in(Path(user_id): Path) -> ApiResult { let id = format!("user_id: {}", user_id); macro_info_log!(&Utc::now().to_string(), &id, "Salt request initiated"); let db = get_users().await?; let query = doc! { "_id" : user_id}; match db.find_one(query, None).await? { Some(user) => { macro_info_log!(&Utc::now().to_string(), &id, "Salt request successful"); Ok(Response::builder() .status(StatusCode::CREATED) .body(Body::from(user.auth.salt.unwrap()))?) }, None => { macro_info_log!(&Utc::now().to_string(), &id, "Salt Request unsuccessful: username does not exist"); Ok(Response::builder() .status(StatusCode::NOT_FOUND) .body(Body::from("User does not exist"))?) } } } pub async fn post_sign_in(Path(user_id): Path, auth: AuthenticationSession, body: String) -> ApiResult { let id = format!("user_id: {}", user_id); macro_info_log!(&Utc::now().to_string(), &id, "Sign-in request initiated"); let db = get_users().await?; let query = doc! { "_id": &user_id, "_auth._hash": body }; match db.find_one(query, None).await? { Some(_user) => { macro_info_log!(&Utc::now().to_string(), &id, "Sign-in request successful"); auth.login_user(user_id); auth.remember_user(true); Ok(Response::builder() .status(StatusCode::OK) .body(Body::from(format!("{}", user_id)))?) }, None => { macro_info_log!(&Utc::now().to_string(), &id, "Sign-in request unsuccessful: incorrect credentials"); 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 id = "guest_user"; macro_info_log!(&Utc::now().to_string(), &id, "Sign-up request initiated"); let db = get_users().await?; let query = to_document(&body)?; match db.find_one(query.clone(), None).await? { Some(_user) => { macro_info_log!(&Utc::now().to_string(), &id, "Sign-up request unsuccessful: username already exists"); Ok(Response::builder() .status(StatusCode::NOT_ACCEPTABLE) .body(Body::from("Username is already taken"))?) }, None => { macro_info_log!(&Utc::now().to_string(), &id, "Sign-up request successful"); db.insert_one(body, None).await?; Ok(Response::builder() .status(StatusCode::CREATED) .body(Body::from("Account created successfully"))?) } } } pub async fn post_sign_out(Path(user_id): Path, auth: AuthenticationSession) -> ApiResult { let id = format!("user_id: {}", user_id); macro_info_log!(&Utc::now().to_string(), &id, "Sign-out request initiated"); match auth.is_authenticated() { true => { macro_info_log!(&Utc::now().to_string(), &id, "Sign-out request successful"); auth.logout_user(); Ok(Response::builder() .status(StatusCode::OK) .body(Body::from("Sign out successful"))?) }, false => { macro_info_log!(&Utc::now().to_string(), &id, "Sign-out request unsuccessful: user was not logged in"); Ok(Response::builder() .status(StatusCode::NOT_ACCEPTABLE) .body(Body::from("No user is not logged in"))?) }, } } pub async fn post_backup() {} //TODO: Backup pub async fn get_restore() {} //TODO: restore