Skip to main content

fbc_starter/entity/
ip_info.rs

1use crate::entity::ip_detail::IpDetail;
2/// 用户 IP 信息
3///
4/// 对应 Java: IpInfo
5use serde::{Deserialize, Serialize};
6
7/// 用户 IP 信息
8#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
9#[serde(rename_all = "camelCase")]
10pub struct IpInfo {
11    /// 注册时的 IP
12    pub create_ip: Option<String>,
13
14    /// 注册时的 IP 详情
15    pub create_ip_detail: Option<IpDetail>,
16
17    /// 最新登录的 IP
18    pub update_ip: Option<String>,
19
20    /// 最新登录的 IP 详情
21    pub update_ip_detail: Option<IpDetail>,
22}
23
24impl IpInfo {
25    /// 创建新的 IpInfo 实例
26    pub fn new() -> Self {
27        Self::default()
28    }
29
30    /// 刷新 IP
31    ///
32    /// 如果 IP 为空,则不更新
33    /// 如果 create_ip 为空,则同时设置 create_ip 和 update_ip
34    /// 否则只更新 update_ip
35    pub fn refresh_ip(&mut self, ip: Option<String>) {
36        let ip = match ip {
37            Some(ip) if !ip.trim().is_empty() => ip,
38            _ => return,
39        };
40
41        self.update_ip = Some(ip.clone());
42
43        if self.create_ip.is_none() {
44            self.create_ip = Some(ip);
45        }
46    }
47
48    /// 需要刷新的 IP
49    ///
50    /// 判断更新 IP 是否需要刷新详情
51    /// 如果 update_ip_detail 存在且其 IP 与 update_ip 相同,则不需要刷新
52    /// 返回需要刷新的 IP,如果不需要刷新则返回 None
53    pub fn need_refresh_ip(&self) -> Option<&String> {
54        let not_need_refresh = self
55            .update_ip_detail
56            .as_ref()
57            .and_then(|detail| detail.ip.as_ref())
58            .map(|ip| ip == self.update_ip.as_ref().unwrap_or(&String::new()))
59            .unwrap_or(false);
60
61        if not_need_refresh {
62            None
63        } else {
64            self.update_ip.as_ref()
65        }
66    }
67
68    /// 刷新 IP 详情
69    ///
70    /// 根据 IP 详情中的 IP 地址,更新对应的 create_ip_detail 或 update_ip_detail
71    pub fn refresh_ip_detail(&mut self, ip_detail: IpDetail) {
72        if let Some(ip) = &ip_detail.ip {
73            // 如果 IP 详情中的 IP 与 create_ip 相同,更新 create_ip_detail
74            if self.create_ip.as_ref().map(|s| s == ip).unwrap_or(false) {
75                self.create_ip_detail = Some(ip_detail.clone());
76            }
77
78            // 如果 IP 详情中的 IP 与 update_ip 相同,更新 update_ip_detail
79            if self.update_ip.as_ref().map(|s| s == ip).unwrap_or(false) {
80                self.update_ip_detail = Some(ip_detail);
81            }
82        }
83    }
84}
85
86#[cfg(test)]
87mod tests {
88    use super::*;
89
90    #[test]
91    fn test_refresh_ip() {
92        let mut ip_info = IpInfo::new();
93
94        // 测试首次设置 IP
95        ip_info.refresh_ip(Some("127.0.0.1".to_string()));
96        assert_eq!(ip_info.create_ip, Some("127.0.0.1".to_string()));
97        assert_eq!(ip_info.update_ip, Some("127.0.0.1".to_string()));
98
99        // 测试更新 IP
100        ip_info.refresh_ip(Some("192.168.1.1".to_string()));
101        assert_eq!(ip_info.create_ip, Some("127.0.0.1".to_string())); // create_ip 不变
102        assert_eq!(ip_info.update_ip, Some("192.168.1.1".to_string())); // update_ip 更新
103
104        // 测试空 IP(不更新)
105        ip_info.refresh_ip(Some("".to_string()));
106        assert_eq!(ip_info.update_ip, Some("192.168.1.1".to_string())); // 不变
107
108        // 测试 None(不更新)
109        ip_info.refresh_ip(None);
110        assert_eq!(ip_info.update_ip, Some("192.168.1.1".to_string())); // 不变
111    }
112
113    #[test]
114    fn test_need_refresh_ip() {
115        let mut ip_info = IpInfo::new();
116
117        // 没有 update_ip,返回 None
118        assert_eq!(ip_info.need_refresh_ip(), None);
119
120        // 有 update_ip 但没有 update_ip_detail,需要刷新
121        ip_info.update_ip = Some("127.0.0.1".to_string());
122        assert_eq!(ip_info.need_refresh_ip(), Some(&"127.0.0.1".to_string()));
123
124        // 有 update_ip_detail 但 IP 不匹配,需要刷新
125        ip_info.update_ip_detail = Some(IpDetail::builder().ip("192.168.1.1".to_string()).build());
126        assert_eq!(ip_info.need_refresh_ip(), Some(&"127.0.0.1".to_string()));
127
128        // 有 update_ip_detail 且 IP 匹配,不需要刷新
129        ip_info.update_ip_detail = Some(IpDetail::builder().ip("127.0.0.1".to_string()).build());
130        assert_eq!(ip_info.need_refresh_ip(), None);
131    }
132
133    #[test]
134    fn test_refresh_ip_detail() {
135        let mut ip_info = IpInfo::new();
136        ip_info.create_ip = Some("127.0.0.1".to_string());
137        ip_info.update_ip = Some("192.168.1.1".to_string());
138
139        // 刷新 create_ip 的详情
140        let create_detail = IpDetail::builder()
141            .ip("127.0.0.1".to_string())
142            .city("北京".to_string())
143            .build();
144        ip_info.refresh_ip_detail(create_detail.clone());
145        assert_eq!(ip_info.create_ip_detail, Some(create_detail));
146        assert_eq!(ip_info.update_ip_detail, None);
147
148        // 刷新 update_ip 的详情
149        let update_detail = IpDetail::builder()
150            .ip("192.168.1.1".to_string())
151            .city("上海".to_string())
152            .build();
153        ip_info.refresh_ip_detail(update_detail.clone());
154        assert_eq!(ip_info.update_ip_detail, Some(update_detail));
155
156        // 刷新不匹配的 IP(不应该更新)
157        let other_detail = IpDetail::builder()
158            .ip("10.0.0.1".to_string())
159            .city("广州".to_string())
160            .build();
161        let create_detail_before = ip_info.create_ip_detail.clone();
162        let update_detail_before = ip_info.update_ip_detail.clone();
163        ip_info.refresh_ip_detail(other_detail);
164        assert_eq!(ip_info.create_ip_detail, create_detail_before);
165        assert_eq!(ip_info.update_ip_detail, update_detail_before);
166    }
167
168    #[test]
169    fn test_deserialize_from_json() {
170        let json_str = r#"{
171            "createIp": "206.237.119.215",
172            "updateIp": "120.231.232.41",
173            "createIpDetail": {
174                "ip": "206.237.119.215",
175                "isp": "",
176                "area": "",
177                "city": "",
178                "ispId": "",
179                "region": "",
180                "cityId": "",
181                "country": "美国",
182                "regionId": "",
183                "countryId": "US"
184            },
185            "updateIpDetail": {
186                "ip": "120.231.232.41",
187                "isp": "移动",
188                "area": "",
189                "city": "",
190                "ispId": "100025",
191                "region": "广东",
192                "cityId": "",
193                "country": "中国",
194                "regionId": "440000",
195                "countryId": "CN"
196            }
197        }"#;
198
199        let ip_info: IpInfo = serde_json::from_str(json_str).expect("反序列化 JSON 失败");
200
201        // 验证 create_ip
202        assert_eq!(ip_info.create_ip, Some("206.237.119.215".to_string()));
203
204        // 验证 update_ip
205        assert_eq!(ip_info.update_ip, Some("120.231.232.41".to_string()));
206
207        // 验证 create_ip_detail
208        assert!(ip_info.create_ip_detail.is_some());
209        let create_detail = ip_info.create_ip_detail.as_ref().unwrap();
210        assert_eq!(create_detail.ip, Some("206.237.119.215".to_string()));
211        assert_eq!(create_detail.country, Some("美国".to_string()));
212        assert_eq!(create_detail.country_id, Some("US".to_string()));
213        assert_eq!(create_detail.isp, Some("".to_string()));
214        assert_eq!(create_detail.area, Some("".to_string()));
215
216        // 验证 update_ip_detail
217        assert!(ip_info.update_ip_detail.is_some());
218        let update_detail = ip_info.update_ip_detail.as_ref().unwrap();
219        assert_eq!(update_detail.ip, Some("120.231.232.41".to_string()));
220        assert_eq!(update_detail.isp, Some("移动".to_string()));
221        assert_eq!(update_detail.isp_id, Some("100025".to_string()));
222        assert_eq!(update_detail.region, Some("广东".to_string()));
223        assert_eq!(update_detail.region_id, Some("440000".to_string()));
224        assert_eq!(update_detail.country, Some("中国".to_string()));
225        assert_eq!(update_detail.country_id, Some("CN".to_string()));
226    }
227
228    #[test]
229    fn test_serialize_to_json() {
230        let mut ip_info = IpInfo::new();
231        ip_info.create_ip = Some("206.237.119.215".to_string());
232        ip_info.update_ip = Some("120.231.232.41".to_string());
233
234        let create_detail = IpDetail::builder()
235            .ip("206.237.119.215".to_string())
236            .country("美国".to_string())
237            .country_id("US".to_string())
238            .isp("".to_string())
239            .area("".to_string())
240            .build();
241        ip_info.create_ip_detail = Some(create_detail);
242
243        let update_detail = IpDetail::builder()
244            .ip("120.231.232.41".to_string())
245            .isp("移动".to_string())
246            .isp_id("100025".to_string())
247            .region("广东".to_string())
248            .region_id("440000".to_string())
249            .country("中国".to_string())
250            .country_id("CN".to_string())
251            .build();
252        ip_info.update_ip_detail = Some(update_detail);
253
254        let json_str = serde_json::to_string(&ip_info).expect("序列化 JSON 失败");
255
256        // 验证可以反序列化回来
257        let deserialized: IpInfo = serde_json::from_str(&json_str).expect("反序列化 JSON 失败");
258
259        assert_eq!(deserialized.create_ip, ip_info.create_ip);
260        assert_eq!(deserialized.update_ip, ip_info.update_ip);
261        assert_eq!(deserialized.create_ip_detail, ip_info.create_ip_detail);
262        assert_eq!(deserialized.update_ip_detail, ip_info.update_ip_detail);
263    }
264}