v0.2 release #153

Merged
kdeng00 merged 11 commits from v0.2 into main 2025-08-30 13:34:06 -04:00
5 changed files with 209 additions and 15 deletions
Showing only changes of commit 598996cb8d - Show all commits
Generated
+6 -6
View File
@@ -819,7 +819,7 @@ dependencies = [
[[package]] [[package]]
name = "icarus" name = "icarus"
version = "0.1.101" version = "0.1.102"
dependencies = [ dependencies = [
"axum", "axum",
"axum-extra", "axum-extra",
@@ -849,8 +849,8 @@ dependencies = [
[[package]] [[package]]
name = "icarus_envy" name = "icarus_envy"
version = "0.3.0" version = "0.3.2"
source = "git+ssh://git@git.kundeng.us/phoenix/icarus_envy.git?tag=v0.3.0-devel-d73fba9899-006#d73fba9899372b0655a90cb426645930135152da" source = "git+ssh://git@git.kundeng.us/phoenix/icarus_envy.git?tag=v0.3.2#d84a8144aedf02e1b459d67c4023a7e0833f89fd"
dependencies = [ dependencies = [
"const_format", "const_format",
"dotenvy", "dotenvy",
@@ -859,15 +859,15 @@ dependencies = [
[[package]] [[package]]
name = "icarus_meta" name = "icarus_meta"
version = "0.3.0" version = "0.3.0"
source = "git+ssh://git@git.kundeng.us/phoenix/icarus_meta.git?tag=v0.3.0-devel-f4b71de969-680#f4b71de9692029a706b1ce82c39f6715c560158e" source = "git+ssh://git@git.kundeng.us/phoenix/icarus_meta.git?tag=v0.3.0#f87c049ab3139995230485b33038a0425f2e7430"
dependencies = [ dependencies = [
"lofty", "lofty",
] ]
[[package]] [[package]]
name = "icarus_models" name = "icarus_models"
version = "0.5.2" version = "0.5.5"
source = "git+ssh://git@git.kundeng.us/phoenix/icarus_models.git?tag=v0.5.2-devel-d3251f935e-111#d3251f935e76caa110727203d910ee0683a668a0" source = "git+ssh://git@git.kundeng.us/phoenix/icarus_models.git?tag=v0.5.5#f43bcaa314694c25cea65dbfcfbabc8fc7bf395a"
dependencies = [ dependencies = [
"josekit", "josekit",
"rand 0.9.1", "rand 0.9.1",
+4 -4
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "icarus" name = "icarus"
version = "0.1.101" version = "0.1.102"
edition = "2024" edition = "2024"
rust-version = "1.88" rust-version = "1.88"
@@ -23,9 +23,9 @@ thiserror = "1.0"
base64 = "0.21" base64 = "0.21"
jsonwebtoken = { version = "9.3.1" } jsonwebtoken = { version = "9.3.1" }
josekit = { version = "0.10.1" } josekit = { version = "0.10.1" }
icarus_meta = { git = "ssh://git@git.kundeng.us/phoenix/icarus_meta.git", tag = "v0.3.0-devel-f4b71de969-680" } icarus_meta = { git = "ssh://git@git.kundeng.us/phoenix/icarus_meta.git", tag = "v0.3.0" }
icarus_models = { git = "ssh://git@git.kundeng.us/phoenix/icarus_models.git", tag = "v0.5.2-devel-d3251f935e-111" } icarus_models = { git = "ssh://git@git.kundeng.us/phoenix/icarus_models.git", tag = "v0.5.5" }
icarus_envy = { git = "ssh://git@git.kundeng.us/phoenix/icarus_envy.git", tag = "v0.3.0-devel-d73fba9899-006" } icarus_envy = { git = "ssh://git@git.kundeng.us/phoenix/icarus_envy.git", tag = "v0.3.2" }
[dev-dependencies] [dev-dependencies]
common-multipart-rfc7578 = { version = "0.7.0" } common-multipart-rfc7578 = { version = "0.7.0" }
+1
View File
@@ -17,6 +17,7 @@ pub mod endpoints {
pub const CREATESONG: &str = "/api/v2/song"; pub const CREATESONG: &str = "/api/v2/song";
pub const GETSONGS: &str = "/api/v2/song"; pub const GETSONGS: &str = "/api/v2/song";
pub const GETALLSONGS: &str = "/api/v2/song/all";
pub const STREAMSONG: &str = "/api/v2/song/stream/{id}"; pub const STREAMSONG: &str = "/api/v2/song/stream/{id}";
pub const DOWNLOADSONG: &str = "/api/v2/song/download/{id}"; pub const DOWNLOADSONG: &str = "/api/v2/song/download/{id}";
pub const DELETESONG: &str = "/api/v2/song/{id}"; pub const DELETESONG: &str = "/api/v2/song/{id}";
+123
View File
@@ -351,6 +351,108 @@ pub mod song_db {
} }
} }
pub async fn get_all_songs(
pool: &sqlx::PgPool,
) -> Result<Vec<icarus_models::song::Song>, sqlx::Error> {
let result = sqlx::query(
r#"
SELECT * FROM "song";
"#,
)
.fetch_all(pool)
.await
.map_err(|e| {
eprintln!("Error querying data: {e:?}");
});
match result {
Ok(rows) => {
let mut songs: Vec<icarus_models::song::Song> = Vec::new();
for row in rows {
let date_created_time: time::OffsetDateTime = row
.try_get("date_created")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap();
let song = icarus_models::song::Song {
id: row
.try_get("id")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
title: row
.try_get("title")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
artist: row
.try_get("artist")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
album_artist: row
.try_get("album_artist")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
album: row
.try_get("album")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
genre: row
.try_get("genre")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
year: row
.try_get("year")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
track: row
.try_get("track")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
disc: row
.try_get("disc")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
track_count: row
.try_get("track_count")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
disc_count: row
.try_get("disc_count")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
duration: row
.try_get("duration")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
audio_type: row
.try_get("audio_type")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
filename: row
.try_get("filename")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
directory: row
.try_get("directory")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
date_created: date_created_time.to_string(),
user_id: row
.try_get("user_id")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
data: Vec::new(),
};
songs.push(song);
}
Ok(songs)
}
Err(_err) => Err(sqlx::Error::RowNotFound),
}
}
pub async fn delete_song( pub async fn delete_song(
pool: &sqlx::PgPool, pool: &sqlx::PgPool,
id: &uuid::Uuid, id: &uuid::Uuid,
@@ -1126,6 +1228,27 @@ pub mod endpoint {
} }
} }
pub async fn get_all_songs(
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
) -> (
axum::http::StatusCode,
axum::Json<super::response::get_songs::Response>,
) {
let mut response = super::response::get_songs::Response::default();
match super::song_db::get_all_songs(&pool).await {
Ok(songs) => {
response.message = String::from(super::super::response::SUCCESSFUL);
response.data = songs;
(axum::http::StatusCode::OK, axum::Json(response))
}
Err(err) => {
response.message = err.to_string();
(axum::http::StatusCode::NOT_FOUND, axum::Json(response))
}
}
}
pub async fn stream_song( pub async fn stream_song(
axum::Extension(pool): axum::Extension<sqlx::PgPool>, axum::Extension(pool): axum::Extension<sqlx::PgPool>,
axum::extract::Path(id): axum::extract::Path<uuid::Uuid>, axum::extract::Path(id): axum::extract::Path<uuid::Uuid>,
+75 -5
View File
@@ -190,6 +190,10 @@ pub mod init {
axum::middleware::from_fn(crate::auth::auth::<axum::body::Body>), axum::middleware::from_fn(crate::auth::auth::<axum::body::Body>),
), ),
) )
.route(
crate::callers::endpoints::GETALLSONGS,
get(crate::callers::song::endpoint::get_all_songs),
)
} }
pub async fn app() -> axum::Router { pub async fn app() -> axum::Router {
@@ -341,11 +345,20 @@ mod tests {
) )
} }
pub const TEST_USER_ID: uuid::Uuid = uuid::uuid!("cc938368-615a-4694-b2ca-6e122fa31c52");
pub async fn test_token() -> Result<String, josekit::JoseError> { pub async fn test_token() -> Result<String, josekit::JoseError> {
let key: String = icarus_envy::environment::get_secret_main_key().await; let key: String = icarus_envy::environment::get_secret_main_key().await;
let (message, issuer, audience) = token_fields(); let (message, issuer, audience) = token_fields();
match icarus_models::token::create_token(&key, &message, &issuer, &audience) { let token_resource = icarus_models::token::TokenResource {
message: message,
issuer: issuer,
audiences: vec![audience],
id: TEST_USER_ID,
};
match icarus_models::token::create_token(&key, &token_resource, time::Duration::hours(1)) {
Ok((access_token, _some_time)) => Ok(access_token), Ok((access_token, _some_time)) => Ok(access_token),
Err(err) => Err(err), Err(err) => Err(err),
} }
@@ -607,9 +620,7 @@ mod tests {
let song_queue_id = resp.data[0]; let song_queue_id = resp.data[0];
assert_eq!(false, song_queue_id.is_nil(), "Should not be empty"); assert_eq!(false, song_queue_id.is_nil(), "Should not be empty");
let user_id = uuid::Uuid::new_v4(); let user_id = super::TEST_USER_ID;
// match super::get_resp_data::<crate::callers::song::response::link_user_id::Response>(response).await {
match super::song_queue_link_req(&app, &song_queue_id, &user_id).await { match super::song_queue_link_req(&app, &song_queue_id, &user_id).await {
Ok(response) => { Ok(response) => {
@@ -876,7 +887,7 @@ mod tests {
assert_eq!(false, resp.data[0].is_nil(), "Should not be empty"); assert_eq!(false, resp.data[0].is_nil(), "Should not be empty");
let song_queue_id = &resp.data[0]; let song_queue_id = &resp.data[0];
let user_id = uuid::Uuid::new_v4(); let user_id = TEST_USER_ID;
println!("User Id: {user_id:?}"); println!("User Id: {user_id:?}");
match song_queue_link_req(&app, &song_queue_id, &user_id).await { match song_queue_link_req(&app, &song_queue_id, &user_id).await {
@@ -2435,5 +2446,64 @@ mod tests {
let _ = super::db_mgr::drop_database(&tm_pool, &db_name).await; let _ = super::db_mgr::drop_database(&tm_pool, &db_name).await;
} }
#[tokio::test]
async fn test_get_all_songs() {
let tm_pool = super::db_mgr::get_pool().await.unwrap();
let db_name = super::db_mgr::generate_db_name().await;
match super::db_mgr::create_database(&tm_pool, &db_name).await {
Ok(_) => {
println!("Success");
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
}
let pool = super::db_mgr::connect_to_db(&db_name).await.unwrap();
super::db_mgr::migrations(&pool).await;
let app = super::init::app(pool).await;
match app
.clone()
.oneshot(
axum::http::Request::builder()
.method(axum::http::Method::GET)
.uri(crate::callers::endpoints::GETALLSONGS)
.header(axum::http::header::CONTENT_TYPE, "application/json")
.header(
axum::http::header::AUTHORIZATION,
super::bearer_auth().await,
)
.body(axum::body::Body::empty())
.unwrap(),
)
.await
{
Ok(response) => {
let resp = super::get_resp_data::<
crate::callers::song::response::get_songs::Response,
>(response)
.await;
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
let songs = &resp.data;
assert_eq!(
2,
songs.len(),
"Returned song count does not match. Returned song count {:?} song count {}",
songs.len(),
2
);
}
Err(err) => {
assert!(false, "Error: {err:?}");
}
}
let _ = super::db_mgr::drop_database(&tm_pool, &db_name).await;
}
} }
} }