From 007071cf12459452efb7b37c296ee655de4b1a57 Mon Sep 17 00:00:00 2001 From: Romain Mallard Date: Mon, 22 Sep 2025 23:58:07 +0200 Subject: [PATCH] simple Log In endpoint without encryption --- Cargo.lock | 332 +++++++++++++++++- Cargo.toml | 3 + authbruh.rs | 37 ++ db/auth.sqlite | Bin 0 -> 28672 bytes src/main.rs | 23 +- src/rooms/handler.rs | 32 +- src/rooms/routes.rs | 10 +- src/routes/mod.rs | 28 +- src/{utils/dpPool.rs => services/handlers.rs} | 0 src/services/mod.rs | 0 src/utils/auth.rs | 227 ++++++++++++ src/utils/db_pool.rs | 28 +- src/utils/mod.rs | 4 +- src/utils/routes.rs | 16 + 14 files changed, 680 insertions(+), 60 deletions(-) create mode 100644 authbruh.rs create mode 100644 db/auth.sqlite rename src/{utils/dpPool.rs => services/handlers.rs} (100%) create mode 100644 src/services/mod.rs create mode 100644 src/utils/auth.rs create mode 100644 src/utils/routes.rs diff --git a/Cargo.lock b/Cargo.lock index dbfa9e5..e6d3eff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,15 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -112,7 +121,7 @@ checksum = "abaf6da45c74385272ddf00e1ac074c7d8a6c1a1dda376902bd6a427522a8b2c" dependencies = [ "base64", "blowfish", - "getrandom", + "getrandom 0.3.3", "subtle", "zeroize", ] @@ -151,12 +160,35 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +[[package]] +name = "cc" +version = "1.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65193589c6404eb80b450d618eaf9a2cafaaafd57ecce47370519ef674a7bd44" +dependencies = [ + "find-msvc-tools", + "shlex", +] + [[package]] name = "cfg-if" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +[[package]] +name = "chrono" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-link", +] + [[package]] name = "cipher" version = "0.4.4" @@ -167,6 +199,12 @@ dependencies = [ "inout", ] +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -197,6 +235,21 @@ dependencies = [ "parking_lot_core", ] +[[package]] +name = "deranged" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + [[package]] name = "fallible-iterator" version = "0.3.0" @@ -209,6 +262,12 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" +[[package]] +name = "find-msvc-tools" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d" + [[package]] name = "fnv" version = "1.0.7" @@ -273,6 +332,19 @@ dependencies = [ "version_check", ] +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "wasm-bindgen", +] + [[package]] name = "getrandom" version = "0.3.3" @@ -321,7 +393,10 @@ version = "0.1.0" dependencies = [ "axum", "bcrypt", + "chrono", "dashmap", + "dotenvy", + "jsonwebtoken", "r2d2", "r2d2_sqlite", "rusqlite", @@ -413,6 +488,30 @@ dependencies = [ "tower-service", ] +[[package]] +name = "iana-time-zone" +version = "0.1.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "inout" version = "0.1.4" @@ -449,6 +548,21 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jsonwebtoken" +version = "9.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" +dependencies = [ + "base64", + "js-sys", + "pem", + "ring", + "serde", + "serde_json", + "simple_asn1", +] + [[package]] name = "libc" version = "0.2.175" @@ -516,7 +630,41 @@ checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", ] [[package]] @@ -557,6 +705,16 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "pem" +version = "3.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" +dependencies = [ + "base64", + "serde", +] + [[package]] name = "percent-encoding" version = "2.3.2" @@ -581,6 +739,12 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -662,7 +826,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom", + "getrandom 0.3.3", ] [[package]] @@ -674,6 +838,20 @@ dependencies = [ "bitflags", ] +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + [[package]] name = "rusqlite" version = "0.37.0" @@ -775,6 +953,12 @@ dependencies = [ "serde", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook-registry" version = "1.4.6" @@ -784,6 +968,18 @@ dependencies = [ "libc", ] +[[package]] +name = "simple_asn1" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" +dependencies = [ + "num-bigint", + "num-traits", + "thiserror", + "time", +] + [[package]] name = "slab" version = "0.4.11" @@ -803,7 +999,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -829,6 +1025,56 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +[[package]] +name = "thiserror" +version = "2.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.3.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83bde6f1ec10e72d583d91623c939f623002284ef622b87de38cfd546cbf2031" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" + +[[package]] +name = "time-macros" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tokio" version = "1.47.1" @@ -846,7 +1092,7 @@ dependencies = [ "slab", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -920,13 +1166,19 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "uuid" version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ - "getrandom", + "getrandom 0.3.3", "js-sys", "rand", "wasm-bindgen", @@ -1017,6 +1269,74 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "windows-core" +version = "0.62.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57fe7168f7de578d2d8a05b07fd61870d2e73b4020e9f49aa00da8471723497c" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" + +[[package]] +name = "windows-result" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.59.0" diff --git a/Cargo.toml b/Cargo.toml index 905fb58..a7b973d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,9 @@ r2d2 = "0.8" r2d2_sqlite = "0.31.0" dashmap = "6.1" rusqlite = "0.37.0" +jsonwebtoken = "9.3.1" +dotenvy = "0.15.7" +chrono = "0.4.42" diff --git a/authbruh.rs b/authbruh.rs new file mode 100644 index 0000000..3701d3f --- /dev/null +++ b/authbruh.rs @@ -0,0 +1,37 @@ +use std::time::Duration; +use axum::{ + body::{to_bytes, Body}, + http::{Request as HttpRequest, StatusCode}, + middleware::Next, + response::{Response, IntoResponse}, + Json, + extract::{Path, State, FromRequest} +}; +use axum::extract::Request as ExtractRequest; +use jsonwebtoken::{decode, DecodingKey, Validation, encode, EncodingKey, Header}; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use chrono::{Utc}; +use rusqlite::{params, Connection, OptionalExtension}; + +//use crate::utils::db_pool::; +use crate::utils::db_pool::{ + HotelPool, + AppState, +}; + + +pub async fn clean_auth_loging( + State(state): State, + // LoginPayload(payload): LoginPayload, +) -> impl IntoResponse { + // You can access state.pool and state.jwt_secret here + format!("Got secret: {}", state.jwt_secret) +} + + +fn internal_error(err: E) -> (StatusCode, String) { + (StatusCode::INTERNAL_SERVER_ERROR, format!("Internal error: {}", err)) +} + + diff --git a/db/auth.sqlite b/db/auth.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..1253b8f07d0d770c13d55a27ab1882dca04d977f GIT binary patch literal 28672 zcmeI*!EVzq7{GC->C$Y{W^SSC#m7aPkYHSqC@4Y|UAC1}q8FM#gNSIGt!cIGh>&;? z-iO!V4YqOMfa`1$OhB*D{;fEvqt8yipM0^JG%t?Y*)&ye^T{Zgsy%T>SeAIKln|n# zYfaaiV(Aann}$Bl+lxv?-23Ej%5TEis*A1n@{9Z|Pi0#-C%KPyfR! ztLAy0^|4{boE7P$FuTex{bO@3R@-qlh*c|$f@eWT9d=s#%}!4}4|=NEjSgC&?zA6- zk?Mx6qi&$WgGhzlc6(Qu0p?eYRTRAZUBGct6sP$_5C4aNK~@|Olk>k0@-CmI!~Rd- z(f8LJ?~!MTY&=NMt{IZqG&k+ONvr?R92~#8ICRg1uKD)j&<7^8>Q@$r-Z!DPo@DNP zqHXGG$*)3h6a)}J009ILKmY**5I_I{1Q7VI1?~z*)V;>~Bp)T&I2nwxaVOWie72$U zvgCK6Hwpp>AbZn^%y6!LNj6C@=B5I_I{1Q0*~0R#|0 z009J6T43F-yXCzA<@*0h$g7nGA$bH4KmY**5I_I{1Q0*~0R)y&z_mTsJO)s%|1X5R zSjIHT2>}EUKmY**5I_I{1Q0*~ffW|mup936^Z(`l|8f8S3eN^oM*sl?5I_I{1Q0*~ S0R#|OS^?M6zyF&T0sH`oea5r^ literal 0 HcmV?d00001 diff --git a/src/main.rs b/src/main.rs index 78a4362..37eb29e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,8 +4,9 @@ use tokio::net::TcpListener; mod utils; mod routes; mod rooms; - -use crate::utils::db_pool::HotelPools; +use r2d2::{Pool}; +use r2d2_sqlite::SqliteConnectionManager; +use crate::utils::db_pool::{HotelPool,AppState}; use routes::create_router; @@ -13,8 +14,22 @@ use routes::create_router; #[tokio::main] async fn main() -> std::io::Result<()> { - let hotel_pools = HotelPools::new(); - let app = create_router(hotel_pools); + + let hotel_pools = HotelPool::new(); + let logs_manager = SqliteConnectionManager::file("db/auth.sqlite"); + let logs_pool = Pool::builder() + .max_size(5) + .build(logs_manager) + .expect("Failed to build logs pool"); + + let state = AppState { + hotel_pools, + logs_pool, + jwt_secret: "your_jwt_secret_key s".to_string(), // better: load from env var + }; + + + let app = create_router(state); let listener = TcpListener::bind("0.0.0.0:3000").await?; serve(listener, app).into_future().await?; Ok(()) diff --git a/src/rooms/handler.rs b/src/rooms/handler.rs index 6d11807..f1158ec 100644 --- a/src/rooms/handler.rs +++ b/src/rooms/handler.rs @@ -3,13 +3,15 @@ use axum::response::IntoResponse; use axum::http::StatusCode; use crate::rooms::extractor::UpdateRoomPayload; +use crate::utils::db_pool::*; + use std::sync::Arc; use r2d2::{Pool}; use r2d2_sqlite::SqliteConnectionManager; use dashmap::DashMap; use rusqlite::params; -use crate::utils::db_pool::*; + pub async fn hello_rooms() -> String { @@ -29,14 +31,12 @@ pub async fn fake_room_update( } pub async fn fake_db_update( - - State(hotel_pools): State, + State(state): State, Path(room_id): Path, UpdateRoomPayload(payload): UpdateRoomPayload, - ) -> impl IntoResponse { - let pool = hotel_pools.get_pool(payload.hotel_id); + let pool = state.hotel_pools.get_pool(payload.hotel_id); let conn = match pool.get() { Ok(conn) => conn, Err(err) => return (StatusCode::INTERNAL_SERVER_ERROR, format!("Pool error: {err}")), @@ -57,23 +57,9 @@ pub async fn fake_db_update( } - -/* -//fake db handler -pub async fn update_room(UpdateRoomPayload(payload): UpdateRoom) -> impl IntoResponse { - match fake_db_update(&payload.token, payload.room_id, &payload.status).await { - Ok(msg) => msg, - Err(err) => format!("Error: {}", err), - } +struct RoomRequest { + item_id: i32, + item_amount: i32, + token: String, } -async fn fake_db_update(token: &str, room_id: i32, status: &str) -> Result { - // Pretend we check the token in the DB - if token != "valid_token" { - return Err("Invalid token".into()); - } - - // Pretend we update the room status in the DB - Ok(format!("Room {} updated to '{}'", room_id, status)) -} -*/ \ No newline at end of file diff --git a/src/rooms/routes.rs b/src/rooms/routes.rs index dfe99b8..c541db1 100644 --- a/src/rooms/routes.rs +++ b/src/rooms/routes.rs @@ -4,14 +4,18 @@ use axum::{ }; use crate::rooms::handler::*; -use crate::utils::db_pool::HotelPools; +use crate::utils::db_pool::{ + HotelPool, + AppState, +}; + // ROOTS -pub fn rooms_routes() -> Router { +pub fn rooms_routes() -> Router { Router::new() .route("/", get(hello_rooms) ) .route("/fakeUpdate/{room_id}", put(fake_room_update)) - .route("/fake_db_update/{room_id}", put(fake_db_update)) + } \ No newline at end of file diff --git a/src/routes/mod.rs b/src/routes/mod.rs index abee7f8..70862cd 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -1,24 +1,26 @@ use axum::{ Router, }; +use r2d2_sqlite::SqliteConnectionManager; +use r2d2::{Pool}; use crate::rooms::routes::rooms_routes; +use crate::utils::routes::utils_routes; pub mod inventory; -use crate::utils::db_pool::HotelPools; +use crate::utils::db_pool::{AppState}; + +//TODO: add secret fomr dotenv here + + + +pub fn create_router(state: AppState) -> Router { -pub fn create_router(hotel_pools: HotelPools) -> Router { Router::new() - .nest("/rooms", rooms_routes()) - .with_state(hotel_pools) // 👈 hotel_db is passed in as argument + + .nest("/auth", utils_routes()) + .with_state(state) // 👈 hotel_db is passed in as argument - } - - -/* -pub fn create_router() -> Router { - Router::new() - .nest("/rooms", rooms_routes()) - //.nest("/inventory", inventory::inventory_routes) } - */ \ No newline at end of file + + diff --git a/src/utils/dpPool.rs b/src/services/handlers.rs similarity index 100% rename from src/utils/dpPool.rs rename to src/services/handlers.rs diff --git a/src/services/mod.rs b/src/services/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/utils/auth.rs b/src/utils/auth.rs new file mode 100644 index 0000000..49d9b0f --- /dev/null +++ b/src/utils/auth.rs @@ -0,0 +1,227 @@ +use std::time::Duration; +use axum::{ + body::{to_bytes, Body}, + http::{Request as HttpRequest, StatusCode}, + middleware::Next, + response::{Response, IntoResponse}, + Json, + extract::{Path, State, FromRequest} +}; +use axum::extract::Request as ExtractRequest; +use jsonwebtoken::{decode, DecodingKey, Validation, encode, EncodingKey, Header}; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use chrono::{Utc}; +use rusqlite::{params, Connection, OptionalExtension}; + +//use crate::utils::db_pool::; +use crate::utils::db_pool::{ + HotelPool, + AppState, +}; + +pub async fn auth_middleware( + mut req: HttpRequest, + next: Next, +) -> Result { + // buffer body + let body = std::mem::take(req.body_mut()); + + // Buffer into bytes + let bytes = to_bytes(body, 1024 * 1024) + .await + .map_err(|_| StatusCode::BAD_REQUEST)?; + + + // parse JSON as generic `Value` + let value: Value = serde_json::from_slice(&bytes) + .map_err(|_| StatusCode::BAD_REQUEST)?; + + // pull out token + let token = value + .get("token") + .and_then(|t| t.as_str()) + .ok_or(StatusCode::UNAUTHORIZED)?; + + // verify token + let key = DecodingKey::from_secret("your_jwt_secret_key".as_ref()); + let validation = Validation::default(); + let claims = decode::(token, &key, &validation) + .map_err(|_| StatusCode::UNAUTHORIZED)? + .claims; + + // inject claims for downstream handlers + req.extensions_mut().insert(claims); + + // restore the original body so the handler can parse it into *its own* struct + req = req.map(|_| Body::from(bytes)); + + + Ok(next.run(req).await) +} + +#[derive(Deserialize, Debug)] +pub struct LoginValues { + username : String, + password : String, + hotel_id: i32, +} + +pub struct LoginPayload(pub LoginValues); + +impl FromRequest for LoginPayload +where S: Send + Sync, +{ + type Rejection = (StatusCode, String); + + async fn from_request(req: ExtractRequest, state: &S) -> Result { + let Json(payload) = Json::::from_request(req, state) + .await + .map_err(|err| (StatusCode::BAD_REQUEST, format!("Invalid body: {}", err)))?; + + Ok(LoginPayload(payload)) + } +} + +#[derive(Deserialize,Debug, Serialize, Clone)] +struct Claims{ + id: i32, + hotel_id: i32, + //display_name + username: String, + exp: usize, +} + +#[derive(Serialize)] +struct LoginResponse { + token: String, +} + +//pub async fn auth_register(); +/* +pub async fn auth_loggin( + // State(hotel_pools): State, + LoginPayload(payload): LoginPayload, +) -> impl IntoResponse { + + let pool = .get_pool(payload.hotel_id); + let conn = pool.get().unwrap(); + /* + let conn = match pool.get() { + Ok(conn) => conn, + Err(err) => return (StatusCode::INTERNAL_SERVER_ERROR, format!("Pool error: {err}")), + }; +*/ + let mut statement = conn + .prepare("SELECT id, displayname, hotel_id FROM users WHERE username = ? 1 AND password = ?2 ") + .unwrap(); + + let user_row = statement + .query_row(params![&payload.username, &payload.password], |row| { + let id: i32 = row.get(0)?; + let displayname: String = row.get(1)?; + let hotel_id: i32 = row.get(2)?; + Ok((id, displayname, hotel_id)) + }) + .optional() + .unwrap(); // returns Ok(Some(...)) or Ok(None) + + if let Some((id, displayname, hotel_id)) = user_row { + let expiration = chrono::Utc::now() + .checked_add_signed(chrono::Duration::minutes(15)) + .unwrap() + .timestamp() as usize; + + let claims = Claims { + id, + hotel_id, + username: displayname, // or payload.username if you prefer + exp: expiration, + }; + + let token = encode( + &Header::default(), + &claims, + &EncodingKey::from_secret("TEST".as_bytes()), + ) + .unwrap(); + + return (StatusCode::OK, Json(LoginResponse { token })); + } + // Fallback if login failed — wrap String in Json or use axum::Json + return (StatusCode::UNAUTHORIZED, Json(LoginResponse { token: "".to_string() })); +} + +*/ + +pub async fn clean_auth_loging( + State(state): State, + LoginPayload(payload): LoginPayload +) -> impl IntoResponse { + // 1️⃣ Get a connection from logs pool + let conn = match state.logs_pool.get() { + Ok(c) => c, + Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "DB connection error").into_response(), + }; + + let user_row = match conn.query_row( + "SELECT id, password, hotel_id, displayname FROM users WHERE username = ?1", + params![&payload.username], + |row| { + let user_id: i32 = row.get(0)?; + let password: String = row.get(1)?; + let hotel_id: i32 = row.get(2)?; + let displayname: String = row.get(3)?; + Ok((user_id, password, hotel_id, displayname)) + }, + ).optional() { + Ok(opt) => opt, + Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "DB query error").into_response(), + }; + + let (user_id, stored_password, hotel_id, displayname) = match user_row { + Some(u) => u, + None => return (StatusCode::UNAUTHORIZED, "Invalid credentials").into_response(), + }; + + if payload.password != stored_password { + return (StatusCode::UNAUTHORIZED, "Invalid credentials").into_response(); + } + + let expiration = chrono::Utc::now() + .checked_add_signed(chrono::Duration::hours(15)) + .unwrap() + .timestamp() as usize; + + + let claims = serde_json::json!({ + "id": user_id, + "hotel_id": payload.hotel_id, + "username": payload.username, + "exp": expiration + }); + + let token = match encode( + &Header::default(), + &claims, + &EncodingKey::from_secret(state.jwt_secret.as_ref()), + ) { + Ok(t) => t, + Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "JWT creation failed").into_response(), + }; + Json(LoginResponse { token }).into_response() +} + +fn internal_error(err: E) -> (StatusCode, String) { + (StatusCode::INTERNAL_SERVER_ERROR, format!("Internal error: {}", err)) +} + + +/* + match result { + Ok(rows) if rows > 0 => (StatusCode::OK, format!("Logged")), + Ok(_) => (StatusCode::NOT_FOUND, "No used".to_string()), + Err(err) => (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {err}")), + } +*/ + diff --git a/src/utils/db_pool.rs b/src/utils/db_pool.rs index 7ccd784..db12556 100644 --- a/src/utils/db_pool.rs +++ b/src/utils/db_pool.rs @@ -6,30 +6,38 @@ use r2d2_sqlite::SqliteConnectionManager; type HotelId = i32; // or i32 if you want numeric ids #[derive(Clone)] -pub struct HotelPools { - pools: Arc>>, +pub struct AppState { + pub hotel_pools: HotelPool, + pub logs_pool: Pool, + pub jwt_secret: String } -impl HotelPools { + +#[derive(Clone)] +pub struct HotelPool { + hotel_pools: Arc>>, +} + +impl HotelPool { pub fn new() -> Self { Self { - pools: Arc::new(DashMap::new()), + hotel_pools: Arc::new(DashMap::new()), } } pub fn get_pool(&self, hotel_id: i32) -> Pool { - if let Some(pool) = self.pools.get(&hotel_id) { + if let Some(pool) = self.hotel_pools.get(&hotel_id) { return pool.clone(); } let db_path = format!("db/{}.sqlite", hotel_id); - let manager = SqliteConnectionManager::file(db_path); - let pool = Pool::builder() + let hotels_manager = SqliteConnectionManager::file(db_path); + let db_pool = Pool::builder() .max_size(5) // adjust based on load - .build(manager) + .build(hotels_manager) .expect("Failed to build pool"); - self.pools.insert(hotel_id, pool.clone()); - pool + self.hotel_pools.insert(hotel_id, db_pool.clone()); + db_pool } } \ No newline at end of file diff --git a/src/utils/mod.rs b/src/utils/mod.rs index b0680f8..1f4231e 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1 +1,3 @@ -pub mod db_pool; \ No newline at end of file +pub mod db_pool; +pub mod auth; +pub mod routes; \ No newline at end of file diff --git a/src/utils/routes.rs b/src/utils/routes.rs new file mode 100644 index 0000000..3252385 --- /dev/null +++ b/src/utils/routes.rs @@ -0,0 +1,16 @@ +use axum::{ + routing::{get, put, post}, + Router, +}; + +use crate::utils::auth::*; +use crate::utils::db_pool::{HotelPool, AppState}; + + +// ROOTS +pub fn utils_routes() -> Router { + + Router::new() + .route("/login", put(clean_auth_loging)) + //.with_state(state) + } \ No newline at end of file