From 3a387813d79c8f40dd0a41d8bdf0e5522b20f02c Mon Sep 17 00:00:00 2001 From: phoenix Date: Fri, 19 Jun 2026 16:02:53 -0400 Subject: [PATCH] Delete scheduled message event endpoint (#19) Reviewed-on: http://git.kundeng.us/phoenix/textsender_api/pulls/19 --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/caller/message/scheduling.rs | 49 ++++++++++++ src/caller/mod.rs | 2 + src/config/mod.rs | 8 +- src/repo/message/scheduling.rs | 19 +++++ tests/test.rs | 129 ++++++++++++++++++++++++++++++- 7 files changed, 206 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f342aea..baf05a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2277,7 +2277,7 @@ dependencies = [ [[package]] name = "textsender_api" -version = "0.1.12" +version = "0.1.13" dependencies = [ "axum", "axum-extra", diff --git a/Cargo.toml b/Cargo.toml index 253522b..4cc484c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "textsender_api" -version = "0.1.12" +version = "0.1.13" edition = "2024" rust-version = "1.96" diff --git a/src/caller/message/scheduling.rs b/src/caller/message/scheduling.rs index 5f3c3b5..161673d 100644 --- a/src/caller/message/scheduling.rs +++ b/src/caller/message/scheduling.rs @@ -67,6 +67,8 @@ pub mod response { } pub use CreateScheduleMessageEventResponse as GetScheduledMessageEventResponse; + + pub use CreateScheduleMessageEventResponse as DeleteScheduledMessageEventResponse; } pub mod endpoint { @@ -355,4 +357,51 @@ pub mod endpoint { (axum::http::StatusCode::OK, axum::Json(response)) } + + /// Endpoint to delete the Scheduled Message Event + #[utoipa::path( + delete, + path = crate::caller::endpoints::DELETE_SCHEDULED_MESSAGE_EVENT, + params(("id" = uuid::Uuid, Path, description = "Scheduled Message Event Id")), + responses( + (status = 200, description = "Deleted", body = super::response::DeleteScheduledMessageEventResponse), + (status = 400, description = "Bad request", body = super::response::DeleteScheduledMessageEventResponse), + (status = 500, description = "Error deleting", body = super::response::DeleteScheduledMessageEventResponse) + ) + )] + pub async fn delete_scheduled_message_event( + axum::Extension(pool): axum::Extension, + axum::extract::Path(id): axum::extract::Path, + ) -> ( + axum::http::StatusCode, + axum::Json, + ) { + let mut response = super::response::DeleteScheduledMessageEventResponse::default(); + match scheduling_repo::sched_msg_event::get(&pool, &id).await { + Ok(scheduled_message_event) => { + match scheduling_repo::sched_msg_event::delete(&pool, &scheduled_message_event) + .await + { + Ok(_) => { + response.message = String::from(super::super::super::response::SUCCESSFUL); + response.data.push(scheduled_message_event); + (axum::http::StatusCode::OK, axum::Json(response)) + } + Err(err) => { + eprintln!("Error: {err:?}"); + response.message = String::from("Error deleting"); + ( + axum::http::StatusCode::INTERNAL_SERVER_ERROR, + axum::Json(response), + ) + } + } + } + Err(err) => { + eprintln!("Error: {err:?}"); + response.message = String::from("Bad request"); + (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) + } + } + } } diff --git a/src/caller/mod.rs b/src/caller/mod.rs index a65b069..6821497 100644 --- a/src/caller/mod.rs +++ b/src/caller/mod.rs @@ -22,6 +22,8 @@ pub mod endpoints { pub const CREATE_SCHEDULED_MESSAGE_EVENT: &str = "/api/v1/schedule/message/event"; /// Constant for getting Scheduled Message Event endpoint pub const GET_SCHEDULED_MESSAGE_EVENT: &str = "/api/v1/schedule/message/event"; + /// Constant for deleting Scheduled Message Event endpoint + pub const DELETE_SCHEDULED_MESSAGE_EVENT: &str = "/api/v1/schedule/message/event/{id}"; } pub mod response { diff --git a/src/config/mod.rs b/src/config/mod.rs index bbf64e4..6eea69c 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -10,7 +10,7 @@ pub mod host { pub mod init { use std::time::Duration; - use axum::routing::{get, patch, post}; + use axum::routing::{delete, get, patch, post}; use tower_http::timeout::TimeoutLayer; use utoipa::OpenApi; @@ -148,6 +148,12 @@ pub mod init { axum::middleware::from_fn(crate::auth::auth::), ), ) + .route( + crate::caller::endpoints::DELETE_SCHEDULED_MESSAGE_EVENT, + delete(scheduling_endpoints::delete_scheduled_message_event).route_layer( + axum::middleware::from_fn(crate::auth::auth::), + ), + ) .layer(cors::configure_cors().await) } diff --git a/src/repo/message/scheduling.rs b/src/repo/message/scheduling.rs index 246a9c9..5e3fe71 100644 --- a/src/repo/message/scheduling.rs +++ b/src/repo/message/scheduling.rs @@ -189,6 +189,25 @@ pub mod sched_msg_event { } } + pub async fn delete( + pool: &sqlx::PgPool, + scheduled_message_event: &textsender_models::message::scheduling::ScheduledMessageEvent, + ) -> Result<(), sqlx::Error> { + match sqlx::query( + r#" + DELETE FROM "scheduled_message_events" + WHERE id = $1 + "#, + ) + .bind(scheduled_message_event.id) + .execute(pool) + .await + { + Ok(_) => Ok(()), + Err(err) => Err(err), + } + } + async fn parse_row( row: &sqlx::postgres::PgRow, ) -> Result { diff --git a/tests/test.rs b/tests/test.rs index 54cc70a..2293c90 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -124,12 +124,10 @@ mod util { serde_json::from_slice(&body).unwrap() } - /* pub async fn format_url_with_value(endpoint: &str, value: &uuid::Uuid) -> String { let last = endpoint.len() - 5; format!("{}/{value}", &endpoint[0..last]) } - */ } pub fn token_fields() -> (String, String, String) { @@ -427,6 +425,25 @@ mod request { Err(err) => Err(err), } } + + pub async fn delete_scheduled_message_event( + app: &axum::Router, + scheduled_message_event_id: &uuid::Uuid, + ) -> Result { + let uri = super::super::super::util::format_url_with_value( + textsender_api::caller::endpoints::DELETE_SCHEDULED_MESSAGE_EVENT, + scheduled_message_event_id, + ) + .await; + + match super::super::run_post(None, &uri, axum::http::Method::DELETE, false).await { + Ok(req) => match app.clone().oneshot(req).await { + Ok(response) => Ok(response), + Err(err) => Err(axum::http::Error::from(err)), + }, + Err(err) => Err(err), + } + } } } @@ -902,3 +919,111 @@ async fn test_get_scheduled_message_event() { let _ = db_mgr::drop_database(&tm_pool, &db_name).await; } + +#[tokio::test] +async fn test_delete_scheduled_message_event() { + let (tm_pool, db_name, pool) = db_mgr::get_database_ready().await; + let app = init::app(pool).await; + + let mut contact_id: uuid::Uuid = uuid::Uuid::nil(); + let mut message_id: uuid::Uuid = uuid::Uuid::nil(); + let mut scheduled_message_id: uuid::Uuid = uuid::Uuid::nil(); + + match request::create_contact(&app).await { + Ok(response) => { + let resp = util::get_resp_data::< + textsender_api::caller::contact::response::AddContactResponse, + >(response) + .await; + assert_eq!(false, resp.data.is_empty(), "Should not be empty"); + contact_id = resp.data[0].id.unwrap(); + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + }; + + match request::message::create_message(&app).await { + Ok(response) => { + let resp = util::get_resp_data::< + textsender_api::caller::message::response::AddMessageResponse, + >(response) + .await; + assert_eq!(false, resp.data.is_empty(), "Should not be empty"); + let message = &resp.data[0]; + message_id = message.id.unwrap(); + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + }; + + match request::message::scheduling::create_scheduled_message(&app).await { + Ok(response) => { + let resp = util::get_resp_data::< + textsender_api::caller::message::scheduling::response::ScheduleMessageResponse, + >(response) + .await; + assert_eq!(false, resp.data.is_empty(), "Should not be empty"); + scheduled_message_id = resp.data[0].id; + } + Err(err) => { + assert!(false, "Error: {err:?}"); + } + } + + match request::message::scheduling::create_scheduled_message_event( + &app, + &contact_id, + &message_id, + &scheduled_message_id, + ) + .await + { + Ok(response) => { + let resp = util::get_resp_data::< + textsender_api::caller::message::scheduling::response::CreateScheduleMessageEventResponse, + >(response) + .await; + assert_eq!(false, resp.data.is_empty(), "Should not be empty"); + } + Err(err) => { + assert!(false, "Error: {err:?}"); + } + } + + match request::message::scheduling::get_scheduled_message_events(&app, &scheduled_message_id) + .await + { + Ok(response) => { + let resp = util::get_resp_data::< + textsender_api::caller::message::scheduling::response::GetScheduledMessageEventResponse, + >(response) + .await; + assert_eq!(false, resp.data.is_empty(), "Should not be empty"); + let scheduled_message_event = &resp.data[0]; + match request::message::scheduling::delete_scheduled_message_event( + &app, + &scheduled_message_event.id, + ) + .await + { + Ok(response) => { + let resp = util::get_resp_data::< + textsender_api::caller::message::scheduling::response::DeleteScheduledMessageEventResponse, + >(response) + .await; + assert_eq!(false, resp.data.is_empty(), "Should not be empty"); + } + Err(err) => { + assert!(false, "Error: {err:?}"); + } + } + } + Err(err) => { + assert!(false, "Error: {err:?}"); + } + } + + let _ = db_mgr::drop_database(&tm_pool, &db_name).await; +}