sa_token_core/token/
mod.rs1use chrono::{DateTime, Utc};
6use serde::{Deserialize, Serialize};
7
8pub mod generator;
9pub mod validator;
10pub mod jwt;
11pub mod map;
12
13pub use generator::TokenGenerator;
14pub use validator::TokenValidator;
15pub use jwt::{JwtManager, JwtClaims, JwtAlgorithm};
16
17#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
19pub struct TokenValue(String);
20
21impl TokenValue {
22 pub fn new(value: impl Into<String>) -> Self {
23 Self(value.into())
24 }
25
26 pub fn as_str(&self) -> &str {
27 &self.0
28 }
29}
30
31impl From<String> for TokenValue {
32 fn from(s: String) -> Self {
33 Self(s)
34 }
35}
36
37impl From<TokenValue> for String {
38 fn from(v: TokenValue) -> Self {
39 v.0
40 }
41}
42
43impl std::fmt::Display for TokenValue {
44 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45 write!(f, "{}", self.0)
46 }
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize)]
67pub struct TokenInfo {
68 pub token: TokenValue,
70
71 pub login_id: String,
73
74 pub login_type: String,
76
77 pub create_time: DateTime<Utc>,
79
80 pub last_active_time: DateTime<Utc>,
82
83 pub expire_time: Option<DateTime<Utc>>,
85
86 pub device: Option<String>,
88
89 pub extra_data: Option<serde_json::Value>,
91
92 pub nonce: Option<String>,
94
95 pub refresh_token: Option<String>,
97
98 pub refresh_token_expire_time: Option<DateTime<Utc>>,
100}
101
102impl TokenInfo {
103 pub fn new(token: TokenValue, login_id: impl Into<String>) -> Self {
104 let now = Utc::now();
105 Self {
106 token,
107 login_id: login_id.into(),
108 login_type: "default".to_string(),
109 create_time: now,
110 last_active_time: now,
111 expire_time: None,
112 device: None,
113 extra_data: None,
114 nonce: None,
115 refresh_token: None,
116 refresh_token_expire_time: None,
117 }
118 }
119
120 pub fn is_expired(&self) -> bool {
121 if let Some(expire_time) = self.expire_time {
122 Utc::now() > expire_time
123 } else {
124 false
125 }
126 }
127
128 pub fn update_active_time(&mut self) {
129 self.last_active_time = Utc::now();
130 }
131
132 pub fn is_freeze(&self, active_timeout: i64) -> bool {
136 if active_timeout <= 0 {
137 return false;
138 }
139 Utc::now()
140 .signed_duration_since(self.last_active_time)
141 .num_seconds()
142 > active_timeout
143 }
144}
145
146#[cfg(test)]
147mod tests {
148 use super::*;
149
150 #[test]
151 fn test_is_freeze_respects_active_timeout() {
152 let mut info = TokenInfo::new(TokenValue::new("t"), "u");
153 info.last_active_time = Utc::now() - chrono::Duration::seconds(120);
154 assert!(info.is_freeze(60));
155 assert!(!info.is_freeze(-1));
156 assert!(!info.is_freeze(0));
157 }
158}
159
160#[derive(Debug, Clone)]
162pub struct TokenSign {
163 pub value: String,
164 pub device: Option<String>,
165}