encryption/integrations/
actix.rs1use std::future::{Ready, ready};
38
39use actix_web::dev::Payload;
40use actix_web::web::Data;
41use actix_web::{Error, FromRequest, HttpRequest};
42
43use super::GuardNotConfigured;
44use crate::guard::Guard;
45
46impl FromRequest for Guard {
47 type Error = Error;
48 type Future = Ready<Result<Self, Self::Error>>;
50
51 fn from_request(req: &HttpRequest, _payload: &mut Payload) -> Self::Future {
52 match req.app_data::<Data<Guard>>() {
53 Some(data) => {
54 let guard: &Guard = data;
58 ready(Ok(guard.clone()))
59 }
60 None => ready(Err(actix_web::error::ErrorInternalServerError(
62 GuardNotConfigured,
63 ))),
64 }
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71 use actix_web::test;
72
73 fn guard() -> Guard {
74 Guard::from_master_key(&[7u8; 32], "aes-256-gcm").unwrap()
75 }
76
77 #[actix_web::test]
78 async fn extracts_from_app_data() {
79 let req = test::TestRequest::default()
80 .app_data(Data::new(guard()))
81 .to_http_request();
82
83 let extracted = Guard::from_request(&req, &mut Payload::None).await.unwrap();
84 assert_eq!(extracted.identifiers().len(), 5);
85 }
86
87 #[actix_web::test]
89 async fn missing_app_data_is_a_500() {
90 let req = test::TestRequest::default().to_http_request();
91 let err = Guard::from_request(&req, &mut Payload::None)
92 .await
93 .unwrap_err();
94 assert_eq!(
95 err.as_response_error().status_code(),
96 actix_web::http::StatusCode::INTERNAL_SERVER_ERROR
97 );
98 }
99
100 #[actix_web::test]
102 async fn handler_and_state_share_one_encrypter() {
103 let state = guard();
104 let token = state.encrypt("共享".as_bytes()).unwrap();
105
106 let req = test::TestRequest::default()
107 .app_data(Data::new(state))
108 .to_http_request();
109 let extracted = Guard::from_request(&req, &mut Payload::None).await.unwrap();
110
111 assert_eq!(extracted.decrypt(&token).unwrap(), "共享".as_bytes());
112 }
113
114 #[actix_web::test]
116 async fn data_from_arc_shares_the_allocation() {
117 use std::sync::Arc;
118
119 let shared = Arc::new(guard());
120 let token = shared.encrypt(b"x").unwrap();
121
122 let req = test::TestRequest::default()
123 .app_data(Data::from(shared.clone()))
124 .to_http_request();
125 let extracted = Guard::from_request(&req, &mut Payload::None).await.unwrap();
126
127 assert_eq!(extracted.decrypt(&token).unwrap(), b"x");
128 assert_eq!(Arc::strong_count(&shared), 2);
130 }
131}