use std::{ future::{ready, Ready}, rc::Rc, }; use actix_identity::IdentityExt; use actix_web::{ dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform}, web, Error, HttpMessage, }; use futures_util::{future::LocalBoxFuture, FutureExt}; use sqlx::PgPool; use crate::models::User; pub struct LoadCurrentUser; impl Transform for LoadCurrentUser where S: Service, Error = Error> + 'static, { type Response = ServiceResponse; type Error = Error; type InitError = (); type Transform = LoadCurrentUserMiddleware; type Future = Ready>; fn new_transform(&self, service: S) -> Self::Future { ready(Ok(LoadCurrentUserMiddleware { service: Rc::new(service), })) } } pub struct LoadCurrentUserMiddleware { service: Rc, } impl Service for LoadCurrentUserMiddleware where S: Service, Error = Error> + 'static, { type Response = ServiceResponse; type Error = Error; type Future = LocalBoxFuture<'static, Result>; forward_ready!(service); fn call(&self, req: ServiceRequest) -> Self::Future { let srv = self.service.clone(); async move { if let Ok(identity) = req.get_identity() { if let Ok(id) = identity.id() { let pool = req.app_data::>().unwrap(); let user = User::read_by_id(pool.get_ref(), id.parse().unwrap()) .await .unwrap() .unwrap(); req.extensions_mut().insert::(user); } } let res = srv.call(req).await?; Ok(res) } .boxed_local() } }