diff options
author | metamuffin <metamuffin@disroot.org> | 2025-05-20 15:59:51 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-05-20 15:59:51 +0200 |
commit | a1db84ac3b776e929ce3286b6f77dd1ca97ea249 (patch) | |
tree | d9f271a0af46960c3d4a65f0213d1a27ca99b737 | |
parent | 09f86ee5b25fbddf667ef98a22eaa076cedba23c (diff) | |
download | jellything-a1db84ac3b776e929ce3286b6f77dd1ca97ea249.tar jellything-a1db84ac3b776e929ce3286b6f77dd1ca97ea249.tar.bz2 jellything-a1db84ac3b776e929ce3286b6f77dd1ca97ea249.tar.zst |
requestinfo from request impl
-rw-r--r-- | logic/src/lib.rs | 9 | ||||
-rw-r--r-- | server/src/helper/mod.rs | 30 | ||||
-rw-r--r-- | server/src/helper/session.rs | 71 |
3 files changed, 73 insertions, 37 deletions
diff --git a/logic/src/lib.rs b/logic/src/lib.rs index 79d27d9..004e008 100644 --- a/logic/src/lib.rs +++ b/logic/src/lib.rs @@ -38,3 +38,12 @@ static CONF: LazyLock<Config> = LazyLock::new(|| { .take() .expect("logic config not preloaded. logic error") }); + +static DATABASE_PRELOAD: Mutex<Option<Database>> = Mutex::new(None); +static DATABASE: LazyLock<Database> = LazyLock::new(|| { + DATABASE_PRELOAD + .lock() + .unwrap() + .take() + .expect("database not preloaded. logic error") +}); diff --git a/server/src/helper/mod.rs b/server/src/helper/mod.rs index 4b0644c..9e8ce79 100644 --- a/server/src/helper/mod.rs +++ b/server/src/helper/mod.rs @@ -11,9 +11,18 @@ pub mod language; pub mod node_id; pub mod session; +use crate::ui::error::{MyError, MyResult}; use accept::Accept; use jellylogic::session::Session; use jellyui::locale::Language; +use language::lang_from_request; +use rocket::{ + async_trait, + http::Status, + request::{FromRequest, Outcome}, + Request, +}; +use session::session_from_request; #[derive(Debug, Clone, Copy, Default)] pub struct A<T>(pub T); @@ -23,3 +32,24 @@ pub struct RequestInfo { pub accept: Accept, pub session: Session, } + +impl RequestInfo { + pub async fn from_request_ut(request: &Request<'_>) -> MyResult<Self> { + Ok(Self { + lang: lang_from_request(request), + accept: Accept::from_request_ut(request), + session: session_from_request(request).await?, + }) + } +} + +#[async_trait] +impl<'r> FromRequest<'r> for RequestInfo { + type Error = MyError; + async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> { + match Self::from_request_ut(request).await { + Ok(a) => Outcome::Success(a), + Err(a) => Outcome::Error((Status::BadRequest, a)), + } + } +} diff --git a/server/src/helper/session.rs b/server/src/helper/session.rs index 7e23152..2ab87a0 100644 --- a/server/src/helper/session.rs +++ b/server/src/helper/session.rs @@ -3,6 +3,7 @@ which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2025 metamuffin <metamuffin.org> */ +use super::A; use crate::ui::error::MyError; use anyhow::anyhow; use jellylogic::{ @@ -18,44 +19,40 @@ use rocket::{ Request, State, }; -use super::A; - -impl A<Session> { - async fn from_request_ut(req: &Request<'_>) -> Result<Self, MyError> { - let username; +pub(super) async fn session_from_request(req: &Request<'_>) -> Result<Session, MyError> { + let username; - #[cfg(not(feature = "bypass-auth"))] - { - let token = req - .query_value("session") - .map(|e| e.unwrap()) - .or_else(|| req.query_value("api_key").map(|e| e.unwrap())) - .or_else(|| req.headers().get_one("X-MediaBrowser-Token")) - .or_else(|| { - req.headers() - .get_one("Authorization") - .and_then(parse_jellyfin_auth) - }) // for jellyfin compat - .or(req.cookies().get("session").map(|cookie| cookie.value())) - .ok_or(anyhow!("not logged in"))?; + #[cfg(not(feature = "bypass-auth"))] + { + let token = req + .query_value("session") + .map(|e| e.unwrap()) + .or_else(|| req.query_value("api_key").map(|e| e.unwrap())) + .or_else(|| req.headers().get_one("X-MediaBrowser-Token")) + .or_else(|| { + req.headers() + .get_one("Authorization") + .and_then(parse_jellyfin_auth) + }) // for jellyfin compat + .or(req.cookies().get("session").map(|cookie| cookie.value())) + .ok_or(anyhow!("not logged in"))?; - // jellyfin urlescapes the token for *some* requests - let token = token.replace("%3D", "="); - username = validate(&token)?; - }; + // jellyfin urlescapes the token for *some* requests + let token = token.replace("%3D", "="); + username = validate(&token)?; + }; - #[cfg(feature = "bypass-auth")] - { - parse_jellyfin_auth("a"); // unused warning is annoying - username = "admin".to_string(); - } + #[cfg(feature = "bypass-auth")] + { + parse_jellyfin_auth("a"); // unused warning is annoying + username = "admin".to_string(); + } - let db = req.guard::<&State<Database>>().await.unwrap(); + let db = req.guard::<&State<Database>>().await.unwrap(); - let user = db.get_user(&username)?.ok_or(anyhow!("user not found"))?; + let user = db.get_user(&username)?.ok_or(anyhow!("user not found"))?; - Ok(A(Session { user })) - } + Ok(Session { user }) } fn parse_jellyfin_auth(h: &str) -> Option<&str> { @@ -75,8 +72,8 @@ impl<'r> FromRequest<'r> for A<Session> { async fn from_request<'life0>( request: &'r Request<'life0>, ) -> request::Outcome<Self, Self::Error> { - match A::<Session>::from_request_ut(request).await { - Ok(x) => Outcome::Success(x), + match session_from_request(request).await { + Ok(x) => Outcome::Success(A(x)), Err(e) => { warn!("authentificated route rejected: {e:?}"); Outcome::Forward(Status::Unauthorized) @@ -91,10 +88,10 @@ impl<'r> FromRequest<'r> for A<AdminSession> { async fn from_request<'life0>( request: &'r Request<'life0>, ) -> request::Outcome<Self, Self::Error> { - match A::<Session>::from_request_ut(request).await { + match session_from_request(request).await { Ok(x) => { - if x.0.user.admin { - Outcome::Success(A(AdminSession(x.0))) + if x.user.admin { + Outcome::Success(A(AdminSession(x))) } else { Outcome::Error(( Status::Unauthorized, |