diff --git a/crates/presenter/src/dto/accounts.rs b/crates/presenter/src/dto/accounts.rs index 4ca9c5f..eda6885 100644 --- a/crates/presenter/src/dto/accounts.rs +++ b/crates/presenter/src/dto/accounts.rs @@ -12,6 +12,7 @@ mod failure; mod kind; +mod name; mod redact; #[cfg(test)] #[path = "accounts/tests.rs"] @@ -19,6 +20,7 @@ mod tests; pub use failure::{AccountNotice, AccountNoticeCode, LoginFailure}; pub use kind::AccountKind; +pub use name::valid_offline_name; pub use redact::{looks_like_jwt, redact, REDACTED}; use serde::{Deserialize, Serialize}; @@ -76,17 +78,6 @@ impl AccountView { } } -/// 离线名字的**界面契约**(3–16 位 ascii 字母/数字/下划线)。 -/// -/// 放在 `dto` 而不是 host 里:它是 UI(提交按钮能不能点)与 host(写盘前的最后一道校验) -/// 共用的**同一个判据**——两处各写一遍就会出现「按钮亮着但必然失败」的坑。 -/// core 侧还有一道同名规则做兜底(`offline_meta`),这里只管界面这条。 -#[must_use] -pub fn valid_offline_name(name: &str) -> bool { - let len = name.chars().count(); - (3..=16).contains(&len) && name.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') -} - /// 一张皮肤原图。 /// /// **停在「原图」这一层是刻意的**:presenter 不引入图片解码依赖(`presenter-no-ui` + diff --git a/crates/presenter/src/dto/accounts/name.rs b/crates/presenter/src/dto/accounts/name.rs new file mode 100644 index 0000000..1eb48e9 --- /dev/null +++ b/crates/presenter/src/dto/accounts/name.rs @@ -0,0 +1,29 @@ +//! 离线档案的名字契约(**UI 与 host 共用的同一个判据**)。 +//! +//! 放在 `dto` 而不是 host 里:UI 用它决定「创建档案」按钮亮不亮,host 用它做写盘前校验。 +//! 两处各写一遍,迟早会漂成「按钮亮着但必然失败」——那正是复审 r1 P2-2 的一半。 +//! core 侧还有一道同名规则做兜底(`auth::offline::offline_meta`),这里只管界面这条。 + +/// 3–16 位 ascii 字母 / 数字 / 下划线。 +#[must_use] +pub fn valid_offline_name(name: &str) -> bool { + let len = name.chars().count(); + (3..=16).contains(&len) && name.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn the_rule_is_three_to_sixteen_ascii_word_chars() { + assert!(valid_offline_name("Steve")); + assert!(valid_offline_name("a_1")); + assert!(valid_offline_name("abcdefghijklmnop"), "16 位是上限"); + assert!(!valid_offline_name("ab"), "太短"); + assert!(!valid_offline_name("abcdefghijklmnopq"), "太长"); + assert!(!valid_offline_name("has space")); + assert!(!valid_offline_name("中文名字"), "非 ascii"); + assert!(!valid_offline_name("")); + } +}