Link user id to song queue (#159)

* Added initial code for endpoint to link user id with song queue #156

* Updated songQueue to have a user_id field #156

* Added function to link user_id with songQueue record #156

* Added useful constant #156

* Finished adding code #156

Need to make the endpoint available and then write a test. Might have to modify existing tests

* Made link user id endpoint available #156

* Added TODOs for later

* Changing location of test code

* Code formatting

* Added test #156

* Formatted code

* Added user_id to SongQueue and added more related code

* Code formatting

* Fixing possible nil user_id field in SongQueue when calling a function

* Fixed another issue

* Made changes to function to also return user_id

* Making use of user_id in test requests

* Code formatting

* Updated workflow

* Forgot to include port

* Docker changes for port change

* Reverting port changes

* Cleaning up Dockerfile

* Version bump
This commit was merged in pull request #159.
This commit is contained in:
KD
2025-07-22 21:36:29 -04:00
committed by GitHub
parent c9bcea5f98
commit 34e292bea9
7 changed files with 508 additions and 328 deletions
Generated
+1 -1
View File
@@ -752,7 +752,7 @@ dependencies = [
[[package]] [[package]]
name = "icarus" name = "icarus"
version = "0.1.92" version = "0.1.93"
dependencies = [ dependencies = [
"axum", "axum",
"common-multipart-rfc7578", "common-multipart-rfc7578",
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "icarus" name = "icarus"
version = "0.1.92" version = "0.1.93"
edition = "2024" edition = "2024"
rust-version = "1.88" rust-version = "1.88"
+7 -8
View File
@@ -1,14 +1,9 @@
# Stage 1: Build the application # Stage 1: Build the application
# Use a specific Rust version for reproducibility. Choose one that matches your development environment.
# Using slim variant for smaller base image
FROM rust:1.88 as builder FROM rust:1.88 as builder
# Set the working directory inside the container # Set the working directory inside the container
WORKDIR /usr/src/app WORKDIR /usr/src/app
# Install build dependencies if needed (e.g., for certain crates like sqlx with native TLS)
# RUN apt-get update && apt-get install -y pkg-config libssl-dev
# Install build dependencies if needed (e.g., git for cloning) # Install build dependencies if needed (e.g., git for cloning)
RUN apt-get update && apt-get install -y --no-install-recommends \ RUN apt-get update && apt-get install -y --no-install-recommends \
pkg-config libssl3 \ pkg-config libssl3 \
@@ -16,10 +11,14 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
openssh-client git \ openssh-client git \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# << --- ADD HOST KEY HERE --- >> # Create .ssh/ directory for internal dependencies
# Replace 'yourgithost.com' with the actual hostname (e.g., github.com)
RUN mkdir -p -m 0700 ~/.ssh && \ RUN mkdir -p -m 0700 ~/.ssh && \
ssh-keyscan git.kundeng.us >> ~/.ssh/known_hosts echo "Host git.kundeng.us" >> ~/.ssh/config && \
echo " User git" >> ~/.ssh/config && \
chmod 600 ~/.ssh/config
# << --- ADD HOST KEY HERE --- >>
RUN ssh-keyscan git.kundeng.us >> ~/.ssh/known_hosts
# Copy Cargo manifests # Copy Cargo manifests
COPY Cargo.toml Cargo.lock ./ COPY Cargo.toml Cargo.lock ./
+2 -1
View File
@@ -6,7 +6,8 @@ CREATE TABLE IF NOT EXISTS "songQueue" (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(), id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
filename TEXT NOT NULL, filename TEXT NOT NULL,
status TEXT CHECK (status IN ('pending', 'ready', 'processing', 'done')), status TEXT CHECK (status IN ('pending', 'ready', 'processing', 'done')),
data BYTEA NULL data BYTEA NULL,
user_id UUID NULL
); );
-- Table to store queued metadata -- Table to store queued metadata
+5
View File
@@ -4,6 +4,7 @@ pub mod song;
pub mod endpoints { pub mod endpoints {
pub const QUEUESONG: &str = "/api/v2/song/queue"; pub const QUEUESONG: &str = "/api/v2/song/queue";
pub const QUEUESONGLINKUSERID: &str = "/api/v2/song/queue/link";
pub const QUEUESONGDATA: &str = "/api/v2/song/queue/{id}"; pub const QUEUESONGDATA: &str = "/api/v2/song/queue/{id}";
pub const QUEUESONGUPDATE: &str = "/api/v2/song/queue/{id}"; pub const QUEUESONGUPDATE: &str = "/api/v2/song/queue/{id}";
pub const NEXTQUEUESONG: &str = "/api/v2/song/queue/next"; pub const NEXTQUEUESONG: &str = "/api/v2/song/queue/next";
@@ -17,3 +18,7 @@ pub mod endpoints {
pub const CREATESONG: &str = "/api/v2/song"; pub const CREATESONG: &str = "/api/v2/song";
pub const CREATECOVERART: &str = "/api/v2/coverart"; pub const CREATECOVERART: &str = "/api/v2/coverart";
} }
pub mod response {
pub const SUCCESSFUL: &str = "SUCCESSFUL";
}
+99 -6
View File
@@ -84,6 +84,14 @@ pub mod request {
pub song_queue_id: uuid::Uuid, pub song_queue_id: uuid::Uuid,
} }
} }
pub mod link_user_id {
#[derive(Debug, serde::Deserialize, serde::Serialize)]
pub struct Request {
pub song_queue_id: uuid::Uuid,
pub user_id: uuid::Uuid,
}
}
} }
pub mod response { pub mod response {
@@ -142,6 +150,14 @@ pub mod response {
pub data: Vec<uuid::Uuid>, pub data: Vec<uuid::Uuid>,
} }
} }
pub mod link_user_id {
#[derive(Debug, Default, serde::Deserialize, serde::Serialize)]
pub struct Response {
pub message: String,
pub data: Vec<uuid::Uuid>,
}
}
} }
// TODO: Might make a distinction between year and date in a song's tag at some point // TODO: Might make a distinction between year and date in a song's tag at some point
@@ -320,6 +336,7 @@ mod song_queue {
pub id: uuid::Uuid, pub id: uuid::Uuid,
pub filename: String, pub filename: String,
pub status: String, pub status: String,
pub user_id: uuid::Uuid,
} }
pub async fn insert( pub async fn insert(
@@ -393,7 +410,7 @@ mod song_queue {
FOR UPDATE SKIP LOCKED FOR UPDATE SKIP LOCKED
LIMIT 1 LIMIT 1
) )
RETURNING id, filename, status; RETURNING id, filename, status, user_id;
"#, "#,
) )
.bind(super::status::PROCESSING) .bind(super::status::PROCESSING)
@@ -405,7 +422,9 @@ mod song_queue {
}); });
match result { match result {
Ok(row) => Ok(SongQueue { Ok(row) => {
let user_id_result = row.try_get("user_id");
let song_queue = SongQueue {
id: row id: row
.try_get("id") .try_get("id")
.map_err(|_e| sqlx::Error::RowNotFound) .map_err(|_e| sqlx::Error::RowNotFound)
@@ -418,7 +437,14 @@ mod song_queue {
.try_get("status") .try_get("status")
.map_err(|_e| sqlx::Error::RowNotFound) .map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(), .unwrap(),
}), user_id: match user_id_result {
Ok(id) => id,
Err(_) => uuid::Uuid::nil(),
},
};
Ok(song_queue)
}
Err(_err) => Err(sqlx::Error::RowNotFound), Err(_err) => Err(sqlx::Error::RowNotFound),
} }
} }
@@ -475,13 +501,40 @@ mod song_queue {
} }
} }
pub async fn link_user_id(
pool: &sqlx::PgPool,
id: &uuid::Uuid,
user_id: &uuid::Uuid,
) -> Result<uuid::Uuid, sqlx::Error> {
let result = sqlx::query(
r#"
UPDATE "songQueue" SET user_id = $1 WHERE id = $2 RETURNING user_id;
"#,
)
.bind(user_id)
.bind(id)
.fetch_one(pool)
.await
.map_err(|e| {
eprintln!("Error updating record {e}");
});
match result {
Ok(row) => Ok(row
.try_get("user_id")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap()),
Err(_) => Err(sqlx::Error::RowNotFound),
}
}
pub async fn get_song_queue( pub async fn get_song_queue(
pool: &sqlx::PgPool, pool: &sqlx::PgPool,
id: &uuid::Uuid, id: &uuid::Uuid,
) -> Result<SongQueue, sqlx::Error> { ) -> Result<SongQueue, sqlx::Error> {
let result = sqlx::query( let result = sqlx::query(
r#" r#"
SELECT id, filename, status FROM "songQueue" WHERE id = $1 SELECT id, filename, status, user_id FROM "songQueue" WHERE id = $1
"#, "#,
) )
.bind(id) .bind(id)
@@ -492,7 +545,9 @@ mod song_queue {
}); });
match result { match result {
Ok(row) => Ok(SongQueue { Ok(row) => {
let user_id_result = row.try_get("user_id");
let song_queue = SongQueue {
id: row id: row
.try_get("id") .try_get("id")
.map_err(|_e| sqlx::Error::RowNotFound) .map_err(|_e| sqlx::Error::RowNotFound)
@@ -505,7 +560,14 @@ mod song_queue {
.try_get("status") .try_get("status")
.map_err(|_e| sqlx::Error::RowNotFound) .map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(), .unwrap(),
}), user_id: match user_id_result {
Ok(id) => id,
Err(_) => uuid::Uuid::nil(),
},
};
Ok(song_queue)
}
Err(_err) => Err(sqlx::Error::RowNotFound), Err(_err) => Err(sqlx::Error::RowNotFound),
} }
} }
@@ -616,6 +678,37 @@ pub mod endpoint {
(StatusCode::OK, Json(response)) (StatusCode::OK, Json(response))
} }
pub async fn link_user_id(
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
axum::Json(payload): axum::Json<super::request::link_user_id::Request>,
) -> (
axum::http::StatusCode,
axum::Json<super::response::link_user_id::Response>,
) {
let mut response = super::response::link_user_id::Response::default();
match super::song_queue::get_song_queue(&pool, &payload.song_queue_id).await {
Ok(song_queue) => {
match super::song_queue::link_user_id(&pool, &song_queue.id, &payload.user_id).await
{
Ok(user_id) => {
response.message = String::from(crate::callers::response::SUCCESSFUL);
response.data.push(user_id);
(axum::http::StatusCode::OK, axum::Json(response))
}
Err(err) => {
response.message = err.to_string();
(axum::http::StatusCode::BAD_REQUEST, axum::Json(response))
}
}
}
Err(err) => {
response.message = err.to_string();
(axum::http::StatusCode::BAD_REQUEST, axum::Json(response))
}
}
}
pub async fn fetch_queue_song( pub async fn fetch_queue_song(
axum::Extension(pool): axum::Extension<sqlx::PgPool>, axum::Extension(pool): axum::Extension<sqlx::PgPool>,
) -> ( ) -> (
+130 -48
View File
@@ -59,6 +59,10 @@ pub mod init {
crate::callers::endpoints::QUEUESONG, crate::callers::endpoints::QUEUESONG,
patch(crate::callers::song::endpoint::update_song_queue_status), patch(crate::callers::song::endpoint::update_song_queue_status),
) )
.route(
crate::callers::endpoints::QUEUESONGLINKUSERID,
patch(crate::callers::song::endpoint::link_user_id),
)
.route( .route(
crate::callers::endpoints::QUEUESONGDATA, crate::callers::endpoints::QUEUESONGDATA,
get(crate::callers::song::endpoint::download_flac), get(crate::callers::song::endpoint::download_flac),
@@ -237,6 +241,7 @@ mod tests {
} }
} }
// TODO: Put the *_req() functions in their own module
async fn song_queue_req( async fn song_queue_req(
app: &axum::Router, app: &axum::Router,
) -> Result<axum::response::Response, std::convert::Infallible> { ) -> Result<axum::response::Response, std::convert::Infallible> {
@@ -256,6 +261,26 @@ mod tests {
app.clone().oneshot(req).await app.clone().oneshot(req).await
} }
async fn song_queue_link_req(
app: &axum::Router,
song_queue_id: &uuid::Uuid,
user_id: &uuid::Uuid,
) -> Result<axum::response::Response, std::convert::Infallible> {
let payload = serde_json::json!({
"song_queue_id": song_queue_id,
"user_id": user_id
});
let req = axum::http::Request::builder()
.method(axum::http::Method::PATCH)
.uri(crate::callers::endpoints::QUEUESONGLINKUSERID)
.header(axum::http::header::CONTENT_TYPE, "application/json")
.body(axum::body::Body::from(payload.to_string()))
.unwrap();
app.clone().oneshot(req).await
}
async fn fetch_queue_req( async fn fetch_queue_req(
app: &axum::Router, app: &axum::Router,
) -> Result<axum::response::Response, std::convert::Infallible> { ) -> Result<axum::response::Response, std::convert::Infallible> {
@@ -380,6 +405,7 @@ mod tests {
async fn create_song_req( async fn create_song_req(
app: &axum::Router, app: &axum::Router,
song_queue_id: &uuid::Uuid, song_queue_id: &uuid::Uuid,
user_id: &uuid::Uuid,
) -> Result<axum::response::Response, std::convert::Infallible> { ) -> Result<axum::response::Response, std::convert::Infallible> {
let payload = serde_json::json!({ let payload = serde_json::json!({
"title": "Power of Soul", "title": "Power of Soul",
@@ -394,7 +420,7 @@ mod tests {
"disc_count": 1, "disc_count": 1,
"duration": 330, "duration": 330,
"audio_type": "flac", "audio_type": "flac",
"user_id": "d6e159c1-9648-4c85-81e5-52f502ff53e4", "user_id": user_id,
"song_queue_id": song_queue_id "song_queue_id": song_queue_id
}); });
@@ -451,7 +477,7 @@ mod tests {
// Flow for queueing song // Flow for queueing song
pub async fn queue_song_flow( pub async fn queue_song_flow(
app: &axum::Router, app: &axum::Router,
) -> Result<axum::response::Response, std::convert::Infallible> { ) -> Result<(axum::response::Response, uuid::Uuid), std::convert::Infallible> {
match super::song_queue_req(&app).await { match super::song_queue_req(&app).await {
Ok(response) => { Ok(response) => {
let resp = let resp =
@@ -462,7 +488,23 @@ 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");
match super::queue_metadata_req(&app, &resp.data[0]).await { let user_id = uuid::Uuid::new_v4();
// 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 {
Ok(response) => {
let resp = super::get_resp_data::<
crate::callers::song::response::link_user_id::Response,
>(response)
.await;
assert_eq!(
false,
resp.data.is_empty(),
"The response should not be empty"
);
match super::queue_metadata_req(&app, &song_queue_id).await {
Ok(response) => { Ok(response) => {
let resp = super::get_resp_data::< let resp = super::get_resp_data::<
crate::callers::song::response::Response, crate::callers::song::response::Response,
@@ -473,7 +515,7 @@ mod tests {
let id = resp.data[0]; let id = resp.data[0];
match super::fetch_metadata_queue_req(&app, &id).await { match super::fetch_metadata_queue_req(&app, &id).await {
Ok(response) => Ok(response), Ok(response) => Ok((response, user_id)),
Err(err) => Err(err), Err(err) => Err(err),
} }
} }
@@ -482,6 +524,9 @@ mod tests {
Err(err) => Err(err), Err(err) => Err(err),
} }
} }
Err(err) => Err(err),
}
}
// Flow for queueing coverart // Flow for queueing coverart
pub async fn queue_coverart_flow( pub async fn queue_coverart_flow(
@@ -533,7 +578,7 @@ mod tests {
app: &axum::Router, app: &axum::Router,
) -> Result<(axum::response::Response, uuid::Uuid), std::convert::Infallible> { ) -> Result<(axum::response::Response, uuid::Uuid), std::convert::Infallible> {
match queue_song_flow(&app).await { match queue_song_flow(&app).await {
Ok(song_response) => { Ok((song_response, user_id)) => {
let resp = super::get_resp_data::< let resp = super::get_resp_data::<
crate::callers::metadata::response::fetch_metadata::Response, crate::callers::metadata::response::fetch_metadata::Response,
>(song_response) >(song_response)
@@ -541,7 +586,7 @@ mod tests {
assert_eq!(false, resp.data.is_empty(), "Data should not be empty"); assert_eq!(false, resp.data.is_empty(), "Data should not be empty");
let song_queue_id = resp.data[0].song_queue_id; let song_queue_id = resp.data[0].song_queue_id;
match super::create_song_req(&app, &song_queue_id).await { match super::create_song_req(&app, &song_queue_id, &user_id).await {
Ok(response) => { Ok(response) => {
let resp = super::get_resp_data::< let resp = super::get_resp_data::<
crate::callers::song::response::create_metadata::Response, crate::callers::song::response::create_metadata::Response,
@@ -586,12 +631,14 @@ mod tests {
} }
} }
// TODO: Put this in a util module
pub async fn resp_to_bytes( pub async fn resp_to_bytes(
response: axum::response::Response, response: axum::response::Response,
) -> Result<axum::body::Bytes, axum::Error> { ) -> Result<axum::body::Bytes, axum::Error> {
axum::body::to_bytes(response.into_body(), usize::MAX).await axum::body::to_bytes(response.into_body(), usize::MAX).await
} }
// TODO: Put this in a util module
pub async fn get_resp_data<Data>(response: axum::response::Response) -> Data pub async fn get_resp_data<Data>(response: axum::response::Response) -> Data
where where
Data: for<'a> serde::Deserialize<'a>, Data: for<'a> serde::Deserialize<'a>,
@@ -600,6 +647,7 @@ mod tests {
serde_json::from_slice(&body).unwrap() serde_json::from_slice(&body).unwrap()
} }
// TODO: Change the name of the function to be more expressive and put into it's own module
pub mod payload_data { pub mod payload_data {
pub async fn queue_metadata_payload_data(song_queue_id: &uuid::Uuid) -> serde_json::Value { pub async fn queue_metadata_payload_data(song_queue_id: &uuid::Uuid) -> serde_json::Value {
serde_json::json!( serde_json::json!(
@@ -655,11 +703,68 @@ mod tests {
let _ = db_mgr::drop_database(&tm_pool, &db_name).await; let _ = db_mgr::drop_database(&tm_pool, &db_name).await;
} }
mod special_area { #[tokio::test]
async fn test_song_queue_link_user_id() {
let tm_pool = db_mgr::get_pool().await.unwrap();
let db_name = db_mgr::generate_db_name().await;
use super::*; match db_mgr::create_database(&tm_pool, &db_name).await {
Ok(_) => {
println!("Success");
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
}
use std::io::Write; let pool = db_mgr::connect_to_db(&db_name).await.unwrap();
db::migrations(&pool).await;
let app = init::app(pool).await;
match song_queue_req(&app).await {
Ok(response) => {
let resp =
get_resp_data::<crate::callers::song::response::Response>(response).await;
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
assert_eq!(false, resp.data[0].is_nil(), "Should not be empty");
let song_queue_id = &resp.data[0];
let user_id = uuid::Uuid::new_v4();
println!("User Id: {user_id:?}");
match song_queue_link_req(&app, &song_queue_id, &user_id).await {
Ok(response) => {
let resp = get_resp_data::<
crate::callers::song::response::link_user_id::Response,
>(response)
.await;
let collected_user_id = &resp.data[0];
assert!(
!collected_user_id.is_nil(),
"Collected user id should not be nil {collected_user_id:?}"
);
assert_eq!(
user_id, *collected_user_id,
"User Id is different. First {user_id:?} Second {collected_user_id:?}"
);
}
Err(err) => {
assert!(
false,
"Error: {err:?} songQueue Id {song_queue_id:?} user id {user_id:?}"
);
}
}
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
};
let _ = db_mgr::drop_database(&tm_pool, &db_name).await;
}
#[tokio::test] #[tokio::test]
async fn test_song_fetch_queue_item() { async fn test_song_fetch_queue_item() {
@@ -702,10 +807,7 @@ mod tests {
assert_eq!(false, resp.data.is_empty(), "Should not be empty"); assert_eq!(false, resp.data.is_empty(), "Should not be empty");
let changed_status = &resp.data[0]; let changed_status = &resp.data[0];
assert_eq!( assert_eq!(*old, changed_status.old_status, "Old status does not match");
*old, changed_status.old_status,
"Old status does not match"
);
assert_eq!( assert_eq!(
target_status, changed_status.new_status, target_status, changed_status.new_status,
"New status does not match" "New status does not match"
@@ -769,11 +871,7 @@ mod tests {
match fetch_queue_data_req(&app, &id).await { match fetch_queue_data_req(&app, &id).await {
Ok(response) => match resp_to_bytes(response).await { Ok(response) => match resp_to_bytes(response).await {
Ok(bytes) => { Ok(bytes) => {
assert_eq!( assert_eq!(false, bytes.is_empty(), "Queued data should not be empty");
false,
bytes.is_empty(),
"Queued data should not be empty"
);
let temp_file = let temp_file =
tempfile::tempdir().expect("Could not create test directory"); tempfile::tempdir().expect("Could not create test directory");
@@ -790,8 +888,7 @@ mod tests {
let content_type = form.content_type(); let content_type = form.content_type();
let body = MultipartBody::from(form); let body = MultipartBody::from(form);
let raw_uri = let raw_uri = String::from(crate::callers::endpoints::QUEUESONGUPDATE);
String::from(crate::callers::endpoints::QUEUESONGUPDATE);
let end_index = raw_uri.len() - 5; let end_index = raw_uri.len() - 5;
let uri = format!( let uri = format!(
@@ -817,11 +914,7 @@ mod tests {
crate::callers::song::response::update_song_queue::Response, crate::callers::song::response::update_song_queue::Response,
>(response) >(response)
.await; .await;
assert_eq!( assert_eq!(false, resp.data.is_empty(), "Should not be empty");
false,
resp.data.is_empty(),
"Should not be empty"
);
let updated_song_queued_id = resp.data[0]; let updated_song_queued_id = resp.data[0];
assert_eq!( assert_eq!(
@@ -883,11 +976,7 @@ mod tests {
match fetch_queue_data_req(&app, &id).await { match fetch_queue_data_req(&app, &id).await {
Ok(response) => match resp_to_bytes(response).await { Ok(response) => match resp_to_bytes(response).await {
Ok(bytes) => { Ok(bytes) => {
assert_eq!( assert_eq!(false, bytes.is_empty(), "Queued data should not be empty");
false,
bytes.is_empty(),
"Queued data should not be empty"
);
} }
Err(err) => { Err(err) => {
assert!(false, "Error: {:?}", err); assert!(false, "Error: {:?}", err);
@@ -947,14 +1036,8 @@ mod tests {
assert_eq!(false, resp.data.is_empty(), "Should not be empty"); assert_eq!(false, resp.data.is_empty(), "Should not be empty");
let changed_status = &resp.data[0]; let changed_status = &resp.data[0];
assert_eq!( assert_eq!(*old, changed_status.old_status, "Old status does not match");
*old, changed_status.old_status, assert_eq!(done, changed_status.new_status, "New status does not match");
"Old status does not match"
);
assert_eq!(
done, changed_status.new_status,
"New status does not match"
);
} }
Err(err) => { Err(err) => {
assert!(false, "Error: {:?}", err); assert!(false, "Error: {:?}", err);
@@ -968,7 +1051,6 @@ mod tests {
let _ = db_mgr::drop_database(&tm_pool, &db_name).await; let _ = db_mgr::drop_database(&tm_pool, &db_name).await;
} }
}
#[tokio::test] #[tokio::test]
async fn test_song_metadata_queue() { async fn test_song_metadata_queue() {
@@ -1038,7 +1120,7 @@ mod tests {
// Send request // Send request
match sequence_flow::queue_song_flow(&app).await { match sequence_flow::queue_song_flow(&app).await {
Ok(response) => { Ok((response, _user_id)) => {
let resp = get_resp_data::< let resp = get_resp_data::<
crate::callers::metadata::response::fetch_metadata::Response, crate::callers::metadata::response::fetch_metadata::Response,
>(response) >(response)
@@ -1354,7 +1436,7 @@ mod tests {
// Send request // Send request
match sequence_flow::queue_song_flow(&app).await { match sequence_flow::queue_song_flow(&app).await {
Ok(response) => { Ok((response, user_id)) => {
let resp = get_resp_data::< let resp = get_resp_data::<
crate::callers::metadata::response::fetch_metadata::Response, crate::callers::metadata::response::fetch_metadata::Response,
>(response) >(response)
@@ -1362,7 +1444,7 @@ mod tests {
assert_eq!(false, resp.data.is_empty(), "Data should not be empty"); assert_eq!(false, resp.data.is_empty(), "Data should not be empty");
let song_q_id = resp.data[0].song_queue_id; let song_q_id = resp.data[0].song_queue_id;
match create_song_req(&app, &song_q_id).await { match create_song_req(&app, &song_q_id, &user_id).await {
Ok(response) => { Ok(response) => {
let resp = get_resp_data::< let resp = get_resp_data::<
crate::callers::song::response::create_metadata::Response, crate::callers::song::response::create_metadata::Response,
@@ -1417,7 +1499,7 @@ mod tests {
// Send request // Send request
match sequence_flow::queue_song_flow(&app).await { match sequence_flow::queue_song_flow(&app).await {
Ok(response) => { Ok((response, user_id)) => {
let resp = get_resp_data::< let resp = get_resp_data::<
crate::callers::metadata::response::fetch_metadata::Response, crate::callers::metadata::response::fetch_metadata::Response,
>(response) >(response)
@@ -1425,7 +1507,7 @@ mod tests {
assert_eq!(false, resp.data.is_empty(), "Data should not be empty"); assert_eq!(false, resp.data.is_empty(), "Data should not be empty");
let song_queue_id = resp.data[0].song_queue_id; let song_queue_id = resp.data[0].song_queue_id;
match create_song_req(&app, &song_queue_id).await { match create_song_req(&app, &song_queue_id, &user_id).await {
Ok(response) => { Ok(response) => {
let resp = get_resp_data::< let resp = get_resp_data::<
crate::callers::song::response::create_metadata::Response, crate::callers::song::response::create_metadata::Response,
@@ -1512,7 +1594,7 @@ mod tests {
// Send request // Send request
match sequence_flow::queue_song_flow(&app).await { match sequence_flow::queue_song_flow(&app).await {
Ok(response) => { Ok((response, user_id)) => {
let resp = get_resp_data::< let resp = get_resp_data::<
crate::callers::metadata::response::fetch_metadata::Response, crate::callers::metadata::response::fetch_metadata::Response,
>(response) >(response)
@@ -1520,7 +1602,7 @@ mod tests {
assert_eq!(false, resp.data.is_empty(), "Data should not be empty"); assert_eq!(false, resp.data.is_empty(), "Data should not be empty");
let song_q_id = resp.data[0].song_queue_id; let song_q_id = resp.data[0].song_queue_id;
match create_song_req(&app, &song_q_id).await { match create_song_req(&app, &song_q_id, &user_id).await {
Ok(response) => { Ok(response) => {
let resp = get_resp_data::< let resp = get_resp_data::<
crate::callers::song::response::create_metadata::Response, crate::callers::song::response::create_metadata::Response,
@@ -1617,7 +1699,7 @@ mod tests {
let app = init::app(pool).await; let app = init::app(pool).await;
match sequence_flow::queue_song_flow(&app).await { match sequence_flow::queue_song_flow(&app).await {
Ok(response) => { Ok((response, user_id)) => {
let resp = get_resp_data::< let resp = get_resp_data::<
crate::callers::metadata::response::fetch_metadata::Response, crate::callers::metadata::response::fetch_metadata::Response,
>(response) >(response)
@@ -1625,7 +1707,7 @@ mod tests {
assert_eq!(false, resp.data.is_empty(), "Data should not be empty"); assert_eq!(false, resp.data.is_empty(), "Data should not be empty");
let song_queue_id = resp.data[0].song_queue_id; let song_queue_id = resp.data[0].song_queue_id;
match create_song_req(&app, &song_queue_id).await { match create_song_req(&app, &song_queue_id, &user_id).await {
Ok(response) => { Ok(response) => {
let resp = get_resp_data::< let resp = get_resp_data::<
crate::callers::song::response::create_metadata::Response, crate::callers::song::response::create_metadata::Response,