254 lines
6.2 KiB
Rust
254 lines
6.2 KiB
Rust
//! NAC Lens协议类型定义
|
||
//!
|
||
//! 定义NAC Lens协议的核心数据结构
|
||
|
||
use nac_udm::primitives::{Hash, Timestamp};
|
||
use serde::{Deserialize, Serialize};
|
||
use serde_json::Value;
|
||
|
||
/// NAC Lens请求
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct NacLensRequest {
|
||
/// JSON-RPC版本(固定为"3.0")
|
||
pub jsonrpc: String,
|
||
|
||
/// 请求ID
|
||
pub id: RequestId,
|
||
|
||
/// 方法名
|
||
pub method: String,
|
||
|
||
/// 参数
|
||
pub params: Value,
|
||
|
||
/// 时间戳(NAC扩展)
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
pub timestamp: Option<Timestamp>,
|
||
|
||
/// 资产DNA哈希(NAC扩展)
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
pub dna_hash: Option<Hash>,
|
||
|
||
/// 签名(NAC扩展)
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
pub signature: Option<String>,
|
||
}
|
||
|
||
/// NAC Lens响应
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct NacLensResponse {
|
||
/// JSON-RPC版本
|
||
pub jsonrpc: String,
|
||
|
||
/// 请求ID
|
||
pub id: RequestId,
|
||
|
||
/// 结果(成功时)
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
pub result: Option<Value>,
|
||
|
||
/// 错误(失败时)
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
pub error: Option<NAC Lens3Error>,
|
||
|
||
/// 时间戳(NAC扩展)
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
pub timestamp: Option<Timestamp>,
|
||
|
||
/// 服务器签名(NAC扩展)
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
pub server_signature: Option<String>,
|
||
}
|
||
|
||
/// NAC Lens错误
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct NAC Lens3Error {
|
||
/// 错误代码
|
||
pub code: i32,
|
||
|
||
/// 错误消息
|
||
pub message: String,
|
||
|
||
/// 错误数据(可选)
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
pub data: Option<Value>,
|
||
}
|
||
|
||
/// 请求ID类型
|
||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
||
#[serde(untagged)]
|
||
pub enum RequestId {
|
||
/// 数字ID
|
||
Number(u64),
|
||
|
||
/// 字符串ID
|
||
String(String),
|
||
|
||
/// 空ID(通知)
|
||
Null,
|
||
}
|
||
|
||
/// NAC Lens批量请求
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct NAC Lens3BatchRequest {
|
||
/// 批量请求列表
|
||
pub requests: Vec<NacLensRequest>,
|
||
}
|
||
|
||
/// NAC Lens批量响应
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct NAC Lens3BatchResponse {
|
||
/// 批量响应列表
|
||
pub responses: Vec<NacLensResponse>,
|
||
}
|
||
|
||
/// NAC Lens错误代码
|
||
pub mod error_codes {
|
||
/// 解析错误
|
||
pub const PARSE_ERROR: i32 = -32700;
|
||
|
||
/// 无效请求
|
||
pub const INVALID_REQUEST: i32 = -32600;
|
||
|
||
/// 方法不存在
|
||
pub const METHOD_NOT_FOUND: i32 = -32601;
|
||
|
||
/// 无效参数
|
||
pub const INVALID_PARAMS: i32 = -32602;
|
||
|
||
/// 内部错误
|
||
pub const INTERNAL_ERROR: i32 = -32603;
|
||
|
||
/// 服务器错误范围
|
||
pub const SERVER_ERROR_START: i32 = -32000;
|
||
pub const SERVER_ERROR_END: i32 = -32099;
|
||
|
||
// NAC扩展错误代码
|
||
|
||
/// 时间戳过期
|
||
pub const TIMESTAMP_EXPIRED: i32 = -33001;
|
||
|
||
/// DNA验证失败
|
||
pub const DNA_VERIFICATION_FAILED: i32 = -33002;
|
||
|
||
/// 签名无效
|
||
pub const INVALID_SIGNATURE: i32 = -33003;
|
||
|
||
/// 合规检查失败
|
||
pub const COMPLIANCE_CHECK_FAILED: i32 = -33004;
|
||
|
||
/// 权限不足
|
||
pub const INSUFFICIENT_PERMISSIONS: i32 = -33005;
|
||
}
|
||
|
||
impl NacLensRequest {
|
||
/// 创建新请求
|
||
pub fn new(id: RequestId, method: impl Into<String>, params: Value) -> Self {
|
||
Self {
|
||
jsonrpc: "3.0".to_string(),
|
||
id,
|
||
method: method.into(),
|
||
params,
|
||
timestamp: Some(Timestamp::now()),
|
||
dna_hash: None,
|
||
signature: None,
|
||
}
|
||
}
|
||
|
||
/// 验证请求
|
||
pub fn validate(&self) -> Result<(), String> {
|
||
if self.jsonrpc != "3.0" {
|
||
return Err("Invalid JSON-RPC version".to_string());
|
||
}
|
||
|
||
if self.method.is_empty() {
|
||
return Err("Method name cannot be empty".to_string());
|
||
}
|
||
|
||
// 验证时间戳(如果存在)
|
||
if let Some(ts) = self.timestamp {
|
||
let now = Timestamp::now();
|
||
let diff = if now > ts { now - ts } else { ts - now };
|
||
|
||
// 允许5分钟的时间偏差
|
||
if diff > 300 {
|
||
return Err("Timestamp expired or too far in future".to_string());
|
||
}
|
||
}
|
||
|
||
Ok(())
|
||
}
|
||
}
|
||
|
||
impl NacLensResponse {
|
||
/// 创建成功响应
|
||
pub fn success(id: RequestId, result: Value) -> Self {
|
||
Self {
|
||
jsonrpc: "3.0".to_string(),
|
||
id,
|
||
result: Some(result),
|
||
error: None,
|
||
timestamp: Some(Timestamp::now()),
|
||
server_signature: None,
|
||
}
|
||
}
|
||
|
||
/// 创建错误响应
|
||
pub fn error(id: RequestId, code: i32, message: impl Into<String>) -> Self {
|
||
Self {
|
||
jsonrpc: "3.0".to_string(),
|
||
id,
|
||
result: None,
|
||
error: Some(NAC Lens3Error {
|
||
code,
|
||
message: message.into(),
|
||
data: None,
|
||
}),
|
||
timestamp: Some(Timestamp::now()),
|
||
server_signature: None,
|
||
}
|
||
}
|
||
}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
use serde_json::json;
|
||
|
||
#[test]
|
||
fn test_request_creation() {
|
||
let req = NacLensRequest::new(
|
||
RequestId::Number(1),
|
||
"test_method",
|
||
json!({"param": "value"}),
|
||
);
|
||
|
||
assert_eq!(req.jsonrpc, "3.0");
|
||
assert_eq!(req.method, "test_method");
|
||
assert!(req.timestamp.is_some());
|
||
}
|
||
|
||
#[test]
|
||
fn test_request_validation() {
|
||
let req = NacLensRequest::new(
|
||
RequestId::Number(1),
|
||
"test_method",
|
||
json!({}),
|
||
);
|
||
|
||
assert!(req.validate().is_ok());
|
||
}
|
||
|
||
#[test]
|
||
fn test_response_creation() {
|
||
let resp = NacLensResponse::success(
|
||
RequestId::Number(1),
|
||
json!({"result": "success"}),
|
||
);
|
||
|
||
assert_eq!(resp.jsonrpc, "3.0");
|
||
assert!(resp.result.is_some());
|
||
assert!(resp.error.is_none());
|
||
}
|
||
}
|