sz_rust_core/plugin/
schema.rs1use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct SysUser {
14 pub id: i64,
15 pub tenant_id: i64,
16 pub username: String,
17 pub display_name: String,
18 #[serde(skip_serializing)]
19 pub password_hash: String,
20 pub email: Option<String>,
21 pub phone: Option<String>,
22 pub status: String,
23 pub extra: serde_json::Value,
24 pub created_at: chrono::DateTime<chrono::Utc>,
25 pub updated_at: chrono::DateTime<chrono::Utc>,
26}
27
28#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct SysPermission {
31 pub id: i64,
32 pub tenant_id: i64,
33 pub name: String,
34 pub description: String,
35 pub resource: String,
36 pub action: String,
37 pub conditions: Option<serde_json::Value>,
38 pub created_at: chrono::DateTime<chrono::Utc>,
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct SysEvent {
47 pub id: i64,
48 pub tenant_id: i64,
49 pub event_type: String,
50 pub source_plugin: String,
51 pub payload: serde_json::Value,
52 pub delivered: bool,
53 pub delivered_at: Option<chrono::DateTime<chrono::Utc>>,
54 pub retry_count: i32,
55 pub max_retries: i32,
56 pub created_at: chrono::DateTime<chrono::Utc>,
57 pub updated_at: chrono::DateTime<chrono::Utc>,
58}
59
60impl SysUser {
61 pub fn table_name() -> &'static str {
62 "sys_users"
63 }
64}
65
66impl SysPermission {
67 pub fn table_name() -> &'static str {
68 "sys_permissions"
69 }
70}
71
72impl SysEvent {
73 pub fn table_name() -> &'static str {
74 "sys_events"
75 }
76
77 pub fn new(
79 tenant_id: i64,
80 event_type: impl Into<String>,
81 source_plugin: impl Into<String>,
82 payload: serde_json::Value,
83 ) -> Self {
84 let now = chrono::Utc::now();
85 Self {
86 id: 0,
87 tenant_id,
88 event_type: event_type.into(),
89 source_plugin: source_plugin.into(),
90 payload,
91 delivered: false,
92 delivered_at: None,
93 retry_count: 0,
94 max_retries: 3,
95 created_at: now,
96 updated_at: now,
97 }
98 }
99
100 pub fn mark_delivered(&mut self) {
102 self.delivered = true;
103 self.delivered_at = Some(chrono::Utc::now());
104 self.updated_at = chrono::Utc::now();
105 }
106
107 pub fn increment_retry(&mut self) {
109 self.retry_count += 1;
110 self.updated_at = chrono::Utc::now();
111 }
112
113 pub fn is_exhausted(&self) -> bool {
115 self.retry_count >= self.max_retries
116 }
117}
118
119#[cfg(test)]
120mod tests {
121 use super::*;
122
123 #[test]
124 fn test_sys_event_new() {
125 let event = SysEvent::new(1, "order.created", "shop", serde_json::json!({"id": 1}));
126 assert_eq!(event.tenant_id, 1);
127 assert_eq!(event.event_type, "order.created");
128 assert!(!event.delivered);
129 assert_eq!(event.retry_count, 0);
130 assert_eq!(event.max_retries, 3);
131 }
132
133 #[test]
134 fn test_mark_delivered() {
135 let mut event = SysEvent::new(1, "test", "test", serde_json::json!({}));
136 event.mark_delivered();
137 assert!(event.delivered);
138 assert!(event.delivered_at.is_some());
139 }
140
141 #[test]
142 fn test_retry_exhaustion() {
143 let mut event = SysEvent::new(1, "test", "test", serde_json::json!({}));
144 assert!(!event.is_exhausted());
145 event.increment_retry();
146 event.increment_retry();
147 event.increment_retry();
148 assert!(event.is_exhausted());
149 }
150
151 #[test]
152 fn test_password_hash_skip_serializing() {
153 let user = SysUser {
154 id: 1,
155 tenant_id: 1,
156 username: "admin".to_string(),
157 display_name: "Admin".to_string(),
158 password_hash: "secret_hash".to_string(),
159 email: None,
160 phone: None,
161 status: "active".to_string(),
162 extra: serde_json::json!({}),
163 created_at: chrono::Utc::now(),
164 updated_at: chrono::Utc::now(),
165 };
166 let json = serde_json::to_string(&user).expect("序列化失败");
167 assert!(!json.contains("password_hash"), "敏感字段不应出现在 JSON 中");
168 assert!(!json.contains("secret_hash"), "敏感值不应出现在 JSON 中");
169 }
170}