aboutsummaryrefslogtreecommitdiff
path: root/server/src/logic
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/logic')
-rw-r--r--server/src/logic/mod.rs2
-rw-r--r--server/src/logic/session.rs109
-rw-r--r--server/src/logic/stream.rs6
-rw-r--r--server/src/logic/userdata.rs34
4 files changed, 22 insertions, 129 deletions
diff --git a/server/src/logic/mod.rs b/server/src/logic/mod.rs
index 745d11b..26f45de 100644
--- a/server/src/logic/mod.rs
+++ b/server/src/logic/mod.rs
@@ -4,6 +4,6 @@
Copyright (C) 2025 metamuffin <metamuffin.org>
*/
pub mod playersync;
-pub mod session;
pub mod stream;
pub mod userdata;
+
diff --git a/server/src/logic/session.rs b/server/src/logic/session.rs
deleted file mode 100644
index 105aa10..0000000
--- a/server/src/logic/session.rs
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- This file is part of jellything (https://codeberg.org/metamuffin/jellything)
- which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
- Copyright (C) 2025 metamuffin <metamuffin.org>
-*/
-use crate::ui::error::MyError;
-use anyhow::anyhow;
-use jellybase::database::Database;
-use jellylogic::session::{validate, AdminSession, Session};
-use log::warn;
-use rocket::{
- async_trait,
- http::Status,
- outcome::Outcome,
- request::{self, FromRequest},
- Request, State,
-};
-
-pub struct A<T>(pub T);
-
-impl A<Session> {
- async fn from_request_ut(req: &Request<'_>) -> Result<Self, 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"))?;
-
- // 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();
- }
-
- let db = req.guard::<&State<Database>>().await.unwrap();
-
- let user = db.get_user(&username)?.ok_or(anyhow!("user not found"))?;
-
- Ok(A(Session { user }))
- }
-}
-
-fn parse_jellyfin_auth(h: &str) -> Option<&str> {
- for tok in h.split(" ") {
- if let Some(tok) = tok.strip_prefix("Token=\"") {
- if let Some(tok) = tok.strip_suffix("\"") {
- return Some(tok);
- }
- }
- }
- None
-}
-
-#[async_trait]
-impl<'r> FromRequest<'r> for A<Session> {
- type Error = MyError;
- async fn from_request<'life0>(
- request: &'r Request<'life0>,
- ) -> request::Outcome<Self, Self::Error> {
- match Session::from_request_ut(request).await {
- Ok(x) => Outcome::Success(x),
- Err(e) => {
- warn!("authentificated route rejected: {e:?}");
- Outcome::Forward(Status::Unauthorized)
- }
- }
- }
-}
-
-#[async_trait]
-impl<'r> FromRequest<'r> for A<AdminSession> {
- type Error = MyError;
- async fn from_request<'life0>(
- request: &'r Request<'life0>,
- ) -> request::Outcome<Self, Self::Error> {
- match A::<Session>::from_request_ut(request).await {
- Ok(x) => {
- if x.user.admin {
- Outcome::Success(A(AdminSession(x.0)))
- } else {
- Outcome::Error((
- Status::Unauthorized,
- MyError(anyhow!("you are not an admin")),
- ))
- }
- }
- Err(e) => {
- warn!("authentificated route rejected: {e:?}");
- Outcome::Forward(Status::Unauthorized)
- }
- }
- }
-}
diff --git a/server/src/logic/stream.rs b/server/src/logic/stream.rs
index f9cdb41..9d4db6d 100644
--- a/server/src/logic/stream.rs
+++ b/server/src/logic/stream.rs
@@ -3,7 +3,7 @@
which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
Copyright (C) 2025 metamuffin <metamuffin.org>
*/
-use crate::{database::Database, ui::error::MyError};
+use crate::{database::Database, helper::A, ui::error::MyError};
use anyhow::{anyhow, Result};
use jellybase::{assetfed::AssetInner, federation::Federation};
use jellycommon::{stream::StreamSpec, TrackSource};
@@ -26,7 +26,7 @@ use tokio::io::{duplex, DuplexStream};
#[head("/n/<_id>/stream?<spec..>")]
pub async fn r_stream_head(
- _sess: Session,
+ _sess: A<Session>,
_id: &str,
spec: BTreeMap<String, String>,
) -> Result<Either<StreamResponse, Redirect>, MyError> {
@@ -42,7 +42,7 @@ pub async fn r_stream_head(
#[get("/n/<id>/stream?<spec..>")]
pub async fn r_stream(
- _session: Session,
+ _session: A<Session>,
_federation: &State<Federation>,
db: &State<Database>,
id: &str,
diff --git a/server/src/logic/userdata.rs b/server/src/logic/userdata.rs
index 8da6be9..25d3893 100644
--- a/server/src/logic/userdata.rs
+++ b/server/src/logic/userdata.rs
@@ -3,10 +3,12 @@
which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
Copyright (C) 2025 metamuffin <metamuffin.org>
*/
-use crate::ui::error::MyResult;
+use crate::{helper::A, ui::error::MyResult};
use jellybase::database::Database;
use jellycommon::{
- routes::u_node_id, user::{NodeUserData, WatchedState}, NodeID
+ routes::u_node_id,
+ user::{NodeUserData, WatchedState},
+ NodeID,
};
use jellylogic::session::Session;
use rocket::{
@@ -23,25 +25,25 @@ pub enum UrlWatchedState {
#[get("/n/<id>/userdata")]
pub fn r_node_userdata(
- session: Session,
+ session: A<Session>,
db: &State<Database>,
- id: NodeID,
+ id: A<NodeID>,
) -> MyResult<Json<NodeUserData>> {
let u = db
- .get_node_udata(id, &session.user.name)?
+ .get_node_udata(id.0, &session.0.user.name)?
.unwrap_or_default();
Ok(Json(u))
}
#[post("/n/<id>/watched?<state>")]
pub async fn r_node_userdata_watched(
- session: Session,
+ session: A<Session>,
db: &State<Database>,
- id: NodeID,
+ id: A<NodeID>,
state: UrlWatchedState,
) -> MyResult<Redirect> {
// TODO perm
- db.update_node_udata(id, &session.user.name, |udata| {
+ db.update_node_udata(id.0, &session.0.user.name, |udata| {
udata.watched = match state {
UrlWatchedState::None => WatchedState::None,
UrlWatchedState::Watched => WatchedState::Watched,
@@ -49,7 +51,7 @@ pub async fn r_node_userdata_watched(
};
Ok(())
})?;
- Ok(Redirect::found(u_node_id(id)))
+ Ok(Redirect::found(u_node_id(id.0)))
}
#[derive(FromForm)]
@@ -60,28 +62,28 @@ pub struct UpdateRating {
#[post("/n/<id>/update_rating", data = "<form>")]
pub async fn r_node_userdata_rating(
- session: Session,
+ session: A<Session>,
db: &State<Database>,
- id: NodeID,
+ id: A<NodeID>,
form: Form<UpdateRating>,
) -> MyResult<Redirect> {
// TODO perm
- db.update_node_udata(id, &session.user.name, |udata| {
+ db.update_node_udata(id.0, &session.0.user.name, |udata| {
udata.rating = form.rating;
Ok(())
})?;
- Ok(Redirect::found(u_node_id(id)))
+ Ok(Redirect::found(u_node_id(id.0)))
}
#[post("/n/<id>/progress?<t>")]
pub async fn r_node_userdata_progress(
- session: Session,
+ session: A<Session>,
db: &State<Database>,
- id: NodeID,
+ id: A<NodeID>,
t: f64,
) -> MyResult<()> {
// TODO perm
- db.update_node_udata(id, &session.user.name, |udata| {
+ db.update_node_udata(id.0, &session.0.user.name, |udata| {
udata.watched = match udata.watched {
WatchedState::None | WatchedState::Pending | WatchedState::Progress(_) => {
WatchedState::Progress(t)