8 Commits

Author SHA1 Message Date
be999d9086 Add function to generate random paths
All checks were successful
Push Workflows / rustfmt (push) Successful in 7s
Push Workflows / mdbook (push) Successful in 8s
Push Workflows / docs (push) Successful in 37s
Push Workflows / clippy (push) Successful in 56s
Push Workflows / leptos-test (push) Successful in 1m34s
Push Workflows / mdbook-server (push) Successful in 1m33s
Push Workflows / test (push) Successful in 1m57s
Push Workflows / build (push) Successful in 2m48s
Push Workflows / docker-build (push) Successful in 6m53s
Push Workflows / nix-build (push) Successful in 9m12s
2025-06-07 19:01:37 +00:00
432cb659db Add rand crate 2025-06-07 17:36:11 +00:00
33dc7cb1a3 Add image_path to playlist model
All checks were successful
Push Workflows / rustfmt (push) Successful in 6s
Push Workflows / mdbook (push) Successful in 7s
Push Workflows / docs (push) Successful in 39s
Push Workflows / clippy (push) Successful in 49s
Push Workflows / mdbook-server (push) Successful in 1m14s
Push Workflows / leptos-test (push) Successful in 1m27s
Push Workflows / test (push) Successful in 1m38s
Push Workflows / build (push) Successful in 2m28s
Push Workflows / docker-build (push) Successful in 4m16s
Push Workflows / nix-build (push) Successful in 8m55s
2025-06-07 17:15:07 +00:00
92e13dfba7 Add image_path column to playlists table 2025-06-07 15:17:15 +00:00
f6211cbe2e Add image_path to user model 2025-06-07 15:12:52 +00:00
4a092fc78d Add image_path column to users table 2025-06-07 15:12:52 +00:00
d472a663ff Add image_path to artists model 2025-06-07 15:12:51 +00:00
8cad1816a7 Add image_path column to artists table 2025-06-07 14:53:15 +00:00
18 changed files with 138 additions and 12 deletions

88
Cargo.lock generated
View File

