sa_token_core/session/
terminal.rs1use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
14pub struct SaTerminalInfo {
15 pub index: i32,
17 pub token_value: String,
19 pub device_type: String,
21 pub device_id: Option<String>,
23 pub extra_data: Option<serde_json::Value>,
25 pub create_time: i64,
27}
28
29impl SaTerminalInfo {
30 pub fn new(token_value: impl Into<String>, device_type: impl Into<String>) -> Self {
32 Self {
33 index: 0,
34 token_value: token_value.into(),
35 device_type: device_type.into(),
36 device_id: None,
37 extra_data: None,
38 create_time: chrono::Utc::now().timestamp_millis(),
39 }
40 }
41
42 pub fn with_device_id(mut self, device_id: impl Into<String>) -> Self {
44 self.device_id = Some(device_id.into());
45 self
46 }
47
48 pub fn with_extra_data(mut self, extra: serde_json::Value) -> Self {
50 self.extra_data = Some(extra);
51 self
52 }
53
54 pub fn have_extra_data(&self) -> bool {
56 matches!(&self.extra_data, Some(v) if !v.is_null())
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63 use serde_json::json;
64
65 #[test]
66 fn test_new_defaults() {
67 let t = SaTerminalInfo::new("tok1", "PC");
68 assert_eq!(t.index, 0);
69 assert_eq!(t.token_value, "tok1");
70 assert_eq!(t.device_type, "PC");
71 assert!(t.device_id.is_none());
72 assert!(!t.have_extra_data());
73 assert!(t.create_time > 0);
74 }
75
76 #[test]
77 fn test_with_extra_data() {
78 let t = SaTerminalInfo::new("tok1", "APP").with_extra_data(json!({"k": 1}));
79 assert!(t.have_extra_data());
80 }
81
82 #[test]
83 fn test_serde_round_trip() {
84 let t = SaTerminalInfo::new("tok1", "PC")
85 .with_device_id("dev-1")
86 .with_extra_data(json!({"ip": "127.0.0.1"}));
87 let json = serde_json::to_string(&t).unwrap();
88 let back: SaTerminalInfo = serde_json::from_str(&json).unwrap();
89 assert_eq!(t, back);
90 }
91}