chimes_rust/utils/
mod.rs

1use std::fmt::Debug;
2use std::time::SystemTime;
3
4use chimes_utils::AppConfig;
5
6use chrono::offset::Local;
7use chrono::DateTime;
8use jsonwebtoken::{DecodingKey, EncodingKey, Header};
9use serde_derive::{Deserialize, Serialize};
10
11use std::collections::HashMap;
12
13mod auth;
14pub use auth::*;
15
16mod app;
17pub use app::*;
18
19#[allow(dead_code)]
20pub fn num_to_string(n: i64) -> String {
21    let base_codec = [
22        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
23        'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '7', '8', '9',
24    ];
25    let len = base_codec.len() as i64;
26    let mut t = n;
27    let mut result = "".to_string();
28    while t > 0 {
29        let idx = (t % len) as usize;
30        let ch = base_codec[idx];
31        t /= len;
32        result.insert(0, ch);
33    }
34    result
35}
36
37#[allow(dead_code)]
38pub fn f32_to_decimal(f: f32) -> Option<rbatis::Decimal> {
39    match rbatis::Decimal::from_str(format!("{:.2}", f).as_str()) {
40        Ok(r) => Some(r),
41        Err(_) => None,
42    }
43}
44
45#[allow(dead_code)]
46pub fn decimal_to_f32(dc: Option<rbatis::Decimal>) -> f32 {
47    match dc {
48        Some(r) => r.to_string().parse::<f32>().unwrap_or(0f32),
49        None => 0f32,
50    }
51}
52
53#[allow(dead_code)]
54pub fn make_decimal_negative(dc: Option<rbatis::Decimal>) -> Option<rbatis::Decimal> {
55    match dc {
56        Some(r) => match r.to_string().parse::<f32>() {
57            Ok(t) => f32_to_decimal(-t),
58            Err(_) => f32_to_decimal(0f32),
59        },
60        None => f32_to_decimal(0f32),
61    }
62}
63
64#[allow(dead_code)]
65pub fn generate_rand_string(len: usize) -> String {
66    let mut retkey = "".to_string();
67
68    while retkey.len() < len {
69        let rng = rand::random::<u16>();
70        let key = num_to_string(rng as i64);
71        retkey += key.as_str();
72    }
73
74    retkey.chars().take(len).collect()
75}
76
77#[allow(dead_code)]
78pub fn get_local_timestamp() -> u64 {
79    let now = SystemTime::now();
80    let date: DateTime<Local> = now.into();
81    date.timestamp_millis() as u64
82}
83
84#[allow(dead_code)]
85pub fn parse_query(query_string: &str) -> HashMap<String, String> {
86    if query_string.is_empty() {
87        return HashMap::new();
88    }
89    let q_a: Vec<&str> = query_string.split('&').collect();
90    let mut res: HashMap<String, String> = HashMap::new();
91    use percent_encoding::percent_decode;
92    for s in q_a {
93        // let ss: &str = s;
94        let kv: Vec<&str> = s.split('=').collect();
95        let kvalue = percent_decode(kv[1].as_bytes()).decode_utf8().unwrap();
96        res.insert(kv[0].to_string(), kvalue.to_string());
97    }
98    res
99}
100
101#[allow(dead_code)]
102pub fn get_hash_value(query_params: &HashMap<String, String>, key: &str) -> String {
103    match query_params.get(key) {
104        Some(val) => val.clone(),
105        None => "".to_owned(),
106    }
107}
108
109#[derive(Debug, Serialize, Deserialize)]
110pub struct UserClaims {
111    pub aud: String,
112    pub sub: String,
113    pub exp: usize,
114}
115
116impl UserClaims {
117    pub fn encode(&self) -> Option<String> {
118        let conf = AppConfig::get().lock().unwrap().to_owned();
119
120        match jsonwebtoken::encode(
121            &Header::default(),
122            &self,
123            &EncodingKey::from_secret(conf.webserver_conf.rsa_cert.as_bytes()),
124        ) {
125            Ok(t) => Some(t),
126            Err(_) => None,
127        }
128    }
129
130    pub fn decode(token: &str) -> Option<Self> {
131        let conf = AppConfig::get().lock().unwrap().to_owned();
132        let validation = jsonwebtoken::Validation::new(jsonwebtoken::Algorithm::HS256);
133        match jsonwebtoken::decode::<UserClaims>(
134            token,
135            &DecodingKey::from_secret(conf.webserver_conf.rsa_cert.as_bytes()),
136            &validation,
137        ) {
138            Ok(c) => Some(c.claims),
139            Err(err) => {
140                match *err.kind() {
141                    jsonwebtoken::errors::ErrorKind::InvalidToken => {
142                        log::error!("Token is invalid")
143                    } // Example on how to handle a specific error
144                    jsonwebtoken::errors::ErrorKind::InvalidIssuer => {
145                        log::error!("Issuer is invalid")
146                    } // Example on how to handle a specific error
147                    _ => log::error!("Some other errors"),
148                };
149
150                None
151            }
152        }
153    }
154}
155
156fn field_is_none<T>(t: &Option<T>) -> bool {
157    t.is_none()
158}
159
160#[derive(Debug, Clone, Default, Serialize, Deserialize)]
161pub struct MenuMetadata {
162    pub icon: Option<String>,
163    pub no_cache: bool,
164    pub title: Option<String>,
165}
166
167#[derive(Debug, Clone, Default, Serialize, Deserialize)]
168pub struct MenuTreeModel {
169    #[serde(skip_serializing_if = "field_is_none")]
170    pub always_show: Option<bool>,
171    pub id: i64,
172    pub meta: MenuMetadata,
173    pub name: String,
174    pub path: String,
175    pub hidden: bool,
176    pub iframe: bool,
177    pub permission: String,
178    pub component: String,
179    #[serde(skip_serializing_if = "field_is_none")]
180    pub pid: Option<i64>,
181    pub children: Vec<MenuTreeModel>,
182    #[serde(skip_serializing_if = "field_is_none")]
183    pub redirect: Option<String>,
184    pub sort: i32,
185}
186
187#[allow(dead_code)]
188pub fn num_to_string_v2(n: i64) -> String {
189    let base_codec = [
190        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't',
191        'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M',
192        'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7',
193        '8', '9',
194    ];
195    let len = base_codec.len() as i64;
196    let mut t = n;
197    let mut result = "".to_string();
198    while t > 0 {
199        let idx = (t % len) as usize;
200        let ch = base_codec[idx];
201        t /= len;
202        result.insert(0, ch);
203    }
204    result
205}
206
207#[allow(dead_code)]
208pub fn generate_rand_string_v2(len: usize) -> String {
209    let mut retkey = "".to_string();
210
211    while retkey.len() < len {
212        let rng = rand::random::<u16>();
213        let key = num_to_string_v2(rng as i64);
214        retkey += key.as_str();
215    }
216
217    retkey.chars().take(len).collect()
218}
219
220#[allow(dead_code)]
221pub fn number_to_string(n: i64) -> String {
222    let base_codec = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'];
223    let len = base_codec.len() as i64;
224    let mut t = n;
225    let mut result = "".to_string();
226    while t > 0 {
227        let idx = (t % len) as usize;
228        let ch = base_codec[idx];
229        t /= len;
230        result.insert(0, ch);
231    }
232    result
233}
234
235#[allow(dead_code)]
236pub fn generate_rand_numberstring(len: usize) -> String {
237    let mut retkey = "".to_string();
238
239    while retkey.len() < len {
240        let rng = rand::random::<u16>();
241        let key = number_to_string(rng as i64);
242        retkey += key.as_str();
243    }
244
245    retkey.chars().take(len).collect()
246}