1use crate::axum::auth::BearerTokenAuthLayer;
2use crate::offer::auth::OfferBearerTokenValidator;
3use crate::offer::handler::OfferHandlers;
4use crate::offer::state::OfferState;
5use axum::routing::{delete, get, post, put};
6use axum::Router;
7use switchgear_service_api::offer::{OfferMetadataStore, OfferStore};
8use switchgear_service_api::service::StatusCode;
9
10#[derive(Debug)]
11pub struct OfferService;
12
13impl OfferService {
14 pub fn router<S, M>(state: OfferState<S, M>) -> Router
15 where
16 S: OfferStore + Clone + Send + Sync + 'static,
17 M: OfferMetadataStore + Clone + Send + Sync + 'static,
18 {
19 Router::new()
20 .route("/offers/{partition}/{id}", get(OfferHandlers::get_offer))
21 .route("/offers/{partition}/{id}", put(OfferHandlers::put_offer))
22 .route(
23 "/offers/{partition}/{id}",
24 delete(OfferHandlers::delete_offer),
25 )
26 .route("/offers/{partition}", get(OfferHandlers::get_offers))
27 .route("/offers", post(OfferHandlers::post_offer))
28 .route(
29 "/metadata/{partition}/{id}",
30 get(OfferHandlers::get_metadata),
31 )
32 .route(
33 "/metadata/{partition}/{id}",
34 put(OfferHandlers::put_metadata),
35 )
36 .route(
37 "/metadata/{partition}/{id}",
38 delete(OfferHandlers::delete_metadata),
39 )
40 .route(
41 "/metadata/{partition}",
42 get(OfferHandlers::get_all_metadata),
43 )
44 .route("/metadata", post(OfferHandlers::post_metadata))
45 .layer(BearerTokenAuthLayer::new(
46 OfferBearerTokenValidator::new(state.auth_authority().clone()),
47 "offer",
48 ))
49 .route("/health", get(Self::health_check_handler))
50 .with_state(state)
51 }
52
53 async fn health_check_handler() -> StatusCode {
54 StatusCode::OK
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use crate::offer::service::OfferService;
61 use crate::offer::state::OfferState;
62 use crate::testing::offer::store::TestOfferStore;
63 use crate::{OfferAudience, OfferClaims};
64 use axum::http::StatusCode;
65 use axum_test::TestServer;
66 use chrono::{Duration, Utc};
67 use jsonwebtoken::{encode, Algorithm, DecodingKey, EncodingKey, Header};
68 use p256::ecdsa::SigningKey;
69 use p256::pkcs8::EncodePrivateKey;
70 use p256::pkcs8::EncodePublicKey;
71 use rand::thread_rng;
72 use std::time::{SystemTime, UNIX_EPOCH};
73 use switchgear_service_api::offer::{
74 OfferMetadata, OfferMetadataIdentifier, OfferMetadataImage, OfferMetadataSparse,
75 OfferMetadataStore, OfferRecord, OfferRecordSparse, OfferStore,
76 };
77 use uuid::Uuid;
78
79 fn create_test_offer_with_metadata_id(metadata_id: Uuid) -> OfferRecord {
80 OfferRecord {
81 partition: "default".to_string(),
82 id: Uuid::new_v4(),
83 offer: OfferRecordSparse {
84 max_sendable: 1000000,
85 min_sendable: 1000,
86 metadata_id,
87 metadata: None,
88 timestamp: Utc::now() - Duration::hours(1),
89 expires: Some(Utc::now() + Duration::hours(1)),
90 },
91 }
92 }
93
94 fn create_test_metadata() -> OfferMetadata {
95 OfferMetadata {
96 id: Uuid::new_v4(),
97 partition: "default".to_string(),
98 metadata: OfferMetadataSparse {
99 text: "Test offer".to_string(),
100 long_text: Some("This is a test offer description".to_string()),
101 image: Some(OfferMetadataImage::Png(vec![0x89, 0x50, 0x4E, 0x47])),
102 identifier: Some(OfferMetadataIdentifier::Email(
103 "test@example.com".parse().unwrap(),
104 )),
105 },
106 }
107 }
108
109 async fn create_test_server_with_offer(
110 offers: Vec<OfferRecord>,
111 metadata: Vec<OfferMetadata>,
112 ) -> TestServerWithAuthorization {
113 let mut rng = thread_rng();
114 let private_key = SigningKey::random(&mut rng);
115 let public_key = *private_key.verifying_key();
116
117 let private_key = private_key
118 .to_pkcs8_pem(p256::pkcs8::LineEnding::default())
119 .unwrap();
120 let encoding_key = EncodingKey::from_ec_pem(private_key.as_bytes()).unwrap();
121
122 let public_key = public_key
123 .to_public_key_pem(p256::pkcs8::LineEnding::default())
124 .unwrap();
125 let decoding_key = DecodingKey::from_ec_pem(public_key.as_bytes()).unwrap();
126
127 let header = Header::new(Algorithm::ES256);
128 let claims = OfferClaims {
129 aud: OfferAudience::Offer,
130 exp: (SystemTime::now()
131 .duration_since(UNIX_EPOCH)
132 .unwrap()
133 .as_secs()
134 + 3600) as usize,
135 };
136 let authorization = encode(&header, &claims, &encoding_key).unwrap();
137
138 let store = TestOfferStore::default();
139
140 for m in metadata {
141 store.put_metadata(m).await.unwrap();
142 }
143
144 for o in offers {
145 store.put_offer(o).await.unwrap();
146 }
147
148 let state = OfferState::new(store.clone(), store, decoding_key, 100);
149
150 let app = OfferService::router(state);
151 TestServerWithAuthorization {
152 server: TestServer::new(app).unwrap(),
153 authorization,
154 }
155 }
156
157 async fn create_test_server_with_metadata(
158 metadata: OfferMetadata,
159 ) -> TestServerWithAuthorization {
160 let mut rng = thread_rng();
161 let private_key = SigningKey::random(&mut rng);
162 let public_key = *private_key.verifying_key();
163
164 let private_key = private_key
165 .to_pkcs8_pem(p256::pkcs8::LineEnding::default())
166 .unwrap();
167 let encoding_key = EncodingKey::from_ec_pem(private_key.as_bytes()).unwrap();
168
169 let public_key = public_key
170 .to_public_key_pem(p256::pkcs8::LineEnding::default())
171 .unwrap();
172 let decoding_key = DecodingKey::from_ec_pem(public_key.as_bytes()).unwrap();
173
174 let header = Header::new(Algorithm::ES256);
175 let claims = OfferClaims {
176 aud: OfferAudience::Offer,
177 exp: (SystemTime::now()
178 .duration_since(UNIX_EPOCH)
179 .unwrap()
180 .as_secs()
181 + 3600) as usize,
182 };
183 let authorization = encode(&header, &claims, &encoding_key).unwrap();
184
185 let store = TestOfferStore::default();
186 store.put_metadata(metadata).await.unwrap();
187 let state = OfferState::new(store.clone(), store, decoding_key, 100);
188
189 let app = OfferService::router(state);
190 TestServerWithAuthorization {
191 server: TestServer::new(app).unwrap(),
192 authorization,
193 }
194 }
195
196 fn create_empty_test_server() -> TestServerWithAuthorization {
197 let mut rng = thread_rng();
198 let private_key = SigningKey::random(&mut rng);
199 let public_key = *private_key.verifying_key();
200
201 let private_key = private_key
202 .to_pkcs8_pem(p256::pkcs8::LineEnding::default())
203 .unwrap();
204 let encoding_key = EncodingKey::from_ec_pem(private_key.as_bytes()).unwrap();
205
206 let public_key = public_key
207 .to_public_key_pem(p256::pkcs8::LineEnding::default())
208 .unwrap();
209 let decoding_key = DecodingKey::from_ec_pem(public_key.as_bytes()).unwrap();
210
211 let header = Header::new(Algorithm::ES256);
212 let claims = OfferClaims {
213 aud: OfferAudience::Offer,
214 exp: (SystemTime::now()
215 .duration_since(UNIX_EPOCH)
216 .unwrap()
217 .as_secs()
218 + 3600) as usize,
219 };
220 let authorization = encode(&header, &claims, &encoding_key).unwrap();
221
222 let store = TestOfferStore::default();
223 let state = OfferState::new(store.clone(), store, decoding_key, 100);
224
225 let app = OfferService::router(state);
226 TestServerWithAuthorization {
227 server: TestServer::new(app).unwrap(),
228 authorization,
229 }
230 }
231
232 struct TestServerWithAuthorization {
233 server: TestServer,
234 authorization: String,
235 }
236
237 #[tokio::test]
240 async fn health_check_when_called_then_returns_ok() {
241 let server = create_empty_test_server();
242 let response = server.server.get("/health").await;
243
244 assert_eq!(response.status_code(), StatusCode::OK);
245 }
246
247 #[tokio::test]
250 async fn delete_offer_when_exists_then_removes_and_second_delete_not_found() {
251 let test_metadata = create_test_metadata();
252 let test_offer = create_test_offer_with_metadata_id(test_metadata.id);
253 let offer_id = test_offer.id;
254 let server = create_test_server_with_offer(vec![test_offer], vec![test_metadata]).await;
255 let response = server
256 .server
257 .delete(&format!("/offers/default/{offer_id}"))
258 .authorization_bearer(server.authorization.clone())
259 .await;
260
261 assert_eq!(response.status_code(), StatusCode::NO_CONTENT);
262
263 let response = server
265 .server
266 .delete(&format!("/offers/default/{offer_id}"))
267 .authorization_bearer(server.authorization.clone())
268 .await;
269 assert_eq!(response.status_code(), StatusCode::NOT_FOUND);
270 }
271
272 #[tokio::test]
273 async fn delete_offer_when_not_exists_then_returns_not_found() {
274 let server = create_empty_test_server();
275 let non_existent_id = Uuid::new_v4();
276 let response = server
277 .server
278 .delete(&format!("/offers/default/{non_existent_id}"))
279 .authorization_bearer(server.authorization.clone())
280 .await;
281
282 assert_eq!(response.status_code(), StatusCode::NOT_FOUND);
283 }
284
285 #[tokio::test]
286 async fn get_offer_when_exists_then_returns_resource() {
287 let test_metadata = create_test_metadata();
288 let mut test_offer = create_test_offer_with_metadata_id(test_metadata.id);
289 let offer_id = test_offer.id;
290
291 let server =
292 create_test_server_with_offer(vec![test_offer.clone()], vec![test_metadata.clone()])
293 .await;
294 let response = server
295 .server
296 .get(&format!("/offers/default/{offer_id}"))
297 .authorization_bearer(server.authorization.clone())
298 .await;
299
300 assert_eq!(response.status_code(), StatusCode::OK);
301 let returned_offer: OfferRecord = response.json();
302 assert_eq!(test_offer, returned_offer);
303
304 let response = server
305 .server
306 .get(&format!("/offers/default/{offer_id}?sparse=false"))
307 .authorization_bearer(server.authorization.clone())
308 .await;
309
310 test_offer.offer.metadata = Some(test_metadata.metadata);
311 assert_eq!(response.status_code(), StatusCode::OK);
312 let returned_offer: OfferRecord = response.json();
313 assert_eq!(test_offer, returned_offer);
314 }
315
316 #[tokio::test]
317 async fn get_offer_when_invalid_uuid_then_returns_not_found() {
318 let server = create_empty_test_server();
319 let response = server
320 .server
321 .get("/offers/default/invalid-uuid")
322 .authorization_bearer(server.authorization.clone())
323 .await;
324
325 assert_eq!(response.status_code(), StatusCode::NOT_FOUND);
326 }
327
328 #[tokio::test]
329 async fn get_offer_when_not_exists_then_returns_not_found() {
330 let server = create_empty_test_server();
331 let non_existent_id = Uuid::new_v4();
332 let response = server
333 .server
334 .get(&format!("/offers/default/{non_existent_id}"))
335 .authorization_bearer(server.authorization.clone())
336 .await;
337
338 assert_eq!(response.status_code(), StatusCode::NOT_FOUND);
339 }
340
341 #[tokio::test]
342 async fn get_offers_when_empty_then_returns_empty_list() {
343 let server = create_empty_test_server();
344 let response = server
345 .server
346 .get("/offers/default")
347 .authorization_bearer(server.authorization.clone())
348 .await;
349
350 assert_eq!(response.status_code(), StatusCode::OK);
351 let offers: Vec<OfferRecord> = response.json();
352 assert!(offers.is_empty());
353 }
354
355 #[tokio::test]
356 async fn get_offers_when_exists_then_returns_list() {
357 let test_metadata = create_test_metadata();
358 let metadata_id = test_metadata.id;
359
360 let mut expected_offers = Vec::new();
361 for i in 0..10 {
362 let mut offer = create_test_offer_with_metadata_id(metadata_id);
363 offer.id = Uuid::from_u128(i as u128);
364 expected_offers.push(offer);
365 }
366
367 let server =
368 create_test_server_with_offer(expected_offers.clone(), vec![test_metadata]).await;
369
370 let response = server
371 .server
372 .get("/offers/default")
373 .authorization_bearer(server.authorization.clone())
374 .await;
375 assert_eq!(response.status_code(), StatusCode::OK);
376 let all_offers: Vec<OfferRecord> = response.json();
377 assert_eq!(all_offers.as_slice(), expected_offers.as_slice());
378
379 let response = server
380 .server
381 .get("/offers/default?start=1")
382 .authorization_bearer(server.authorization.clone())
383 .await;
384 assert_eq!(response.status_code(), StatusCode::OK);
385 let next_nine: Vec<OfferRecord> = response.json();
386 assert_eq!(next_nine.as_slice(), &expected_offers[1..]);
387
388 let response = server
389 .server
390 .get("/offers/default?count=1")
391 .authorization_bearer(server.authorization.clone())
392 .await;
393 assert_eq!(response.status_code(), StatusCode::OK);
394 let first: Vec<OfferRecord> = response.json();
395 assert_eq!(first.as_slice(), &expected_offers[0..1]);
396
397 let response = server
398 .server
399 .get("/offers/default?start=3&count=4")
400 .authorization_bearer(server.authorization.clone())
401 .await;
402 assert_eq!(response.status_code(), StatusCode::OK);
403 let middle_offers: Vec<OfferRecord> = response.json();
404 assert_eq!(middle_offers.as_slice(), &expected_offers[3..7]);
405
406 let response = server
407 .server
408 .get("/offers/default?count=101")
409 .authorization_bearer(server.authorization.clone())
410 .await;
411 assert_eq!(response.status_code(), StatusCode::BAD_REQUEST);
412 }
413
414 #[tokio::test]
415 async fn post_offer_when_new_then_creates_and_returns_location() {
416 let test_metadata = create_test_metadata();
417 let metadata_id = test_metadata.id;
418 let server = create_test_server_with_metadata(test_metadata).await;
419
420 let test_offer = create_test_offer_with_metadata_id(metadata_id);
421 let response = server
422 .server
423 .post("/offers")
424 .authorization_bearer(server.authorization.clone())
425 .json(&test_offer)
426 .await;
427
428 assert_eq!(response.status_code(), StatusCode::CREATED);
429 assert!(response.headers().contains_key("location"));
430
431 let location = response
433 .headers()
434 .get("location")
435 .unwrap()
436 .to_str()
437 .unwrap();
438 let get_response = server
439 .server
440 .get(&format!("/offers/{location}"))
441 .authorization_bearer(server.authorization.clone())
442 .await;
443
444 assert_eq!(get_response.status_code(), StatusCode::OK);
445 let returned_offer: OfferRecord = get_response.json();
446 assert_eq!(returned_offer.id, test_offer.id);
447 assert_eq!(
448 returned_offer.offer.max_sendable,
449 test_offer.offer.max_sendable
450 );
451 assert_eq!(
452 returned_offer.offer.min_sendable,
453 test_offer.offer.min_sendable
454 );
455 assert_eq!(
456 returned_offer.offer.metadata_id,
457 test_offer.offer.metadata_id
458 );
459
460 let response = server
462 .server
463 .post("/offers")
464 .json(&test_offer)
465 .authorization_bearer(server.authorization.clone())
466 .await;
467 assert_eq!(response.status_code(), StatusCode::CONFLICT);
468 assert!(response.headers().contains_key("location"));
469 }
470
471 #[tokio::test]
472 async fn put_offer_when_exists_then_updates_no_content() {
473 let test_metadata = create_test_metadata();
474 let test_offer = create_test_offer_with_metadata_id(test_metadata.id);
475 let offer_id = test_offer.id;
476 let server =
477 create_test_server_with_offer(vec![test_offer.clone()], vec![test_metadata]).await;
478
479 let mut updated_offer = test_offer.offer.clone();
480 updated_offer.max_sendable = 2000000;
481
482 let response = server
483 .server
484 .put(&format!("/offers/default/{offer_id}"))
485 .authorization_bearer(server.authorization.clone())
486 .json(&updated_offer)
487 .await;
488
489 assert_eq!(response.status_code(), StatusCode::NO_CONTENT);
490 }
491
492 #[tokio::test]
493 async fn put_offer_when_new_then_created() {
494 let test_metadata = create_test_metadata();
495 let metadata_id = test_metadata.id;
496 let server = create_test_server_with_metadata(test_metadata).await;
497
498 let test_offer = create_test_offer_with_metadata_id(metadata_id);
499 let offer_id = test_offer.id;
500 let response = server
501 .server
502 .put(&format!("/offers/default/{offer_id}"))
503 .authorization_bearer(server.authorization.clone())
504 .json(&test_offer.offer)
505 .await;
506
507 assert_eq!(response.status_code(), StatusCode::CREATED);
508 }
509
510 #[tokio::test]
511 async fn post_offer_when_metadata_missing_then_returns_bad_request() {
512 let server = create_empty_test_server();
513 let non_existent_metadata_id = Uuid::new_v4();
514 let test_offer = create_test_offer_with_metadata_id(non_existent_metadata_id);
515
516 let response = server
517 .server
518 .post("/offers")
519 .authorization_bearer(server.authorization.clone())
520 .json(&test_offer)
521 .await;
522
523 assert_eq!(response.status_code(), StatusCode::BAD_REQUEST);
524 }
525
526 #[tokio::test]
527 async fn put_offer_when_metadata_missing_then_returns_bad_request() {
528 let test_metadata = create_test_metadata();
530 let metadata_id = test_metadata.id;
531 let server = create_test_server_with_metadata(test_metadata).await;
532
533 let test_offer = create_test_offer_with_metadata_id(metadata_id);
534 let offer_id = test_offer.id;
535
536 let response = server
538 .server
539 .put(&format!("/offers/default/{offer_id}"))
540 .authorization_bearer(server.authorization.clone())
541 .json(&test_offer.offer)
542 .await;
543
544 assert_eq!(response.status_code(), StatusCode::CREATED);
545
546 let get_response = server
548 .server
549 .get(&format!("/offers/default/{offer_id}"))
550 .authorization_bearer(server.authorization.clone())
551 .await;
552
553 assert_eq!(get_response.status_code(), StatusCode::OK);
554 let created_offer: OfferRecord = get_response.json();
555 assert_eq!(created_offer.id, offer_id);
556 assert_eq!(created_offer.offer.metadata_id, metadata_id);
557
558 let non_existent_metadata_id = Uuid::new_v4();
560 let mut invalid_offer = test_offer.offer.clone();
561 invalid_offer.metadata_id = non_existent_metadata_id;
562
563 let response = server
564 .server
565 .put(&format!("/offers/default/{offer_id}"))
566 .authorization_bearer(server.authorization.clone())
567 .json(&invalid_offer)
568 .await;
569
570 assert_eq!(response.status_code(), StatusCode::BAD_REQUEST);
571 }
572
573 #[tokio::test]
574 async fn delete_metadata_when_referenced_by_offers_then_returns_bad_request() {
575 let test_metadata = create_test_metadata();
577 let metadata_id = test_metadata.id;
578 let server = create_test_server_with_metadata(test_metadata).await;
579
580 let test_offer = create_test_offer_with_metadata_id(metadata_id);
582 let response = server
583 .server
584 .put(&format!("/offers/default/{}", test_offer.id))
585 .authorization_bearer(server.authorization.clone())
586 .json(&test_offer.offer)
587 .await;
588
589 assert_eq!(response.status_code(), StatusCode::CREATED);
590
591 let response = server
593 .server
594 .delete(&format!("/metadata/default/{metadata_id}"))
595 .authorization_bearer(server.authorization.clone())
596 .await;
597
598 assert_eq!(response.status_code(), StatusCode::BAD_REQUEST);
599
600 let delete_offer_response = server
602 .server
603 .delete(&format!("/offers/default/{}", test_offer.id))
604 .authorization_bearer(server.authorization.clone())
605 .await;
606
607 assert_eq!(delete_offer_response.status_code(), StatusCode::NO_CONTENT);
608
609 let second_response = server
611 .server
612 .delete(&format!("/metadata/default/{metadata_id}"))
613 .authorization_bearer(server.authorization.clone())
614 .await;
615
616 assert_eq!(second_response.status_code(), StatusCode::NO_CONTENT);
617 }
618
619 #[tokio::test]
622 async fn delete_metadata_when_exists_then_removes_and_second_delete_not_found() {
623 let test_metadata = create_test_metadata();
624 let metadata_id = test_metadata.id;
625 let server = create_test_server_with_metadata(test_metadata).await;
626 let response = server
627 .server
628 .delete(&format!("/metadata/default/{metadata_id}"))
629 .authorization_bearer(server.authorization.clone())
630 .await;
631
632 assert_eq!(response.status_code(), StatusCode::NO_CONTENT);
633
634 let response = server
636 .server
637 .delete(&format!("/metadata/default/{metadata_id}"))
638 .authorization_bearer(server.authorization.clone())
639 .await;
640 assert_eq!(response.status_code(), StatusCode::NOT_FOUND);
641 }
642
643 #[tokio::test]
644 async fn delete_metadata_when_not_exists_then_returns_not_found() {
645 let server = create_empty_test_server();
646 let non_existent_id = Uuid::new_v4();
647 let response = server
648 .server
649 .delete(&format!("/metadata/default/{non_existent_id}"))
650 .authorization_bearer(server.authorization.clone())
651 .await;
652
653 assert_eq!(response.status_code(), StatusCode::NOT_FOUND);
654 }
655
656 #[tokio::test]
657 async fn get_metadata_when_exists_then_returns_resource() {
658 let test_metadata = create_test_metadata();
659 let metadata_id = test_metadata.id;
660 let server = create_test_server_with_metadata(test_metadata.clone()).await;
661 let response = server
662 .server
663 .get(&format!("/metadata/default/{metadata_id}"))
664 .authorization_bearer(server.authorization.clone())
665 .await;
666
667 assert_eq!(response.status_code(), StatusCode::OK);
668 let returned_metadata: OfferMetadata = response.json();
669 assert_eq!(returned_metadata.id, metadata_id);
670 assert_eq!(returned_metadata.metadata.text, test_metadata.metadata.text);
671 }
672
673 #[tokio::test]
674 async fn get_metadata_when_not_exists_then_returns_not_found() {
675 let server = create_empty_test_server();
676 let non_existent_id = Uuid::new_v4();
677 let response = server
678 .server
679 .get(&format!("/metadata/default/{non_existent_id}"))
680 .authorization_bearer(server.authorization.clone())
681 .await;
682
683 assert_eq!(response.status_code(), StatusCode::NOT_FOUND);
684 }
685
686 #[tokio::test]
687 async fn get_all_metadata_when_empty_then_returns_empty_list() {
688 let server = create_empty_test_server();
689 let response = server
690 .server
691 .get("/metadata/default")
692 .authorization_bearer(server.authorization.clone())
693 .await;
694
695 assert_eq!(response.status_code(), StatusCode::OK);
696 let metadata: Vec<OfferMetadata> = response.json();
697 assert!(metadata.is_empty());
698 }
699
700 #[tokio::test]
701 async fn get_all_metadata_when_exists_then_returns_list() {
702 let mut expected_metadata = Vec::new();
703 for i in 0..10 {
704 let mut metadata = create_test_metadata();
705 metadata.id = Uuid::from_u128(i as u128);
706 expected_metadata.push(metadata);
707 }
708
709 let server = create_test_server_with_offer(vec![], expected_metadata.clone()).await;
710
711 let response = server
712 .server
713 .get("/metadata/default")
714 .authorization_bearer(server.authorization.clone())
715 .await;
716 assert_eq!(response.status_code(), StatusCode::OK);
717 let all_metadata: Vec<OfferMetadata> = response.json();
718 assert_eq!(all_metadata.as_slice(), expected_metadata.as_slice());
719
720 let response = server
721 .server
722 .get("/metadata/default?start=1")
723 .authorization_bearer(server.authorization.clone())
724 .await;
725 assert_eq!(response.status_code(), StatusCode::OK);
726 let next_nine: Vec<OfferMetadata> = response.json();
727 assert_eq!(next_nine.as_slice(), &expected_metadata[1..]);
728
729 let response = server
730 .server
731 .get("/metadata/default?count=1")
732 .authorization_bearer(server.authorization.clone())
733 .await;
734 assert_eq!(response.status_code(), StatusCode::OK);
735 let first: Vec<OfferMetadata> = response.json();
736 assert_eq!(first.as_slice(), &expected_metadata[0..1]);
737
738 let response = server
739 .server
740 .get("/metadata/default?start=3&count=4")
741 .authorization_bearer(server.authorization.clone())
742 .await;
743 assert_eq!(response.status_code(), StatusCode::OK);
744 let middle_metadata: Vec<OfferMetadata> = response.json();
745 assert_eq!(middle_metadata.as_slice(), &expected_metadata[3..7]);
746
747 let response = server
748 .server
749 .get("/metadata/default?count=101")
750 .authorization_bearer(server.authorization.clone())
751 .await;
752 assert_eq!(response.status_code(), StatusCode::BAD_REQUEST);
753 }
754
755 #[tokio::test]
756 async fn post_metadata_when_new_then_creates_and_returns_location() {
757 let server = create_empty_test_server();
758 let test_metadata = create_test_metadata();
759 let response = server
760 .server
761 .post("/metadata")
762 .authorization_bearer(server.authorization.clone())
763 .json(&test_metadata)
764 .await;
765
766 assert_eq!(response.status_code(), StatusCode::CREATED);
767 assert!(response.headers().contains_key("location"));
768
769 let location = response
771 .headers()
772 .get("location")
773 .unwrap()
774 .to_str()
775 .unwrap();
776 let get_response = server
777 .server
778 .get(&format!("/metadata/{location}"))
779 .authorization_bearer(server.authorization.clone())
780 .await;
781
782 assert_eq!(get_response.status_code(), StatusCode::OK);
783 let returned_metadata: OfferMetadata = get_response.json();
784 assert_eq!(returned_metadata.id, test_metadata.id);
785 assert_eq!(returned_metadata.metadata.text, test_metadata.metadata.text);
786 assert_eq!(
787 returned_metadata.metadata.long_text,
788 test_metadata.metadata.long_text
789 );
790 assert_eq!(
791 returned_metadata.metadata.image,
792 test_metadata.metadata.image
793 );
794 assert_eq!(
795 returned_metadata.metadata.identifier,
796 test_metadata.metadata.identifier
797 );
798
799 let response = server
801 .server
802 .post("/metadata")
803 .json(&test_metadata)
804 .authorization_bearer(server.authorization.clone())
805 .await;
806 assert_eq!(response.status_code(), StatusCode::CONFLICT);
807 assert!(response.headers().contains_key("location"));
808 }
809
810 #[tokio::test]
811 async fn put_metadata_when_exists_then_updates_no_content() {
812 let test_metadata = create_test_metadata();
813 let metadata_id = test_metadata.id;
814 let server = create_test_server_with_metadata(test_metadata.clone()).await;
815
816 let mut updated_metadata = test_metadata.metadata.clone();
817 updated_metadata.text = "Updated text".to_string();
818
819 let response = server
820 .server
821 .put(&format!("/metadata/default/{metadata_id}"))
822 .authorization_bearer(server.authorization.clone())
823 .json(&updated_metadata)
824 .await;
825
826 assert_eq!(response.status_code(), StatusCode::NO_CONTENT);
827 }
828
829 #[tokio::test]
830 async fn put_metadata_when_new_then_created() {
831 let server = create_empty_test_server();
832 let test_metadata = create_test_metadata();
833 let metadata_id = test_metadata.id;
834 let response = server
835 .server
836 .put(&format!("/metadata/default/{metadata_id}"))
837 .authorization_bearer(server.authorization.clone())
838 .json(&test_metadata.metadata)
839 .await;
840
841 assert_eq!(response.status_code(), StatusCode::CREATED);
842 }
843
844 #[tokio::test]
845 async fn unauthorized() {
846 let server = create_empty_test_server();
847 let test_metadata = create_test_metadata();
848 let test_offer = create_test_offer_with_metadata_id(test_metadata.id);
849
850 let response = server.server.post("/offers").json(&test_offer).await;
851
852 assert_eq!(response.status_code(), StatusCode::UNAUTHORIZED);
853
854 let response = server.server.get("/offers/default").await;
855
856 assert_eq!(response.status_code(), StatusCode::UNAUTHORIZED);
857
858 let response = server.server.put("/offers/default").json(&test_offer).await;
859
860 assert_eq!(response.status_code(), StatusCode::UNAUTHORIZED);
861
862 let response = server.server.delete("/offers/default").await;
863
864 assert_eq!(response.status_code(), StatusCode::UNAUTHORIZED);
865
866 let response = server.server.post("/metadata").json(&test_offer).await;
867
868 assert_eq!(response.status_code(), StatusCode::UNAUTHORIZED);
869
870 let response = server.server.get("/metadata/default").await;
871
872 assert_eq!(response.status_code(), StatusCode::UNAUTHORIZED);
873
874 let response = server
875 .server
876 .put("/metadata/default")
877 .json(&test_offer)
878 .await;
879
880 assert_eq!(response.status_code(), StatusCode::UNAUTHORIZED);
881
882 let response = server.server.delete("/metadata/default").await;
883
884 assert_eq!(response.status_code(), StatusCode::UNAUTHORIZED);
885 }
886}