From 3150c7267dfad3a97600340d24e84454ee42016f Mon Sep 17 00:00:00 2001 From: jude Date: Sun, 18 Dec 2022 13:38:43 +0000 Subject: [PATCH] Add validating to length-validated fields on edit Can't just replace edit logic with overwrite logic because partial editing is used in enabling/disabling. So need to replicate logic in a sensible way. --- web/src/routes/dashboard/guild.rs | 27 ++++++++++++------- web/src/routes/dashboard/mod.rs | 34 ++++++++++++++++++++--- web/static/js/interval.js | 45 ++++++++++++++++++++----------- web/static/js/main.js | 16 ++++++----- 4 files changed, 86 insertions(+), 36 deletions(-) diff --git a/web/src/routes/dashboard/guild.rs b/web/src/routes/dashboard/guild.rs index aac433e..641835b 100644 --- a/web/src/routes/dashboard/guild.rs +++ b/web/src/routes/dashboard/guild.rs @@ -386,33 +386,40 @@ pub async fn edit_reminder( let user_id = cookies.get_private("userid").map(|c| c.value().parse::().ok()).flatten().unwrap(); + if reminder.message_ok() { + update_field!(pool.inner(), error, reminder.[ + content, + embed_author, + embed_description, + embed_footer, + embed_title, + embed_fields, + username + ]); + } else { + error.push("Message exceeds limits.".to_string()); + } + update_field!(pool.inner(), error, reminder.[ attachment, attachment_name, avatar, - content, - embed_author, embed_author_url, embed_color, - embed_description, - embed_footer, embed_footer_url, embed_image_url, embed_thumbnail_url, - embed_title, - embed_fields, enabled, expires, name, restartable, tts, - username, utc_time ]); - if reminder.interval_days.is_some() - || reminder.interval_months.is_some() - || reminder.interval_seconds.is_some() + if reminder.interval_days.flatten().is_some() + || reminder.interval_months.flatten().is_some() + || reminder.interval_seconds.flatten().is_some() { if check_guild_subscription(&serenity_context.inner(), id).await || check_subscription(&serenity_context.inner(), user_id).await diff --git a/web/src/routes/dashboard/mod.rs b/web/src/routes/dashboard/mod.rs index f0724e2..35182a9 100644 --- a/web/src/routes/dashboard/mod.rs +++ b/web/src/routes/dashboard/mod.rs @@ -50,6 +50,10 @@ fn id_default() -> u32 { 0 } +fn interval_default() -> Unset> { + None +} + fn deserialize_optional_field<'de, T, D>(deserializer: D) -> Result>, D::Error> where D: Deserializer<'de>, @@ -229,13 +233,13 @@ pub struct PatchReminder { #[serde(default)] #[serde(deserialize_with = "deserialize_optional_field")] expires: Unset>, - #[serde(default)] + #[serde(default = "interval_default")] #[serde(deserialize_with = "deserialize_optional_field")] interval_seconds: Unset>, - #[serde(default)] + #[serde(default = "interval_default")] #[serde(deserialize_with = "deserialize_optional_field")] interval_days: Unset>, - #[serde(default)] + #[serde(default = "interval_default")] #[serde(deserialize_with = "deserialize_optional_field")] interval_months: Unset>, #[serde(default)] @@ -251,6 +255,30 @@ pub struct PatchReminder { utc_time: Unset, } +impl PatchReminder { + fn message_ok(&self) -> bool { + self.content.as_ref().map_or(true, |c| c.len() <= MAX_CONTENT_LENGTH) + && self.embed_author.as_ref().map_or(true, |c| c.len() <= MAX_EMBED_AUTHOR_LENGTH) + && self + .embed_description + .as_ref() + .map_or(true, |c| c.len() <= MAX_EMBED_DESCRIPTION_LENGTH) + && self.embed_footer.as_ref().map_or(true, |c| c.len() <= MAX_EMBED_FOOTER_LENGTH) + && self.embed_title.as_ref().map_or(true, |c| c.len() <= MAX_EMBED_TITLE_LENGTH) + && self.embed_fields.as_ref().map_or(true, |c| { + c.0.len() <= MAX_EMBED_FIELDS + && c.0.iter().all(|f| { + f.title.len() <= MAX_EMBED_FIELD_TITLE_LENGTH + && f.value.len() <= MAX_EMBED_FIELD_VALUE_LENGTH + }) + }) + && self + .username + .as_ref() + .map_or(true, |c| c.as_ref().map_or(true, |v| v.len() <= MAX_USERNAME_LENGTH)) + } +} + pub fn generate_uid() -> String { let mut generator: OsRng = Default::default(); diff --git a/web/static/js/interval.js b/web/static/js/interval.js index 7909afe..efb6fb0 100644 --- a/web/static/js/interval.js +++ b/web/static/js/interval.js @@ -22,25 +22,38 @@ function update_interval(element) { let minutes = element.querySelector('input[name="interval_minutes"]'); let seconds = element.querySelector('input[name="interval_seconds"]'); - months.value = months.value.padStart(1, "0"); - days.value = days.value.padStart(1, "0"); - hours.value = hours.value.padStart(2, "0"); - minutes.value = minutes.value.padStart(2, "0"); - seconds.value = seconds.value.padStart(2, "0"); + let interval = get_interval(element); - if (seconds.value >= 60) { - let quotient = Math.floor(seconds.value / 60); - let remainder = seconds.value % 60; + if (interval.months === null && interval.days === null && interval.seconds === null) { + months.value = ""; + days.value = ""; + hours.value = ""; + minutes.value = ""; + seconds.value = ""; + } else { + months.value = months.value.padStart(1, "0"); + days.value = days.value.padStart(1, "0"); + hours.value = hours.value.padStart(2, "0"); + minutes.value = minutes.value.padStart(2, "0"); + seconds.value = seconds.value.padStart(2, "0"); - seconds.value = String(remainder).padStart(2, "0"); - minutes.value = String(Number(minutes.value) + Number(quotient)).padStart(2, "0"); - } - if (minutes.value >= 60) { - let quotient = Math.floor(minutes.value / 60); - let remainder = minutes.value % 60; + if (seconds.value >= 60) { + let quotient = Math.floor(seconds.value / 60); + let remainder = seconds.value % 60; - minutes.value = String(remainder).padStart(2, "0"); - hours.value = String(Number(hours.value) + Number(quotient)).padStart(2, "0"); + seconds.value = String(remainder).padStart(2, "0"); + minutes.value = String(Number(minutes.value) + Number(quotient)).padStart( + 2, + "0" + ); + } + if (minutes.value >= 60) { + let quotient = Math.floor(minutes.value / 60); + let remainder = minutes.value % 60; + + minutes.value = String(remainder).padStart(2, "0"); + hours.value = String(Number(hours.value) + Number(quotient)).padStart(2, "0"); + } } } diff --git a/web/static/js/main.js b/web/static/js/main.js index b795b3a..9ac1e85 100644 --- a/web/static/js/main.js +++ b/web/static/js/main.js @@ -355,6 +355,8 @@ function deserialize_reminder(reminder, frame, mode) { } } + update_interval(frame); + const lastChild = frame.querySelector("div.embed-multifield-box .embed-field-box"); for (let field of reminder["embed_fields"]) { @@ -838,13 +840,6 @@ $deleteTemplateBtn.addEventListener("click", (ev) => { }); }); -document.querySelectorAll("textarea.autoresize").forEach((element) => { - element.addEventListener("input", () => { - element.style.height = ""; - element.style.height = element.scrollHeight + 3 + "px"; - }); -}); - let $img; const $urlModal = document.querySelector("div#addImageModal"); const $urlInput = $urlModal.querySelector("input"); @@ -900,6 +895,13 @@ document.addEventListener("remindersLoaded", () => { window.getComputedStyle($discordFrame).borderLeftColor; }); }); + + document.querySelectorAll("textarea.autoresize").forEach((element) => { + element.addEventListener("input", () => { + element.style.height = ""; + element.style.height = element.scrollHeight + 3 + "px"; + }); + }); }); function check_embed_fields() {