use poem::http::StatusCode;
use poem::web::{FromRequest, RequestBody};
use poem::{Error, Request, Result};
use super::GuardNotConfigured;
use crate::guard::Guard;
impl<'a> FromRequest<'a> for Guard {
async fn from_request(req: &'a Request, _body: &mut RequestBody) -> Result<Self> {
req.extensions().get::<Guard>().cloned().ok_or_else(|| {
Error::from_string(
GuardNotConfigured.to_string(),
StatusCode::INTERNAL_SERVER_ERROR,
)
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use poem::Request;
fn guard() -> Guard {
Guard::from_master_key(&[7u8; 32], "aes-256-gcm").unwrap()
}
async fn extract(req: &Request) -> Result<Guard> {
let mut body = RequestBody::default();
Guard::from_request(req, &mut body).await
}
#[tokio::test]
async fn extracts_from_request_extensions() {
let mut req = Request::builder().finish();
req.extensions_mut().insert(guard());
let extracted = extract(&req).await.unwrap();
assert_eq!(extracted.identifiers().len(), 5);
}
#[tokio::test]
async fn missing_data_is_a_500() {
let req = Request::builder().finish();
let err = extract(&req).await.unwrap_err();
assert_eq!(err.status(), StatusCode::INTERNAL_SERVER_ERROR);
}
#[tokio::test]
async fn handler_and_state_share_one_encrypter() {
let state = guard();
let token = state.encrypt("共享".as_bytes()).unwrap();
let mut req = Request::builder().finish();
req.extensions_mut().insert(state);
let extracted = extract(&req).await.unwrap();
assert_eq!(extracted.decrypt(&token).unwrap(), "共享".as_bytes());
}
}