* Allow Arabic and Cyrillic usernames/community names (fixes #1764) * update comment
This commit is contained in:
parent
722d9efc13
commit
d55bd2f2bc
4 changed files with 46 additions and 9 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -11,8 +11,6 @@ checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "activitypub_federation"
|
name = "activitypub_federation"
|
||||||
version = "0.5.0-beta.3"
|
version = "0.5.0-beta.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "509cbafa1b42e01b7ca76c26298814a6638825df4fd67aef2f4c9d36a39c2b6d"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"activitystreams-kinds",
|
"activitystreams-kinds",
|
||||||
"actix-web",
|
"actix-web",
|
||||||
|
|
|
@ -70,7 +70,7 @@ lemmy_routes = { version = "=0.19.0-rc.3", path = "./crates/routes" }
|
||||||
lemmy_db_views = { version = "=0.19.0-rc.3", path = "./crates/db_views" }
|
lemmy_db_views = { version = "=0.19.0-rc.3", path = "./crates/db_views" }
|
||||||
lemmy_db_views_actor = { version = "=0.19.0-rc.3", path = "./crates/db_views_actor" }
|
lemmy_db_views_actor = { version = "=0.19.0-rc.3", path = "./crates/db_views_actor" }
|
||||||
lemmy_db_views_moderator = { version = "=0.19.0-rc.3", path = "./crates/db_views_moderator" }
|
lemmy_db_views_moderator = { version = "=0.19.0-rc.3", path = "./crates/db_views_moderator" }
|
||||||
activitypub_federation = { version = "0.5.0-beta.3", default-features = false, features = [
|
activitypub_federation = { git = "https://github.com/LemmyNet/activitypub-federation-rust.git", branch = "webfinger-alphabets", default-features = false, features = [
|
||||||
"actix-web",
|
"actix-web",
|
||||||
] }
|
] }
|
||||||
diesel = "2.1.0"
|
diesel = "2.1.0"
|
||||||
|
|
|
@ -129,3 +129,21 @@ test("Requests with invalid auth should be treated as unauthenticated", async ()
|
||||||
let posts = invalid_auth.getPosts(form);
|
let posts = invalid_auth.getPosts(form);
|
||||||
expect((await posts).posts).toBeDefined();
|
expect((await posts).posts).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Create user with Arabic name", async () => {
|
||||||
|
let userRes = await registerUser(alpha, "تجريب");
|
||||||
|
expect(userRes.jwt).toBeDefined();
|
||||||
|
let user = new LemmyHttp(alphaUrl, {
|
||||||
|
headers: { Authorization: `Bearer ${userRes.jwt ?? ""}` },
|
||||||
|
});
|
||||||
|
|
||||||
|
let site = await getSite(user);
|
||||||
|
expect(site.my_user).toBeDefined();
|
||||||
|
if (!site.my_user) {
|
||||||
|
throw "Missing site user";
|
||||||
|
}
|
||||||
|
apShortname = `@${site.my_user.local_user_view.person.name}@lemmy-alpha:8541`;
|
||||||
|
|
||||||
|
let alphaPerson = (await resolvePerson(alpha, apShortname)).person;
|
||||||
|
expect(alphaPerson).toBeDefined();
|
||||||
|
});
|
||||||
|
|
|
@ -4,8 +4,6 @@ use once_cell::sync::Lazy;
|
||||||
use regex::{Regex, RegexBuilder};
|
use regex::{Regex, RegexBuilder};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
static VALID_ACTOR_NAME_REGEX: Lazy<Regex> =
|
|
||||||
Lazy::new(|| Regex::new(r"^[a-zA-Z0-9_]{3,}$").expect("compile regex"));
|
|
||||||
static VALID_POST_TITLE_REGEX: Lazy<Regex> =
|
static VALID_POST_TITLE_REGEX: Lazy<Regex> =
|
||||||
Lazy::new(|| Regex::new(r".*\S{3,200}.*").expect("compile regex"));
|
Lazy::new(|| Regex::new(r".*\S{3,200}.*").expect("compile regex"));
|
||||||
|
|
||||||
|
@ -89,10 +87,23 @@ fn has_newline(name: &str) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_valid_actor_name(name: &str, actor_name_max_length: usize) -> LemmyResult<()> {
|
pub fn is_valid_actor_name(name: &str, actor_name_max_length: usize) -> LemmyResult<()> {
|
||||||
let check = name.chars().count() <= actor_name_max_length
|
static VALID_ACTOR_NAME_REGEX_EN: Lazy<Regex> =
|
||||||
&& VALID_ACTOR_NAME_REGEX.is_match(name)
|
Lazy::new(|| Regex::new(r"^[a-zA-Z0-9_]{3,}$").expect("compile regex"));
|
||||||
&& !has_newline(name);
|
static VALID_ACTOR_NAME_REGEX_AR: Lazy<Regex> =
|
||||||
if !check {
|
Lazy::new(|| Regex::new(r"^[\p{Arabic}0-9_]{3,}$").expect("compile regex"));
|
||||||
|
static VALID_ACTOR_NAME_REGEX_RU: Lazy<Regex> =
|
||||||
|
Lazy::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);
|
||||||
|
|
||||||
|
if !check || !lang_check {
|
||||||
Err(LemmyErrorType::InvalidName.into())
|
Err(LemmyErrorType::InvalidName.into())
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -329,8 +340,18 @@ mod tests {
|
||||||
let actor_name_max_length = 20;
|
let actor_name_max_length = 20;
|
||||||
assert!(is_valid_actor_name("Hello_98", actor_name_max_length).is_ok());
|
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("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());
|
||||||
|
|
||||||
|
// 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());
|
||||||
|
// dash
|
||||||
assert!(is_valid_actor_name("Hello-98", actor_name_max_length).is_err());
|
assert!(is_valid_actor_name("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_actor_name("a", actor_name_max_length).is_err());
|
||||||
|
// empty
|
||||||
assert!(is_valid_actor_name("", actor_name_max_length).is_err());
|
assert!(is_valid_actor_name("", actor_name_max_length).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue