mirams/
lib.rs

1
2pub mod store;
3pub mod db_sqlite;
4
5pub mod static_files;
6pub mod server;
7
8pub mod types;
9pub mod ipv6;
10pub mod ipv4;
11pub mod asn;
12pub mod user;
13
14pub use store::Store;
15pub use types::Error;
16pub use types::ErrorKind;
17
18
19pub mod example_data {
20    use crate::*;
21
22    pub fn add_example_data<T: store::DbConnection + Clone + Send + Sync + 'static>(store: store::Store<T>) {
23        let asn_store = store.asn_assignments();
24        let ipv4_store = store.ipv4_assignments();
25        let ipv6_store = store.ipv6_assignments();
26
27        let space = asn::AssignmentSpaceAsn {
28            id: 0,
29            name: "Example ASN space".to_string(),
30            description: "Example ASN space".to_string(),
31            space_visibility: types::ObjectVisibility::Public,
32            asn_from: 65000,
33            asn_to: 65199,
34        };
35        let space_id = asn_store.create_space(&space).unwrap();
36        let pool = asn::AssignmentPoolAsn {
37            id: 0,
38            assignment_space_id: space_id,
39            name: "Example ASN pool".to_string(),
40            description: "Example ASN pool".to_string(),
41            pool_visibility: types::ObjectVisibility::Public,
42            asn_from: 65000,
43            asn_to: 65099,
44        };
45        let pool_id = asn_store.create_pool(&pool).unwrap();
46        let assignment = asn::AssignmentAsn {
47            id: 0,
48            assignment_pool_id: pool_id,
49            name: "Example ASN assignment".to_string(),
50            description: "Example ASN assignment".to_string(),
51            assignment_visibility: types::ObjectVisibility::Public,
52            asn: 65000,
53        };
54        asn_store.create_assignment(&assignment).unwrap();
55
56        let space = ipv4::AssignmentSpaceIpv4 {
57            id: 0,
58            name: "Example IPv4 space".to_string(),
59            description: "Example IPv4 space".to_string(),
60            space_visibility: types::ObjectVisibility::Public,
61            ipv4_prefix: [192, 168, 0, 0],
62            ipv4_prefix_len: 16,
63        };
64        let space_id = ipv4_store.create_space(&space).unwrap();
65        let pool = ipv4::AssignmentPoolIpv4 {
66            id: 0,
67            assignment_space_id: space_id,
68            name: "Example IPv4 pool".to_string(),
69            description: "Example IPv4 pool".to_string(),
70            pool_visibility: types::ObjectVisibility::Public,
71            ipv4_prefix: [192, 168, 1, 0],
72            ipv4_prefix_len: 24,
73        };
74        let pool_id = ipv4_store.create_pool(&pool).unwrap();
75        let assignment = ipv4::AssignmentIpv4 {
76            id: 0,
77            assignment_pool_id: pool_id,
78            name: "Example IPv4 assignment".to_string(),
79            description: "Example IPv4 assignment".to_string(),
80            assignment_visibility: types::ObjectVisibility::Public,
81            ipv4_prefix: [192, 168, 1, 1],
82            ipv4_prefix_len: 32,
83        };
84        ipv4_store.create_assignment(&assignment).unwrap();
85
86        let space = ipv6::AssignmentSpaceIpv6 {
87            id: 0,
88            name: "Example IPv6 space".to_string(),
89            description: "Example IPv6 space".to_string(),
90            space_visibility: types::ObjectVisibility::Public,
91            ipv6_prefix: "2001:db8::".parse::<std::net::Ipv6Addr>().unwrap().octets(),
92            ipv6_prefix_len: 32,
93        };
94        let space_id = ipv6_store.create_space(&space).unwrap();
95        let pool = ipv6::AssignmentPoolIpv6 {
96            id: 0,
97            assignment_space_id: space_id,
98            name: "Example IPv6 pool".to_string(),
99            description: "Example IPv6 pool".to_string(),
100            pool_visibility: types::ObjectVisibility::Public,
101            ipv6_prefix: "2001:db8:1::".parse::<std::net::Ipv6Addr>().unwrap().octets(),
102            ipv6_prefix_len: 48,
103        };
104        let pool_id = ipv6_store.create_pool(&pool).unwrap();
105        let assignment = ipv6::AssignmentIpv6 {
106            id: 0,
107            assignment_pool_id: pool_id,
108            name: "Example IPv6 assignment".to_string(),
109            description: "Example IPv6 assignment".to_string(),
110            assignment_visibility: types::ObjectVisibility::Public,
111            ipv6_prefix: "2001:db8:1:1::".parse::<std::net::Ipv6Addr>().unwrap().octets(),
112            ipv6_prefix_len: 64,
113        };
114        ipv6_store.create_assignment(&assignment).unwrap();
115    }
116}
117
118
119/// Top-level tests
120#[cfg(test)]
121mod tests {
122    use super::*;
123
124    #[test]
125    fn user_store() {
126        let db = db_sqlite::SqliteConnection::open_memory().unwrap();
127        let store = Store::new(db);
128        let user_store = store.users();
129        user_store.set_password("alice", "password").unwrap();
130        assert!(user_store.check_password("alice", "password").unwrap());
131        assert!(!user_store.check_password("alice", "wrong").unwrap());
132        let key = user_store.generate_api_key("alice").unwrap();
133        assert_eq!(user_store.get_user_from_api_key(&key).unwrap(), Some("alice".to_string()));
134    }
135
136    #[test]
137    fn ipv4_masks() {
138        use std::net::Ipv4Addr;
139
140        let mask = ipv4::ipv4_subnet_mask(20);
141        assert_eq!(mask, Ipv4Addr::new(255, 255, 240, 0).octets());
142        let mask = ipv4::ipv4_subnet_mask(16);
143        assert_eq!(mask, Ipv4Addr::new(255, 255, 0, 0).octets());
144        let mask = ipv4::ipv4_subnet_mask(8);
145        assert_eq!(mask, Ipv4Addr::new(255, 0, 0, 0).octets());
146        let mask = ipv4::ipv4_subnet_mask(32);
147        assert_eq!(mask, Ipv4Addr::new(255, 255, 255, 255).octets());
148        let mask = ipv4::ipv4_wildcard_mask(20);
149        assert_eq!(mask, Ipv4Addr::new(0, 0, 15, 255).octets());
150        let mask = ipv4::ipv4_wildcard_mask(16);
151        assert_eq!(mask, Ipv4Addr::new(0, 0, 255, 255).octets());
152        let mask = ipv4::ipv4_wildcard_mask(8);
153        assert_eq!(mask, Ipv4Addr::new(0, 255, 255, 255).octets());
154        let mask = ipv4::ipv4_wildcard_mask(32);
155        assert_eq!(mask, Ipv4Addr::new(0, 0, 0, 0).octets());
156
157        let network = ipv4::ipv4_network_address(Ipv4Addr::new(192, 168, 1, 1).octets(), 24);
158        assert_eq!(network, Ipv4Addr::new(192, 168, 1, 0).octets());
159        let network = ipv4::ipv4_network_address(Ipv4Addr::new(192, 168, 1, 1).octets(), 16);
160        assert_eq!(network, Ipv4Addr::new(192, 168, 0, 0).octets());
161        let network = ipv4::ipv4_network_address(Ipv4Addr::new(192, 168, 1, 1).octets(), 8);
162        assert_eq!(network, Ipv4Addr::new(192, 0, 0, 0).octets());
163        let network = ipv4::ipv4_network_address(Ipv4Addr::new(192, 168, 1, 1).octets(), 32);
164        assert_eq!(network, Ipv4Addr::new(192, 168, 1, 1).octets());
165
166        let broadcast = ipv4::ipv4_broadcast_address(Ipv4Addr::new(192, 168, 1, 1).octets(), 24);
167        assert_eq!(broadcast, Ipv4Addr::new(192, 168, 1, 255).octets());
168        let broadcast = ipv4::ipv4_broadcast_address(Ipv4Addr::new(192, 168, 1, 1).octets(), 16);
169        assert_eq!(broadcast, Ipv4Addr::new(192, 168, 255, 255).octets());
170        let broadcast = ipv4::ipv4_broadcast_address(Ipv4Addr::new(192, 168, 1, 1).octets(), 8);
171        assert_eq!(broadcast, Ipv4Addr::new(192, 255, 255, 255).octets());
172        let broadcast = ipv4::ipv4_broadcast_address(Ipv4Addr::new(192, 168, 1, 1).octets(), 32);
173        assert_eq!(broadcast, Ipv4Addr::new(192, 168, 1, 1).octets());
174    }
175
176    #[test]
177    fn ipv4_assignment_store() {
178        use std::net::Ipv4Addr;
179
180        let db = db_sqlite::SqliteConnection::open_memory().unwrap();
181        let store = Store::new(db);
182        let ipv4_store = store.ipv4_assignments();
183        let space = ipv4::AssignmentSpaceIpv4 {
184            id: 0,
185            name: "Test assignment space".to_string(),
186            description: "Description".to_string(),
187            space_visibility: types::ObjectVisibility::Public,
188            ipv4_prefix: Ipv4Addr::new(192, 168, 0, 0).octets(),
189            ipv4_prefix_len: 16,
190        };
191        let space_id = ipv4_store.create_space(&space).unwrap();
192        let space2 = ipv4::AssignmentSpaceIpv4 {
193            id: 0,
194            name: "Test assignment space 2".to_string(),
195            description: "Description".to_string(),
196            space_visibility: types::ObjectVisibility::Public,
197            ipv4_prefix: Ipv4Addr::new(172, 16, 0, 0).octets(),
198            ipv4_prefix_len: 16,
199        };
200        ipv4_store.create_space(&space2).unwrap();
201        let pool = ipv4::AssignmentPoolIpv4 {
202            id: 0,
203            assignment_space_id: space_id,
204            name: "Test pool".to_string(),
205            description: "Description".to_string(),
206            pool_visibility: types::ObjectVisibility::Public,
207            ipv4_prefix: Ipv4Addr::new(192, 168, 0, 0).octets(),
208            ipv4_prefix_len: 24,
209        };
210        let pool_id = ipv4_store.create_pool(&pool).unwrap();
211        let pool2 = ipv4::AssignmentPoolIpv4 {
212            id: 0,
213            assignment_space_id: space_id,
214            name: "Test pool 2".to_string(),
215            description: "Description".to_string(),
216            pool_visibility: types::ObjectVisibility::Public,
217            ipv4_prefix: Ipv4Addr::new(192, 168, 1, 0).octets(),
218            ipv4_prefix_len: 24,
219        };
220        ipv4_store.create_pool(&pool2).unwrap();
221        let overlapping_pool_1 = ipv4::AssignmentPoolIpv4 {
222            id: 0,
223            assignment_space_id: space_id,
224            name: "overlapping pool 1".to_string(),
225            description: "Description".to_string(),
226            pool_visibility: types::ObjectVisibility::Public,
227            ipv4_prefix: Ipv4Addr::new(192, 168, 0, 0).octets(),
228            ipv4_prefix_len: 24,
229        };
230        assert!(ipv4_store.create_pool(&overlapping_pool_1).is_err());
231        let overlapping_pool_2 = ipv4::AssignmentPoolIpv4 {
232            id: 0,
233            assignment_space_id: space_id,
234            name: "overlapping pool 2".to_string(),
235            description: "Description".to_string(),
236            pool_visibility: types::ObjectVisibility::Public,
237            ipv4_prefix: Ipv4Addr::new(192, 168, 0, 128).octets(),
238            ipv4_prefix_len: 25,
239        };
240        assert!(ipv4_store.create_pool(&overlapping_pool_2).is_err());
241        let overlapping_pool_3 = ipv4::AssignmentPoolIpv4 {
242            id: 0,
243            assignment_space_id: space_id,
244            name: "overlapping pool 3".to_string(),
245            description: "Description".to_string(),
246            pool_visibility: types::ObjectVisibility::Public,
247            ipv4_prefix: Ipv4Addr::new(192, 168, 0, 0).octets(),
248            ipv4_prefix_len: 23,
249        };
250        assert!(ipv4_store.create_pool(&overlapping_pool_3).is_err());
251        let assignment = ipv4::AssignmentIpv4 {
252            id: 0,
253            assignment_pool_id: pool_id,
254            name: "Test assignment".to_string(),
255            description: "Description".to_string(),
256            assignment_visibility: types::ObjectVisibility::Public,
257            ipv4_prefix: Ipv4Addr::new(192, 168, 0, 1).octets(),
258            ipv4_prefix_len: 32,
259        };
260        let assignment_id = ipv4_store.create_assignment(&assignment).unwrap();
261        assert!(ipv4_store.get_space(space_id).is_ok());
262        assert!(ipv4_store.get_pool(pool_id).is_ok());
263        assert!(ipv4_store.get_assignment(assignment_id).is_ok());
264        assert_eq!(ipv4_store.get_pools(space_id).unwrap().len(), 2);
265        ipv4_store.delete_space(space_id).unwrap();
266        assert!(ipv4_store.get_space(space_id).is_err());
267    }
268
269    #[test]
270    fn ipv6_masks() {
271        use std::net::Ipv6Addr;
272
273        let mask = ipv6::ipv6_subnet_mask(56);
274        let assumed_mask = "ffff:ffff:ffff:ff00::".parse::<Ipv6Addr>().unwrap().octets();
275        assert_eq!(mask, assumed_mask);
276
277        let mask = ipv6::ipv6_wildcard_mask(80);
278        let assumed_mask = "::ffff:ffff:ffff".parse::<Ipv6Addr>().unwrap().octets();
279        assert_eq!(mask, assumed_mask);
280
281        let network = ipv6::ipv6_network_address("2001:db8::1".parse::<Ipv6Addr>().unwrap().octets(), 64);
282        let assumed_network = "2001:db8::".parse::<Ipv6Addr>().unwrap().octets();
283        assert_eq!(network, assumed_network);
284
285        let broadcast = ipv6::ipv6_broadcast_address("2001:db8::1".parse::<Ipv6Addr>().unwrap().octets(), 64);
286        let assumed_broadcast = "2001:db8::ffff:ffff:ffff:ffff".parse::<Ipv6Addr>().unwrap().octets();
287        assert_eq!(broadcast, assumed_broadcast);
288    }
289
290    #[test]
291    fn ipv6_assignment_store() {
292        use std::net::Ipv6Addr;
293
294        let db = db_sqlite::SqliteConnection::open_memory().unwrap();
295        let store = Store::new(db);
296        let ipv6_store = store.ipv6_assignments();
297        let space = ipv6::AssignmentSpaceIpv6 {
298            id: 0,
299            name: "Test assignment space".to_string(),
300            description: "Description".to_string(),
301            space_visibility: types::ObjectVisibility::Public,
302            ipv6_prefix: "2001:db8::".parse::<Ipv6Addr>().unwrap().octets(),
303            ipv6_prefix_len: 32,
304        };
305        let space_id = ipv6_store.create_space(&space).unwrap();
306        let space2 = ipv6::AssignmentSpaceIpv6 {
307            id: 0,
308            name: "Test assignment space 2".to_string(),
309            description: "Description".to_string(),
310            space_visibility: types::ObjectVisibility::Public,
311            ipv6_prefix: "fd12:3456::".parse::<Ipv6Addr>().unwrap().octets(),
312            ipv6_prefix_len: 32,
313        };
314        ipv6_store.create_space(&space2).unwrap();
315        let pool = ipv6::AssignmentPoolIpv6 {
316            id: 0,
317            assignment_space_id: space_id,
318            name: "Test pool".to_string(),
319            description: "Description".to_string(),
320            pool_visibility: types::ObjectVisibility::Public,
321            ipv6_prefix: "2001:db8::".parse::<Ipv6Addr>().unwrap().octets(),
322            ipv6_prefix_len: 48,
323        };
324        let pool_id = ipv6_store.create_pool(&pool).unwrap();
325        let pool2 = ipv6::AssignmentPoolIpv6 {
326            id: 0,
327            assignment_space_id: space_id,
328            name: "Test pool 2".to_string(),
329            description: "Description".to_string(),
330            pool_visibility: types::ObjectVisibility::Public,
331            ipv6_prefix: "2001:db8:1::".parse::<Ipv6Addr>().unwrap().octets(),
332            ipv6_prefix_len: 48,
333        };
334        ipv6_store.create_pool(&pool2).unwrap();
335        let overlapping_pool_1 = ipv6::AssignmentPoolIpv6 {
336            id: 0,
337            assignment_space_id: space_id,
338            name: "overlapping pool 1".to_string(),
339            description: "Description".to_string(),
340            pool_visibility: types::ObjectVisibility::Public,
341            ipv6_prefix: "2001:db8::".parse::<Ipv6Addr>().unwrap().octets(),
342            ipv6_prefix_len: 48,
343        };
344        assert!(ipv6_store.create_pool(&overlapping_pool_1).is_err());
345        let overlapping_pool_2 = ipv6::AssignmentPoolIpv6 {
346            id: 0,
347            assignment_space_id: space_id,
348            name: "overlapping pool 2".to_string(),
349            description: "Description".to_string(),
350            pool_visibility: types::ObjectVisibility::Public,
351            ipv6_prefix: "2001:db8:1:8000::".parse::<Ipv6Addr>().unwrap().octets(),
352            ipv6_prefix_len: 49,
353        };
354        assert!(ipv6_store.create_pool(&overlapping_pool_2).is_err());
355        let overlapping_pool_3 = ipv6::AssignmentPoolIpv6 {
356            id: 0,
357            assignment_space_id: space_id,
358            name: "overlapping pool 3".to_string(),
359            description: "Description".to_string(),
360            pool_visibility: types::ObjectVisibility::Public,
361            ipv6_prefix: "2001:db8::".parse::<Ipv6Addr>().unwrap().octets(),
362            ipv6_prefix_len: 47,
363        };
364        assert!(ipv6_store.create_pool(&overlapping_pool_3).is_err());
365        let assignment = ipv6::AssignmentIpv6 {
366            id: 0,
367            assignment_pool_id: pool_id,
368            name: "Test assignment".to_string(),
369            description: "Description".to_string(),
370            assignment_visibility: types::ObjectVisibility::Public,
371            ipv6_prefix: "2001:db8:0:1::".parse::<Ipv6Addr>().unwrap().octets(),
372            ipv6_prefix_len: 64,
373        };
374        let assignment_id = ipv6_store.create_assignment(&assignment).unwrap();
375        assert!(ipv6_store.get_space(space_id).is_ok());
376        assert!(ipv6_store.get_pool(pool_id).is_ok());
377        assert!(ipv6_store.get_assignment(assignment_id).is_ok());
378        assert_eq!(ipv6_store.get_pools(space_id).unwrap().len(), 2);
379        ipv6_store.delete_space(space_id).unwrap();
380        assert!(ipv6_store.get_space(space_id).is_err());
381        assert!(ipv6_store.get_assignment(assignment_id).is_err());
382    }
383
384    #[test]
385    fn asn_store() {
386        let db = db_sqlite::SqliteConnection::open_memory().unwrap();
387        let store = Store::new(db);
388        let asn_store = store.asn_assignments();
389        let space = asn::AssignmentSpaceAsn {
390            id: 0,
391            name: "Test assignment space".to_string(),
392            description: "Description".to_string(),
393            space_visibility: types::ObjectVisibility::Public,
394            asn_from: 65000,
395            asn_to: 65199,
396        };
397        let space_id = asn_store.create_space(&space).unwrap();
398        let space2 = asn::AssignmentSpaceAsn {
399            id: 0,
400            name: "Test assignment space 2".to_string(),
401            description: "Description".to_string(),
402            space_visibility: types::ObjectVisibility::Public,
403            asn_from: 65200,
404            asn_to: 65399,
405        };
406        asn_store.create_space(&space2).unwrap();
407        let pool = asn::AssignmentPoolAsn {
408            id: 0,
409            assignment_space_id: space_id,
410            name: "Test pool".to_string(),
411            description: "Description".to_string(),
412            pool_visibility: types::ObjectVisibility::Public,
413            asn_from: 65000,
414            asn_to: 65099,
415        };
416        let pool_id = asn_store.create_pool(&pool).unwrap();
417        let pool2 = asn::AssignmentPoolAsn {
418            id: 0,
419            assignment_space_id: space_id,
420            name: "Test pool 2".to_string(),
421            description: "Description".to_string(),
422            pool_visibility: types::ObjectVisibility::Public,
423            asn_from: 65100,
424            asn_to: 65199,
425        };
426        asn_store.create_pool(&pool2).unwrap();
427        let overlapping_pool_1 = asn::AssignmentPoolAsn {
428            id: 0,
429            assignment_space_id: space_id,
430            name: "overlapping pool 1".to_string(),
431            description: "Description".to_string(),
432            pool_visibility: types::ObjectVisibility::Public,
433            asn_from: 65000,
434            asn_to: 65099,
435        };
436        assert!(asn_store.create_pool(&overlapping_pool_1).is_err());
437        let overlapping_pool_2 = asn::AssignmentPoolAsn {
438            id: 0,
439            assignment_space_id: space_id,
440            name: "overlapping pool 2".to_string(),
441            description: "Description".to_string(),
442            pool_visibility: types::ObjectVisibility::Public,
443            asn_from: 65050,
444            asn_to: 65149,
445        };
446        assert!(asn_store.create_pool(&overlapping_pool_2).is_err());
447        let overlapping_pool_3 = asn::AssignmentPoolAsn {
448            id: 0,
449            assignment_space_id: space_id,
450            name: "overlapping pool 3".to_string(),
451            description: "Description".to_string(),
452            pool_visibility: types::ObjectVisibility::Public,
453            asn_from: 65000,
454            asn_to: 65098,
455        };
456        assert!(asn_store.create_pool(&overlapping_pool_3).is_err());
457        let assignment = asn::AssignmentAsn {
458            id: 0,
459            assignment_pool_id: pool_id,
460            name: "Test assignment".to_string(),
461            description: "Description".to_string(),
462            assignment_visibility: types::ObjectVisibility::Public,
463            asn: 65000,
464        };
465        let assignment_id = asn_store.create_assignment(&assignment).unwrap();
466        assert!(asn_store.get_space(space_id).is_ok());
467        assert!(asn_store.get_pool(pool_id).is_ok());
468        assert!(asn_store.get_assignment(assignment_id).is_ok());
469        assert_eq!(asn_store.get_pools(space_id).unwrap().len(), 2);
470        asn_store.delete_space(space_id).unwrap();
471        assert!(asn_store.get_space(space_id).is_err());
472        assert!(asn_store.get_assignment(assignment_id).is_err());
473    }
474
475    #[test]
476    fn static_files() {
477        let files = static_files::frontend_files();
478        assert!(files.len() > 0);
479        for (path, _) in files {
480            assert!(path.len() > 0);
481            println!("{}", path);
482        }
483    }
484}