user-service 0.4.1

A user management microservice.
Documentation
use super::*;
use std::future::{ready, Ready};

use actix_web::{
    dev::{Service, ServiceRequest, ServiceResponse, Transform},
    Error,
};
use futures_util::future::LocalBoxFuture;

use std::rc::Rc;

use actix_web::dev;

pub struct Exists;

impl<S: 'static, B> Transform<S, ServiceRequest> for Exists
where
    S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
    B: 'static,
{
    type Response = ServiceResponse<B>;
    type Error = Error;
    type InitError = ();
    type Transform = ExistsMiddleware<S>;
    type Future = Ready<Result<Self::Transform, Self::InitError>>;

    fn new_transform(&self, service: S) -> Self::Future {
        ready(Ok(ExistsMiddleware {
            service: Rc::new(service),
        }))
    }
}

pub struct ExistsMiddleware<S> {
    // This is special: We need this to avoid lifetime issues.
    service: Rc<S>,
}

impl<S, B> Service<ServiceRequest> for ExistsMiddleware<S>
where
    S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
    S::Future: 'static,
    B: 'static,
{
    type Response = ServiceResponse<B>;
    type Error = Error;
    type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;

    dev::forward_ready!(service);

    fn call(&self, req: ServiceRequest) -> Self::Future {
        let svc = self.service.clone();
        let db = req.app_data::<web::Data<Database>>().unwrap().clone();

        Box::pin(async move {
            let info = req.match_info().load::<Info>().unwrap();

            let result: bool = web::block(move || {
                use diesel::dsl::*;
                use schema::user::dsl::*;

                let mut conn = db.get_conn();

                conn.transaction(|conn| {
                    select(exists(user.filter(id.eq(info.user_id)))).get_result(conn)
                })
            })
            .await
            .unwrap()
            .unwrap();

            match result {
                false => Err(ErrorCode::NotFound.into()),
                true => {
                    let res = svc.call(req).await?;

                    Ok(res)
                }
            }
        })
    }
}