diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 48596371d1..5320dbbe30 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -15,7 +15,9 @@ actix-web = "4.0.0-beta.8" actix-http = "3.0.0-beta.8" actix-rt = "2" actix-web-actors = { version = "4.0.0-beta.6" } +actix-service = "2.0.0-beta.5" actix-identity = "0.4.0-beta.2" +#actix-cors = "0.5.4" futures = "0.3.15" bytes = "1" diff --git a/backend/src/application.rs b/backend/src/application.rs index fa42b29dfe..866e33cd00 100644 --- a/backend/src/application.rs +++ b/backend/src/application.rs @@ -53,6 +53,7 @@ pub fn run(listener: TcpListener, app_ctx: AppContext) -> Result Transform for AuthenticationService +where + S: Service, Error = Error> + 'static, + S::Future: 'static, + B: MessageBody + 'static, + B::Error: StdError, +{ + type Response = ServiceResponse; + type Error = Error; + type Transform = AuthenticationMiddleware; + type InitError = (); + type Future = Ready>; + + fn new_transform(&self, service: S) -> Self::Future { ok(AuthenticationMiddleware { service }) } +} +pub struct AuthenticationMiddleware { + service: S, +} + +impl Service for AuthenticationMiddleware +where + S: Service, Error = Error> + 'static, + S::Future: 'static, + B: MessageBody + 'static, + B::Error: StdError, +{ + type Response = ServiceResponse; + type Error = Error; + type Future = LocalBoxFuture<'static, Result>; + + fn poll_ready(&self, cx: &mut Context<'_>) -> Poll> { + self.service.poll_ready(cx) + } + + fn call(&self, mut req: ServiceRequest) -> Self::Future { + let mut authenticate_pass: bool = false; + for ignore_route in IGNORE_ROUTES.iter() { + if req.path().starts_with(ignore_route) { + authenticate_pass = true; + break; + } + } + + if !authenticate_pass { + if let Some(header) = req.headers().get(HEADER_TOKEN) { + let logger_user: LoggedUser = header.try_into().unwrap(); + if AUTHORIZED_USERS.is_authorized(&logger_user) { + authenticate_pass = true; + } + } + } + + if authenticate_pass { + let fut = self.service.call(req); + return Box::pin(async move { + let res = fut.await?; + Ok(res.map_body(|_, body| AnyBody::from_message(body))) + }); + } else { + Box::pin(async move { Ok(req.into_response(unauthorized_response())) }) + } + } +} + +fn unauthorized_response() -> HttpResponse { + let error = ServerError::unauthorized(); + error.error_response() +} diff --git a/backend/src/middleware/mod.rs b/backend/src/middleware/mod.rs new file mode 100644 index 0000000000..13aef75be1 --- /dev/null +++ b/backend/src/middleware/mod.rs @@ -0,0 +1,3 @@ +mod auth_middleware; + +pub use auth_middleware::*; diff --git a/rust-lib/flowy-net/src/response/response_http.rs b/rust-lib/flowy-net/src/response/response_http.rs index 61fc069603..dcd400eb3a 100644 --- a/rust-lib/flowy-net/src/response/response_http.rs +++ b/rust-lib/flowy-net/src/response/response_http.rs @@ -2,6 +2,7 @@ use crate::response::*; use actix_web::{error::ResponseError, HttpResponse}; use crate::errors::ServerError; +use actix_web::body::AnyBody; impl ResponseError for ServerError { fn error_response(&self) -> HttpResponse { @@ -12,3 +13,12 @@ impl ResponseError for ServerError { impl std::convert::Into for FlowyResponse { fn into(self) -> HttpResponse { HttpResponse::Ok().json(self) } } + +impl std::convert::Into for FlowyResponse { + fn into(self) -> AnyBody { + match serde_json::to_string(&self) { + Ok(body) => AnyBody::from(body), + Err(err) => AnyBody::Empty, + } + } +}