cloudillo_types/
extract.rs1use std::sync::Arc;
7
8use async_trait::async_trait;
9use axum::extract::FromRequestParts;
10use axum::http::request::Parts;
11
12use crate::error::Error;
13use crate::types::TnId;
14
15#[derive(Clone, Debug)]
19pub struct IdTag(pub Box<str>);
20
21impl IdTag {
22 pub fn new(id_tag: &str) -> IdTag {
23 IdTag(Box::from(id_tag))
24 }
25}
26
27impl<S> FromRequestParts<S> for IdTag
28where
29 S: Send + Sync,
30{
31 type Rejection = Error;
32
33 async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
34 if let Some(id_tag) = parts.extensions.get::<IdTag>().cloned() {
35 Ok(id_tag)
36 } else {
37 Err(Error::PermissionDenied)
38 }
39 }
40}
41
42#[async_trait]
49pub trait TnIdResolver: Send + Sync {
50 async fn resolve_tn_id(&self, id_tag: &str) -> Result<TnId, Error>;
51}
52
53#[async_trait]
56impl<T: TnIdResolver> TnIdResolver for Arc<T> {
57 async fn resolve_tn_id(&self, id_tag: &str) -> Result<TnId, Error> {
58 (**self).resolve_tn_id(id_tag).await
59 }
60}
61
62impl<S> FromRequestParts<S> for TnId
63where
64 S: TnIdResolver + Send + Sync,
65{
66 type Rejection = Error;
67
68 async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
69 if let Some(id_tag) = parts.extensions.get::<IdTag>().cloned() {
70 state.resolve_tn_id(&id_tag.0).await.map_err(|_| Error::PermissionDenied)
71 } else {
72 Err(Error::PermissionDenied)
73 }
74 }
75}
76
77