mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-11-08 17:34:16 +00:00
Add lowercase only check for community names
This commit is contained in:
parent
02ba54c589
commit
eef51e35d2
|
@ -5,26 +5,15 @@ use lemmy_api_common::{
|
|||
community::{CommunityResponse, CreateCommunity},
|
||||
context::LemmyContext,
|
||||
utils::{
|
||||
generate_followers_url,
|
||||
generate_inbox_url,
|
||||
generate_local_apub_endpoint,
|
||||
get_url_blocklist,
|
||||
is_admin,
|
||||
local_site_to_slur_regex,
|
||||
process_markdown_opt,
|
||||
proxy_image_link_api,
|
||||
EndpointType,
|
||||
generate_followers_url, generate_inbox_url, generate_local_apub_endpoint, get_url_blocklist,
|
||||
is_admin, local_site_to_slur_regex, process_markdown_opt, proxy_image_link_api, EndpointType,
|
||||
},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
actor_language::{CommunityLanguage, SiteLanguage},
|
||||
community::{
|
||||
Community,
|
||||
CommunityFollower,
|
||||
CommunityFollowerForm,
|
||||
CommunityInsertForm,
|
||||
CommunityModerator,
|
||||
Community, CommunityFollower, CommunityFollowerForm, CommunityInsertForm, CommunityModerator,
|
||||
CommunityModeratorForm,
|
||||
},
|
||||
},
|
||||
|
@ -37,9 +26,7 @@ use lemmy_utils::{
|
|||
utils::{
|
||||
slurs::check_slurs,
|
||||
validation::{
|
||||
is_valid_actor_name,
|
||||
is_valid_body_field,
|
||||
site_or_community_description_length_check,
|
||||
is_valid_body_field, is_valid_community_name, site_or_community_description_length_check,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -80,7 +67,7 @@ pub async fn create_community(
|
|||
let banner = diesel_url_create(data.banner.as_deref())?;
|
||||
let banner = proxy_image_link_api(banner, &context).await?;
|
||||
|
||||
is_valid_actor_name(&data.name, local_site.actor_name_max_length as usize)?;
|
||||
is_valid_community_name(&data.name, local_site.actor_name_max_length as usize)?;
|
||||
|
||||
// Double check for duplicate community actor_ids
|
||||
let community_actor_id = generate_local_apub_endpoint(
|
||||
|
|
|
@ -6,17 +6,9 @@ use lemmy_api_common::{
|
|||
oauth_provider::AuthenticateWithOauth,
|
||||
person::{LoginResponse, Register},
|
||||
utils::{
|
||||
check_email_verified,
|
||||
check_registration_application,
|
||||
check_user_valid,
|
||||
generate_inbox_url,
|
||||
generate_local_apub_endpoint,
|
||||
honeypot_check,
|
||||
local_site_to_slur_regex,
|
||||
password_length_check,
|
||||
send_new_applicant_email_to_admins,
|
||||
send_verification_email,
|
||||
EndpointType,
|
||||
check_email_verified, check_registration_application, check_user_valid, generate_inbox_url,
|
||||
generate_local_apub_endpoint, honeypot_check, local_site_to_slur_regex, password_length_check,
|
||||
send_new_applicant_email_to_admins, send_verification_email, EndpointType,
|
||||
},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
|
@ -41,7 +33,7 @@ use lemmy_utils::{
|
|||
error::{LemmyError, LemmyErrorExt, LemmyErrorType, LemmyResult},
|
||||
utils::{
|
||||
slurs::{check_slurs, check_slurs_opt},
|
||||
validation::is_valid_actor_name,
|
||||
validation::is_valid_username,
|
||||
},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -407,7 +399,7 @@ async fn create_person(
|
|||
context: &Data<LemmyContext>,
|
||||
) -> Result<Person, LemmyError> {
|
||||
let actor_keypair = generate_actor_keypair()?;
|
||||
is_valid_actor_name(&username, local_site.actor_name_max_length as usize)?;
|
||||
is_valid_username(&username, local_site.actor_name_max_length as usize)?;
|
||||
let actor_id = generate_local_apub_endpoint(
|
||||
EndpointType::Person,
|
||||
&username,
|
||||
|
|
|
@ -84,27 +84,37 @@ fn has_newline(name: &str) -> bool {
|
|||
name.contains('\n')
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
pub fn is_valid_username(name: &str, actor_name_max_length: usize) -> LemmyResult<()> {
|
||||
// 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_USERNAME_REGEX: LazyLock<Regex> = LazyLock::new(|| {
|
||||
Regex::new(r"^(?:[a-zA-Z0-9_]{3,}|[0-9_\p{Arabic}]{3,}|[0-9_\p{Cyrillic}]{3,})$")
|
||||
.expect("compile regex")
|
||||
});
|
||||
|
||||
if !check || !lang_check {
|
||||
Err(LemmyErrorType::InvalidName.into())
|
||||
} else {
|
||||
is_valid_actor_name(name, actor_name_max_length, &VALID_USERNAME_REGEX)
|
||||
}
|
||||
|
||||
pub fn is_valid_community_name(name: &str, actor_name_max_length: usize) -> LemmyResult<()> {
|
||||
// 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.
|
||||
static VALID_COMMUNITY_NAME_REGEX: LazyLock<Regex> = LazyLock::new(|| {
|
||||
Regex::new(
|
||||
r"^(?:[0-9_a-z]{3,}|[0-9_[\p{Arabic}]&&\P{Lu}&&\P{Lt}]{3,}|[0-9_[\p{Cyrillic}&&\P{Lu}&&\P{Lt}]]{3,})$",
|
||||
)
|
||||
.expect("compile regex")
|
||||
});
|
||||
|
||||
is_valid_actor_name(name, actor_name_max_length, &VALID_COMMUNITY_NAME_REGEX)
|
||||
}
|
||||
|
||||
fn is_valid_actor_name(name: &str, actor_name_max_length: usize, r: &Regex) -> LemmyResult<()> {
|
||||
if name.len() <= actor_name_max_length && !has_newline(name) && r.is_match(name) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(LemmyErrorType::InvalidName.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -356,24 +366,11 @@ mod tests {
|
|||
use crate::{
|
||||
error::{LemmyErrorType, LemmyResult},
|
||||
utils::validation::{
|
||||
build_and_check_regex,
|
||||
check_site_visibility_valid,
|
||||
check_urls_are_valid,
|
||||
clean_url,
|
||||
clean_urls_in_text,
|
||||
is_url_blocked,
|
||||
is_valid_actor_name,
|
||||
is_valid_bio_field,
|
||||
is_valid_display_name,
|
||||
is_valid_matrix_id,
|
||||
is_valid_post_title,
|
||||
is_valid_url,
|
||||
site_name_length_check,
|
||||
site_or_community_description_length_check,
|
||||
BIO_MAX_LENGTH,
|
||||
SITE_DESCRIPTION_MAX_LENGTH,
|
||||
SITE_NAME_MAX_LENGTH,
|
||||
URL_MAX_LENGTH,
|
||||
build_and_check_regex, check_site_visibility_valid, check_urls_are_valid, clean_url,
|
||||
clean_urls_in_text, is_url_blocked, is_valid_bio_field, is_valid_community_name,
|
||||
is_valid_display_name, is_valid_matrix_id, is_valid_post_title, is_valid_url,
|
||||
is_valid_username, site_name_length_check, site_or_community_description_length_check,
|
||||
BIO_MAX_LENGTH, SITE_DESCRIPTION_MAX_LENGTH, SITE_NAME_MAX_LENGTH, URL_MAX_LENGTH,
|
||||
},
|
||||
};
|
||||
use pretty_assertions::assert_eq;
|
||||
|
@ -421,23 +418,46 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_valid_actor_name() {
|
||||
fn test_valid_username() {
|
||||
let actor_name_max_length = 20;
|
||||
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("تجريب", actor_name_max_length).is_ok());
|
||||
assert!(is_valid_actor_name("تجريب_123", actor_name_max_length).is_ok());
|
||||
assert!(is_valid_actor_name("Владимир", actor_name_max_length).is_ok());
|
||||
assert!(is_valid_username("Hello_98", actor_name_max_length).is_ok());
|
||||
assert!(is_valid_username("ten", actor_name_max_length).is_ok());
|
||||
assert!(is_valid_username("تجريب", actor_name_max_length).is_ok());
|
||||
assert!(is_valid_username("تجريب_123", actor_name_max_length).is_ok());
|
||||
assert!(is_valid_username("Владимир", actor_name_max_length).is_ok());
|
||||
|
||||
// mixed scripts
|
||||
assert!(is_valid_actor_name("تجريب_abc", actor_name_max_length).is_err());
|
||||
assert!(is_valid_actor_name("Влад_abc", actor_name_max_length).is_err());
|
||||
assert!(is_valid_username("تجريب_abc", actor_name_max_length).is_err());
|
||||
assert!(is_valid_username("Влад_abc", actor_name_max_length).is_err());
|
||||
// dash
|
||||
assert!(is_valid_actor_name("Hello-98", actor_name_max_length).is_err());
|
||||
assert!(is_valid_username("Hello-98", actor_name_max_length).is_err());
|
||||
// too short
|
||||
assert!(is_valid_actor_name("a", actor_name_max_length).is_err());
|
||||
assert!(is_valid_username("a", actor_name_max_length).is_err());
|
||||
// empty
|
||||
assert!(is_valid_actor_name("", actor_name_max_length).is_err());
|
||||
assert!(is_valid_username("", actor_name_max_length).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_valid_community_name() {
|
||||
let actor_name_max_length = 20;
|
||||
assert!(is_valid_community_name("hello_98", actor_name_max_length).is_ok());
|
||||
assert!(is_valid_community_name("ten", actor_name_max_length).is_ok());
|
||||
assert!(is_valid_community_name("تجريب", actor_name_max_length).is_ok());
|
||||
assert!(is_valid_community_name("تجريب_123", actor_name_max_length).is_ok());
|
||||
assert!(is_valid_community_name("владимир", actor_name_max_length).is_ok());
|
||||
|
||||
// uppercase
|
||||
assert!(is_valid_community_name("Ten", actor_name_max_length).is_err());
|
||||
assert!(is_valid_community_name("Владимир", actor_name_max_length).is_err());
|
||||
// mixed scripts
|
||||
assert!(is_valid_community_name("تجريب_abc", actor_name_max_length).is_err());
|
||||
assert!(is_valid_community_name("Влад_abc", actor_name_max_length).is_err());
|
||||
// dash
|
||||
assert!(is_valid_community_name("hello-98", actor_name_max_length).is_err());
|
||||
// too short
|
||||
assert!(is_valid_community_name("a", actor_name_max_length).is_err());
|
||||
// empty
|
||||
assert!(is_valid_community_name("", actor_name_max_length).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Reference in a new issue