diff --git a/src/api_data/mod.rs b/src/api_data/mod.rs index 5450729..90fd5d9 100644 --- a/src/api_data/mod.rs +++ b/src/api_data/mod.rs @@ -34,4 +34,5 @@ pub mod post_api; pub mod movie_api; pub mod survey_choice_api; pub mod survey_api; -pub mod comment_api; \ No newline at end of file +pub mod comment_api; +pub mod res_create_post; \ No newline at end of file diff --git a/src/api_data/res_create_post.rs b/src/api_data/res_create_post.rs new file mode 100644 index 0000000..3cef76f --- /dev/null +++ b/src/api_data/res_create_post.rs @@ -0,0 +1,21 @@ +//! # Create a post result +//! +//! @author Pierre Hubert +use serde::Serialize; + +#[derive(Serialize)] +#[allow(non_snake_case)] +pub struct ResCreatePost { + success: String, + postID: u64, +} + +impl ResCreatePost { + /// Initialize a new structure + pub fn new(post_id: u64) -> ResCreatePost { + ResCreatePost { + success: "The post has been created!".to_string(), + postID: post_id, + } + } +} diff --git a/src/controllers/posts_controller.rs b/src/controllers/posts_controller.rs index 231c246..cb8c046 100644 --- a/src/controllers/posts_controller.rs +++ b/src/controllers/posts_controller.rs @@ -3,11 +3,15 @@ //! @author Pierre Hubert use crate::api_data::post_api::PostAPI; +use crate::api_data::res_create_post::ResCreatePost; use crate::controllers::routes::RequestResult; +use crate::data::error::ExecError; use crate::data::group::GroupAccessLevel; use crate::data::http_request_handler::HttpRequestHandler; -use crate::data::post::{PostAccessLevel, PostPageKind}; +use crate::data::post::{Post, PostAccessLevel, PostKind, PostPageKind, PostVisibilityLevel}; use crate::helpers::{groups_helper, posts_helper, user_helper}; +use crate::utils::date_utils::time; +use crate::utils::string_utils::check_string_before_insert; /// Get the list of posts of a user pub fn get_list_user(r: &mut HttpRequestHandler) -> RequestResult { @@ -86,7 +90,35 @@ pub fn create_post(r: &mut HttpRequestHandler) -> RequestResult { } }; - println!("Create post on {:?}", target_page); + // Start to create post + let post = Post { + id: 0, + user_id: r.user_id()?, + time_create: time(), + target_page, + content: Some(r.post_string_opt("content", 0, false)?), + visibility: PostVisibilityLevel::VISIBILITY_PUBLIC, + kind: PostKind::POST_KIND_TEXT, + }; - r.success("Continue implementation") + // Handle different post types + match r.post_string("kind")?.as_str() { + + // Text posts + "text" => { + if !check_string_before_insert(post.content.as_ref().unwrap_or(&String::new())) { + r.forbidden("Specified post content is invalid!".to_string())?; + } + } + + _ => { + return r.internal_error(ExecError::boxed_new("Unsupported kind of post!")); + } + } + + // Create the post + let post_id = posts_helper::create(&post)?; + + // TODO : create a notification + r.set_response(ResCreatePost::new(post_id)) } \ No newline at end of file diff --git a/src/helpers/posts_helper.rs b/src/helpers/posts_helper.rs index 6d95a54..5759a27 100644 --- a/src/helpers/posts_helper.rs +++ b/src/helpers/posts_helper.rs @@ -12,7 +12,7 @@ use crate::data::post::{Post, PostAccessLevel, PostFile, PostKind, PostPageKind, use crate::data::post::PostKind::{POST_KIND_COUNTDOWN, POST_KIND_IMAGE, POST_KIND_MOVIE, POST_KIND_PDF, POST_KIND_SURVEY, POST_KIND_WEBLINK, POST_KIND_YOUTUBE}; use crate::data::user::UserID; use crate::helpers::{database, friends_helper, groups_helper, user_helper}; -use crate::utils::date_utils::time; +use crate::utils::date_utils::{mysql_date, time}; impl PostVisibilityLevel { pub fn to_db(&self) -> u32 { @@ -35,6 +35,54 @@ impl PostVisibilityLevel { } } +impl PostKind { + pub fn to_db(&self) -> String { + match self { + PostKind::POST_KIND_TEXT => "texte", + POST_KIND_IMAGE(_) => "image", + POST_KIND_WEBLINK(_) => "webpage_link", + POST_KIND_PDF(_) => "pdf", + POST_KIND_MOVIE(_) => "video", + POST_KIND_COUNTDOWN(_) => "count_down", + POST_KIND_SURVEY => "sondage", + POST_KIND_YOUTUBE(_) => "youtube", + }.to_string() + } +} + +/// Create a new post +pub fn create(p: &Post) -> ResultBoxError { + + // Determine post target + let (user_id, friend_id, group_id) = match &p.target_page { + PostPageKind::PAGE_KIND_USER(user_id) => { + (user_id, Some(&p.user_id), None) + } + PostPageKind::PAGE_KIND_GROUP(group_id) => { + (&p.user_id, None, Some(group_id)) + } + }; + + // Start insert query + let insert_query = database::InsertQuery::new(POSTS_TABLE) + .add_user_id("ID_personne", user_id) + .add_u64("ID_amis", friend_id.map(|f| f.id()).unwrap_or(0)) + .add_u64("group_id", group_id.map(|f| f.id()).unwrap_or(0)) + .add_str("date_envoi", &mysql_date()) + .add_u64("time_insert", p.time_create) + .add_u32("niveau_visibilite", p.visibility.to_db()) + .add_str("type", &p.kind.to_db()) + .add_opt_str("texte", p.content.as_ref()); + + // Execute insertion + let post_id = match insert_query.insert()? { + None => Err(ExecError::new("Insert post query did not return a result!")), + Some(id) => Ok(id), + }?; + + Ok(post_id) +} + pub struct PostsQuery { /// The ID of the user making the request diff --git a/src/utils/date_utils.rs b/src/utils/date_utils.rs index 9b92f40..12abd00 100644 --- a/src/utils/date_utils.rs +++ b/src/utils/date_utils.rs @@ -4,6 +4,8 @@ use std::time::{SystemTime, UNIX_EPOCH}; +use chrono::{TimeZone, Utc}; + /// Get the current time since epoch /// /// ``` @@ -13,4 +15,23 @@ use std::time::{SystemTime, UNIX_EPOCH}; /// ``` pub fn time() -> u64 { SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() +} + + +/// Get Mysql formatted date at specific time +/// +/// ``` +/// use comunic_server::utils::date_utils::time_to_mysql_date; +/// +/// assert_eq!(time_to_mysql_date(1594140466), "2020-07-07 16:47:46"); +/// ``` +pub fn time_to_mysql_date(time: u64) -> String { + let utc = Utc.timestamp(time as i64, 0); + let str = utc.to_rfc3339(); + (&str[..19]).replace("T", " ") +} + +/// Get current Mysql formatted date +pub fn mysql_date() -> String { + time_to_mysql_date(time()) } \ No newline at end of file diff --git a/src/utils/string_utils.rs b/src/utils/string_utils.rs index 3d6a96f..7cc745b 100644 --- a/src/utils/string_utils.rs +++ b/src/utils/string_utils.rs @@ -35,4 +35,19 @@ pub fn remove_html_nodes(input: &str) -> String { /// ``` pub fn check_url(url: &str) -> bool { Uri::from_str(url).is_ok() +} + +/// Check a string before its insertion +/// +/// Legacy function that might be completed / replaced in the future +/// +/// ``` +/// use comunic_server::utils::string_utils::check_string_before_insert; +/// +/// assert_eq!(check_string_before_insert("s"), false); +/// assert_eq!(check_string_before_insert(" s"), false); +/// assert_eq!(check_string_before_insert("Hello world"), true); +/// ``` +pub fn check_string_before_insert(s: &str) -> bool { + s.trim().len() > 3 } \ No newline at end of file