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