From 213d696e9396024e30162d4d442aed762a401bde Mon Sep 17 00:00:00 2001 From: Romain Mallard Date: Thu, 25 Sep 2025 06:55:47 +0200 Subject: [PATCH] implemented simple chat conversation creation endpoint --- db/1.sqlite | Bin 16384 -> 32768 bytes src/chat/extractor.rs | 32 ++++++++++++++++++++++++++++++ src/chat/handlers.rs | 44 ++++++++++++++++++++++++++++++++++++++++++ src/chat/mod.rs | 5 +++++ src/chat/routes.rs | 17 ++++++++++++++++ src/lib.rs | 1 + src/main.rs | 2 ++ src/rooms/handler.rs | 4 ++++ src/routes/mod.rs | 9 ++------- 9 files changed, 107 insertions(+), 7 deletions(-) create mode 100644 src/chat/extractor.rs create mode 100644 src/chat/handlers.rs create mode 100644 src/chat/mod.rs create mode 100644 src/chat/routes.rs diff --git a/db/1.sqlite b/db/1.sqlite index 919dd66e97c7cffc0d8ec4e14f231ce73867350e..1258c17a35da95dbf6a60939f6005e4d901551e9 100644 GIT binary patch literal 32768 zcmeI*?Q7FO90%~brcWE|Znzggd~-O4Et}d0A5ajjGn2Be+qx9o8{4csCE6w~NyUd( zn}39VkAHyR8~*}@A$z6ZQ1FG9bj4)Sv3IihJxDH>yG!r)xvY?6+1A&prYHC#+vyn| zFOexiDY?TrA##(Dv|NTME;syTnCNihhdgF?T4w9dhQ&3Gwm6hUC|S+Ydjui>4myh)-|q|?^ZS5I;d>% zY|HGlc%`Om_qF;wZ?$dfxo}*=Gi|FGs^WERQLAgU1#Lars1+O`C%d}B>If&&skWl? zTBBMW9M}_<*W$YNK<@lgA-j1^V_0!dTP!!KI?paN>hk0Cre0ar*7fr8YA(0^Jeg8& z-=;gSg8(B#eP%eG**2dUmgkPFNJSAww)0scm0^hC(2pU~cSn0Xu}w>Kjv079o>FIL z>CVhwfrp2g7#-fBiRP>I%5u5B!I!iRUT)|sm746kEWLT7R#|Ik;R$Lx!tm_K#LD^f zOs^{jv+2*S-zF4J?s_7rF3nP6%5&m{yVaG~s7<5q$)IJq86I`B5H2NGm83d1M>m2< z4?4PHt1qm!I8=;B;yqNEwTzyampyaaS(;K+mF`>)j_KHT&ka_wNdI6L&yI7M%#Oe2 z!=H=MT=PM5tKZuc4v(JN2a+g#Bb+WrhR+ z2tWV=5P$##AOHafKmY;|fWS!>NGa1)-Vsm+c`=q$rpM$>fQ*bO#y%1DU9ONI009U< z00Izz00bZa0SG_<0uVT<0#h+%mWE%FP{ydD(!qNGgX{lY|M~we+dHWtV%!jb00bZa z0SG_<0uX=z1Rwwb2uOh`B|*k!Na!7b1WEWZ{_p?C*gj#u*uMNz07wvk00bZa0SG_< z0uX=z1Rwwb2%HLmghHvmC^Dtf{_}szL`Qo-f_Ja_wg6x_|v2{HMSFSqHI000Izz00bZa0SG_<0uX=z I1WviYZ=O+#4*&oF delta 117 zcmZo@U}|V!oFFa8%)r3F0>m)DI8nz~n3+MZs*soe2Lm(T1qOa4{G@om1q zXU52JjDi0c{}cYJn*|ki@bmF9vM>ls8X6cTt?}%*Zka^ OjLhPUMfv%;#moT6k{ne4 diff --git a/src/chat/extractor.rs b/src/chat/extractor.rs new file mode 100644 index 0000000..2e79e14 --- /dev/null +++ b/src/chat/extractor.rs @@ -0,0 +1,32 @@ +use axum::{ + extract::{ + FromRequest, Request + }, + http::StatusCode, + Json, +}; +use serde::Deserialize; + +#[derive(Deserialize, Debug)] +pub struct CreateConversationValues{ + //pub creator_id: i32, // already in token ? + pub title: String, +} + +pub struct CreateConversationPayload(pub CreateConversationValues); + +impl FromRequest for CreateConversationPayload +where S: Send + Sync, +{ + type Rejection = (StatusCode, String); + + async fn from_request(req: Request, state: &S) -> Result { + let Json(payload) = Json::::from_request(req, state) + .await + .map_err(|err| (StatusCode::BAD_REQUEST, format!("Invalid body: {}", err)))?; + + Ok(CreateConversationPayload(payload)) + + } +} + diff --git a/src/chat/handlers.rs b/src/chat/handlers.rs new file mode 100644 index 0000000..12113ec --- /dev/null +++ b/src/chat/handlers.rs @@ -0,0 +1,44 @@ + +use axum::{ + extract::{ + FromRequest,FromRequestParts, State, + }, + response::IntoResponse, + http::StatusCode, +}; + +use rusqlite::params; + +use crate::chat::extractor::{ +CreateConversationPayload, +}; +use crate::utils::db_pool::{AppState}; +use crate::utils::auth::AuthClaims; + + + +pub async fn create_conversation( + State(state): State, + AuthClaims {user_id, hotel_id, username}: AuthClaims, + CreateConversationPayload(payload): CreateConversationPayload +) -> impl IntoResponse { + + let pool = state.hotel_pools.get_pool(hotel_id); + + let conn = match pool.get(){ + Ok(conn) => conn, + Err(err) => return (StatusCode::INTERNAL_SERVER_ERROR, format!("Pool error")) + }; + + let result = conn.execute( + "INSERT INTO conversation (creator_id, title) VALUES (?1, ?2)", + params![&user_id, &payload.title], +); + + match result { + Ok(rows) if rows > 0 => (StatusCode::OK, format!("Created conversation {}", payload.title)), + Ok(_) => (StatusCode::NOT_FOUND, "not able to create the conversation".to_string() ), + Err(err) => (StatusCode::INTERNAL_SERVER_ERROR, format!("Error when creating the conversation : {err}")), + + } +} \ No newline at end of file diff --git a/src/chat/mod.rs b/src/chat/mod.rs new file mode 100644 index 0000000..4f1dd12 --- /dev/null +++ b/src/chat/mod.rs @@ -0,0 +1,5 @@ +pub mod routes; + + +mod extractor; +mod handlers; \ No newline at end of file diff --git a/src/chat/routes.rs b/src/chat/routes.rs new file mode 100644 index 0000000..d867310 --- /dev/null +++ b/src/chat/routes.rs @@ -0,0 +1,17 @@ +use axum::{ + Router, + routing::put +}; + +use crate::utils::db_pool::AppState; +use crate::chat::handlers::create_conversation; + + + + + +pub fn chat_routes() -> Router { + + Router::new() + .route("/create_conversation", put (create_conversation)) +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 2449eab..80763e0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,3 +4,4 @@ pub mod utils; pub mod routes; pub mod rooms; +pub mod chat; diff --git a/src/main.rs b/src/main.rs index 60b150a..46b8c6a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,8 +6,10 @@ use tokio::net::TcpListener; mod utils; mod routes; mod rooms; +mod chat; use r2d2::{Pool}; use r2d2_sqlite::SqliteConnectionManager; + use crate::utils::db_pool::{HotelPool,AppState}; use routes::create_router; use crate::utils::auth::JwtKeys; diff --git a/src/rooms/handler.rs b/src/rooms/handler.rs index 38717e2..465e43e 100644 --- a/src/rooms/handler.rs +++ b/src/rooms/handler.rs @@ -68,6 +68,10 @@ pub async fn clean_db_update( UpdateRoomPayload(payload): UpdateRoomPayload, ) -> impl IntoResponse { + //TODO: make better error handling : + // if wrong param collumn targeted, + // if missing path param + let pool = state.hotel_pools.get_pool(hotel_id); let conn = match pool.get(){ diff --git a/src/routes/mod.rs b/src/routes/mod.rs index bd2f16d..13549a1 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -6,26 +6,21 @@ use r2d2::{Pool}; use crate::rooms::routes::rooms_routes; use crate::utils::routes::utils_routes; - +use crate::chat::routes::chat_routes; use crate::utils::db_pool::{AppState}; - //TODO: add secret fomr dotenv here - - - /* Function to build our main router that regroup all feature centered router - */ - pub fn create_router(state: AppState) -> Router { Router::new() .nest("/auth", utils_routes().with_state(state.clone())) .nest("/rooms", rooms_routes().with_state(state.clone())) + .nest("/chat", chat_routes().with_state(state.clone())) .with_state(state) }