use axum::{ http::HeaderMap, http::StatusCode, routing::get, routing::post, routing::put, Json, Router, }; use serde_json::{json, Value}; use serde::Deserialize; use redis::Commands; #[derive(Deserialize)] pub struct User { username: String, password: String, } #[tokio::main] async fn main() { // build our application with a single route let app = Router::new() .route("/", get(root)) .route("/users/create", post(create_user)) .route("/users/auth", get(auth_user)) .route("/syncs/progress", put(update_progress)) .route("/syncs/progress/:document", put(get_progress)) .route("/healthcheck", get(healthcheck)); // run it with hyper on localhost:3000 axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) .serve(app.into_make_service()) .await .unwrap(); } async fn root() -> &'static str { "KOreader sync server" } async fn create_user(Json(payload): Json) -> (StatusCode, String) { let client = redis::Client::open("redis://127.0.0.1/").unwrap(); let mut con = client.get_connection().unwrap(); let username = payload.username; let password = payload.password; let user_key = format!("user:{username}:key"); let does_exist: bool = con.exists(&user_key).unwrap(); if does_exist == false { let _: () = con.set(&user_key, password).unwrap(); } else { return ( StatusCode::PAYMENT_REQUIRED, "Username is already registered.".to_owned(), ); } (StatusCode::CREATED, format!("username = {username}")) } async fn auth_user(headers: HeaderMap) -> StatusCode { let client = redis::Client::open("redis://127.0.0.1/").unwrap(); let mut con = client.get_connection().unwrap(); let username = headers["x-auth-user"].to_str().unwrap_or(""); let password = headers["x-auth-key"].to_str().unwrap_or(""); if username.is_empty() || password.is_empty() { return StatusCode::UNAUTHORIZED; } let user_key = format!("user:{username}:key"); let redis_pw: String = con.get(&user_key).unwrap(); if password != redis_pw { return StatusCode::UNAUTHORIZED; } StatusCode::OK } async fn update_progress() {} async fn get_progress() {} async fn healthcheck() -> (StatusCode, String) { (StatusCode::OK, "state = 'OK'".to_owned()) }