diff --git a/migrations/20241204225151_create_comment_table.up.sql b/migrations/20241204225151_create_comment_table.up.sql index a92af64..5f432d7 100644 --- a/migrations/20241204225151_create_comment_table.up.sql +++ b/migrations/20241204225151_create_comment_table.up.sql @@ -1,7 +1,7 @@ -- Add up migration script here CREATE TABLE IF NOT EXISTS "comment"( - post_creation_time TIMESTAMPTZ NOT NULL REFERENCES "post"(creation_time), creation_time TIMESTAMPTZ PRIMARY KEY NOT NULL UNIQUE DEFAULT NOW(), + post_creation_time TIMESTAMPTZ NOT NULL REFERENCES "post"(creation_time), user_id BIGSERIAL NOT NULL REFERENCES "user"(id), comment VARCHAR NOT NULL ); \ No newline at end of file diff --git a/src/feature/comment.rs b/src/feature/comment.rs index 22acc3f..4b43dd8 100644 --- a/src/feature/comment.rs +++ b/src/feature/comment.rs @@ -1,10 +1,53 @@ use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; +use sqlx::{Pool, Postgres}; + +use crate::database::comment; #[derive(Debug, Serialize, Deserialize)] pub struct Comment { - pub post_creation_time: DateTime, pub creation_time: DateTime, + pub post_creation_time: DateTime, pub user_id: i64, pub comment: String, } + +impl Comment { + pub async fn create( + post_creation_time: &DateTime, + user_id: &i64, + comment: &String, + database_connection: &Pool, + ) -> Result { + comment::create(post_creation_time, user_id, comment, database_connection).await + } + + pub async fn read( + creation_time: &DateTime, + database_connection: &Pool, + ) -> Result { + comment::read(creation_time, database_connection).await + } + + pub async fn update( + creation_time: &DateTime, + comment: &String, + database_connection: &Pool, + ) -> Result { + comment::update(creation_time, comment, database_connection).await + } + + pub async fn delete( + creation_time: &DateTime, + database_connection: &Pool, + ) -> Result { + comment::delete(creation_time, database_connection).await + } + + pub async fn read_all_for_post( + post_creation_time: &DateTime, + database_connection: &Pool, + ) -> Result, sqlx::Error> { + comment::read_all_for_post(post_creation_time, database_connection).await + } +} diff --git a/src/routing.rs b/src/routing.rs index ce68fa6..7dc243b 100644 --- a/src/routing.rs +++ b/src/routing.rs @@ -1,3 +1,4 @@ +pub mod comment; pub mod post; pub mod role; pub mod user; @@ -11,13 +12,21 @@ pub async fn route(State(app_state): State) -> Router { Router::new() .route("/", get(alive)) .nest( - "/role", + "/roles", role::route(axum::extract::State(app_state.clone())), ) .nest( - "/user", + "/users", user::route(axum::extract::State(app_state.clone())), ) + .nest( + "/posts", + post::route(axum::extract::State(app_state.clone())), + ) + .nest( + "/comments", + comment::route(axum::extract::State(app_state.clone())), + ) .layer(CorsLayer::permissive()) .with_state(app_state) } diff --git a/src/routing/comment.rs b/src/routing/comment.rs new file mode 100644 index 0000000..2d7826c --- /dev/null +++ b/src/routing/comment.rs @@ -0,0 +1,112 @@ +use axum::{ + extract::{Path, State}, + http::StatusCode, + response::IntoResponse, + routing::{delete, get, patch, post}, + Json, Router, +}; +use chrono::{DateTime, Utc}; +use serde::{Deserialize, Serialize}; + +use crate::{feature::comment::Comment, AppState}; + +#[derive(Debug, Serialize, Deserialize)] +struct CreateComment { + post_creation_time: DateTime, + user_id: i64, + comment: String, +} + +#[derive(Debug, Serialize, Deserialize)] +struct UpdateComment { + creation_time: DateTime, + comment: String, +} + +pub fn route(State(app_state): State) -> Router { + Router::new() + .route("/", post(create)) + .route("/:creation_time", get(read)) + .route("/", patch(update)) + .route("/:creation_time", delete(delete_)) + .route("/posts/:post_creation_time", get(read_all_for_post)) + .with_state(app_state) +} + +async fn create( + State(app_state): State, + Json(create_comment): Json, +) -> impl IntoResponse { + match Comment::create( + &create_comment.post_creation_time, + &create_comment.user_id, + &create_comment.comment, + &app_state.database_connection, + ) + .await + { + Ok(comment) => (StatusCode::CREATED, Json(serde_json::json!(comment))), + Err(err_val) => ( + StatusCode::BAD_REQUEST, + Json(serde_json::json!(err_val.to_string())), + ), + } +} + +async fn read( + State(app_state): State, + Path(creation_time): Path>, +) -> impl IntoResponse { + match Comment::read(&creation_time, &app_state.database_connection).await { + Ok(comment) => (StatusCode::OK, Json(serde_json::json!(comment))), + Err(err_val) => ( + StatusCode::BAD_REQUEST, + Json(serde_json::json!(err_val.to_string())), + ), + } +} + +async fn update( + State(app_state): State, + Json(update_comment): Json, +) -> impl IntoResponse { + match Comment::update( + &update_comment.creation_time, + &update_comment.comment, + &app_state.database_connection, + ) + .await + { + Ok(comment) => (StatusCode::ACCEPTED, Json(serde_json::json!(comment))), + Err(err_val) => ( + StatusCode::BAD_REQUEST, + Json(serde_json::json!(err_val.to_string())), + ), + } +} + +async fn delete_( + State(app_state): State, + Path(creation_time): Path>, +) -> impl IntoResponse { + match Comment::delete(&creation_time, &app_state.database_connection).await { + Ok(comment) => (StatusCode::NO_CONTENT, Json(serde_json::json!(comment))), + Err(err_val) => ( + StatusCode::BAD_REQUEST, + Json(serde_json::json!(err_val.to_string())), + ), + } +} + +async fn read_all_for_post( + State(app_state): State, + Path(post_creation_time): Path>, +) -> impl IntoResponse { + match Comment::read_all_for_post(&post_creation_time, &app_state.database_connection).await { + Ok(comments) => (StatusCode::OK, Json(serde_json::json!(comments))), + Err(err_val) => ( + StatusCode::BAD_REQUEST, + Json(serde_json::json!(err_val.to_string())), + ), + } +}