From fcf43dc0bc3083b62925fe3d919bb82396587719 Mon Sep 17 00:00:00 2001 From: jakubmanczak Date: Tue, 24 Feb 2026 02:06:24 +0100 Subject: [PATCH] case-insensitive UserHandles --- src/database/migrations/2026-02-20--01.sql | 2 +- src/users/handle.rs | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/database/migrations/2026-02-20--01.sql b/src/database/migrations/2026-02-20--01.sql index 9c62387..a994ff5 100644 --- a/src/database/migrations/2026-02-20--01.sql +++ b/src/database/migrations/2026-02-20--01.sql @@ -1,6 +1,6 @@ CREATE TABLE users ( id BLOB NOT NULL UNIQUE PRIMARY KEY, -- UUIDv7 as bytes - handle TEXT NOT NULL UNIQUE, + handle TEXT NOT NULL UNIQUE COLLATE NOCASE, password TEXT, -- hashed, nullable in case of OAuth2-only login prof_pic TEXT -- link probably ); diff --git a/src/users/handle.rs b/src/users/handle.rs index e75f6d7..181c5aa 100644 --- a/src/users/handle.rs +++ b/src/users/handle.rs @@ -1,4 +1,4 @@ -use std::{fmt::Display, ops::Deref, str::FromStr}; +use std::{fmt::Display, hash::Hash, ops::Deref, str::FromStr}; use rusqlite::{ Result as RusqliteResult, @@ -6,7 +6,7 @@ use rusqlite::{ }; use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(into = "String")] #[serde(try_from = "String")] pub struct UserHandle(String); @@ -42,6 +42,19 @@ impl UserHandle { &self.0 } } + +impl PartialEq for UserHandle { + fn eq(&self, other: &Self) -> bool { + self.0.eq_ignore_ascii_case(&other.0) + } +} +impl Eq for UserHandle {} +impl Hash for UserHandle { + fn hash(&self, state: &mut H) { + self.0.to_ascii_lowercase().hash(state); + } +} + impl AsRef for UserHandle { fn as_ref(&self) -> &str { &self.0