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

362 lines
12 KiB
Rust
Raw Normal View History

2020-06-03 13:28:28 +02:00
//! # Groups helper
//!
//! @author Pierre Hubert
2020-06-24 09:08:31 +02:00
use crate::constants::database_tables_names::{GROUPS_LIST_TABLE, GROUPS_MEMBERS_TABLE};
use crate::data::error::{ExecError, ResultBoxError};
2020-06-24 18:23:44 +02:00
use crate::data::group::{Group, GroupAccessLevel, GroupPostsCreationLevel, GroupRegistrationLevel, GroupVisibilityLevel};
2020-06-23 18:55:23 +02:00
use crate::data::group_id::GroupID;
2020-06-24 09:08:31 +02:00
use crate::data::group_member::{GroupMember, GroupMembershipLevel};
use crate::data::new_group::NewGroup;
2020-06-24 09:21:24 +02:00
use crate::data::user::UserID;
2020-06-03 13:28:28 +02:00
use crate::helpers::database;
2020-06-24 09:08:31 +02:00
use crate::utils::date_utils::time;
2020-06-23 18:55:23 +02:00
impl GroupVisibilityLevel {
pub fn to_db(&self) -> u64 {
match self {
GroupVisibilityLevel::OPEN_GROUP => 0,
GroupVisibilityLevel::PRIVATE_GROUP => 1,
GroupVisibilityLevel::SECRETE_GROUP => 2,
}
}
pub fn from_db(level: u32) -> GroupVisibilityLevel {
match level {
0 => GroupVisibilityLevel::OPEN_GROUP,
1 => GroupVisibilityLevel::PRIVATE_GROUP,
2 => GroupVisibilityLevel::SECRETE_GROUP,
_ => GroupVisibilityLevel::SECRETE_GROUP
}
}
2020-06-23 18:55:23 +02:00
}
2020-06-03 13:28:28 +02:00
2020-06-24 09:08:31 +02:00
impl GroupMembershipLevel {
pub fn to_db(&self) -> u32 {
match self {
GroupMembershipLevel::ADMINISTRATOR => 0,
GroupMembershipLevel::MODERATOR => 1,
GroupMembershipLevel::MEMBER => 2,
GroupMembershipLevel::INVITED => 3,
GroupMembershipLevel::PENDING => 4,
GroupMembershipLevel::VISITOR => 5,
}
}
pub fn from_db(level: u32) -> GroupMembershipLevel {
match level {
0 => GroupMembershipLevel::ADMINISTRATOR,
1 => GroupMembershipLevel::MODERATOR,
2 => GroupMembershipLevel::MEMBER,
3 => GroupMembershipLevel::INVITED,
4 => GroupMembershipLevel::PENDING,
5 => GroupMembershipLevel::VISITOR,
_ => GroupMembershipLevel::VISITOR
}
}
2020-06-24 09:08:31 +02:00
}
2020-06-24 18:23:44 +02:00
impl GroupRegistrationLevel {
pub fn to_db(&self) -> u32 {
match self {
GroupRegistrationLevel::OPEN_REGISTRATION => 0,
GroupRegistrationLevel::MODERATED_REGISTRATION => 1,
GroupRegistrationLevel::CLOSED_REGISTRATION => 2,
}
}
pub fn from_db(level: u32) -> GroupRegistrationLevel {
match level {
0 => GroupRegistrationLevel::OPEN_REGISTRATION,
1 => GroupRegistrationLevel::MODERATED_REGISTRATION,
2 => GroupRegistrationLevel::CLOSED_REGISTRATION,
_ => GroupRegistrationLevel::CLOSED_REGISTRATION,
}
}
}
impl GroupPostsCreationLevel {
pub fn to_db(&self) -> u32 {
match self {
GroupPostsCreationLevel::POSTS_LEVEL_MODERATORS => 0,
GroupPostsCreationLevel::POSTS_LEVEL_ALL_MEMBERS => 1,
}
}
pub fn from_db(level: u32) -> GroupPostsCreationLevel {
match level {
0 => GroupPostsCreationLevel::POSTS_LEVEL_MODERATORS,
1 => GroupPostsCreationLevel::POSTS_LEVEL_ALL_MEMBERS,
_ => GroupPostsCreationLevel::POSTS_LEVEL_ALL_MEMBERS,
}
}
}
2020-06-24 09:08:31 +02:00
/// Create a new group. Returns the ID of the new group
pub fn create(group: &NewGroup) -> ResultBoxError<GroupID> {
// First, create the group
let group_id = database::InsertQuery::new(GROUPS_LIST_TABLE)
.add_u64("time_create", time())
2020-06-25 10:08:34 +02:00
.add_user_id("userid_create", &group.owner_id)
2020-06-24 09:08:31 +02:00
.add_str("name", &group.name)
.insert()?.ok_or(ExecError::new("Could not get group ID!"))?;
let group_id = GroupID::new(group_id);
// Insert first member
insert_member(&GroupMember {
id: 0,
2020-06-25 10:08:34 +02:00
user_id: group.owner_id.clone(),
2020-06-24 09:08:31 +02:00
group_id: group_id.clone(),
time_create: time(),
level: GroupMembershipLevel::ADMINISTRATOR,
following: true,
})?;
Ok(group_id)
}
/// Insert a new group into the database
pub fn insert_member(m: &GroupMember) -> ResultBoxError<()> {
database::InsertQuery::new(GROUPS_MEMBERS_TABLE)
.add_group_id("groups_id", &m.group_id)
2020-06-25 10:08:34 +02:00
.add_user_id("user_id", &m.user_id)
2020-06-24 09:08:31 +02:00
.add_u64("time_create", m.time_create)
.add_u32("level", m.level.to_db())
.insert_drop_result()
}
2020-06-24 09:21:24 +02:00
/// Get the list of groups of a user
pub fn get_list_user(user_id: UserID, only_followed: bool) -> ResultBoxError<Vec<GroupID>> {
let mut query = database::QueryInfo::new(GROUPS_MEMBERS_TABLE)
.add_field("groups_id")
2020-06-25 10:08:34 +02:00
.cond_user_id("user_id", &user_id);
2020-06-24 09:21:24 +02:00
if only_followed {
query = query.cond_legacy_bool("following", true);
}
query.exec(|row| row.get_group_id("groups_id"))
}
2020-06-24 18:26:20 +02:00
/// Get information about a group
2020-06-24 18:23:44 +02:00
pub fn get_info(group_id: &GroupID) -> ResultBoxError<Group> {
database::QueryInfo::new(GROUPS_LIST_TABLE)
.cond_group_id("id", group_id)
.query_row(db_to_group)
}
/// Check out whether a group exists or not
pub fn exists(group_id: &GroupID) -> ResultBoxError<bool> {
database::QueryInfo::new(GROUPS_LIST_TABLE)
.cond_group_id("id", group_id)
.exec_count()
.map(|m| m > 0)
}
2020-06-03 13:28:28 +02:00
/// Find a group id by virtual directory
2020-06-23 19:01:07 +02:00
pub fn find_by_virtual_directory(dir: &str) -> ResultBoxError<GroupID> {
2020-06-03 13:28:28 +02:00
database::QueryInfo::new(GROUPS_LIST_TABLE)
.cond("virtual_directory", dir)
.add_field("id")
2020-06-23 19:01:07 +02:00
.query_row(|res| res.get_group_id("id"))
2020-06-23 18:55:23 +02:00
}
/// Search for group
pub fn search_group(query: &str, limit: u64) -> ResultBoxError<Vec<GroupID>> {
database::QueryInfo::new(GROUPS_LIST_TABLE)
.set_custom_where("name LIKE ? AND visibility != ?")
.add_custom_where_argument_str(format!("%{}%", query).as_str())
.add_custom_where_argument_u64(GroupVisibilityLevel::SECRETE_GROUP.to_db())
.set_limit(limit)
.add_field("id")
.exec(|row| row.get_group_id("id"))
}
2020-06-25 08:16:20 +02:00
/// Get information about the membership of a user over a group
pub fn get_membership(group_id: &GroupID, user_id: Option<UserID>) -> ResultBoxError<GroupMember> {
2020-06-25 08:22:26 +02:00
let default_membership = GroupMember {
id: 0,
2020-06-25 10:08:34 +02:00
user_id: UserID::new(0),
2020-06-25 08:22:26 +02:00
group_id: group_id.clone(),
time_create: 0,
level: GroupMembershipLevel::VISITOR,
following: false,
};
2020-06-25 08:16:20 +02:00
if user_id == None {
2020-06-25 08:22:26 +02:00
return Ok(default_membership);
2020-06-25 08:16:20 +02:00
}
let user_id = user_id.unwrap();
2020-06-25 08:22:26 +02:00
Ok(database::QueryInfo::new(GROUPS_MEMBERS_TABLE)
2020-06-25 08:16:20 +02:00
.cond_group_id("groups_id", group_id)
2020-06-25 10:08:34 +02:00
.cond_user_id("user_id", &user_id)
2020-06-25 08:16:20 +02:00
.query_row(db_to_group_member)
2020-06-25 08:22:26 +02:00
.unwrap_or(default_membership))
2020-06-25 08:16:20 +02:00
}
/// Get the membership level of a user for a group
pub fn get_membership_level(group_id: &GroupID, user_id: Option<UserID>) -> ResultBoxError<GroupMembershipLevel> {
match user_id {
None => Ok(GroupMembershipLevel::VISITOR),
Some(user_id) => {
let level = database::QueryInfo::new(GROUPS_MEMBERS_TABLE)
.cond_group_id("groups_id", group_id)
2020-06-25 10:08:34 +02:00
.cond_user_id("user_id", &user_id)
.add_field("level")
.query_row(|f| f.get_u32("level"))
.unwrap_or(GroupMembershipLevel::VISITOR.to_db());
Ok(GroupMembershipLevel::from_db(level))
}
}
}
/// Get the visibility level of a group
pub fn get_visibility(group_id: &GroupID) -> ResultBoxError<GroupVisibilityLevel> {
let result = database::QueryInfo::new(GROUPS_LIST_TABLE)
.cond_group_id("id", group_id)
.add_field("visibility")
.query_row(|f| f.get_u32("visibility"))?;
Ok(GroupVisibilityLevel::from_db(result))
}
/// Get the current access level of a user over a group
pub fn get_access_level(group_id: &GroupID, user_id: Option<UserID>) -> ResultBoxError<GroupAccessLevel> {
let membership_level = get_membership_level(group_id, user_id)?;
// Check if the user is a confirmed member of group
if membership_level == GroupMembershipLevel::ADMINISTRATOR {
return Ok(GroupAccessLevel::ADMIN_ACCESS);
}
if membership_level == GroupMembershipLevel::MODERATOR {
return Ok(GroupAccessLevel::MODERATOR_ACCESS);
}
if membership_level == GroupMembershipLevel::MEMBER {
return Ok(GroupAccessLevel::MEMBER_ACCESS);
}
let visibility_level = get_visibility(group_id)?;
//If the group is open, everyone has view access
if visibility_level == GroupVisibilityLevel::OPEN_GROUP {
return Ok(GroupAccessLevel::VIEW_ACCESS);
}
//Else, all pending and invited membership get limited access
if membership_level == GroupMembershipLevel::PENDING ||
membership_level == GroupMembershipLevel::INVITED {
return Ok(GroupAccessLevel::LIMITED_ACCESS);
}
//Private groups gives limited access
if visibility_level == GroupVisibilityLevel::PRIVATE_GROUP {
return Ok(GroupAccessLevel::LIMITED_ACCESS);
}
// Else the user can not see the group
// Especially in the case of secrete group
Ok(GroupAccessLevel::NO_ACCESS)
2020-06-24 18:23:44 +02:00
}
/// Count the number of members of a group
pub fn count_members(group_id: &GroupID) -> ResultBoxError<usize> {
database::QueryInfo::new(GROUPS_MEMBERS_TABLE)
.cond_group_id("groups_id", group_id)
2020-06-25 08:16:20 +02:00
.set_custom_where("level <= ?")
.add_custom_where_argument_u32(GroupMembershipLevel::MEMBER.to_db())
2020-06-24 18:23:44 +02:00
.exec_count()
}
2020-06-26 08:58:00 +02:00
/// Check the availability of a virtual directory for a group
pub fn check_directory_availability(dir: &str, group_id: Option<GroupID>) -> ResultBoxError<bool> {
let group = find_by_virtual_directory(dir);
match (group, group_id) {
(Ok(_), None) => Ok(false),
(Ok(g), Some(g2)) => Ok(g == g2),
(Err(_), _) => Ok(true)
}
}
/// Set new settings to the group, except group logo
pub fn set_settings(g: &Group) -> ResultBoxError {
database::UpdateInfo::new(GROUPS_LIST_TABLE)
.cond_group_id("id", &g.id)
// Updates
.set_str("name", &g.name)
.set_u64("visibility", g.visibility.to_db())
.set_u32("registration_level", g.registration_level.to_db())
.set_u32("posts_level", g.posts_creation_level.to_db())
.set_opt_str("virtual_directory", g.virtual_directory.clone())
.set_opt_str("description", g.description.clone())
.set_opt_str("url", g.url.clone())
.exec()
}
2020-06-26 10:35:54 +02:00
/// Set a new path for a logo
pub fn set_logo_path(g: &GroupID, path: Option<String>) -> ResultBoxError {
database::UpdateInfo::new(GROUPS_LIST_TABLE)
.cond_group_id("id", g)
.set_opt_str("path_logo", path)
.exec()
}
/// Delete the logo of a group
pub fn delete_logo(g: &GroupID) -> ResultBoxError {
let group = get_info(g)?;
if !group.has_logo() {
return Ok(());
}
let logo_path = group.get_logo_sys_path();
if logo_path.exists() {
std::fs::remove_file(logo_path)?;
}
set_logo_path(g, None)
}
2020-06-27 07:23:38 +02:00
/// Get the list of memberships of a group
pub fn get_list_members(g: &GroupID) -> ResultBoxError<Vec<GroupMember>> {
database::QueryInfo::new(GROUPS_MEMBERS_TABLE)
.cond_group_id("groups_id", g)
.exec(db_to_group_member)
}
2020-06-25 08:16:20 +02:00
/// Turn a database entry into a group struct
2020-06-24 18:23:44 +02:00
fn db_to_group(row: &database::RowResult) -> ResultBoxError<Group> {
let group_id = row.get_group_id("id")?;
Ok(Group {
id: group_id.clone(),
name: row.get_str("name")?,
visibility: GroupVisibilityLevel::from_db(row.get_u32("visibility")?),
registration_level: GroupRegistrationLevel::from_db(row.get_u32("registration_level")?),
posts_creation_level: GroupPostsCreationLevel::from_db(row.get_u32("posts_level")?),
logo: row.get_optional_str("path_logo")?,
virtual_directory: row.get_optional_str("virtual_directory")?,
time_create: row.get_u64("time_create")?,
description: row.get_optional_str("description")?,
url: row.get_optional_str("url")?,
})
2020-06-25 08:16:20 +02:00
}
/// Turn a database entry into a group member struct
fn db_to_group_member(row: &database::RowResult) -> ResultBoxError<GroupMember> {
Ok(GroupMember {
id: row.get_u64("id")?,
user_id: row.get_user_id("user_id")?,
group_id: row.get_group_id("groups_id")?,
time_create: row.get_u64("time_create")?,
level: GroupMembershipLevel::from_db(row.get_u32("level")?),
following: row.get_legacy_bool("following")?,
})
2020-06-03 13:28:28 +02:00
}