fix: username and community title validation

This commit is contained in:
trisua 2025-05-19 19:31:12 -04:00
parent a4d7f44aa3
commit efb259764e
7 changed files with 79 additions and 25 deletions

1
Cargo.lock generated
View file

@ -3324,6 +3324,7 @@ dependencies = [
"md-5", "md-5",
"pathbufd", "pathbufd",
"redis", "redis",
"regex",
"reqwest", "reqwest",
"rusqlite", "rusqlite",
"serde", "serde",

View file

@ -167,7 +167,7 @@ pub fn save_buffer(path: &str, bytes: Vec<u8>, format: image::ImageFormat) -> st
const WEBP_ENCODE_QUALITY: f32 = 85.0; const WEBP_ENCODE_QUALITY: f32 = 85.0;
/// Create a WEBP image buffer given an input of `bytes`. /// Create a WEBP image buffer given an input of `bytes`.
pub fn save_webp_buffer(path: &str, bytes: Vec<u8>) -> std::io::Result<()> { pub fn save_webp_buffer(path: &str, bytes: Vec<u8>, quality: Option<f32>) -> std::io::Result<()> {
let img = match image::load_from_memory(&bytes) { let img = match image::load_from_memory(&bytes) {
Ok(i) => i, Ok(i) => i,
Err(_) => { Err(_) => {
@ -188,7 +188,10 @@ pub fn save_webp_buffer(path: &str, bytes: Vec<u8>) -> std::io::Result<()> {
} }
}; };
let mem = encoder.encode(WEBP_ENCODE_QUALITY); let mem = encoder.encode(match quality {
Some(q) => q,
None => WEBP_ENCODE_QUALITY,
});
if std::fs::write(path, &*mem).is_err() { if std::fs::write(path, &*mem).is_err() {
return Err(std::io::Error::new( return Err(std::io::Error::new(

View file

@ -1,10 +1,8 @@
use std::fs::exists; use std::fs::exists;
use image::ImageFormat;
use pathbufd::PathBufD; use pathbufd::PathBufD;
use crate::{ use crate::{
get_user_from_token, get_user_from_token,
image::{save_buffer, Image}, image::{save_webp_buffer, Image},
routes::api::v1::{auth::images::read_image, UpdateEmojiName}, routes::api::v1::{auth::images::read_image, UpdateEmojiName},
State, State,
}; };
@ -146,11 +144,9 @@ pub async fn create_request(
return Json(Error::MiscError(e.to_string()).into()); return Json(Error::MiscError(e.to_string()).into());
} }
} else { } else {
if let Err(e) = save_buffer( if let Err(e) =
&upload.path(&data.0).to_string(), save_webp_buffer(&upload.path(&data.0).to_string(), img.0.to_vec(), None)
img.0.to_vec(), {
ImageFormat::WebP,
) {
return Json(Error::MiscError(e.to_string()).into()); return Json(Error::MiscError(e.to_string()).into());
} }
} }

View file

@ -108,7 +108,8 @@ pub async fn create_request(
Err(e) => return Json(e.into()), Err(e) => return Json(e.into()),
}; };
if let Err(e) = save_webp_buffer(&upload.path(&data.0).to_string(), image.to_vec()) if let Err(e) =
save_webp_buffer(&upload.path(&data.0).to_string(), image.to_vec(), None)
{ {
return Json(Error::MiscError(e.to_string()).into()); return Json(Error::MiscError(e.to_string()).into());
} }

View file

@ -34,3 +34,4 @@ tokio-postgres = { version = "0.7.13", optional = true }
bb8-postgres = { version = "0.9.0", optional = true } bb8-postgres = { version = "0.9.0", optional = true }
base64 = "0.22.1" base64 = "0.22.1"
emojis = "0.6.4" emojis = "0.6.4"
regex = "1.11.1"

View file

@ -128,14 +128,15 @@ impl DataManager {
return Err(Error::MiscError("This username cannot be used".to_string())); return Err(Error::MiscError("This username cannot be used".to_string()));
} }
if data.username.contains(" ") { let regex = regex::RegexBuilder::new(r"[^\w_\-\.!]+")
return Err(Error::MiscError("Name cannot contain spaces".to_string())); .multi_line(true)
} else if data.username.contains("%") { .build()
return Err(Error::MiscError("Name cannot contain \"%\"".to_string())); .unwrap();
} else if data.username.contains("?") {
return Err(Error::MiscError("Name cannot contain \"?\"".to_string())); if regex.captures(&data.username).is_some() {
} else if data.username.contains("&") { return Err(Error::MiscError(
return Err(Error::MiscError("Name cannot contain \"&\"".to_string())); "This username contains invalid characters".to_string(),
));
} }
// make sure username isn't taken // make sure username isn't taken
@ -436,6 +437,29 @@ impl DataManager {
} }
pub async fn update_user_username(&self, id: usize, to: String, user: User) -> Result<()> { pub async fn update_user_username(&self, id: usize, to: String, user: User) -> Result<()> {
// check value
if to.len() < 2 {
return Err(Error::DataTooShort("username".to_string()));
} else if to.len() > 32 {
return Err(Error::DataTooLong("username".to_string()));
}
if self.0.banned_usernames.contains(&to) {
return Err(Error::MiscError("This username cannot be used".to_string()));
}
let regex = regex::RegexBuilder::new(r"[^\w_\-\.!]+")
.multi_line(true)
.build()
.unwrap();
if regex.captures(&to).is_some() {
return Err(Error::MiscError(
"This username contains invalid characters".to_string(),
));
}
// ...
let conn = match self.connect().await { let conn = match self.connect().await {
Ok(c) => c, Ok(c) => c,
Err(e) => return Err(Error::DatabaseConnection(e.to_string())), Err(e) => return Err(Error::DatabaseConnection(e.to_string())),

View file

@ -209,16 +209,21 @@ impl DataManager {
return Err(Error::DataTooLong("title".to_string())); return Err(Error::DataTooLong("title".to_string()));
} }
if !data.title.is_ascii() | data.title.contains(" ") {
return Err(Error::MiscError(
"Title contains characters which aren't allowed".to_string(),
));
}
if self.0.banned_usernames.contains(&data.title) { if self.0.banned_usernames.contains(&data.title) {
return Err(Error::MiscError("This title cannot be used".to_string())); return Err(Error::MiscError("This title cannot be used".to_string()));
} }
let regex = regex::RegexBuilder::new(r"[^\w_\-\.!]+")
.multi_line(true)
.build()
.unwrap();
if regex.captures(&data.title).is_some() {
return Err(Error::MiscError(
"This title contains invalid characters".to_string(),
));
}
// check number of communities // check number of communities
let owner = self.get_user_by_id(data.owner).await?; let owner = self.get_user_by_id(data.owner).await?;
@ -382,6 +387,29 @@ impl DataManager {
} }
pub async fn update_community_title(&self, id: usize, user: User, title: &str) -> Result<()> { pub async fn update_community_title(&self, id: usize, user: User, title: &str) -> Result<()> {
// check values
if title.len() < 2 {
return Err(Error::DataTooShort("title".to_string()));
} else if title.len() > 32 {
return Err(Error::DataTooLong("title".to_string()));
}
if self.0.banned_usernames.contains(&title.to_string()) {
return Err(Error::MiscError("This title cannot be used".to_string()));
}
let regex = regex::RegexBuilder::new(r"[^\w_\-\.!]+")
.multi_line(true)
.build()
.unwrap();
if regex.captures(&title).is_some() {
return Err(Error::MiscError(
"This title contains invalid characters".to_string(),
));
}
// ...
let y = self.get_community_by_id(id).await?; let y = self.get_community_by_id(id).await?;
if user.id != y.owner { if user.id != y.owner {