diff --git a/backend/src/api/get/get_post.rs b/backend/src/api/get/get_post.rs index 06663bf..a9c9fec 100644 --- a/backend/src/api/get/get_post.rs +++ b/backend/src/api/get/get_post.rs @@ -5,8 +5,7 @@ use axum::{ http::StatusCode, Json, }; -use chrono::{DateTime, Utc}; -use serde_json::{json, Map, Value}; +use serde_json::{json, Value}; use sqlx::{Error, PgPool, query, Row}; use tracing::error; use uuid::Uuid; @@ -24,101 +23,90 @@ pub async fn get_post( e.to_string() ); return Err(( - StatusCode::INTERNAL_SERVER_ERROR, + StatusCode::BAD_REQUEST, Json::from(json!(("error", e.to_string()))), )); } }; + let post = match query( + r#" +SELECT jsonb_strip_nulls(to_jsonb(t.*)) - 'post_id' AS post +FROM post t +WHERE post_id = $1; +"#, + ) + .bind(post_id) + .fetch_one(&db_connection) + .await + { + Ok(value) => value.get::("post"), + Err(e) => { + error!( + "Database error on Reading `base post information` from table `post`: <{}>: {}", + post_id.to_string(), + e.to_string() + ); + return match e { + Error::RowNotFound => Err(( + StatusCode::BAD_REQUEST, + Json::from(json!({"error": e.to_string()})), + )), + _ => Err(( + StatusCode::INTERNAL_SERVER_ERROR, + Json::from(json!({"error": e.to_string()})), + )), + }; + } + }; + + let tags: Vec<_> = match query("SELECT tag FROM Tag WHERE post_id = $1;") + .bind(post_id) + .fetch_all(&db_connection) + .await + { + Ok(tags) => tags.iter().map(|tag| tag.get::("tag")).collect(), + Err(e) => { + error!("Database query error :{}", e.to_string()); + return Err(( + StatusCode::INTERNAL_SERVER_ERROR, + Json::from(json!({"error": e.to_string()})), + )); + } + }; + let meta = match query( r#" -SELECT * -FROM Post +SELECT jsonb_strip_nulls(to_jsonb(t.*)) - 'post_id' AS meta +FROM meta t WHERE post_id = $1; - "#, + "#, ) .bind(post_id) .fetch_one(&db_connection) .await { - Ok(value) => value, + Ok(value) => value.get::("meta"), Err(e) => { - error!("Database query error on fetching meta: {}", e.to_string()); - return match e { - Error::RowNotFound => Err(( - StatusCode::BAD_REQUEST, - Json::from(json!(format!("{{error: {}}}", e.to_string()))), - )), - _ => Err(( - StatusCode::INTERNAL_SERVER_ERROR, - Json::from(json!(format!("{{error: {}}}", e.to_string()))), - )), - }; - } - }; - - let tags = query( - r#" -SELECT tag FROM Tag WHERE post_id = $1; - "#, - ) - .bind(post_id) - .fetch_all(&db_connection) - .await; - let tags = match tags { - Ok(tags) => tags, - Err(e) => { - error!("Database query error :{}", e.to_string()); + error!( + "Database error on Reading `{}` from table `{}`: <{}>: {}", + "post meta data", + "meta", + post_id.to_string(), + e.to_string() + ); return Err(( StatusCode::INTERNAL_SERVER_ERROR, - Json::from(json!(("error", e.to_string()))), + Json::from(json!({"error": e.to_string()})), )); } }; - let mut res = Map::new(); + // todo: next, prev post - res.insert( - "title".to_string(), - json!(meta.get::("title")), - ); - res.insert( - "sub_title".to_string(), - json!(meta.get::("sub_title")), - ); - res.insert( - "category".to_string(), - json!(meta.get::("category")), - ); - res.insert( - "header_img".to_string(), - json!(meta.get::("header_img")), - ); - res.insert( - "summary".to_string(), - json!(meta.get::("summary")), - ); - res.insert( - "content".to_string(), - json!(meta.get::("content")), - ); - res.insert( - "last_update".to_string(), - json!(meta.get::, &str>("last_update")), - ); - res.insert( - "first_update".to_string(), - json!(meta.get::, &str>("first_update")), - ); + let mut res = post.as_object().unwrap().to_owned(); + res.insert("tags".to_string(), tags.into()); + res.insert("meta".to_string(), meta.into()); - let tags: Vec = tags - .iter() - .map(|tag| { - let tag: String = tag.get("tag"); - tag - }) - .collect(); - res.insert("tags".to_string(), Value::from(tags)); - - Ok(Json::from(Value::from(res))) + Ok(Json::from(json!(res))) } diff --git a/backend/src/api/get/get_post_list.rs b/backend/src/api/get/get_post_list.rs index f4b87a5..74307cb 100644 --- a/backend/src/api/get/get_post_list.rs +++ b/backend/src/api/get/get_post_list.rs @@ -1,5 +1,4 @@ -use axum::{extract::State, http::StatusCode, Json}; -use axum::extract::Query; +use axum::{extract::Query, extract::State, http::StatusCode, Json}; use chrono::{DateTime, Utc}; use futures::future::join_all; use serde::Deserialize; diff --git a/backend/src/api/post/errors/refresh.rs b/backend/src/api/post/errors/refresh.rs index 20a7c70..1c4224a 100644 --- a/backend/src/api/post/errors/refresh.rs +++ b/backend/src/api/post/errors/refresh.rs @@ -46,7 +46,7 @@ pub enum PostIdxError { }, #[error( - "Database error on Reading `{}` to table `{}`: <{}>: {}", + "Database error on Reading `{}` from table `{}`: <{}>: {}", data_desc, db_table, id, diff --git a/backend/src/api/post/utils/build_post_idx.rs b/backend/src/api/post/utils/build_post_idx.rs index d82510a..3779367 100644 --- a/backend/src/api/post/utils/build_post_idx.rs +++ b/backend/src/api/post/utils/build_post_idx.rs @@ -1,5 +1,4 @@ -use base64::Engine; -use base64::engine::general_purpose; +use base64::{Engine, engine::general_purpose}; use chrono::DateTime; use serde_json::{Map, Value}; use sqlx::{PgPool, query, Row}; @@ -218,7 +217,7 @@ pub async fn meta(db_connection: &PgPool, post_id: Uuid, meta: &Value) -> Result loop { if let Err(e) = query( format!( - r" + r#" DO $$ DECLARE @@ -231,11 +230,16 @@ $$ _insert_columns TEXT := 'post_id'; _insert_values TEXT := quote_literal(_post_id); _update_set TEXT := ''; + _blacklist TEXT[] := ARRAY['id', 'tags']; BEGIN SELECT EXISTS(SELECT 1 FROM meta WHERE post_id = _post_id) INTO _exists; FOR _col_name, _col_value IN SELECT key, value FROM jsonb_each_text(_meta_cols) LOOP + IF _col_name = ANY(_blacklist) THEN + CONTINUE; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'meta' @@ -261,7 +265,7 @@ $$ END IF; END; $$ LANGUAGE plpgsql; - ", post_id.to_string().as_str(), meta.to_string() + "#, post_id.to_string().as_str(), meta.to_string() ).as_str() ) .execute(db_connection)