diff --git a/db/1.sqlite b/db/1.sqlite index c2779fe..14805d3 100644 Binary files a/db/1.sqlite and b/db/1.sqlite differ diff --git a/src/chat/extractor.rs b/src/chat/extractor.rs index f17f399..dc3e5d7 100644 --- a/src/chat/extractor.rs +++ b/src/chat/extractor.rs @@ -51,5 +51,28 @@ where S: Send + Sync, Ok(AddUserConversationPayload(payload)) + } +} + +#[derive(Deserialize, Debug)] +pub struct SendMessageValues{ + pub conv_id: u32, + pub message: String, +} + +pub struct SendMessagePayload(pub SendMessageValues); + +impl FromRequest for SendMessagePayload +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(SendMessagePayload(payload)) + } } \ No newline at end of file diff --git a/src/chat/handlers.rs b/src/chat/handlers.rs index 3bfbc9b..8e4bab4 100644 --- a/src/chat/handlers.rs +++ b/src/chat/handlers.rs @@ -8,7 +8,7 @@ use axum::{ use rusqlite::params; use crate::chat::extractor::{ -AddUserConversationPayload, CreateConversationPayload +AddUserConversationPayload, CreateConversationPayload, SendMessagePayload }; use crate::utils::db_pool::{AppState}; use crate::utils::auth::AuthClaims; @@ -61,7 +61,7 @@ pub async fn add_user_to_conv( Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "prepare failed".to_string()) }; - if !statement.exists(params![user_id, payload.conv_id ]) + if !statement.exists(params![user_id, payload.conv_id]) .map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "Query failed".to_string())).unwrap() { // Early exit if not creator @@ -87,4 +87,43 @@ pub async fn add_user_to_conv( return (StatusCode::OK, "ok".to_string()); +} + +pub async fn send_message( + State(state): State, + AuthClaims {user_id, hotel_id,username}: AuthClaims, + SendMessagePayload(payload):SendMessagePayload +) -> 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 mut statement = match conn.prepare( + "SELECT 1 FROM conversation_participants WHERE user_id = ?1 AND conversation_id = ?2" , + ){ + Ok(statement) => statement, + Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "prepare failed".to_string()) + }; + + if !statement.exists(params![user_id, payload.conv_id]) + .map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "Query failed".to_string())).unwrap() + { + // Early exit if not creator + return ((StatusCode::FORBIDDEN, "Not the creator".to_string())); + } + + let result = conn.execute( + "INSERT INTO message (sender_id, content, conversation_id) VALUES (?1, ?2, ?3)", + params![&user_id, &payload.message, &payload.conv_id], + ); + + match result { + Ok(rows) if rows > 0 => (StatusCode::OK, "added message succesfully".to_string()), + Ok(_) => (StatusCode::NOT_FOUND, "not able to add the message, conversation may not exist".to_string() ), + Err(err) => (StatusCode::INTERNAL_SERVER_ERROR, format!("Error when adding the message : {err}")), + } } \ No newline at end of file diff --git a/src/chat/routes.rs b/src/chat/routes.rs index 3c03755..534dfb0 100644 --- a/src/chat/routes.rs +++ b/src/chat/routes.rs @@ -1,11 +1,12 @@ use axum::{ Router, - routing::put + routing::put, + routing::post }; use crate::utils::db_pool::AppState; use crate::chat::handlers::{ - create_conversation,add_user_to_conv, + create_conversation,add_user_to_conv,send_message }; @@ -15,7 +16,8 @@ use crate::chat::handlers::{ pub fn chat_routes() -> Router { Router::new() - .route("/create_conversation", put (create_conversation)) + .route("/create_conversation", post (create_conversation)) .route("/add_users_conv", put(add_user_to_conv)) - + .route("/send_message", post(send_message)) + } \ No newline at end of file