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#[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}