use axum::extract::Request;
use axum::middleware::Next;
use axum::response::{IntoResponse, Response};
use uuid::Uuid;
use crate::application::service::chatter_acl::MessagingIdentity;
#[derive(Debug, Clone, Copy)]
pub struct AuthPartnerId(pub Uuid);
#[derive(Debug, Clone, Copy, Default)]
pub struct IsAdmin(pub bool);
#[derive(Debug, Clone)]
pub enum WireIdentity {
Identified(MessagingIdentity),
Anonymous,
}
impl WireIdentity {
pub fn identity(&self) -> Option<&MessagingIdentity> {
match self {
WireIdentity::Identified(id) => Some(id),
WireIdentity::Anonymous => None,
}
}
pub fn partner_id(&self) -> Option<Uuid> {
self.identity().and_then(|i| i.partner_id())
}
pub fn is_guest(&self) -> bool {
matches!(self.identity(), Some(MessagingIdentity::Guest { .. }))
}
}
pub async fn guest_context(mut req: Request, next: Next) -> Response {
if req.extensions().get::<IsAdmin>().is_none() {
req.extensions_mut().insert(IsAdmin(false));
}
if let Some(AuthPartnerId(partner_id)) = req.extensions().get::<AuthPartnerId>().copied() {
req.extensions_mut().insert(WireIdentity::Identified(MessagingIdentity::User { partner_id }));
return next.run(req).await;
}
let dgid = req
.headers()
.get(axum::http::header::COOKIE)
.and_then(|v| v.to_str().ok())
.and_then(|cookies| {
cookies.split(';').map(|c| c.trim()).find_map(|c| {
c.strip_prefix("dgid=").filter(|v| !v.is_empty())
})
});
let identity = dgid
.and_then(|v| Uuid::parse_str(v).ok())
.map(|guest_id| MessagingIdentity::Guest { guest_id });
let wire = match identity {
Some(id) => WireIdentity::Identified(id),
None => WireIdentity::Anonymous,
};
req.extensions_mut().insert(wire);
next.run(req).await
}
pub fn unauthorized() -> Response {
(
axum::http::StatusCode::UNAUTHORIZED,
axum::Json(serde_json::json!({"error": "authentication required"})),
)
.into_response()
}
pub fn forbidden(reason: &str) -> Response {
(
axum::http::StatusCode::FORBIDDEN,
axum::Json(serde_json::json!({"error": reason})),
)
.into_response()
}