fix(用户管理): 修复用户列表页面加载失败问题
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled

修复用户列表页面加载失败导致测试超时的问题,确保页面元素正确渲染
This commit is contained in:
iven
2026-04-19 08:46:28 +08:00
parent 0ee9d22634
commit 841766b168
174 changed files with 26366 additions and 675 deletions

View File

@@ -5,6 +5,7 @@ pub mod error;
pub mod events;
pub mod module;
pub mod rbac;
pub mod sanitize;
pub mod types;
// 便捷导出

View File

@@ -0,0 +1,100 @@
/// HTML/Script 内容清理工具。
///
/// 在用户输入进入数据库之前,剥离所有 HTML 标签,防止存储型 XSS。
/// 覆盖场景:用户名、显示名、邮箱、电话等字符串字段。
/// 剥离字符串中的所有 HTML 标签,返回纯文本。
///
/// ```rust
/// use erp_core::sanitize::strip_html_tags;
/// assert_eq!(strip_html_tags("<script>alert(1)</script>"), "alert(1)");
/// assert_eq!(strip_html_tags("<img src=x onerror=alert(1)>"), "");
/// assert_eq!(strip_html_tags("Hello <b>World</b>"), "Hello World");
/// ```
pub fn strip_html_tags(input: &str) -> String {
let mut result = String::with_capacity(input.len());
let mut in_tag = false;
let mut depth = 0usize;
for ch in input.chars() {
match ch {
'<' => {
in_tag = true;
depth += 1;
}
'>' => {
if depth > 0 {
depth -= 1;
}
if depth == 0 {
in_tag = false;
}
}
_ => {
if !in_tag {
result.push(ch);
}
}
}
}
result.trim().to_string()
}
/// 对 Option<String> 类型的字段进行清理。
pub fn sanitize_option(input: Option<String>) -> Option<String> {
input.map(|s| strip_html_tags(&s)).filter(|s| !s.is_empty())
}
/// 对 String 类型的必填字段进行清理。
pub fn sanitize_string(input: &str) -> String {
strip_html_tags(input)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn strips_script_tag() {
assert_eq!(strip_html_tags("<script>alert('xss')</script>"), "alert('xss')");
}
#[test]
fn strips_img_onerror() {
assert_eq!(strip_html_tags("<img src=x onerror=alert(1)>"), "");
}
#[test]
fn strips_bold_tags() {
assert_eq!(strip_html_tags("Hello <b>World</b>"), "Hello World");
}
#[test]
fn no_tags_passthrough() {
assert_eq!(strip_html_tags("Normal text"), "Normal text");
}
#[test]
fn nested_tags() {
assert_eq!(strip_html_tags("<div><p>text</p></div>"), "text");
}
#[test]
fn sanitize_option_some() {
assert_eq!(
sanitize_option(Some("<script>evil</script>".to_string())),
Some("evil".to_string())
);
}
#[test]
fn sanitize_option_none() {
assert_eq!(sanitize_option(None), None);
}
#[test]
fn sanitize_option_becomes_empty() {
assert_eq!(sanitize_option(Some("<img>".to_string())), None);
}
}