From 1e67f223f7df7462701bf290a9fe289c99690d42 Mon Sep 17 00:00:00 2001 From: JMARyA Date: Fri, 26 Jul 2024 14:14:08 +0200 Subject: [PATCH] update --- Cargo.lock | 89 ++++++++++++++++++++--------------------- src/library/mod.rs | 11 +++-- src/library/playlist.rs | 35 ++++++++++++++++ src/library/track.rs | 33 ++++++++++++++- src/library/user.rs | 25 +++++++----- src/route/album.rs | 10 ++--- src/route/artist.rs | 4 +- src/route/mod.rs | 3 +- src/route/track.rs | 20 ++++----- src/route/user.rs | 26 ++++++------ 10 files changed, 164 insertions(+), 92 deletions(-) create mode 100644 src/library/playlist.rs diff --git a/Cargo.lock b/Cargo.lock index d93fe71..3befb94 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -73,7 +73,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -84,7 +84,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -403,7 +403,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.0", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -436,7 +436,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -590,7 +590,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -1039,19 +1039,20 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.11" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" dependencies = [ + "hermit-abi", "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "mongod" -version = "0.1.0" -source = "git+https://git.hydrar.de/jmarya/mongod#e3c6740b1a4389d1d5b05f5a7563995bfd8a06fc" +version = "0.2.0" +source = "git+https://git.hydrar.de/jmarya/mongod#c4f2b6eb8152dd086a2f296119a1898032712cd8" dependencies = [ "chrono", "futures", @@ -1067,7 +1068,7 @@ dependencies = [ [[package]] name = "mongod_derive" version = "0.1.0" -source = "git+https://git.hydrar.de/jmarya/mongod#e3c6740b1a4389d1d5b05f5a7563995bfd8a06fc" +source = "git+https://git.hydrar.de/jmarya/mongod#c4f2b6eb8152dd086a2f296119a1898032712cd8" dependencies = [ "case", "proc-macro2", @@ -1178,9 +1179,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.1" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" +checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" dependencies = [ "memchr", ] @@ -1249,7 +1250,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -1299,7 +1300,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", "version_check", "yansi", ] @@ -1381,7 +1382,7 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -1503,7 +1504,7 @@ dependencies = [ "proc-macro2", "quote", "rocket_http", - "syn 2.0.71", + "syn 2.0.72", "unicode-xid", "version_check", ] @@ -1720,7 +1721,7 @@ checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -1737,9 +1738,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" dependencies = [ "serde", ] @@ -1901,9 +1902,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.71" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", @@ -1968,7 +1969,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -2029,32 +2030,30 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.38.1" +version = "1.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2caba9f80616f438e09748d5acda951967e1ea58508ef53d9c6402485a46df" +checksum = "d040ac2b29ab03b09d4129c2f5bbd012a3ac2f79d38ff506a4bf8dd34b0eac8a" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", - "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2 0.5.7", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -2094,9 +2093,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac2caab0bf757388c6c0ae23b3293fdb463fee59434529014f85e3263b995c28" +checksum = "81967dd0dd2c1ab0bc3468bd7caecc32b8a4aa47d0c8c695d8c2b2108168d62c" dependencies = [ "serde", "serde_spanned", @@ -2106,18 +2105,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "f8fb9f64314842840f1d940ac544da178732128f1c78c21772e876579e0da1db" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.16" +version = "0.22.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "278f3d518e152219c994ce877758516bca5e118eaed6996192a774fb9fbf0788" +checksum = "8d9f8729f5aea9562aac1cc0441f5d6de3cff1ee0c5d67293eeca5eb36ee7c16" dependencies = [ "indexmap", "serde", @@ -2151,7 +2150,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] @@ -2367,9 +2366,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "walkdir" @@ -2417,7 +2416,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", "wasm-bindgen-shared", ] @@ -2439,7 +2438,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2652,9 +2651,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.14" +version = "0.6.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374ec40a2d767a3c1b4972d9475ecd557356637be906f2cb3f7fe17a6eb5e22f" +checksum = "b480ae9340fc261e6be3e95a1ba86d54ae3f9171132a73ce8d4bbaf68339507c" dependencies = [ "memchr", ] @@ -2704,7 +2703,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.72", ] [[package]] diff --git a/src/library/mod.rs b/src/library/mod.rs index affef06..c9ff1af 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -11,6 +11,7 @@ use walkdir::WalkDir; pub mod album; pub mod artist; pub mod metadata; +pub mod playlist; pub mod track; pub mod user; @@ -52,7 +53,7 @@ impl Libary { pub async fn add_path_to_library(&self, path: &str) { // search for path already present - if let Some(_) = Track::find_one_partial(doc! { "path": path }, &json!({})).await { + if let Some(_) = Track::find_one_partial(doc! { "path": path }, json!({})).await { return; } @@ -109,7 +110,7 @@ impl Libary { } pub async fn get_artists(&self) -> Vec { - Artist::find(doc! {}).await.unwrap() + Artist::find(doc! {}, None).await.unwrap() } pub async fn get_artist_by_id(&self, id: &str) -> Option { @@ -118,7 +119,9 @@ impl Libary { pub async fn get_albums_by_artist(&self, artist: &str) -> Vec { let artist = format!("artist::{artist}"); - Album::find(doc! { "artist_id": artist}).await.unwrap() + Album::find(doc! { "artist_id": artist}, None) + .await + .unwrap() } pub async fn get_album_by_id(&self, album: &str) -> Option { @@ -126,7 +129,7 @@ impl Libary { } pub async fn get_tracks_of_album(&self, album: &str) -> Vec { - Track::find(doc! { "album_id": album}).await.unwrap() + Track::find(doc! { "album_id": album}, None).await.unwrap() } pub async fn get_track_by_id(&self, track_id: &str) -> Option { diff --git a/src/library/playlist.rs b/src/library/playlist.rs new file mode 100644 index 0000000..4679442 --- /dev/null +++ b/src/library/playlist.rs @@ -0,0 +1,35 @@ +use mongod::{ + assert_reference_of, + derive::{Model, Referencable}, + Referencable, Reference, Validate, +}; +use serde::{Deserialize, Serialize}; + +use crate::library::{track::Track, user::User}; + +#[derive(Debug, Clone, Serialize, Deserialize, Model, Referencable)] +pub struct Playlist { + pub _id: String, + pub owner: Reference, + pub title: String, + pub visibility: Visibility, + pub tracks: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +pub enum Visibility { + Private, + Public, +} + +impl Validate for Playlist { + async fn validate(&self) -> Result<(), String> { + assert_reference_of!(self.owner, User); + + for track in &self.tracks { + assert_reference_of!(track, Track); + } + + Ok(()) + } +} diff --git a/src/library/track.rs b/src/library/track.rs index 1b6b14a..7f43ff0 100644 --- a/src/library/track.rs +++ b/src/library/track.rs @@ -4,8 +4,9 @@ use mongod::{ Model, Referencable, Reference, Validate, }; use serde::{Deserialize, Serialize}; +use serde_json::json; -use crate::library::artist::Artist; +use crate::library::{album::Album, artist::Artist}; use super::metadata::AudioMetadata; @@ -34,6 +35,36 @@ impl Track { .await .unwrap(); } + + pub async fn api(&self) -> serde_json::Value { + let album_title = if let Some(album_ref) = &self.album_id { + album_ref + .get_partial::(json!({"title": 1})) + .await + .title + } else { + None + }; + + let artist_title = if let Some(artist_ref) = &self.artist_id { + artist_ref + .get_partial::(json!({"name": 1})) + .await + .name + } else { + None + }; + + json!({ + "id": self._id, + "title": self.title, + "meta": serde_json::to_value(&self.meta).unwrap(), + "album_id": self.album_id.as_ref().map(|x| x.id().to_string()), + "album": album_title, + "artist_id": self.artist_id.as_ref().map(|x| x.id().to_string()), + "artist": artist_title + }) + } } impl Validate for Track { diff --git a/src/library/user.rs b/src/library/user.rs index bbad84b..00eca6b 100644 --- a/src/library/user.rs +++ b/src/library/user.rs @@ -1,6 +1,8 @@ use data_encoding::HEXUPPER; use mongod::{ - assert_reference_of, derive::{Model, Referencable}, Model, Referencable, Reference, Validate + assert_reference_of, + derive::{Model, Referencable}, + Model, Referencable, Reference, Validate, }; use mongodb::bson::doc; use rand::RngCore; @@ -20,13 +22,13 @@ pub struct User { pub _id: String, pub username: String, pub password: String, - pub role: UserRole + pub role: UserRole, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub enum UserRole { Regular, - Admin + Admin, } impl Validate for User { @@ -37,15 +39,18 @@ impl Validate for User { impl User { pub async fn create(username: &str, password: &str, role: UserRole) -> Option { - if User::find_one_partial(doc! { "username": username }, &json!({})).await.is_some() { + if User::find_one_partial(doc! { "username": username }, json!({})) + .await + .is_some() + { return None; } - let u = User{ + let u = User { _id: uuid::Uuid::new_v4().to_string(), username: username.to_string(), password: bcrypt::hash(password, bcrypt::DEFAULT_COST).unwrap(), - role + role, }; u.insert().await.unwrap(); @@ -64,10 +69,10 @@ impl User { } pub async fn session(&self) -> Session { - let s = Session{ + let s = Session { _id: uuid::Uuid::new_v4().to_string(), token: gen_token(60), - user: self.reference() + user: self.reference(), }; s.insert().await.unwrap(); @@ -88,7 +93,7 @@ impl User { pub struct Session { pub _id: String, pub token: String, - pub user: Reference + pub user: Reference, } impl Validate for Session { @@ -97,4 +102,4 @@ impl Validate for Session { Ok(()) } -} \ No newline at end of file +} diff --git a/src/route/album.rs b/src/route/album.rs index 03438f7..04ab986 100644 --- a/src/route/album.rs +++ b/src/route/album.rs @@ -1,12 +1,12 @@ use std::cmp::Ordering; +use super::api_error; +use super::FallibleApiResponse; +use mongod::Referencable; use mongodb::bson::doc; +use rocket::fs::NamedFile; use rocket::*; use serde_json::json; -use rocket::fs::NamedFile; -use mongod::Referencable; -use super::FallibleApiResponse; -use super::api_error; use crate::library::Libary; @@ -80,4 +80,4 @@ pub async fn album_route(album_id: &str, lib: &State) -> FallibleApiResp .insert("tracks".into(), tracks.into()); Ok(album) -} \ No newline at end of file +} diff --git a/src/route/artist.rs b/src/route/artist.rs index 2277ff7..749e208 100644 --- a/src/route/artist.rs +++ b/src/route/artist.rs @@ -1,7 +1,7 @@ +use super::api_error; +use super::FallibleApiResponse; use mongodb::bson::doc; use rocket::*; -use super::FallibleApiResponse; -use super::api_error; use crate::library::Libary; diff --git a/src/route/mod.rs b/src/route/mod.rs index ed21e46..604f308 100644 --- a/src/route/mod.rs +++ b/src/route/mod.rs @@ -1,12 +1,11 @@ use rocket::response::status::BadRequest; use serde_json::json; -pub mod artist; pub mod album; +pub mod artist; pub mod track; pub mod user; - type ApiError = BadRequest; type FallibleApiResponse = Result; diff --git a/src/route/track.rs b/src/route/track.rs index fad1a91..827047e 100644 --- a/src/route/track.rs +++ b/src/route/track.rs @@ -1,19 +1,19 @@ -use rocket::*; +use super::api_error; +use super::FallibleApiResponse; use fs::NamedFile; use mongodb::bson::doc; -use super::FallibleApiResponse; -use super::api_error; +use rocket::*; use crate::library::Libary; #[get("/track/")] pub async fn track_route(track_id: &str, lib: &State) -> FallibleApiResponse { - Ok(serde_json::to_value( - &lib.get_track_by_id(track_id) - .await - .ok_or_else(|| api_error("No track with that ID found"))?, - ) - .unwrap()) + Ok(lib + .get_track_by_id(track_id) + .await + .ok_or_else(|| api_error("No track with that ID found"))? + .api() + .await) } #[get("/track//audio")] @@ -22,4 +22,4 @@ pub async fn track_audio_route(track_id: &str, lib: &State) -> Option FromRequest<'r> for User { @@ -22,13 +21,13 @@ impl<'r> FromRequest<'r> for User { async fn from_request(request: &'r Request<'_>) -> rocket::request::Outcome { match request.headers().get_one("token") { Some(key) => { - if let Some(session) = Session::find_one(doc! { "token": key} ).await { + if let Some(session) = Session::find_one(doc! { "token": key}).await { let user = session.user.get().await; Outcome::Success(user) } else { Outcome::Error((Status::Unauthorized, ())) } - }, + } None => Outcome::Error((Status::Unauthorized, ())), } } @@ -37,15 +36,16 @@ impl<'r> FromRequest<'r> for User { #[derive(Deserialize)] pub struct LoginData { pub username: String, - pub password: String + pub password: String, } #[post("/login", data = "")] pub async fn login_route(login: Json) -> FallibleApiResponse { - let ses = User::login(&login.username, &login.password).await.ok_or_else(|| api_error("Login failed"))?; + let ses = User::login(&login.username, &login.password) + .await + .ok_or_else(|| api_error("Login failed"))?; Ok(json!({ "token": ses.token })) } -