@ -878,7 +878,7 @@ dependencies = [
"futures",
"log",
"parking_lot",
"rand",
"rand 0.8.5",
"redis-protocol",
"semver",
"socket2",
@ -1008,7 +1008,19 @@ checksum = "a06fddc2749e0528d2813f95e050e87e52c8cbbae56223b9babf73b3e53b0cc6"
dependencies = [
"cfg-if",
"libc",
"wasi",
"wasi 0.11.0+wasi-snapshot-preview1",
]
[[package]]
name = "getrandom"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
dependencies = [
"cfg-if",
"libc",
"r-efi",
"wasi 0.14.2+wasi-0.2.4",
]
[[package]]
@ -1736,7 +1748,7 @@ dependencies = [
"oco_ref",
"or_poisoned",
"paste",
"rand",
"rand 0.8.5",
"reactive_graph",
"rustc-hash 2.1.0",
"send_wrapper",
@ -2014,6 +2026,7 @@ dependencies = [
"once_cell",
"openssl",
"pbkdf2",
"rand 0.9.1",
"reqwest",
"serde",
"server_fn",
@ -2192,7 +2205,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
dependencies = [
"libc",
"wasi",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys",
]
@ -2359,7 +2372,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166"
dependencies = [
"base64ct",
"rand_core",
"rand_core 0.6.4",
"subtle",
]
@ -2612,6 +2625,12 @@ dependencies = [
"syn",
]
[[package]]
name = "r-efi"
version = "5.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
[[package]]
name = "r2d2"
version = "0.8.10"
@ -2630,8 +2649,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
"rand_chacha 0.3.1",
"rand_core 0.6.4",
]
[[package]]
name = "rand"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
dependencies = [
"rand_chacha 0.9.0",
"rand_core 0.9.3",
]
[[package]]
@ -2641,7 +2670,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
"rand_core 0.6.4",
]
[[package]]
name = "rand_chacha"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
dependencies = [
"ppv-lite86",
"rand_core 0.9.3",
]
[[package]]
@ -2650,7 +2689,16 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
"getrandom 0.2.13",
]
[[package]]
name = "rand_core"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
dependencies = [
"getrandom 0.3.3",
]
[[package]]
@ -3571,7 +3619,7 @@ dependencies = [
"futures",
"http",
"parking_lot",
"rand",
"rand 0.8.5",
"serde",
"serde_json",
"thiserror 1.0.63",
@ -3771,7 +3819,7 @@ version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a"
dependencies = [
"getrandom",
"getrandom 0.2.13",
]
[[package]]
@ -3811,6 +3859,15 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasi"
version = "0.14.2+wasi-0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
dependencies = [
"wit-bindgen-rt",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.100"
@ -4206,6 +4263,15 @@ dependencies = [
"memchr",
]
[[package]]
name = "wit-bindgen-rt"
version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
dependencies = [
"bitflags 2.5.0",
]
[[package]]
name = "write16"
version = "1.0.0"

View File

@ -63,6 +63,7 @@ reqwest = { version = "0.12.9", default-features = false, optional = true }
futures = { version = "0.3.25", default-features = false, optional = true }
once_cell = { version = "1.20", default-features = false, optional = true }
libretunes_macro = { git = "https://git.libretunes.xyz/LibreTunes/LibreTunes-Macro.git", branch = "main" }
rand = { version = "0.9.1", optional = true }
[features]
hydrate = [
@ -95,6 +96,7 @@ ssr = [
"flexi_logger",
"leptos-use/ssr",
"image-convert",
"rand",
]
reqwest_api = [
"reqwest",

View File

@ -0,0 +1 @@
ALTER TABLE artists DROP COLUMN image_path;

View File

@ -0,0 +1 @@
ALTER TABLE artists ADD COLUMN image_path VARCHAR;

View File

@ -0,0 +1 @@
ALTER TABLE users DROP COLUMN image_path;

View File

@ -0,0 +1 @@
ALTER TABLE users ADD COLUMN image_path VARCHAR;

View File

@ -0,0 +1 @@
ALTER TABLE playlists DROP COLUMN image_path;

View File

@ -0,0 +1 @@
ALTER TABLE playlists ADD COLUMN image_path VARCHAR;

View File

@ -30,7 +30,10 @@ pub async fn add_artist(artist_name: String) -> Result<(), ServerFnError> {
use crate::schema::artists::dsl::*;
use leptos::server_fn::error::NoCustomError;
let new_artist = NewArtist { name: artist_name };
let new_artist = NewArtist {
name: artist_name,
image_path: None,
};
let db = &mut get_db_conn();
diesel::insert_into(artists)

View File

@ -278,6 +278,7 @@ pub async fn create_playlist(data: MultipartData) -> Result<(), ServerFnError> {
let new_playlist = NewPlaylist {
name: name.clone(),
owner_id: user.id,
image_path: None,
};
let mut db_conn = get_db_conn();

View File

@ -59,6 +59,7 @@ pub fn Upload(open: RwSignal<bool>) -> impl IntoView {
.map(|(artist, _score)| Artist {
id: artist.id,
name: artist.name,
image_path: Some(artist.image_path),
})
.collect::<Vec<_>>()
});

View File

@ -10,6 +10,8 @@ pub struct Artist {
pub id: i32,
/// The artist's name
pub name: String,
/// The path to the artist's image file
pub image_path: Option<String>,
}
impl Artist {

View File

@ -19,4 +19,6 @@ pub struct Playlist {
pub owner_id: i32,
/// The name of the playlist
pub name: String,
/// The path to the playlist's image file
pub image_path: Option<String>,
}

View File

@ -35,6 +35,8 @@ pub struct User {
pub created_at: NaiveDateTime,
/// Whether the user is an admin
pub admin: bool,
/// The path to the user's profile picture file
pub image_path: Option<String>,
}
impl User {

View File

@ -24,6 +24,7 @@ pub fn Signup() -> impl IntoView {
email: email.get_untracked(),
password: Some(password.get_untracked()),
admin: false,
image_path: None,
};
log!("new user: {:?}", new_user);

View File

@ -20,6 +20,7 @@ diesel::table! {
artists (id) {
id -> Int4,
name -> Varchar,
image_path -> Nullable<Varchar>,
}
}
@ -53,6 +54,7 @@ diesel::table! {
updated_at -> Timestamp,
owner_id -> Int4,
name -> Text,
image_path -> Nullable<Varchar>,
}
}
@ -108,6 +110,7 @@ diesel::table! {
password -> Varchar,
created_at -> Timestamp,
admin -> Bool,
image_path -> Nullable<Varchar>,
}
}

View File

@ -9,6 +9,7 @@ cfg_if! {
pub mod auth_backend;
pub mod redis;
pub mod extract_field;
pub mod random_path;
}
}

36
src/util/random_path.rs Normal file
View File

@ -0,0 +1,36 @@
/// Generates random paths for storing assets
use rand::{rng, Rng};
use std::ffi::OsStr;
use std::path::PathBuf;
/// Generate a random path for storing a new file
/// The path will be in the format `base_path/XX/XXXXXXXXXX.extension`
pub fn checked_random_path<P: Into<PathBuf>, E: AsRef<OsStr>>(
base_path: P,
extension: E,
) -> PathBuf {
let base_path: PathBuf = base_path.into();
let mut rng = rng();
// Loop until we find a path that does not exist
// If the existance check fails, we assume the path does not exist
// since it is extremely unlikely to encounter a collision anyway
loop {
let random_bytes: [u8; 16] = rng.random();
let dir_part = format!("{:02x}", random_bytes[0]);
let file_part = random_bytes[1..]
.iter()
.map(|byte| format!("{byte:02x}"))
.collect::<String>();
let path = base_path
.join(dir_part)
.join(file_part)
.with_extension(&extension);
if !path.try_exists().unwrap_or(false) {
return path;
}
}
}