|
|
|
@ -1,4 +1,4 @@
|
|
|
|
|
use crate::error::LemmyError;
|
|
|
|
|
use crate::error::{LemmyError, LemmyResult};
|
|
|
|
|
use itertools::Itertools;
|
|
|
|
|
use once_cell::sync::Lazy;
|
|
|
|
|
use regex::Regex;
|
|
|
|
@ -17,32 +17,77 @@ static CLEAN_URL_PARAMS_REGEX: Lazy<Regex> = Lazy::new(|| {
|
|
|
|
|
Regex::new(r"^utm_source|utm_medium|utm_campaign|utm_term|utm_content|gclid|gclsrc|dclid|fbclid$")
|
|
|
|
|
.expect("compile regex")
|
|
|
|
|
});
|
|
|
|
|
const BODY_MAX_LENGTH: usize = 10000;
|
|
|
|
|
const BIO_MAX_LENGTH: usize = 300;
|
|
|
|
|
|
|
|
|
|
fn has_newline(name: &str) -> bool {
|
|
|
|
|
name.contains('\n')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn is_valid_actor_name(name: &str, actor_name_max_length: usize) -> bool {
|
|
|
|
|
name.chars().count() <= actor_name_max_length
|
|
|
|
|
pub fn is_valid_actor_name(name: &str, actor_name_max_length: usize) -> LemmyResult<()> {
|
|
|
|
|
let check = name.chars().count() <= actor_name_max_length
|
|
|
|
|
&& VALID_ACTOR_NAME_REGEX.is_match(name)
|
|
|
|
|
&& !has_newline(name)
|
|
|
|
|
&& !has_newline(name);
|
|
|
|
|
if !check {
|
|
|
|
|
Err(LemmyError::from_message("invalid_name"))
|
|
|
|
|
} else {
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Can't do a regex here, reverse lookarounds not supported
|
|
|
|
|
pub fn is_valid_display_name(name: &str, actor_name_max_length: usize) -> bool {
|
|
|
|
|
!name.starts_with('@')
|
|
|
|
|
pub fn is_valid_display_name(name: &str, actor_name_max_length: usize) -> LemmyResult<()> {
|
|
|
|
|
let check = !name.starts_with('@')
|
|
|
|
|
&& !name.starts_with('\u{200b}')
|
|
|
|
|
&& name.chars().count() >= 3
|
|
|
|
|
&& name.chars().count() <= actor_name_max_length
|
|
|
|
|
&& !has_newline(name)
|
|
|
|
|
&& !has_newline(name);
|
|
|
|
|
if !check {
|
|
|
|
|
Err(LemmyError::from_message("invalid_username"))
|
|
|
|
|
} else {
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn is_valid_matrix_id(matrix_id: &str) -> LemmyResult<()> {
|
|
|
|
|
let check = VALID_MATRIX_ID_REGEX.is_match(matrix_id) && !has_newline(matrix_id);
|
|
|
|
|
if !check {
|
|
|
|
|
Err(LemmyError::from_message("invalid_matrix_id"))
|
|
|
|
|
} else {
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn is_valid_matrix_id(matrix_id: &str) -> bool {
|
|
|
|
|
VALID_MATRIX_ID_REGEX.is_match(matrix_id) && !has_newline(matrix_id)
|
|
|
|
|
pub fn is_valid_post_title(title: &str) -> LemmyResult<()> {
|
|
|
|
|
let check = VALID_POST_TITLE_REGEX.is_match(title) && !has_newline(title);
|
|
|
|
|
if !check {
|
|
|
|
|
Err(LemmyError::from_message("invalid_post_title"))
|
|
|
|
|
} else {
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn is_valid_post_title(title: &str) -> bool {
|
|
|
|
|
VALID_POST_TITLE_REGEX.is_match(title) && !has_newline(title)
|
|
|
|
|
/// This could be post bodies, comments, or any description field
|
|
|
|
|
pub fn is_valid_body_field(body: &Option<String>) -> LemmyResult<()> {
|
|
|
|
|
if let Some(body) = body {
|
|
|
|
|
let check = body.chars().count() <= BODY_MAX_LENGTH;
|
|
|
|
|
if !check {
|
|
|
|
|
Err(LemmyError::from_message("invalid_body_field"))
|
|
|
|
|
} else {
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn is_valid_bio_field(bio: &str) -> LemmyResult<()> {
|
|
|
|
|
let check = bio.chars().count() <= BIO_MAX_LENGTH;
|
|
|
|
|
if !check {
|
|
|
|
|
Err(LemmyError::from_message("bio_length_overflow"))
|
|
|
|
|
} else {
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn clean_url_params(url: &Url) -> Url {
|
|
|
|
@ -63,7 +108,7 @@ pub fn check_totp_2fa_valid(
|
|
|
|
|
totp_token: &Option<String>,
|
|
|
|
|
site_name: &str,
|
|
|
|
|
username: &str,
|
|
|
|
|
) -> Result<(), LemmyError> {
|
|
|
|
|
) -> LemmyResult<()> {
|
|
|
|
|
// Check only if they have a totp_secret in the DB
|
|
|
|
|
if let Some(totp_secret) = totp_secret {
|
|
|
|
|
// Throw an error if their token is missing
|
|
|
|
@ -131,52 +176,48 @@ mod tests {
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn regex_checks() {
|
|
|
|
|
assert!(!is_valid_post_title("hi"));
|
|
|
|
|
assert!(is_valid_post_title("him"));
|
|
|
|
|
assert!(!is_valid_post_title("n\n\n\n\nanother"));
|
|
|
|
|
assert!(!is_valid_post_title("hello there!\n this is a test."));
|
|
|
|
|
assert!(is_valid_post_title("hello there! this is a test."));
|
|
|
|
|
assert!(is_valid_post_title("hi").is_err());
|
|
|
|
|
assert!(is_valid_post_title("him").is_ok());
|
|
|
|
|
assert!(is_valid_post_title("n\n\n\n\nanother").is_err());
|
|
|
|
|
assert!(is_valid_post_title("hello there!\n this is a test.").is_err());
|
|
|
|
|
assert!(is_valid_post_title("hello there! this is a test.").is_ok());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_valid_actor_name() {
|
|
|
|
|
let actor_name_max_length = 20;
|
|
|
|
|
assert!(is_valid_actor_name("Hello_98", actor_name_max_length));
|
|
|
|
|
assert!(is_valid_actor_name("ten", actor_name_max_length));
|
|
|
|
|
assert!(!is_valid_actor_name("Hello-98", actor_name_max_length));
|
|
|
|
|
assert!(!is_valid_actor_name("a", actor_name_max_length));
|
|
|
|
|
assert!(!is_valid_actor_name("", actor_name_max_length));
|
|
|
|
|
assert!(is_valid_actor_name("Hello_98", actor_name_max_length).is_ok());
|
|
|
|
|
assert!(is_valid_actor_name("ten", actor_name_max_length).is_ok());
|
|
|
|
|
assert!(is_valid_actor_name("Hello-98", actor_name_max_length).is_err());
|
|
|
|
|
assert!(is_valid_actor_name("a", actor_name_max_length).is_err());
|
|
|
|
|
assert!(is_valid_actor_name("", actor_name_max_length).is_err());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_valid_display_name() {
|
|
|
|
|
let actor_name_max_length = 20;
|
|
|
|
|
assert!(is_valid_display_name("hello @there", actor_name_max_length));
|
|
|
|
|
assert!(!is_valid_display_name(
|
|
|
|
|
"@hello there",
|
|
|
|
|
actor_name_max_length
|
|
|
|
|
));
|
|
|
|
|
assert!(is_valid_display_name("hello @there", actor_name_max_length).is_ok());
|
|
|
|
|
assert!(is_valid_display_name("@hello there", actor_name_max_length).is_err());
|
|
|
|
|
|
|
|
|
|
// Make sure zero-space with an @ doesn't work
|
|
|
|
|
assert!(!is_valid_display_name(
|
|
|
|
|
&format!("{}@my name is", '\u{200b}'),
|
|
|
|
|
actor_name_max_length
|
|
|
|
|
));
|
|
|
|
|
assert!(
|
|
|
|
|
is_valid_display_name(&format!("{}@my name is", '\u{200b}'), actor_name_max_length).is_err()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_valid_post_title() {
|
|
|
|
|
assert!(is_valid_post_title("Post Title"));
|
|
|
|
|
assert!(is_valid_post_title(" POST TITLE 😃😃😃😃😃"));
|
|
|
|
|
assert!(!is_valid_post_title("\n \n \n \n ")); // tabs/spaces/newlines
|
|
|
|
|
assert!(is_valid_post_title("Post Title").is_ok());
|
|
|
|
|
assert!(is_valid_post_title(" POST TITLE 😃😃😃😃😃").is_ok());
|
|
|
|
|
assert!(is_valid_post_title("\n \n \n \n ").is_err()); // tabs/spaces/newlines
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_valid_matrix_id() {
|
|
|
|
|
assert!(is_valid_matrix_id("@dess:matrix.org"));
|
|
|
|
|
assert!(!is_valid_matrix_id("dess:matrix.org"));
|
|
|
|
|
assert!(!is_valid_matrix_id(" @dess:matrix.org"));
|
|
|
|
|
assert!(!is_valid_matrix_id("@dess:matrix.org t"));
|
|
|
|
|
assert!(is_valid_matrix_id("@dess:matrix.org").is_ok());
|
|
|
|
|
assert!(is_valid_matrix_id("dess:matrix.org").is_err());
|
|
|
|
|
assert!(is_valid_matrix_id(" @dess:matrix.org").is_err());
|
|
|
|
|
assert!(is_valid_matrix_id("@dess:matrix.org t").is_err());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|