Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify regex for user/community name validation #5164

Merged
merged 13 commits into from
Nov 12, 2024
32 changes: 17 additions & 15 deletions crates/utils/src/utils/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,26 +85,19 @@ fn has_newline(name: &str) -> bool {
}

pub fn is_valid_actor_name(name: &str, actor_name_max_length: usize) -> LemmyResult<()> {
static VALID_ACTOR_NAME_REGEX_EN: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"^[a-zA-Z0-9_]{3,}$").expect("compile regex"));
static VALID_ACTOR_NAME_REGEX_AR: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"^[\p{Arabic}0-9_]{3,}$").expect("compile regex"));
static VALID_ACTOR_NAME_REGEX_RU: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"^[\p{Cyrillic}0-9_]{3,}$").expect("compile regex"));

let check = name.chars().count() <= actor_name_max_length && !has_newline(name);

// Only allow characters from a single alphabet per username. This avoids problems with lookalike
// characters like `o` which looks identical in Latin and Cyrillic, and can be used to imitate
// other users. Checks for additional alphabets can be added in the same way.
let lang_check = VALID_ACTOR_NAME_REGEX_EN.is_match(name)
|| VALID_ACTOR_NAME_REGEX_AR.is_match(name)
|| VALID_ACTOR_NAME_REGEX_RU.is_match(name);
static VALID_ACTOR_NAME_REGEX: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r"^(?:[a-zA-Z0-9_]+|[0-9_\p{Arabic}]+|[0-9_\p{Cyrillic}]+)$").expect("compile regex")
});

if !check || !lang_check {
Err(LemmyErrorType::InvalidName.into())
} else {
min_length_check(name, 3, LemmyErrorType::InvalidName)?;
max_length_check(name, actor_name_max_length, LemmyErrorType::InvalidName)?;
if VALID_ACTOR_NAME_REGEX.is_match(name) {
Ok(())
} else {
Err(LemmyErrorType::InvalidName.into())
}
}

Expand Down Expand Up @@ -438,6 +431,15 @@ mod tests {
assert!(is_valid_actor_name("a", actor_name_max_length).is_err());
// empty
assert!(is_valid_actor_name("", actor_name_max_length).is_err());
// newline
assert!(is_valid_actor_name(
r"Line1

Line3",
actor_name_max_length
)
.is_err());
assert!(is_valid_actor_name("Line1\nLine3", actor_name_max_length).is_err());
}

#[test]
Expand Down