From ec0a310d761a2ae79c226789f5972b5d795eeacb Mon Sep 17 00:00:00 2001 From: phoenix Date: Wed, 17 Jun 2026 14:16:16 -0400 Subject: [PATCH] Adding code for adding message --- src/caller/message.rs | 85 +++++++++++++++++++++++++++++++++++++++++++ src/caller/mod.rs | 3 ++ src/config/mod.rs | 16 ++++++-- src/repo/message.rs | 26 +++++++++++++ src/repo/mod.rs | 1 + 5 files changed, 128 insertions(+), 3 deletions(-) create mode 100644 src/caller/message.rs create mode 100644 src/repo/message.rs diff --git a/src/caller/message.rs b/src/caller/message.rs new file mode 100644 index 0000000..0427aa3 --- /dev/null +++ b/src/caller/message.rs @@ -0,0 +1,85 @@ +pub mod request { + use serde::{Deserialize, Serialize}; + use utoipa::ToSchema; + + #[derive(Debug, Deserialize, Serialize, ToSchema)] + pub struct AddMessageRequest { + pub content: String, + pub user_id: uuid::Uuid + } + + impl AddMessageRequest { + pub fn is_valid(&self) -> bool { + !self.content.is_empty() || !self.user_id.is_nil() + } + } +} + +pub mod response { + use serde::{Deserialize, Serialize}; + use utoipa::ToSchema; + + #[derive(Debug, Default, Deserialize, Serialize, ToSchema)] + pub struct AddMessageResponse { + pub message: String, + pub data: Vec + } +} + +pub mod endpoint { + use crate::repo::message as message_repo; + + /// Endpoint to create Message + #[utoipa::path( + post, + path = super::super::endpoints::ADD_MESSAGE, + request_body( + content = super::request::AddMessageRequest, + description = "Data needed to create a Message", + content_type = "application/json" + ), + responses( + (status = 201, description = "Message created", body = super::response::AddMessageResponse), + (status = 400, description = "Error", body = super::response::AddMessageResponse), + (status = 500, description = "Error creating Message", body = super::response::AddMessageResponse) + ) +)] + pub async fn create_message( + axum::Extension(pool): axum::Extension, + axum::Json(payload): axum::Json, + ) -> ( + axum::http::StatusCode, + axum::Json, + ) { + let mut response = super::response::AddMessageResponse::default(); + + if payload.is_valid() { + let mut msg = textsender_models::message::Message { + content: payload.content, + user_id: Some(payload.user_id), + ..Default::default() + }; + match message_repo::insert(&pool, &msg, &payload.user_id) .await + { + Ok(message_id) => { + msg.id = Some(message_id); + response.data.push(msg); + response.message = String::from("Message created"); + (axum::http::StatusCode::CREATED, axum::Json(response)) + } + Err(err) => { + eprintln!("Error: {err:?}"); + response.message = String::from("Contact not created"); + + ( + axum::http::StatusCode::INTERNAL_SERVER_ERROR, + axum::Json(response), + ) + } + } + } else { + response.message = String::from("Request body is not valid"); + (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) + } + } +} diff --git a/src/caller/mod.rs b/src/caller/mod.rs index 17bc20a..85b102e 100644 --- a/src/caller/mod.rs +++ b/src/caller/mod.rs @@ -1,4 +1,5 @@ pub mod contact; +pub mod message; pub mod endpoints { pub const ROOT: &str = "/"; @@ -9,6 +10,8 @@ pub mod endpoints { pub const GET_CONTACT: &str = "/api/v1/contact"; /// Constant for updating names of a Contact endpoint pub const UPDATE_CONTACT_NAME: &str = "/api/v1/contact/update"; + /// Constant for adding message endpoint + pub const ADD_MESSAGE: &str = "/api/v1/message/new"; } pub mod response { diff --git a/src/config/mod.rs b/src/config/mod.rs index 105fb1c..daf5acb 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -15,8 +15,11 @@ pub mod init { use utoipa::OpenApi; use crate::caller::contact as contact_caller; + use crate::caller::message as message_caller; use contact_caller::endpoint as contact_endpoints; - // use contact_caller::response as contact_responses; + use message_caller::endpoint as message_endpoints; + use contact_caller::response as contact_responses; + use message_caller::response as message_responses; mod cors { pub async fn configure_cors() -> tower_http::cors::CorsLayer { @@ -73,8 +76,9 @@ pub mod init { #[derive(utoipa::OpenApi)] #[openapi( - paths(contact_endpoints::create_contact,), - components(schemas(contact_caller::response::AddContactResponse)), + paths(contact_endpoints::create_contact, + message_endpoints::create_message), + components(schemas(contact_responses::AddContactResponse)), tags( (name = "textsender API", description = "Web API to manage texting") ) @@ -101,6 +105,12 @@ pub mod init { axum::middleware::from_fn(crate::auth::auth::), ), ) + .route( + crate::caller::endpoints::ADD_MESSAGE, + patch(message_endpoints::create_message).route_layer( + axum::middleware::from_fn(crate::auth::auth::), + ), + ) .layer(cors::configure_cors().await) } diff --git a/src/repo/message.rs b/src/repo/message.rs new file mode 100644 index 0000000..a5bf5ae --- /dev/null +++ b/src/repo/message.rs @@ -0,0 +1,26 @@ +use sqlx::Row; + +pub async fn insert( + pool: &sqlx::PgPool, + message: &textsender_models::message::Message, + user_id: &uuid::Uuid, +) -> Result { + match sqlx::query( + r#" + INSERT INTO "contacts" (content, user_id) + VALUES($1, $2) RETURNING id; + "#, + ) + .bind(&message.content) + .bind(user_id) + .fetch_one(pool) + .await + { + Ok(row) => { + let id: uuid::Uuid = row.try_get("id")?; + Ok(id) + } + Err(_) => Err(sqlx::Error::RowNotFound), + } +} + diff --git a/src/repo/mod.rs b/src/repo/mod.rs index 40d6353..2af9758 100644 --- a/src/repo/mod.rs +++ b/src/repo/mod.rs @@ -1 +1,2 @@ pub mod contact; +pub mod message;