freedom_models/
account.rs

1use crate::Hateoas;
2use ipnet::Ipv4Net;
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5#[cfg(feature = "serde")]
6use serde_with::serde_as;
7use std::collections::HashMap;
8use time::OffsetDateTime;
9use url::Url;
10
11#[cfg(feature = "serde")]
12use super::utils;
13
14/// Account CIDR
15///
16/// An IP range indicating the whitelisted IP address for connecting to the ATLAS FPS
17#[cfg_attr(
18    feature = "serde",
19    derive(Serialize, Deserialize),
20    serde(rename_all = "camelCase")
21)]
22#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
23#[cfg_attr(not(feature = "unstable"), non_exhaustive)]
24pub struct AccountCidr {
25    pub name: String,
26    pub cidr: Ipv4Net,
27}
28
29impl std::ops::Deref for AccountCidr {
30    type Target = Ipv4Net;
31
32    fn deref(&self) -> &Self::Target {
33        &self.cidr
34    }
35}
36
37#[cfg_attr(
38    feature = "serde",
39    derive(Serialize, Deserialize),
40    serde(rename_all = "camelCase")
41)]
42#[derive(Debug, Clone, PartialEq)]
43#[cfg_attr(not(feature = "unstable"), non_exhaustive)]
44pub struct Tier {
45    pub tier: u32,
46    pub price: f32,
47    #[cfg_attr(
48        feature = "serde",
49        serde(rename = "_links", with = "utils::links::serde", default)
50    )]
51    pub links: HashMap<String, Url>,
52}
53
54impl Hateoas for Tier {
55    fn get_links(&self) -> &HashMap<String, url::Url> {
56        &self.links
57    }
58
59    fn get_links_mut(&mut self) -> &mut HashMap<String, url::Url> {
60        &mut self.links
61    }
62}
63
64#[cfg_attr(
65    feature = "serde",
66    serde_as,
67    derive(Serialize, Deserialize),
68    serde(rename_all = "camelCase")
69)]
70#[derive(Debug, Clone, PartialEq)]
71#[cfg_attr(not(feature = "unstable"), non_exhaustive)]
72pub struct Account {
73    #[cfg_attr(feature = "serde", serde(with = "time::serde::iso8601"))]
74    pub created: OffsetDateTime,
75    #[cfg_attr(
76        feature = "serde",
77        serde(default, with = "time::serde::iso8601::option")
78    )]
79    pub modified: Option<OffsetDateTime>,
80    #[cfg_attr(feature = "serde", serde(default))]
81    pub internal_meta_data: Option<HashMap<String, String>>,
82    pub name: String,
83    pub storage_key: String,
84    #[cfg_attr(feature = "serde", serde(default))]
85    pub storage_group: Option<String>,
86    pub tiers: Vec<Tier>,
87    pub post_process_done_by_account: bool,
88    pub weeks_of_data_storage: u32,
89    pub verified: bool,
90    #[cfg_attr(feature = "serde", serde(default))]
91    #[cfg_attr(feature = "serde", serde_as(as = "VecSkipError<_>"))]
92    pub access_realtime_cidr: Vec<AccountCidr>,
93    #[cfg_attr(feature = "serde", serde(default))]
94    #[cfg_attr(feature = "serde", serde_as(as = "VecSkipError<_>"))]
95    pub access_api_cidr: Vec<AccountCidr>,
96    #[cfg_attr(feature = "serde", serde(default))]
97    pub external_id: Option<String>,
98    #[cfg_attr(feature = "serde", serde(default))]
99    pub fps_host_name: Option<String>,
100    #[cfg_attr(
101        feature = "serde",
102        serde(rename = "_links", with = "utils::links::serde", default)
103    )]
104    pub links: HashMap<String, Url>,
105}
106
107impl Hateoas for Account {
108    fn get_links(&self) -> &HashMap<String, url::Url> {
109        &self.links
110    }
111
112    fn get_links_mut(&mut self) -> &mut HashMap<String, url::Url> {
113        &mut self.links
114    }
115}
116
117#[cfg(test)]
118mod tests {
119    use std::net::Ipv4Addr;
120
121    use super::*;
122
123    #[cfg(feature = "serde")]
124    #[test]
125    fn ip_cidr_deserialize() {
126        let json = serde_json::json!({
127            "name": "Test Account",
128            "cidr": "192.168.1.96/28"
129        });
130
131        let cidr: AccountCidr = serde_json::from_value(json).unwrap();
132        assert_eq!(cidr.name, "Test Account");
133        assert_eq!(
134            cidr.cidr,
135            Ipv4Net::new_assert(Ipv4Addr::new(192, 168, 1, 96), 28)
136        );
137    }
138
139    #[test]
140    fn ip_cidr_check_28() {
141        let cidr = AccountCidr {
142            name: "Test".into(),
143            cidr: Ipv4Net::new_assert(Ipv4Addr::new(192, 168, 1, 96), 28),
144        };
145
146        assert!(cidr.contains(&Ipv4Addr::new(192, 168, 1, 99)));
147        assert!(cidr.contains(&Ipv4Addr::new(192, 168, 1, 97)));
148        assert!(!cidr.contains(&Ipv4Addr::new(192, 168, 0, 99)));
149    }
150
151    #[test]
152    fn ip_cidr_check_32() {
153        let cidr = AccountCidr {
154            name: "Test".into(),
155            cidr: Ipv4Net::new_assert(Ipv4Addr::new(192, 168, 1, 96), 32),
156        };
157
158        assert!(cidr.contains(&Ipv4Addr::new(192, 168, 1, 96)));
159        assert!(!cidr.contains(&Ipv4Addr::new(192, 168, 1, 97)));
160        assert!(!cidr.contains(&Ipv4Addr::new(192, 168, 1, 95)));
161        assert!(!cidr.contains(&Ipv4Addr::new(0, 0, 0, 0)));
162    }
163}