refactor(presenter): M114 离线名字契约拆到 dto/accounts/name.rs(守 400 行,补边界用例)

dto/accounts.rs 因搬入 valid_offline_name 涨到 404 行;按模块拆分惯例独立成文件,
并补 16 位上限 / 17 位超限 / 空串 / 非 ascii 的边界用例。
This commit is contained in:
AskaEth committed 2026-11-05 05:10:14 +08:00
1 parent 178f6ebbff
commit e09411f975
2 files changed
+31 -11

No files matched your search

+2 -11
View File
@@ -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` +
+29
View File
@@ -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(""));
}
}