This commit is contained in:
JMARyA 2024-07-26 14:14:08 +02:00
parent dcf546fa9c
commit 1e67f223f7
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
10 changed files with 164 additions and 92 deletions

89
Cargo.lock generated
View file

@ -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]]

View file

@ -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> {
Artist::find(doc! {}).await.unwrap()
Artist::find(doc! {}, None).await.unwrap()
}
pub async fn get_artist_by_id(&self, id: &str) -> Option<Artist> {
@ -118,7 +119,9 @@ impl Libary {
pub async fn get_albums_by_artist(&self, artist: &str) -> Vec<Album> {
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<Album> {
@ -126,7 +129,7 @@ impl Libary {
}
pub async fn get_tracks_of_album(&self, album: &str) -> Vec<Track> {
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<Track> {

35
src/library/playlist.rs Normal file
View file

@ -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<Reference>,
}
#[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(())
}
}

View file

@ -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::<Album>(json!({"title": 1}))
.await
.title
} else {
None
};
let artist_title = if let Some(artist_ref) = &self.artist_id {
artist_ref
.get_partial::<Artist>(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 {

View file

@ -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<Self> {
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 {

View file

@ -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;

View file

@ -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;

View file

@ -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<serde_json::Value>;
type FallibleApiResponse = Result<serde_json::Value, ApiError>;

View file

@ -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/<track_id>")]
pub async fn track_route(track_id: &str, lib: &State<Libary>) -> FallibleApiResponse {
Ok(serde_json::to_value(
&lib.get_track_by_id(track_id)
Ok(lib
.get_track_by_id(track_id)
.await
.ok_or_else(|| api_error("No track with that ID found"))?,
)
.unwrap())
.ok_or_else(|| api_error("No track with that ID found"))?
.api()
.await)
}
#[get("/track/<track_id>/audio")]

View file

@ -1,19 +1,18 @@
use rocket::http::Status;
use crate::library::user::Session;
use crate::library::user::User;
use mongod::Model;
use mongodb::bson::doc;
use rocket::http::Status;
use rocket::outcome::Outcome;
use rocket::post;
use rocket::request::FromRequest;
use rocket::Request;
use serde_json::json;
use serde::Deserialize;
use rocket::serde::json::Json;
use crate::library::user::Session;
use crate::library::user::User;
use rocket::Request;
use serde::Deserialize;
use serde_json::json;
use super::FallibleApiResponse;
use super::api_error;
use super::FallibleApiResponse;
#[rocket::async_trait]
impl<'r> FromRequest<'r> for User {
@ -22,13 +21,13 @@ impl<'r> FromRequest<'r> for User {
async fn from_request(request: &'r Request<'_>) -> rocket::request::Outcome<Self, Self::Error> {
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 = "<login>")]
pub async fn login_route(login: Json<LoginData>) -> 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
}))
}