diff --git a/src/api_data/post_api.rs b/src/api_data/post_api.rs index 37b5dd2..05eecbe 100644 --- a/src/api_data/post_api.rs +++ b/src/api_data/post_api.rs @@ -8,7 +8,7 @@ use crate::api_data::survey_api::SurveyAPI; use crate::data::error::ResultBoxError; use crate::data::post::{Post, PostKind}; use crate::data::user::UserID; -use crate::helpers::{likes_helper, movies_helper, survey_helper}; +use crate::helpers::{likes_helper, movies_helper, survey_helper, posts_helper}; use crate::helpers::likes_helper::LikeType; use crate::utils::user_data_utils::user_data_url; @@ -22,6 +22,7 @@ pub struct PostAPI { post_time: u64, content: Option, visibility_level: String, + user_access: String, kind: String, // File specific @@ -62,6 +63,7 @@ impl PostAPI { post_time: p.time_create, content: p.content.clone(), visibility_level: p.visibility.to_api(), + user_access: posts_helper::get_access_level(&p, user)?.to_api(), kind: p.kind.to_api(), // File specific diff --git a/src/data/post.rs b/src/data/post.rs index 32dca15..1535edc 100644 --- a/src/data/post.rs +++ b/src/data/post.rs @@ -5,6 +5,7 @@ use crate::data::group_id::GroupID; use crate::data::user::UserID; +#[derive(PartialEq)] #[allow(non_camel_case_types)] pub enum PostVisibilityLevel { //Posts that can be seen by anyone @@ -31,6 +32,33 @@ impl PostVisibilityLevel { } } +/// Post access level (for a given user) +#[allow(non_camel_case_types)] +pub enum PostAccessLevel { + //When a user can't access to a post + NO_ACCESS = 0, + + //When a user can see a post and perform basic actions such as liking + BASIC_ACCESS = 1, + + //When a user has intermediate access to the post (delete post) + INTERMEDIATE_ACCESS = 2, + + //When a user has a full access to the post + FULL_ACCESS = 3, +} + +impl PostAccessLevel { + pub fn to_api(&self) -> String { + match self { + PostAccessLevel::NO_ACCESS => "no-access", + PostAccessLevel::BASIC_ACCESS => "basic", + PostAccessLevel::INTERMEDIATE_ACCESS => "intermediate", + PostAccessLevel::FULL_ACCESS => "full", + }.to_string() + } +} + #[allow(non_camel_case_types)] pub enum PostPageKind { PAGE_KIND_USER(UserID), diff --git a/src/data/user.rs b/src/data/user.rs index 9868d8c..884228d 100644 --- a/src/data/user.rs +++ b/src/data/user.rs @@ -26,6 +26,14 @@ impl UserID { pub fn is_valid(&self) -> bool { self.0 > 0 } + + /// Turn this `UserID` object as an instance. An invalid user id will become `None` variant + pub fn as_option(&self) -> Option { + match self.is_valid() { + true => Some(self.clone()), + false => None, + } + } } #[derive(Debug, PartialEq)] diff --git a/src/helpers/groups_helper.rs b/src/helpers/groups_helper.rs index 352e195..782fa55 100644 --- a/src/helpers/groups_helper.rs +++ b/src/helpers/groups_helper.rs @@ -249,6 +249,11 @@ pub fn get_visibility(group_id: &GroupID) -> ResultBoxError ResultBoxError { + Ok(get_visibility(group_id)? == GroupVisibilityLevel::OPEN_GROUP) +} + /// Get the current access level of a user over a group pub fn get_access_level(group_id: &GroupID, user_id: Option) -> ResultBoxError { let membership_level = get_membership_level(group_id, user_id)?; diff --git a/src/helpers/posts_helper.rs b/src/helpers/posts_helper.rs index 85727f4..87e6c00 100644 --- a/src/helpers/posts_helper.rs +++ b/src/helpers/posts_helper.rs @@ -4,10 +4,11 @@ use crate::constants::database_tables_names::POSTS_TABLE; use crate::data::error::{ExecError, ResultBoxError}; -use crate::data::post::{Post, PostFile, PostKind, PostPageKind, PostVisibilityLevel, PostWebLink}; +use crate::data::group_member::GroupMembershipLevel; +use crate::data::post::{Post, PostAccessLevel, PostFile, PostKind, PostPageKind, PostVisibilityLevel, PostWebLink}; 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}; +use crate::helpers::{database, friends_helper, groups_helper, user_helper}; use crate::utils::date_utils::time; impl PostVisibilityLevel { @@ -122,6 +123,60 @@ fn get_user(query: &PostsQuery, target_id: &UserID) -> ResultBoxError> .exec(db_to_post) } +/// Get the access level of a user over a post +pub fn get_access_level(p: &Post, user_id: &Option) -> ResultBoxError { + if user_id == &p.user_id.as_option() { + return Ok(PostAccessLevel::FULL_ACCESS); + } + + match &p.target_page { + // User page + PostPageKind::PAGE_KIND_USER(user_page_id) => { + if &user_page_id.as_option() == user_id { + return Ok(PostAccessLevel::INTERMEDIATE_ACCESS); + } + + return match p.visibility { + PostVisibilityLevel::VISIBILITY_PUBLIC => { + if user_helper::can_see_user_page(user_id.as_ref().unwrap_or(&UserID::invalid()), user_page_id)? { + Ok(PostAccessLevel::BASIC_ACCESS) + } else { + Ok(PostAccessLevel::NO_ACCESS) + } + } + + PostVisibilityLevel::VISIBILITY_FRIENDS => { + if user_id.is_some() && friends_helper::are_friend(user_id.as_ref().unwrap_or(&UserID::invalid()), user_page_id)? { + Ok(PostAccessLevel::BASIC_ACCESS) + } else { + Ok(PostAccessLevel::NO_ACCESS) + } + } + + // No access to posts with restricted visibility + PostVisibilityLevel::VISIBILITY_USER => Ok(PostAccessLevel::NO_ACCESS), + _ => Ok(PostAccessLevel::NO_ACCESS), + }; + } + + // Group page + PostPageKind::PAGE_KIND_GROUP(group_id) => { + let access_level = groups_helper::get_membership_level(group_id, user_id.clone())?; + + // Moderators & administrators + if access_level < GroupMembershipLevel::MEMBER { + Ok(PostAccessLevel::INTERMEDIATE_ACCESS) + } else if access_level == GroupMembershipLevel::MEMBER { + Ok(PostAccessLevel::BASIC_ACCESS) + } else if p.visibility != PostVisibilityLevel::VISIBILITY_PUBLIC || !groups_helper::is_open(group_id)? { + Ok(PostAccessLevel::NO_ACCESS) + } else { + Ok(PostAccessLevel::BASIC_ACCESS) + } + } + } +} + /// Turn a post into a database entry fn db_to_post(res: &database::RowResult) -> ResultBoxError { let user_id = if res.get_u64("ID_amis")? == 0 {