diff --git a/src/controllers/groups_controller.rs b/src/controllers/groups_controller.rs index d5a1377..40a619c 100644 --- a/src/controllers/groups_controller.rs +++ b/src/controllers/groups_controller.rs @@ -8,11 +8,12 @@ use crate::api_data::advanced_group_api::AdvancedGroupApi; use crate::api_data::group_api::GroupApi; use crate::api_data::res_create_group::GroupCreationResult; use crate::controllers::routes::RequestResult; -use crate::data::group::GroupAccessLevel; +use crate::data::group::{Group, GroupAccessLevel, GroupPostsCreationLevel, GroupRegistrationLevel, GroupVisibilityLevel}; use crate::data::group_id::GroupID; use crate::data::http_request_handler::HttpRequestHandler; use crate::data::new_group::NewGroup; use crate::helpers::groups_helper; +use crate::helpers::virtual_directory_helper::VirtualDirType; /// Create a new group pub fn create(r: &mut HttpRequestHandler) -> RequestResult { @@ -86,5 +87,22 @@ pub fn get_settings(r: &mut HttpRequestHandler) -> RequestResult { /// Set new settings to the group pub fn set_settings(r: &mut HttpRequestHandler) -> RequestResult { - r.success("implement me") + let group_id = r.post_group_id_with_access("id", GroupAccessLevel::ADMIN_ACCESS)?; + + let new_settings = Group { + id: group_id.clone(), + name: r.post_string_without_html("name", 3, true)?, + visibility: GroupVisibilityLevel::from_api(&r.post_string("visibility")?), + registration_level: GroupRegistrationLevel::from_api(&r.post_string("registration_level")?), + posts_creation_level: GroupPostsCreationLevel::from_api(&r.post_string("posts_level")?), + logo: None, + virtual_directory: r.post_checked_virtual_directory_opt("virtual_directory", group_id.id(), VirtualDirType::GROUP)?, + time_create: 0, + description: r.post_string_without_html_opt("description", 0)?, + url: r.post_url_opt("url", false)?, + }; + + println!("New settings: {:#?}", new_settings); + + r.success("complete implementation") } \ No newline at end of file diff --git a/src/data/group.rs b/src/data/group.rs index 86b6ab6..35b23f6 100644 --- a/src/data/group.rs +++ b/src/data/group.rs @@ -22,6 +22,15 @@ impl GroupVisibilityLevel { GroupVisibilityLevel::SECRETE_GROUP => "secrete", }.to_string() } + + pub fn from_api(level: &str) -> GroupVisibilityLevel { + match level { + "open" => GroupVisibilityLevel::OPEN_GROUP, + "private" => GroupVisibilityLevel::PRIVATE_GROUP, + "secrete" => GroupVisibilityLevel::SECRETE_GROUP, + _ => GroupVisibilityLevel::SECRETE_GROUP + } + } } #[allow(non_camel_case_types)] @@ -40,6 +49,15 @@ impl GroupRegistrationLevel { GroupRegistrationLevel::CLOSED_REGISTRATION => "closed", }.to_string() } + + pub fn from_api(level: &str) -> GroupRegistrationLevel { + match level { + "open" => GroupRegistrationLevel::OPEN_REGISTRATION, + "moderated" => GroupRegistrationLevel::MODERATED_REGISTRATION, + "closed" => GroupRegistrationLevel::CLOSED_REGISTRATION, + _ => GroupRegistrationLevel::CLOSED_REGISTRATION, + } + } } #[allow(non_camel_case_types)] @@ -59,6 +77,14 @@ impl GroupPostsCreationLevel { GroupPostsCreationLevel::POSTS_LEVEL_ALL_MEMBERS => "members", }.to_string() } + + pub fn from_api(level: &str) -> GroupPostsCreationLevel { + match level { + "members" => GroupPostsCreationLevel::POSTS_LEVEL_ALL_MEMBERS, + "moderators" => GroupPostsCreationLevel::POSTS_LEVEL_MODERATORS, + _ => GroupPostsCreationLevel::POSTS_LEVEL_MODERATORS + } + } } #[allow(non_camel_case_types)] diff --git a/src/data/http_request_handler.rs b/src/data/http_request_handler.rs index d40247b..08c8323 100644 --- a/src/data/http_request_handler.rs +++ b/src/data/http_request_handler.rs @@ -17,8 +17,9 @@ use crate::data::error::{ExecError, ResultBoxError}; use crate::data::group::GroupAccessLevel; use crate::data::group_id::GroupID; use crate::data::user::UserID; -use crate::helpers::{account_helper, api_helper, conversations_helper, groups_helper, user_helper}; -use crate::utils::string_utils::remove_html_nodes; +use crate::helpers::{account_helper, api_helper, conversations_helper, groups_helper, user_helper, virtual_directory_helper}; +use crate::helpers::virtual_directory_helper::VirtualDirType; +use crate::utils::string_utils::{check_url, remove_html_nodes}; use crate::utils::user_data_utils::{generate_new_user_data_file_name, prepare_file_creation, user_data_path}; use crate::utils::virtual_directories_utils::check_virtual_directory; @@ -440,6 +441,15 @@ impl HttpRequestHandler { Ok(remove_html_nodes(self.post_string_opt(name, min_length, required)?.as_str())) } + /// Get an optionnal string included in the request, with HTML codes removed + pub fn post_string_without_html_opt(&mut self, name: &str, min_length: usize) -> ResultBoxError> { + if !self.has_post_parameter(name) { + Ok(None) + } else { + Ok(Some(remove_html_nodes(self.post_string_opt(name, min_length, true)?.as_str()))) + } + } + /// Get & return the ID of the conversation included in the POST request pub fn post_conv_id(&mut self, name: &str) -> ResultBoxError { let conv_id = self.post_u64(name)?; @@ -477,4 +487,34 @@ impl HttpRequestHandler { Ok(group_id) } + + /// Get an URL included in the request + pub fn post_url_opt(&mut self, name: &str, required: bool) -> ResultBoxError> { + let url = self.post_string_opt(name, 0, required)?; + + if url.is_empty() && !required { + Ok(None) + } else { + if !check_url(&url) { + self.bad_request(format!("Invalid url specified in {} !", name))?; + } + + Ok(Some(url)) + } + } + + /// Get an optional virtual directory included in the request + pub fn post_checked_virtual_directory_opt(&mut self, name: &str, target_id: u64, target_type: VirtualDirType) -> ResultBoxError> { + if !self.has_post_parameter(name) { + return Ok(None); + } + + let dir = self.post_virtual_directory(name)?; + + if !virtual_directory_helper::check_availability(&dir, target_id, target_type)? { + self.forbidden("Requested virtual directory is not available!".to_string())?; + } + + Ok(Some(dir)) + } } \ No newline at end of file diff --git a/src/helpers/account_helper.rs b/src/helpers/account_helper.rs index d91f54e..5b322fb 100644 --- a/src/helpers/account_helper.rs +++ b/src/helpers/account_helper.rs @@ -1,10 +1,10 @@ +use crate::constants::database_tables_names::USER_ACCESS_TOKENS_TABLE; use crate::data::api_client::APIClient; use crate::data::error::{ExecError, ResultBoxError}; use crate::data::user::UserID; use crate::data::user_token::UserAccessToken; -use crate::constants::database_tables_names::USER_ACCESS_TOKENS_TABLE; use crate::helpers::{database, user_helper}; -use crate::helpers::database::{QueryInfo, InsertQuery, DeleteQuery}; +use crate::helpers::database::{DeleteQuery, InsertQuery, QueryInfo}; use crate::utils::crypt_utils::{crypt_pass, rand_str}; /// Account helper @@ -78,11 +78,27 @@ pub fn get_user_by_login_token(token: &str, client: &APIClient) -> ResultBoxErro /// Destroy a given user login tokens pub fn destroy_login_tokens(id: &UserID, client: &APIClient) -> ResultBoxError<()> { - database::delete(DeleteQuery::new(USER_ACCESS_TOKENS_TABLE) .cond_u32("service_id", client.id) .cond_user_id("user_id", id) )?; Ok(()) +} + +/// Check out whether a virtual directory is taken by a user or not +pub fn check_user_directory_availability(dir: &str, user_id: Option) -> ResultBoxError { + let found_user = user_helper::find_user_by_virtual_directory(dir); + + match (found_user, user_id) { + + // A user was found, but we did not specify a user + (Ok(_), None) => Ok(false), + + // A user was found, and we specified a user ID, we check if the IDs are the same + (Ok(user), Some(id)) => Ok(user.id == id), + + // No user was found, virtual directory is considered as available + (Err(_), _) => Ok(true) + } } \ No newline at end of file diff --git a/src/helpers/groups_helper.rs b/src/helpers/groups_helper.rs index b588c0e..479f6f9 100644 --- a/src/helpers/groups_helper.rs +++ b/src/helpers/groups_helper.rs @@ -271,6 +271,17 @@ pub fn count_members(group_id: &GroupID) -> ResultBoxError { .exec_count() } +/// Check the availability of a virtual directory for a group +pub fn check_directory_availability(dir: &str, group_id: Option) -> ResultBoxError { + 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) + } +} + /// Turn a database entry into a group struct fn db_to_group(row: &database::RowResult) -> ResultBoxError { let group_id = row.get_group_id("id")?; diff --git a/src/helpers/mod.rs b/src/helpers/mod.rs index 673057f..46126e2 100644 --- a/src/helpers/mod.rs +++ b/src/helpers/mod.rs @@ -8,4 +8,5 @@ pub mod custom_emojies_helper; pub mod background_image_helper; pub mod likes_helper; pub mod groups_helper; -pub mod conversations_helper; \ No newline at end of file +pub mod conversations_helper; +pub mod virtual_directory_helper; \ No newline at end of file diff --git a/src/helpers/virtual_directory_helper.rs b/src/helpers/virtual_directory_helper.rs new file mode 100644 index 0000000..7d00576 --- /dev/null +++ b/src/helpers/virtual_directory_helper.rs @@ -0,0 +1,32 @@ +//! # Virtual directory helper +//! +//! @author Pierre Hubert + +use crate::data::error::ResultBoxError; +use crate::data::group_id::GroupID; +use crate::helpers::{account_helper, groups_helper}; +use crate::utils::virtual_directories_utils::check_virtual_directory; + +pub enum VirtualDirType { + USER, + GROUP, +} + +/// Check the availability of a virtual directory +pub fn check_availability(dir: &str, target_id: u64, target_type: VirtualDirType) -> ResultBoxError { + if !check_virtual_directory(dir) { + return Ok(false); + } + + match target_type { + VirtualDirType::USER => { + // TODO : implement this check + unimplemented!(); + } + VirtualDirType::GROUP => { + Ok( + account_helper::check_user_directory_availability(dir, None)? + && groups_helper::check_directory_availability(dir, Some(GroupID::new(target_id)))?) + } + } +} \ No newline at end of file diff --git a/src/utils/string_utils.rs b/src/utils/string_utils.rs index b500f80..3d6a96f 100644 --- a/src/utils/string_utils.rs +++ b/src/utils/string_utils.rs @@ -2,10 +2,8 @@ //! //! This module contains utilities that can be used accross all the application -use std::convert::TryFrom; use std::str::FromStr; -use actix_web::dev::Url; use actix_web::http::Uri; /// Escape an HTML string