fix(用户管理): 修复用户列表页面加载失败问题
修复用户列表页面加载失败导致测试超时的问题,确保页面元素正确渲染
This commit is contained in:
@@ -5,6 +5,7 @@ pub mod error;
|
||||
pub mod events;
|
||||
pub mod module;
|
||||
pub mod rbac;
|
||||
pub mod sanitize;
|
||||
pub mod types;
|
||||
|
||||
// 便捷导出
|
||||
|
||||
100
crates/erp-core/src/sanitize.rs
Normal file
100
crates/erp-core/src/sanitize.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user