From 4ab5b9d3e30be43a9261853339e1b91bcb52c0a2 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Thu, 2 Jul 2020 18:19:04 +0200 Subject: [PATCH] Start to implement post logic --- src/api_data/mod.rs | 3 +- src/api_data/post_api.rs | 26 ++++++ src/constants.rs | 3 + src/controllers/mod.rs | 1 + src/controllers/posts_controller.rs | 24 ++++++ src/controllers/routes.rs | 5 +- src/data/mod.rs | 3 +- src/data/post.rs | 22 ++++++ src/helpers/database.rs | 6 ++ src/helpers/mod.rs | 1 + src/helpers/posts_helper.rs | 118 ++++++++++++++++++++++++++++ 11 files changed, 209 insertions(+), 3 deletions(-) create mode 100644 src/api_data/post_api.rs create mode 100644 src/controllers/posts_controller.rs create mode 100644 src/data/post.rs create mode 100644 src/helpers/posts_helper.rs diff --git a/src/api_data/mod.rs b/src/api_data/mod.rs index 5e293b1..270ce97 100644 --- a/src/api_data/mod.rs +++ b/src/api_data/mod.rs @@ -29,4 +29,5 @@ pub mod advanced_group_api; pub mod res_change_group_logo; pub mod group_member_api; pub mod friend_api; -pub mod friendship_status_api; \ No newline at end of file +pub mod friendship_status_api; +pub mod post_api; \ No newline at end of file diff --git a/src/api_data/post_api.rs b/src/api_data/post_api.rs new file mode 100644 index 0000000..ce25381 --- /dev/null +++ b/src/api_data/post_api.rs @@ -0,0 +1,26 @@ +//! # Post API entry +//! +//! @author Pierre Hubert +use serde::Serialize; + +use crate::data::post::Post; + +#[derive(Serialize)] +#[allow(non_snake_case)] +pub struct PostAPI { + ID: u64, +} + +impl PostAPI { + /// Turn a `Post` entry into an API entry + pub fn new(p: &Post) -> PostAPI { + PostAPI { + ID: p.id + } + } + + /// Turn a list of posts into an API entry + pub fn for_list(l: &Vec) -> Vec { + l.iter().map(Self::new).collect() + } +} \ No newline at end of file diff --git a/src/constants.rs b/src/constants.rs index 29219f5..a9a6675 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -34,6 +34,9 @@ pub mod database_tables_names { pub const CONV_LIST_TABLE: &str = "comunic_conversations_list"; pub const CONV_USERS_TABLE: &str = "comunic_conversations_users"; pub const CONV_MESSAGES_TABLE: &str = "comunic_conversations_messages"; + + /// Posts table + pub const POSTS_TABLE: &str = "texte"; } /// The account image to show for user who do not have any diff --git a/src/controllers/mod.rs b/src/controllers/mod.rs index aba3353..973489f 100644 --- a/src/controllers/mod.rs +++ b/src/controllers/mod.rs @@ -8,4 +8,5 @@ pub mod friends_controller; pub mod conversations_controller; pub mod search_controller; pub mod groups_controller; +pub mod posts_controller; pub mod virtual_directory_controller; \ No newline at end of file diff --git a/src/controllers/posts_controller.rs b/src/controllers/posts_controller.rs new file mode 100644 index 0000000..5e891e6 --- /dev/null +++ b/src/controllers/posts_controller.rs @@ -0,0 +1,24 @@ +//! # Posts controller +//! +//! @author Pierre Hubert + +use crate::api_data::post_api::PostAPI; +use crate::controllers::routes::RequestResult; +use crate::data::http_request_handler::HttpRequestHandler; +use crate::helpers::{posts_helper, user_helper}; + +/// Get the list of posts of a user +pub fn get_list_user(r: &mut HttpRequestHandler) -> RequestResult { + let user_id = r.post_user_id("userID")?; + let start_from = r.post_u64_opt("startFrom", 0)?; + + if !user_helper::can_see_user_page(r.user_id_ref()?, &user_id)? { + r.forbidden("You are not allowed to access this user posts !".to_string())?; + } + + let posts = posts_helper::PostsQuery::new(r.user_id_opt()) + .set_start_from(start_from) + .get_user(&user_id)?; + + r.set_response(PostAPI::for_list(&posts)) +} \ No newline at end of file diff --git a/src/controllers/routes.rs b/src/controllers/routes.rs index a0fb629..831682a 100644 --- a/src/controllers/routes.rs +++ b/src/controllers/routes.rs @@ -1,6 +1,6 @@ use std::error::Error; -use crate::controllers::{account_controller, conversations_controller, friends_controller, groups_controller, search_controller, server_controller, user_controller, virtual_directory_controller}; +use crate::controllers::{account_controller, conversations_controller, friends_controller, groups_controller, search_controller, server_controller, user_controller, virtual_directory_controller, posts_controller}; use crate::controllers::routes::Method::{GET, POST}; use crate::data::http_request_handler::HttpRequestHandler; @@ -196,6 +196,9 @@ pub fn get_routes() -> Vec { Route::post("/groups/delete", Box::new(groups_controller::delete_group)), + // Posts controller + Route::post("/posts/get_user", Box::new(posts_controller::get_list_user)), + // Virtual directory controller Route::post("/user/findbyfolder", Box::new(virtual_directory_controller::find_user)), diff --git a/src/data/mod.rs b/src/data/mod.rs index fdc754d..baec52d 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -18,4 +18,5 @@ pub mod new_group; pub mod group_member; pub mod global_search_result; pub mod friend; -pub mod friendship_status; \ No newline at end of file +pub mod friendship_status; +pub mod post; \ No newline at end of file diff --git a/src/data/post.rs b/src/data/post.rs new file mode 100644 index 0000000..7609a89 --- /dev/null +++ b/src/data/post.rs @@ -0,0 +1,22 @@ +//! # Post +//! +//! @author Pierre Hubert + +#[allow(non_camel_case_types)] +pub enum PostVisibilityLevel { + //Posts that can be seen by anyone + VISIBILITY_PUBLIC = 1, + + //Posts that can be seen by the friends of the user + VISIBILITY_FRIENDS = 2, + + //Posts that can be seen by the user only + VISIBILITY_USER = 3, + + //Posts that can be seen by the members of a group (same as friends) + VISIBILITY_GROUP_MEMBERS = 50, +} + +pub struct Post { + pub id: u64 +} \ No newline at end of file diff --git a/src/helpers/database.rs b/src/helpers/database.rs index 8517fca..a9c0340 100644 --- a/src/helpers/database.rs +++ b/src/helpers/database.rs @@ -176,6 +176,12 @@ impl QueryInfo { self } + /// Add a custom User ID WHERE value + pub fn add_custom_where_argument_user_id(mut self, val: &UserID) -> QueryInfo { + self.custom_where_ars.push(mysql::Value::UInt(val.id())); + self + } + /// Add a custom string WHERE value pub fn add_custom_where_argument_str(mut self, val: &str) -> QueryInfo { self.custom_where_ars.push(mysql::Value::from(val)); diff --git a/src/helpers/mod.rs b/src/helpers/mod.rs index 46126e2..09cb44a 100644 --- a/src/helpers/mod.rs +++ b/src/helpers/mod.rs @@ -8,5 +8,6 @@ pub mod custom_emojies_helper; pub mod background_image_helper; pub mod likes_helper; pub mod groups_helper; +pub mod posts_helper; pub mod conversations_helper; pub mod virtual_directory_helper; \ No newline at end of file diff --git a/src/helpers/posts_helper.rs b/src/helpers/posts_helper.rs new file mode 100644 index 0000000..1108a9b --- /dev/null +++ b/src/helpers/posts_helper.rs @@ -0,0 +1,118 @@ +//! # Posts helper +//! +//! @author Pierre Hubert + +use crate::constants::database_tables_names::POSTS_TABLE; +use crate::data::error::ResultBoxError; +use crate::data::post::{Post, PostVisibilityLevel}; +use crate::data::user::UserID; +use crate::helpers::{database, friends_helper}; + +impl PostVisibilityLevel { + pub fn to_db(&self) -> u32 { + match self { + PostVisibilityLevel::VISIBILITY_PUBLIC => 1, + PostVisibilityLevel::VISIBILITY_FRIENDS => 2, + PostVisibilityLevel::VISIBILITY_USER => 3, + PostVisibilityLevel::VISIBILITY_GROUP_MEMBERS => 50, + } + } +} + + +pub struct PostsQuery { + /// The ID of the user making the request + user_id: Option, + + /// Maximum number of posts to get + limit: u64, + + /// Starting post + start_from: u64, +} + +impl PostsQuery { + /// Construct a new request + pub fn new(user_id: Option) -> PostsQuery { + PostsQuery { + user_id, + limit: 10, + start_from: 0, + } + } + + /// Start starting point + pub fn set_start_from(mut self, start_from: u64) -> PostsQuery { + self.start_from = start_from; + self + } + + /// Set the limit for this query + pub fn set_limit(mut self, limit: u64) -> PostsQuery { + self.limit = limit; + self + } + + /// Get the posts of a user + pub fn get_user(self, user_id: &UserID) -> ResultBoxError> { + get_user(&self, user_id) + } +} + +/// Get the posts of `target_id` +fn get_user(query: &PostsQuery, target_id: &UserID) -> ResultBoxError> { + // Max user visibility + let mut level = PostVisibilityLevel::VISIBILITY_PUBLIC; + + if let Some(user_id) = &query.user_id { + if user_id == target_id { + level = PostVisibilityLevel::VISIBILITY_USER; + } else if friends_helper::are_friend(user_id, target_id)? { + level = PostVisibilityLevel::VISIBILITY_FRIENDS; + } + } + + // Start request + let mut db_query = database::QueryInfo::new(POSTS_TABLE); + let mut custom_where = String::new(); + + // Preprocess conditions + + // ============= PERMISSION CONDITIONS ================= + custom_where.push_str("((niveau_visibilite <= ?) "); + db_query = db_query.add_custom_where_argument_u32(level.to_db()); + + // Add user posts (if signed in) + if let Some(user_id) = &query.user_id { + custom_where.push_str(" OR (ID_amis = ?) "); + db_query = db_query.add_custom_where_argument_user_id(user_id); + } + + custom_where.push_str(")"); + // ============= /PERMISSION CONDITIONS ================= + + + // ============== START POINT CONDITION ================= + if query.start_from != 0 { + custom_where.push_str(" AND ID <= ?"); + db_query = db_query.add_custom_where_argument_u64(query.start_from); + } + // ============== /START POINT CONDITION ================ + + + // Perform the request + db_query + .cond_user_id("ID_personne", target_id) + .cond_u64("group_id", 0) + .set_custom_where(&custom_where) + .set_order("ID DESC") + .set_limit(query.limit) + .exec(db_to_post) +} + +/// Turn a post into a database entry +fn db_to_post(res: &database::RowResult) -> ResultBoxError { + Ok(Post { + id: res.get_u64("ID")? + }) +} \ No newline at end of file