diff --git a/src/controllers/settings_controller.rs b/src/controllers/settings_controller.rs index d9b3d31..393ed72 100644 --- a/src/controllers/settings_controller.rs +++ b/src/controllers/settings_controller.rs @@ -8,12 +8,13 @@ use crate::api_data::general_settings_api::GeneralSettingsAPI; use crate::api_data::language_settings_api::LanguageSettingsAPI; use crate::api_data::res_create_custom_emoji::ResCreateCustomEmoji; use crate::api_data::security_settings_api::SecuritySettingsAPI; -use crate::constants::SUPPORTED_LANGUAGES; +use crate::constants::{conservation_policy, SUPPORTED_LANGUAGES}; use crate::data::base_request_handler::BaseRequestHandler; use crate::data::general_settings::GeneralSettings; use crate::data::http_request_handler::HttpRequestHandler; use crate::data::lang_settings::LangSettings; use crate::data::new_custom_emoji::NewCustomEmoji; +use crate::data::new_data_conservation_policy::NewDataConservationPolicy; use crate::data::security_settings::{SecurityQuestion, SecuritySettings}; use crate::data::user::{AccountImageVisibility, UserPageStatus}; use crate::helpers::{account_helper, custom_emojies_helper, user_helper}; @@ -210,4 +211,47 @@ pub fn get_data_conservation_policy(r: &mut HttpRequestHandler) -> RequestResult let user = user_helper::find_user_by_id(r.user_id_ref()?)?; r.set_response(DataConservationSettingsAPI::new(&user)) +} + +/// Set data conservation policy +pub fn set_data_conservation_policy(r: &mut HttpRequestHandler) -> RequestResult { + let policy = NewDataConservationPolicy { + user_id: r.user_id()?, + delete_account_after: r.post_positive_u64_opt("inactive_account_lifetime")?, + delete_notifications_after: r.post_positive_u64_opt("notification_lifetime")?, + delete_comments_after: r.post_positive_u64_opt("comments_lifetime")?, + delete_posts_after: r.post_positive_u64_opt("posts_lifetime")?, + delete_conversation_messages_after: r.post_positive_u64_opt("conversation_messages_lifetime")?, + delete_likes_after: r.post_positive_u64_opt("likes_lifetime")?, + }; + + + // Check policy is respected + if policy.delete_account_after.map(|f| f < conservation_policy::MIN_INACTIVE_ACCOUNT_LIFETIME.as_secs()) == Some(true) { + r.bad_request("Invalid lifetime for inactive account !".to_string())?; + } + + if policy.delete_notifications_after.map(|f| f < conservation_policy::MIN_NOTIFICATIONS_LIFETIME.as_secs()) == Some(true) { + r.bad_request("Invalid lifetime for notifications !".to_string())?; + } + + if policy.delete_comments_after.map(|f| f < conservation_policy::MIN_COMMENTS_LIFETIME.as_secs()) == Some(true) { + r.bad_request("Invalid lifetime for comments !".to_string())?; + } + + if policy.delete_posts_after.map(|f| f < conservation_policy::MIN_POSTS_LIFETIME.as_secs()) == Some(true) { + r.bad_request("Invalid lifetime for posts !".to_string())?; + } + + if policy.delete_conversation_messages_after.map(|f| f < conservation_policy::MIN_CONVERSATION_MESSAGES_LIFETIME.as_secs()) == Some(true) { + r.bad_request("Invalid lifetime for conversation messages !".to_string())?; + } + + if policy.delete_likes_after.map(|f| f < conservation_policy::MIN_LIKES_LIFETIME.as_secs()) == Some(true) { + r.bad_request("Invalid lifetime for likes !".to_string())?; + } + + account_helper::set_data_conservation_policy(policy)?; + + r.success("Successfully updated data conservation policy!") } \ No newline at end of file diff --git a/src/data/base_request_handler.rs b/src/data/base_request_handler.rs index 64626fe..daa0f4d 100644 --- a/src/data/base_request_handler.rs +++ b/src/data/base_request_handler.rs @@ -356,6 +356,13 @@ pub trait BaseRequestHandler { Ok(self.post_string(name)?.parse::()?) } + fn post_positive_u64_opt(&mut self, name: &str) -> Res> { + match self.post_u64(name)? { + 0 => Ok(None), + val => Ok(Some(val)) + } + } + /// Get a boolean included in a POST request fn post_bool(&mut self, name: &str) -> ResultBoxError { Ok(self.post_string(name)?.eq("true")) diff --git a/src/data/mod.rs b/src/data/mod.rs index f1dc5de..f1b4a2e 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -34,6 +34,7 @@ pub mod survey_response; pub mod general_settings; pub mod lang_settings; pub mod security_settings; +pub mod new_data_conservation_policy; pub mod new_custom_emoji; pub mod user_ws_message; pub mod user_ws_connection; diff --git a/src/data/new_data_conservation_policy.rs b/src/data/new_data_conservation_policy.rs new file mode 100644 index 0000000..e3687da --- /dev/null +++ b/src/data/new_data_conservation_policy.rs @@ -0,0 +1,15 @@ +//! # New data conservation policy settings +//! +//! @author Pierre Hubert + +use crate::data::user::UserID; + +pub struct NewDataConservationPolicy { + pub user_id: UserID, + pub delete_account_after: Option, + pub delete_notifications_after: Option, + pub delete_comments_after: Option, + pub delete_posts_after: Option, + pub delete_conversation_messages_after: Option, + pub delete_likes_after: Option, +} \ No newline at end of file diff --git a/src/helpers/account_helper.rs b/src/helpers/account_helper.rs index a61cf55..7a06098 100644 --- a/src/helpers/account_helper.rs +++ b/src/helpers/account_helper.rs @@ -9,6 +9,7 @@ use crate::data::error::{ExecError, Res, ResultBoxError}; use crate::data::general_settings::GeneralSettings; use crate::data::lang_settings::LangSettings; use crate::data::new_account::NewAccount; +use crate::data::new_data_conservation_policy::NewDataConservationPolicy; use crate::data::security_settings::SecuritySettings; use crate::data::user::{AccountImageVisibility, User, UserID, UserPageStatus}; use crate::data::user_token::UserAccessToken; @@ -280,6 +281,19 @@ pub fn set_account_image_visibility(user_id: &UserID, level: AccountImageVisibil .exec() } +/// Set data conservation policy +pub fn set_data_conservation_policy(new_policy: NewDataConservationPolicy) -> Res { + database::UpdateInfo::new(USERS_TABLE) + .cond_user_id("ID", &new_policy.user_id) + .set_opt_u64_or_zero("delete_account_after", new_policy.delete_account_after) + .set_opt_u64_or_zero("delete_notifications_after", new_policy.delete_notifications_after) + .set_opt_u64_or_zero("delete_comments_after", new_policy.delete_comments_after) + .set_opt_u64_or_zero("delete_posts_after", new_policy.delete_posts_after) + .set_opt_u64_or_zero("delete_conversation_messages_after", new_policy.delete_conversation_messages_after) + .set_opt_u64_or_zero("delete_likes_after", new_policy.delete_likes_after) + .exec() +} + /// Export an account's data pub fn export(user_id: &UserID) -> ResultBoxError { let mut data = AccountExport { diff --git a/src/helpers/database.rs b/src/helpers/database.rs index ba29ad8..4e8e3bd 100644 --- a/src/helpers/database.rs +++ b/src/helpers/database.rs @@ -867,6 +867,16 @@ impl UpdateInfo { self } + /// Set an u64 number + /// + /// None => 0 + /// Some => The value + pub fn set_opt_u64_or_zero(mut self, name: &str, val: Option) -> UpdateInfo { + self.set.insert(name.to_string(), Value::from(val.unwrap_or(0))); + self + } + + /// Set a new legacy boolean pub fn set_legacy_bool(mut self, name: &str, val: bool) -> UpdateInfo { let num = match val { diff --git a/src/routes.rs b/src/routes.rs index 24b3919..de84528 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -175,6 +175,7 @@ pub fn get_routes() -> Vec { Route::post("/settings/upload_custom_emoji", Box::new(settings_controller::upload_custom_emoji)), Route::post("/settings/delete_custom_emoji", Box::new(settings_controller::delete_custom_emoji)), Route::post("/settings/get_data_conservation_policy", Box::new(settings_controller::get_data_conservation_policy)), + Route::post("/settings/set_data_conservation_policy", Box::new(settings_controller::set_data_conservation_policy)), // Friends controller