From 9cc03c4ffe699cabcf9fa10200cec2c014e89911 Mon Sep 17 00:00:00 2001 From: N08I40K Date: Wed, 16 Apr 2025 16:20:32 +0400 Subject: [PATCH] =?UTF-8?q?=D0=A4=D0=B8=D0=BB=D1=8C=D1=82=D1=80=20=D1=8D?= =?UTF-8?q?=D0=BD=D0=B4=D0=BF=D0=BE=D0=B8=D0=BD=D1=82=D0=BE=D0=B2=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20middleware.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 8 +++--- src/middlewares/authorization.rs | 43 +++++++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/main.rs b/src/main.rs index c637d27..3e2db58 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,13 +35,15 @@ pub fn get_api_scope< .service(routes::auth::sign_up_vk); let users_scope = utoipa_actix_web::scope("/users") - .wrap(JWTAuthorization) + .wrap(JWTAuthorization::default()) .service(routes::users::change_group) .service(routes::users::change_username) .service(routes::users::me); let schedule_scope = utoipa_actix_web::scope("/schedule") - .wrap(JWTAuthorization) + .wrap(JWTAuthorization { + ignore: &["/group-names", "/teacher-names"], + }) .service(routes::schedule::schedule) .service(routes::schedule::update_download_url) .service(routes::schedule::cache_status) @@ -51,7 +53,7 @@ pub fn get_api_scope< .service(routes::schedule::teacher_names); let fcm_scope = utoipa_actix_web::scope("/fcm") - .wrap(JWTAuthorization) + .wrap(JWTAuthorization::default()) .service(routes::fcm::update_callback) .service(routes::fcm::set_token); diff --git a/src/middlewares/authorization.rs b/src/middlewares/authorization.rs index 12c775d..3e0892c 100644 --- a/src/middlewares/authorization.rs +++ b/src/middlewares/authorization.rs @@ -8,7 +8,16 @@ use futures_util::future::LocalBoxFuture; use std::future::{Ready, ready}; /// Middleware guard working with JWT tokens. -pub struct JWTAuthorization; +pub struct JWTAuthorization { + /// List of ignored endpoints. + pub ignore: &'static [&'static str], +} + +impl Default for JWTAuthorization { + fn default() -> Self { + Self { ignore: &[] } + } +} impl Transform for JWTAuthorization where @@ -23,12 +32,17 @@ where type Future = Ready>; fn new_transform(&self, service: S) -> Self::Future { - ready(Ok(JWTAuthorizationMiddleware { service })) + ready(Ok(JWTAuthorizationMiddleware { + service, + ignore: self.ignore, + })) } } pub struct JWTAuthorizationMiddleware { service: S, + /// List of ignored endpoints. + ignore: &'static [&'static str], } impl JWTAuthorizationMiddleware @@ -38,7 +52,7 @@ where B: 'static, { /// Checking the validity of the token. - pub fn check_authorization( + fn check_authorization( &self, req: &HttpRequest, payload: &mut Payload, @@ -47,9 +61,25 @@ where .map(|_| ()) .map_err(|e| e.as_error::().unwrap().clone()) } + + fn should_skip(&self, req: &ServiceRequest) -> bool { + let path = req.match_info().unprocessed(); + + self.ignore.iter().any(|ignore| { + if !path.starts_with(ignore) { + return false; + } + + if let Some(other) = path.as_bytes().iter().nth(ignore.len()) { + return ['?' as u8, '/' as u8].contains(other); + } + + true + }) + } } -impl Service for JWTAuthorizationMiddleware +impl<'a, S, B> Service for JWTAuthorizationMiddleware where S: Service, Error = Error>, S::Future: 'static, @@ -62,6 +92,11 @@ where forward_ready!(service); fn call(&self, req: ServiceRequest) -> Self::Future { + if self.should_skip(&req) { + let fut = self.service.call(req); + return Box::pin(async move { Ok(fut.await?.map_into_left_body()) }); + } + let (http_req, mut payload) = req.into_parts(); if let Err(err) = self.check_authorization(&http_req, &mut payload) {