Skip to content

Commit

Permalink
Make account names case-insensitive (#407)
Browse files Browse the repository at this point in the history
* make names insensitive

* add dev dependency

* make users table case-insensitive

* use unicode collation

* always use username from database

* adjust regex

* add validator test

* up cargo deps

* up yarn deps

* flake.lock: Update

Flake lock file updates:

• Updated input 'rust-overlay':
    'github:oxalica/rust-overlay/603e4962d7d2225ba2caf66b0eabfcaa9a93c490' (2023-11-09)
  → 'github:oxalica/rust-overlay/41f7b0618052430d3a050e8f937030d00a2fcced' (2023-11-10)

* add accounts table tests

* add users table tests
  • Loading branch information
aumetra authored Nov 11, 2023
1 parent 22efa4a commit 110b4b3
Show file tree
Hide file tree
Showing 28 changed files with 677 additions and 385 deletions.
33 changes: 19 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/kitsune-blocking/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ version.workspace = true
once_cell = "1.18.0"
rayon = "1.8.0"
thiserror = "1.0.50"
tokio = { version = "1.33.0", features = ["rt", "sync"] }
tokio = { version = "1.34.0", features = ["rt", "sync"] }
tracing = "0.1.40"
2 changes: 1 addition & 1 deletion crates/kitsune-cache/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ tracing = "0.1.40"
typed-builder = "0.18.0"

[dev-dependencies]
tokio = { version = "1.33.0", features = ["macros", "rt"] }
tokio = { version = "1.34.0", features = ["macros", "rt"] }
2 changes: 1 addition & 1 deletion crates/kitsune-captcha/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ edition.workspace = true

[dependencies]
enum_dispatch = "0.3.12"
http = "0.2.9"
http = "0.2.10"
kitsune-http-client = { path = "../kitsune-http-client" }
serde = { version = "1.0.192", features = ["derive"] }
serde_urlencoded = "0.7.1"
Expand Down
2 changes: 1 addition & 1 deletion crates/kitsune-config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ version.workspace = true
eyre = "0.6.8"
serde = { version = "1.0.192", features = ["derive"] }
smol_str = { version = "0.2.0", features = ["serde"] }
tokio = { version = "1.33.0", features = ["fs"] }
tokio = { version = "1.34.0", features = ["fs"] }
toml = { version = "0.8.8", default-features = false, features = ["parse"] }
4 changes: 2 additions & 2 deletions crates/kitsune-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ garde = { version = "0.16.2", default-features = false, features = [
globset = "0.4.13"
headers = "0.3.9"
hex-simd = { version = "0.8.0", features = ["unstable"] }
http = "0.2.9"
http = "0.2.10"
img-parts = "0.3.0"
iso8601-timestamp = "0.2.12"
kitsune-blocking = { path = "../kitsune-blocking" }
Expand Down Expand Up @@ -69,7 +69,7 @@ smol_str = "0.2.0"
speedy-uuid = { path = "../../lib/speedy-uuid", features = ["diesel"] }
thiserror = "1.0.50"
time = "0.3.30"
tokio = { version = "1.33.0", features = ["macros", "rt"] }
tokio = { version = "1.34.0", features = ["macros", "rt"] }
tracing = "0.1.40"
typed-builder = "0.18.0"
url = "2.4.1"
Expand Down
4 changes: 4 additions & 0 deletions crates/kitsune-core/src/service/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -674,27 +674,31 @@ impl AccountService {
..changeset
};
}

if let Some(ref mut note) = update.note {
note.clean_html();
changeset = UpdateAccount {
note: Some(note),
..changeset
};
}

if let Some(avatar) = update.avatar {
let media_attachment = self.attachment_service.upload(avatar).await?;
changeset = UpdateAccount {
avatar_id: Some(media_attachment.id),
..changeset
};
}

if let Some(header) = update.header {
let media_attachment = self.attachment_service.upload(header).await?;
changeset = UpdateAccount {
header_id: Some(media_attachment.id),
..changeset
};
}

if let Some(locked) = update.locked {
changeset = UpdateAccount {
locked: Some(locked),
Expand Down
2 changes: 1 addition & 1 deletion crates/kitsune-core/src/service/attachment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ mod test {
}

async fn handle(_req: Request<Body>) -> Result<Response<Body>, Infallible> {
Ok::<_, Infallible>(Response::new(Body::from("")))
Ok::<_, Infallible>(Response::new(Body::empty()))
}

async fn prepare_db(db_conn: &mut AsyncPgConnection) -> Uuid {
Expand Down
48 changes: 47 additions & 1 deletion crates/kitsune-core/src/service/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ fn is_strong_password(value: &Option<String>, _context: &()) -> garde::Result {
#[derive(Clone, TypedBuilder, Validate)]
pub struct Register {
/// Username of the new user
#[garde(length(min = 1, max = 64), pattern(r"[\w\.]+"))]
#[garde(length(min = 1, max = 64), pattern(r"^[\p{L}\p{N}\.]+$"))]
username: String,

/// Email address of the new user
Expand Down Expand Up @@ -261,3 +261,49 @@ impl UserService {
self.registrations_open
}
}

#[cfg(test)]
mod test {
use super::Register;
use garde::Validate;

#[test]
fn alphanumeric_username() {
let valid_usernames = [
"aumetra",
"AUMETRA",
"aum3tr4",
"äumäträ",
"아우멭라",
"あうめtら",
];

for username in valid_usernames {
let register = Register::builder()
.email("[email protected]".into())
.password("verysecurepassword123".into())
.username(username.into())
.build();

assert!(
register.validate(&()).is_ok(),
"{username} is considered invalid",
);
}

let invalid_usernames = [",,,", "🎃spooky", "weewoo 🚨"];

for username in invalid_usernames {
let register = Register::builder()
.email("[email protected]".into())
.password("verysecurepassword123".into())
.username(username.into())
.build();

assert!(
register.validate(&()).is_err(),
"{username} is considered valid",
);
}
}
}
5 changes: 5 additions & 0 deletions crates/kitsune-db/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,8 @@ speedy-uuid = { path = "../../lib/speedy-uuid", features = ["diesel"] }
thiserror = "1.0.50"
tracing-log = "0.2.0"
typed-builder = "0.18.0"

[dev-dependencies]
kitsune-test = { path = "../kitsune-test" }
serial_test = "2.0.0"
tokio = { version = "1.34.0", features = ["macros"] }
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
CREATE COLLATION ignore_accent_case (
provider = icu,
deterministic = false,
locale = 'und-u-ks-level1'
);

CREATE TABLE accounts (
id UUID PRIMARY KEY,
display_name TEXT,
note TEXT,
username TEXT NOT NULL,
-- Use special collation to ignore case and accent differences
username TEXT NOT NULL COLLATE ignore_accent_case,
locked BOOLEAN NOT NULL,
local BOOLEAN NOT NULL,
domain TEXT NOT NULL,
Expand Down Expand Up @@ -74,7 +81,8 @@ CREATE TABLE users (
id UUID PRIMARY KEY,
account_id UUID NOT NULL UNIQUE,
oidc_id TEXT UNIQUE,
username TEXT NOT NULL,
-- Use special collation to ignore case and accent differences
username TEXT NOT NULL COLLATE ignore_accent_case,
email TEXT NOT NULL UNIQUE,
password TEXT UNIQUE,
domain TEXT NOT NULL,
Expand Down
Loading

0 comments on commit 110b4b3

Please sign in to comment.