1
0
mirror of https://gitlab.com/comunic/comunicapiv3 synced 2025-02-07 09:47:04 +00:00
comunicapiv3/src/helpers/posts_helper.rs

361 lines
12 KiB
Rust
Raw Normal View History

2020-07-02 18:19:04 +02:00
//! # Posts helper
//!
//! @author Pierre Hubert
2020-07-06 09:20:31 +02:00
2020-07-02 18:19:04 +02:00
use crate::constants::database_tables_names::POSTS_TABLE;
2020-07-03 10:06:24 +02:00
use crate::data::error::{ExecError, ResultBoxError};
2020-07-06 09:20:31 +02:00
use crate::data::group_id::GroupID;
2020-07-04 18:34:21 +02:00
use crate::data::group_member::GroupMembershipLevel;
use crate::data::post::{Post, PostAccessLevel, PostFile, PostKind, PostPageKind, PostVisibilityLevel, PostWebLink};
2020-07-04 17:06:06 +02:00
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};
2020-07-02 18:19:04 +02:00
use crate::data::user::UserID;
2020-07-04 18:34:21 +02:00
use crate::helpers::{database, friends_helper, groups_helper, user_helper};
2020-07-02 19:05:05 +02:00
use crate::utils::date_utils::time;
2020-07-02 18:19:04 +02:00
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,
}
}
2020-07-02 19:05:05 +02:00
pub fn from_db(val: u32) -> PostVisibilityLevel {
match val {
1 => PostVisibilityLevel::VISIBILITY_PUBLIC,
2 => PostVisibilityLevel::VISIBILITY_FRIENDS,
3 => PostVisibilityLevel::VISIBILITY_USER,
50 => PostVisibilityLevel::VISIBILITY_GROUP_MEMBERS,
_ => PostVisibilityLevel::VISIBILITY_PUBLIC,
}
}
2020-07-02 18:19:04 +02:00
}
pub struct PostsQuery {
/// The ID of the user making the request
user_id: Option<UserID>,
/// 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<UserID>) -> 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<Vec<Post>> {
get_user(&self, user_id)
}
2020-07-06 09:20:31 +02:00
/// Get the posts of a group
pub fn get_group(self, group_id: &GroupID) -> ResultBoxError<Vec<Post>> {
get_group(&self, group_id)
}
2020-07-06 10:01:54 +02:00
/// Get the latest posts for a user
pub fn get_latest(self, include_groups_posts: bool) -> ResultBoxError<Vec<Post>> {
get_latest(&self, include_groups_posts)
}
2020-07-02 18:19:04 +02:00
}
/// Get the posts of `target_id`
fn get_user(query: &PostsQuery, target_id: &UserID) -> ResultBoxError<Vec<Post>> {
// 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)
}
2020-07-06 09:20:31 +02:00
/// Get the list of posts of a group
fn get_group(query: &PostsQuery, group_id: &GroupID) -> ResultBoxError<Vec<Post>> {
let membership = groups_helper::get_membership_level(group_id, query.user_id.clone())?;
let can_see_all_posts = membership <= GroupMembershipLevel::MEMBER;
let visibility_level = match can_see_all_posts {
true => PostVisibilityLevel::VISIBILITY_GROUP_MEMBERS,
false => PostVisibilityLevel::VISIBILITY_FRIENDS
};
// Prepare request
let mut db_query = database::QueryInfo::new(POSTS_TABLE);
let mut custom_where = String::new();
// =============== VISIBILITY CONDITION ================
custom_where.push_str("(niveau_visibilite <= ?)");
db_query = db_query.add_custom_where_argument_u32(visibility_level.to_db());
// ============== /VISIBILITY CONDITION ================
// ================== START POINT ======================
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 =====================
db_query
.cond_group_id("group_id", group_id)
.set_custom_where(&custom_where)
.set_order("ID DESC")
.set_limit(query.limit)
.exec(db_to_post)
}
2020-07-06 10:01:54 +02:00
/// Get the latest posts of a user
pub fn get_latest(query: &PostsQuery, include_group_posts: bool) -> ResultBoxError<Vec<Post>> {
let user_id = query.user_id.as_ref().ok_or(ExecError::new("Can not get latest posts of no user!"))?;
let visibility_level = PostVisibilityLevel::VISIBILITY_FRIENDS;
// Get the list of friends of the user
let friends_list = friends_helper::GetFriendsQuery::new(user_id)
.set_only_accepted(true)
.set_only_following(true)
.exec()?;
// Prepare the request
let mut db_query = database::QueryInfo::new(POSTS_TABLE);
let mut custom_where = String::new();
// ================== MEMBERSHIP CONDITION ======================
custom_where.push_str("(");
// ========== FRIENDS POSTS ===========
custom_where.push_str("(group_id = 0 AND niveau_visibilite <= ? AND (ID_personne = ?");
db_query = db_query.add_custom_where_argument_u32(visibility_level.to_db());
db_query = db_query.add_custom_where_argument_user_id(&user_id);
for f in &friends_list {
custom_where.push_str(" OR ID_personne = ?");
db_query = db_query.add_custom_where_argument_user_id(&f.friend_id);
};
custom_where.push_str("))");
// ========== /FRIENDS POSTS ==========
// =========== GROUPS POSTS ===========
if include_group_posts {
let groups = groups_helper::get_list_user(user_id, true)?;
for g in &groups {
custom_where.push_str(" OR group_id = ?");
db_query = db_query.add_custom_where_argument_group_id(g);
};
}
// ========== /GROUPS POSTS ===========
custom_where.push_str(")");
// ================== /MEMBERSHIP CONDITION =====================
// ======================= START POINT ==========================
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 ==========================
db_query
.set_custom_where(&custom_where)
.set_order("ID DESC")
.set_limit(query.limit)
.exec(db_to_post)
}
/// Get information about a single post
pub fn get_single(post_id: u64) -> ResultBoxError<Post> {
database::QueryInfo::new(POSTS_TABLE)
.cond_u64("ID", post_id)
.query_row(db_to_post)
}
2020-07-04 18:34:21 +02:00
/// Get the access level of a user over a post
pub fn get_access_level(p: &Post, user_id: &Option<UserID>) -> ResultBoxError<PostAccessLevel> {
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)
}
}
}
}
2020-07-05 19:32:28 +02:00
/// Check out whether it is possible to create comments on a post or not
pub fn allow_comments_on_post(p: &Post) -> ResultBoxError<bool> {
Ok(
!p.is_on_user_page() ||
user_helper::allow_comments(p.user_page_id().unwrap_or(&UserID::invalid()))?)
}
2020-07-02 18:19:04 +02:00
/// Turn a post into a database entry
fn db_to_post(res: &database::RowResult) -> ResultBoxError<Post> {
2020-07-02 19:05:05 +02:00
let user_id = if res.get_u64("ID_amis")? == 0 {
res.get_user_id("ID_personne")
} else {
res.get_user_id("ID_amis")
}?;
let target_page = if res.get_u64("group_id")? == 0 {
PostPageKind::PAGE_KIND_USER(res.get_user_id("ID_personne")?)
} else {
PostPageKind::PAGE_KIND_GROUP(res.get_group_id("group_id")?)
};
2020-07-03 10:06:24 +02:00
let file = match res.get_optional_str("path")? {
None => None,
Some(path) => Some(PostFile {
path,
size: res.get_usize("size").unwrap_or(0),
file_type: res.get_optional_str("file_type")?,
}),
};
let mut post = Post {
2020-07-02 19:05:05 +02:00
// General information
id: res.get_u64("ID")?,
user_id: user_id.clone(),
time_create: res.get_u64("time_insert").unwrap_or(time()),
target_page,
content: res.get_optional_str("texte")?,
visibility: PostVisibilityLevel::from_db(res.get_u32("niveau_visibilite")?),
2020-07-03 10:06:24 +02:00
kind: PostKind::POST_KIND_TEXT,
};
let file = file.ok_or(ExecError::new("A file is required with this post type!"));
match res.get_str("type")?.as_str() {
"image" => post.kind = POST_KIND_IMAGE(file?),
2020-07-03 10:18:26 +02:00
"webpage_link" => post.kind = POST_KIND_WEBLINK(PostWebLink {
url: res.get_str("url_page")?,
title: res.get_optional_str("titre_page")?,
description: res.get_optional_str("description_page")?,
image: res.get_optional_str("image_page")?,
}),
2020-07-03 10:27:09 +02:00
"pdf" => post.kind = POST_KIND_PDF(file?),
2020-07-03 16:41:14 +02:00
"video" => post.kind = POST_KIND_MOVIE(res.get_u64("idvideo")?),
2020-07-03 17:13:02 +02:00
"count_down" => post.kind = POST_KIND_COUNTDOWN(res.get_u64("time_end").unwrap_or(0)),
2020-07-04 16:44:42 +02:00
"sondage" => post.kind = POST_KIND_SURVEY,
2020-07-04 17:06:06 +02:00
"youtube" => post.kind = POST_KIND_YOUTUBE(res.get_str("path")?),
2020-07-03 10:06:24 +02:00
_ => {}
}
Ok(post)
2020-07-02 18:19:04 +02:00
}