1
0
mirror of https://gitlab.com/comunic/comunicapiv3 synced 2024-11-27 15:59:21 +00:00
comunicapiv3/src/controllers/conversations_controller.rs

336 lines
12 KiB
Rust

//! # Conversations controller
//!
//! @author Pierre Hubert
use std::collections::HashMap;
use crate::api_data::conversation_api::ConversationAPI;
use crate::api_data::conversation_message_api::ConversationMessageAPI;
use crate::api_data::conversations_refresh_api::ConversationRefreshResultAPI;
use crate::api_data::list_unread_conversations_api::UnreadConversationAPI;
use crate::api_data::res_count_unread_conversations::ResultCountUnreadConversations;
use crate::api_data::res_create_conversation::ResCreateConversation;
use crate::api_data::res_find_private_conversations::ResFindPrivateConversations;
use crate::controllers::routes::RequestResult;
use crate::data::http_request_handler::HttpRequestHandler;
use crate::data::new_conversation::NewConversation;
use crate::data::new_conversation_message::NewConversationMessage;
use crate::data::user::UserID;
use crate::helpers::{conversations_helper, user_helper};
use crate::utils::string_utils::remove_html_nodes;
/// Create a new conversation
pub fn create(r: &mut HttpRequestHandler) -> RequestResult {
let name = r.post_string("name")?;
let mut members = r.post_numbers_list("users", 1)?
.iter()
.map(|f| UserID::new(f.clone()))
.collect::<Vec<UserID>>();
// Adapt name
let name = match name.as_str() {
"false" => None,
s => Some(s.to_string())
};
// Check if members exists
for user in &members {
if !user_helper::exists(user)? {
r.not_found(format!("User {} not found!", user.id()))?;
}
}
// Add current user ID if required
let curr_user_id = r.user_id()?;
if !members.contains(&curr_user_id) {
members.push(curr_user_id);
}
let conv = NewConversation {
owner_id: r.user_id()?,
name,
owner_following: r.post_bool("follow")?,
members,
can_everyone_add_members: r.post_bool_opt("canEveryoneAddMembers", true),
};
// Create the conversation
let conv_id = conversations_helper::create(&conv)?;
r.set_response(ResCreateConversation::new(conv_id))
}
/// Get the list of conversations of a user
pub fn get_list(r: &mut HttpRequestHandler) -> RequestResult {
let list = conversations_helper::get_list_user(&r.user_id()?)?;
r.set_response(list.iter().map(|c| ConversationAPI::new(c)).collect::<Vec<ConversationAPI>>())
}
/// Get information about a single conversation
pub fn get_single(r: &mut HttpRequestHandler) -> RequestResult {
let conversation_id = r.post_conv_id("conversationID")?;
let conv = conversations_helper::get_single(conversation_id, &r.user_id()?)?;
r.set_response(ConversationAPI::new(&conv))
}
/// Update the settings of a conversation
pub fn update_settings(r: &mut HttpRequestHandler) -> RequestResult {
let conv_id = r.post_conv_id("conversationID")?;
let is_moderator = conversations_helper::is_user_moderator(&r.user_id()?, conv_id)?;
// Update following state, if required
if r.has_post_parameter("following") {
conversations_helper::set_following(
&r.user_id()?,
conv_id,
r.post_bool("following")?,
)?;
}
// Update members list
if r.has_post_parameter("members") {
let mut members = r.post_numbers_list("members", 1)?
.iter()
.map(|f| UserID::new(f.clone()))
.collect::<Vec<UserID>>();
let can_everyone_add_members = conversations_helper::can_everyone_add_members(conv_id)?;
if !is_moderator && !can_everyone_add_members {
r.forbidden("You can not update the list of members of this conversation!".to_string())?;
}
// Check if the members of the conversation really exists
for member in &members {
if !user_helper::exists(member)? {
r.not_found(format!("User {} not found!", member.id()))?;
}
}
if !members.contains(&r.user_id()?) {
members.push(r.user_id()?);
}
conversations_helper::set_members(conv_id, &members, is_moderator)?;
}
// Change moderator settings
if r.has_post_parameter("name") || r.has_post_parameter("canEveryoneAddMembers") {
if !is_moderator {
r.forbidden("You are not allowed to perform changes on this conversation!".to_string())?;
}
// Change conversation name
if r.has_post_parameter("name") {
let name = r.post_string_opt("name", 0, true)?;
let name = if name.eq("false") || name.is_empty() {
None
} else {
Some(remove_html_nodes(&name))
};
conversations_helper::set_name(conv_id, name)?;
}
// Change "canEveryoneAddMembers" parameter
if r.has_post_parameter("canEveryoneAddMembers") {
conversations_helper::set_can_everyone_add_members(
conv_id, r.post_bool("canEveryoneAddMembers")?)?;
}
}
r.success("Conversation information successfully updated!")
}
/// Find a private conversation
pub fn find_private(r: &mut HttpRequestHandler) -> RequestResult {
let other_user = r.post_user_id("otherUser")?;
let allow_create = r.post_bool_opt("allowCreate", false);
// Query the database
let mut list = conversations_helper::find_private(&r.user_id()?, &other_user)?;
if list.is_empty() {
if !allow_create {
return r.not_found(format!("Not any private conversation was found. The server was not allowed to create a new one..."));
}
let new_conv = NewConversation {
owner_id: r.user_id()?,
name: None,
owner_following: true,
members: vec![r.user_id()?, other_user],
can_everyone_add_members: true,
};
let conv_id = conversations_helper::create(&new_conv)?;
list.push(conv_id);
}
r.set_response(ResFindPrivateConversations::new(list))
}
/// DEPRECATED : refresh current user conversations
///
/// This method was used only by ComunicWeb before the introduction of WebSockets
pub fn refresh_list(r: &mut HttpRequestHandler) -> RequestResult {
let mut list = HashMap::new();
// Check for new conversations
if r.has_post_parameter("newConversations") {
for conv_id in r.post_numbers_list("newConversations", 0)? {
if !conversations_helper::does_user_belongs_to(&r.user_id()?, conv_id)? {
r.forbidden(format!("Your do not belongs to conversation {} !", conv_id))?;
}
let list_conv = conversations_helper::get_last_messages(conv_id , 10)?;
list.insert(conv_id as u64, list_conv);
conversations_helper::mark_user_seen(conv_id as u64, &r.user_id()?)?;
}
}
// Check for refresh of already initialized conversations
if r.has_post_parameter("toRefresh") {
let v: HashMap<String, HashMap<String, serde_json::Value>> =
serde_json::from_str(r.post_string("toRefresh")?.as_str())?;
for (k, v) in v {
// Get conversation ID
if !k.starts_with("conversation-") {
return r.bad_request("Entries of 'toRefresh' must start with 'conversation-'!".to_string());
}
let conv_id = k.replace("conversation-", "").parse::<u64>()?;
// Extract last message id
if !v.contains_key("last_message_id") {
return r.bad_request(format!("Missing 'last_message_id' in conversation {}!", conv_id));
}
let last_message_id = v["last_message_id"].as_u64().unwrap_or(0);
// Check user rights
if !conversations_helper::does_user_belongs_to(&r.user_id()?, conv_id)? {
return r.forbidden(format!("You do not belong to conversation {}!", conv_id));
}
let list_conv = conversations_helper::get_new_messages(conv_id, last_message_id)?;
list.insert(conv_id, list_conv);
conversations_helper::mark_user_seen(conv_id as u64, &r.user_id()?)?;
}
}
r.set_response(ConversationRefreshResultAPI::new(list))
}
/// Refresh a single conversation
pub fn refresh_single(r: &mut HttpRequestHandler) -> RequestResult {
let conv_id = r.post_conv_id("conversationID")?;
let last_message_id = r.post_u64("last_message_id")?;
let messages = match last_message_id {
// Get latest messages of the conversation
0 => conversations_helper::get_last_messages(conv_id, 10)?,
// Get new messages
_ => conversations_helper::get_new_messages(conv_id, last_message_id)?,
};
conversations_helper::mark_user_seen(conv_id, &r.user_id()?)?;
r.set_response(ConversationMessageAPI::for_list(&messages))
}
/// Get older messages of a conversation
pub fn get_older_messages(r: &mut HttpRequestHandler) -> RequestResult {
let conv_id = r.post_conv_id("conversationID")?;
let max_id = r.post_u64("oldest_message_id")? - 1;
// Determine limit
let limit = r.post_u64("limit")?;
let limit = match limit {
0 => 1,
1..=60 => limit,
_ => 60
};
let messages = conversations_helper::get_older_messages(conv_id, max_id, limit)?;
r.set_response(ConversationMessageAPI::for_list(&messages))
}
/// Send a new message
pub fn send_message(r: &mut HttpRequestHandler) -> RequestResult {
let conv_id = r.post_conv_id("conversationID")?;
let message = r.post_string_without_html("message", 0, false)?;
// Get image
let image_path = match r.has_file("image") {
false => None,
true => Some(r.save_post_image("image", "conversations", 1200, 1200)?)
};
if image_path == None && message.len() < 3 {
r.bad_request("Message is empty!".to_string())?;
}
conversations_helper::send_message(&NewConversationMessage {
user_id: r.user_id()?,
conv_id,
message,
image_path,
})?;
r.success("Conversation message was successfully sent!")
}
/// Count the number of unread conversation of the user
pub fn count_unread(r: &mut HttpRequestHandler) -> RequestResult {
let num = conversations_helper::count_unread_for_user(&r.user_id()?)?;
r.set_response(ResultCountUnreadConversations::new(num))
}
/// Get the list of unread conversations of a user
pub fn list_unread(r: &mut HttpRequestHandler) -> RequestResult {
let list = conversations_helper::get_list_unread(&r.user_id()?)?;
r.set_response(UnreadConversationAPI::for_list(&list))
}
/// Delete a conversation
pub fn delete_conversation(r: &mut HttpRequestHandler) -> RequestResult {
let conv_id = r.post_conv_id("conversationID")?;
conversations_helper::remove_user_from_conversation(&r.user_id()?, conv_id)?;
r.success("The conversation has been deleted")
}
/// Update a single conversation message
pub fn update_message(r: &mut HttpRequestHandler) -> RequestResult {
let msg_id = r.post_u64("messageID")?;
let new_content = r.post_string_opt("content", 3, true)?;
if !conversations_helper::is_message_owner(&r.user_id()?, msg_id)? {
r.forbidden("You are not the owner of this message!".to_string())?;
}
conversations_helper::update_message_content(msg_id, &new_content)?;
r.success("Conversation message content successfully updated")
}
/// Delete a conversation message
pub fn delete_message(r: &mut HttpRequestHandler) -> RequestResult {
let msg_id = r.post_u64("messageID")?;
if !conversations_helper::is_message_owner(&r.user_id()?, msg_id)? {
r.forbidden("You are not the owner of this message!".to_string())?;
}
conversations_helper::delete_message_by_id(msg_id)?;
r.success("The message has been successfully deleted!")
}