How do I implement traits? On running cargo build I get this error.
Also I commented out type Request = ServiceRequest;
. How would this affect the code? I updated actix-service to 2.0.0-beta.2 in Cargo.toml, then the build failed.
error[E0107]: missing generics for trait `actix_service::Service`
--> src/middleware.rs:57:8
|
57 | S: Service<Response = ServiceResponse<B>, Error = Error> + 'static,
| ^^^^^^^ expected 1 type argument
|
note: trait defined here, with 1 type parameter: `Req`
--> /home/samarpan/.cargo/registry/src/github.com-1ecc6299db9ec823/actix-service-2.0.0-beta.5/src/lib.rs:85:11
|
85 | pub trait Service<Req> {
| ^^^^^^^ ---
help: use angle brackets to add missing type argument
|
57 | S: Service<Req><Response = ServiceResponse<B>, Error = Error> + 'static,
| ^^^^^
This is my middleware.rs -
#![allow(clippy::type_complexity)]
use std::cell::RefCell;
use std::ops::{Deref, DerefMut};
use std::pin::Pin;
use std::rc::Rc;
use std::sync::Arc;
use std::task::{Context, Poll};
use futures::future::{ok, Ready};
use futures::Future;
use actix_service::{Service, Transform};
use actix_web::{
dev::ServiceRequest, dev::ServiceResponse, Error, HttpMessage, HttpResponse, Result,
};
use casbin::prelude::{TryIntoAdapter, TryIntoModel};
use casbin::{CachedEnforcer, CoreApi, Result as CasbinResult};
#[cfg(feature = "runtime-tokio")]
use tokio::sync::RwLock;
#[cfg(feature = "runtime-async-std")]
use async_std::sync::RwLock;
#[derive(Clone)]
pub struct CasbinVals {
pub subject: String,
pub domain: Option<String>,
}
#[derive(Clone)]
pub struct CasbinService {
enforcer: Arc<RwLock<CachedEnforcer>>,
}
impl CasbinService {
pub async fn new<M: TryIntoModel, A: TryIntoAdapter>(m: M, a: A) -> CasbinResult<Self> {
let enforcer: CachedEnforcer = CachedEnforcer::new(m, a).await?;
Ok(CasbinService {
enforcer: Arc::new(RwLock::new(enforcer)),
})
}
pub fn get_enforcer(&mut self) -> Arc<RwLock<CachedEnforcer>> {
self.enforcer.clone()
}
pub fn set_enforcer(e: Arc<RwLock<CachedEnforcer>>) -> CasbinService {
CasbinService { enforcer: e }
}
}
impl<S, B> Transform<S, B> for CasbinService
where
S: Service<Response = ServiceResponse<B>, Error = Error> + 'static,
S::Future: 'static,
B: 'static,
{
//type Request = ServiceRequest;
type Response = ServiceResponse<B>;
type Error = Error;
type InitError = ();
type Transform = CasbinMiddleware<S>;
type Future = Ready<Result<Self::Transform, Self::InitError>>;
fn new_transform(&self, service: S) -> Self::Future {
ok(CasbinMiddleware {
enforcer: self.enforcer.clone(),
service: Rc::new(RefCell::new(service)),
})
}
}
impl Deref for CasbinService {
type Target = Arc<RwLock<CachedEnforcer>>;
fn deref(&self) -> &Self::Target {
&self.enforcer
}
}
impl DerefMut for CasbinService {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.enforcer
}
}
pub struct CasbinMiddleware<S> {
service: Rc<RefCell<S>>,
enforcer: Arc<RwLock<CachedEnforcer>>,
}
impl<S, B> Service<B> for CasbinMiddleware<S>
where
S: Service<Response = ServiceResponse<B>, Error = Error> + 'static,
S::Future: 'static,
B: 'static,
{
//type Request = ServiceRequest;
type Response = ServiceResponse<B>;
type Error = Error;
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>;
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.service.poll_ready(cx)
}
fn call(&mut self, req: ServiceRequest) -> Self::Future {
let cloned_enforcer = self.enforcer.clone();
let mut srv = self.service.clone();
Box::pin(async move {
let path = req.path().to_string();
let action = req.method().as_str().to_string();
let option_vals = req.extensions().get::<CasbinVals>().map(|x| x.to_owned());
let vals = match option_vals {
Some(value) => value,
None => {
return Ok(req.into_response(HttpResponse::Unauthorized().finish().into_body()))
}
};
let subject = vals.subject.clone();
if !vals.subject.is_empty() {
if let Some(domain) = vals.domain {
let mut lock = cloned_enforcer.write().await;
match lock.enforce_mut(vec![subject, domain, path, action]) {
Ok(true) => {
drop(lock);
srv.call(req).await
}
Ok(false) => {
drop(lock);
Ok(req.into_response(HttpResponse::Forbidden().finish().into_body()))
}
Err(_) => {
drop(lock);
Ok(req.into_response(HttpResponse::BadGateway().finish().into_body()))
}
}
} else {
let mut lock = cloned_enforcer.write().await;
match lock.enforce_mut(vec![subject, path, action]) {
Ok(true) => {
drop(lock);
srv.call(req).await
}
Ok(false) => {
drop(lock);
Ok(req.into_response(HttpResponse::Forbidden().finish().into_body()))
}
Err(_) => {
drop(lock);
Ok(req.into_response(HttpResponse::BadGateway().finish().into_body()))
}
}
}
} else {
Ok(req.into_response(HttpResponse::Unauthorized().finish().into_body()))
}
})
}
}
original repo link - https://github.com/casbin-rs/actix-casbin-auth
my changes - https://github.com/smrpn/actix-casbin-auth/tree/feature/bumpactixweb