diff --git a/crates/ezidam/src/guards/jwt.rs b/crates/ezidam/src/guards/jwt.rs index 72bb9c8..2850ba7 100644 --- a/crates/ezidam/src/guards/jwt.rs +++ b/crates/ezidam/src/guards/jwt.rs @@ -3,7 +3,6 @@ use crate::guards::refresh_token::get_refresh_token_from_cookie; use crate::tokens::{ JWT_COOKIE_NAME, JWT_DURATION_MINUTES, REFRESH_TOKEN_COOKIE_NAME, REFRESH_TOKEN_DURATION_DAYS, }; -pub use admin::JwtAdmin; use id::KeyID; use jwt::database::Key; use jwt::{JwtClaims, PrivateKey}; @@ -11,11 +10,15 @@ use rocket::http::Status; use rocket::request::Outcome; use rocket::tokio::task; use rocket::Request; -pub use user::JwtUser; mod admin; +mod admin_not_current; mod user; +pub use admin::JwtAdmin; +pub use admin_not_current::JwtAdminNotCurrent; +pub use user::JwtUser; + #[derive(Debug)] pub enum Error { GetDatabase, diff --git a/crates/ezidam/src/guards/jwt/admin_not_current.rs b/crates/ezidam/src/guards/jwt/admin_not_current.rs new file mode 100644 index 0000000..ddc54be --- /dev/null +++ b/crates/ezidam/src/guards/jwt/admin_not_current.rs @@ -0,0 +1,53 @@ +use super::Error; +use crate::guards::use_access_token_or_refresh_token; +use crate::id::RocketUserID; +use jwt::JwtClaims; +use rocket::request::{FromRequest, Outcome}; +use rocket::Request; + +#[derive(Debug)] +/// Use to allow access to an admin that is not the currently signed-in admin +pub struct JwtAdminNotCurrent(pub JwtClaims); + +#[rocket::async_trait] +impl<'r> FromRequest<'r> for JwtAdminNotCurrent { + type Error = Error; + + async fn from_request(request: &'r Request<'_>) -> Outcome { + let get_admin: Option = Some(true); + + let user_id = match { + let mut ret = None; + + // In all segments of uri, attempt to parse a valid user id + for (idx, _) in request.uri().path().segments().enumerate() { + if let Ok(user_id) = request.param::(idx).transpose() { + // Found user id, save it + ret = user_id; + } + } + + ret + } { + Some(user_id) => user_id, + None => return Outcome::Forward(()), + }; + + match use_access_token_or_refresh_token(request, get_admin) + .await + .map(Self) + { + // Do we have a valid admin? + Outcome::Success(success) => { + // Is the requested user is not the current logged-in user? + if success.0.subject != user_id.0 .0 { + Outcome::Success(success) + } else { + Outcome::Forward(()) + } + } + Outcome::Failure(failure) => Outcome::Failure(failure), + Outcome::Forward(forward) => Outcome::Forward(forward), + } + } +}