Skip to main content

openclaw_node/
validation.rs

1//! Input validation bindings.
2
3use napi_derive::napi;
4
5use openclaw_core::types::{AgentId, ChannelId, PeerId, PeerType, SessionKey};
6
7/// Validate a message content string.
8///
9/// Performs:
10/// - Length check (default max 100KB)
11/// - Null byte removal
12/// - Unicode normalization
13///
14/// Returns JSON: `{"valid": true, "sanitized": "..."}` or `{"valid": false, "error": "..."}`
15#[napi]
16#[must_use]
17pub fn validate_message(content: String, max_length: Option<u32>) -> String {
18    let max_len = max_length.unwrap_or(100_000) as usize;
19    match openclaw_core::validation::validate_message_content(&content, max_len) {
20        Ok(sanitized) => serde_json::json!({"valid": true, "sanitized": sanitized}).to_string(),
21        Err(e) => serde_json::json!({"valid": false, "error": e.to_string()}).to_string(),
22    }
23}
24
25/// Validate a file path for safety.
26///
27/// Checks for:
28/// - Path traversal attempts
29/// - Null bytes
30/// - Absolute paths starting with /
31///
32/// Returns JSON: `{"valid": true}` or `{"valid": false, "error": "..."}`
33#[napi]
34#[must_use]
35pub fn validate_path(path: String) -> String {
36    match openclaw_core::validation::validate_path(&path) {
37        Ok(()) => serde_json::json!({"valid": true}).to_string(),
38        Err(e) => serde_json::json!({"valid": false, "error": e.to_string()}).to_string(),
39    }
40}
41
42/// Build a session key from components.
43///
44/// # Arguments
45///
46/// * `agent_id` - The agent ID
47/// * `channel` - Channel ID (e.g., "telegram", "discord")
48/// * `account_id` - Account/bot ID on the channel
49/// * `peer_type` - "dm", "group", "channel", or "thread"
50/// * `peer_id` - The peer/user/group ID
51#[napi]
52#[must_use]
53pub fn build_session_key(
54    agent_id: String,
55    channel: String,
56    account_id: String,
57    peer_type: String,
58    peer_id: String,
59) -> String {
60    let pt = match peer_type.as_str() {
61        "dm" => PeerType::Dm,
62        "group" => PeerType::Group,
63        "channel" => PeerType::Channel,
64        "thread" => PeerType::Thread,
65        _ => PeerType::Dm,
66    };
67
68    SessionKey::build(
69        &AgentId::new(&agent_id),
70        &ChannelId::new(&channel),
71        &account_id,
72        pt,
73        &PeerId::new(&peer_id),
74    )
75    .as_ref()
76    .to_string()
77}