diff --git a/crates/server/Cargo.toml b/crates/server/Cargo.toml index 0071758..9461928 100644 --- a/crates/server/Cargo.toml +++ b/crates/server/Cargo.toml @@ -29,4 +29,4 @@ reqwest = { version = "0.12.4", features = ["json"] } tower = "0.4.13" chrono-tz = { version = "0.9.0", features = ["serde"] } rand_core = { version = "0.6.4", features = ["std"] } -serde_repr = "0.1.19" +serde_repr = "0.1.19" \ No newline at end of file diff --git a/crates/server/src/models/log.rs b/crates/server/src/models/log.rs index b559d4f..d2da62b 100644 --- a/crates/server/src/models/log.rs +++ b/crates/server/src/models/log.rs @@ -73,7 +73,7 @@ impl Log { Ok(result.rows_affected()) } - pub async fn list(pool: &SqlitePool, limit: Option) -> sqlx::Result> { + pub async fn list_all(pool: &SqlitePool, limit: Option) -> sqlx::Result> { let logs = sqlx::query_as::<_, Log>(r#"SELECT * FROM logs ORDER BY id DESC LIMIT ?"#) .bind(limit.unwrap_or(100)) .fetch_all(pool) @@ -81,6 +81,22 @@ impl Log { Ok(logs) } + + pub async fn list( + pool: &SqlitePool, + service_id: u32, + limit: Option, + ) -> sqlx::Result> { + let logs = sqlx::query_as::<_, Log>( + r#"SELECT * FROM logs WHERE service_id = ? ORDER BY id DESC LIMIT ?"#, + ) + .bind(service_id) + .bind(limit.unwrap_or(100)) + .fetch_all(pool) + .await?; + + Ok(logs) + } } impl std::fmt::Display for LogForCreate { @@ -116,7 +132,7 @@ mod tests { #[sqlx::test(fixtures("users", "services", "logs"))] async fn list_logs(pool: SqlitePool) -> sqlx::Result<()> { - let logs = Log::list(&pool, None).await?; + let logs = Log::list_all(&pool, None).await?; dbg!(&logs); @@ -127,7 +143,7 @@ mod tests { #[sqlx::test(fixtures("users", "services", "logs"))] async fn list_logs_limit(pool: SqlitePool) -> sqlx::Result<()> { - let logs = Log::list(&pool, Some(2)).await?; + let logs = Log::list_all(&pool, Some(2)).await?; dbg!(&logs); @@ -138,7 +154,20 @@ mod tests { #[sqlx::test(fixtures("users", "services", "logs"))] async fn list_logs_order(pool: SqlitePool) -> sqlx::Result<()> { - let logs = Log::list(&pool, Some(2)).await?; + let logs = Log::list_all(&pool, Some(2)).await?; + + dbg!(&logs); + + assert!(logs.first().unwrap().id > logs.last().unwrap().id); + + assert_eq!(logs.len(), 2); + + Ok(()) + } + + #[sqlx::test(fixtures("users", "services", "logs"))] + async fn list_service_logs(pool: SqlitePool) -> sqlx::Result<()> { + let logs = Log::list(&pool, 2, Some(2)).await?; dbg!(&logs); diff --git a/crates/server/src/routes/logs.rs b/crates/server/src/routes/logs.rs index 9aaa15d..1498b87 100644 --- a/crates/server/src/routes/logs.rs +++ b/crates/server/src/routes/logs.rs @@ -22,7 +22,7 @@ async fn list_logs( State(state): State, pagination: Query, ) -> Response { - match Log::list(&state.pool, pagination.limit).await { + match Log::list_all(&state.pool, pagination.limit).await { Ok(logs) => Response::builder() .header("Content-Type", "application/json") .body(json!({ "logs": logs }).to_string()) diff --git a/crates/server/src/routes/service.rs b/crates/server/src/routes/service.rs index 4749eeb..b82329e 100644 --- a/crates/server/src/routes/service.rs +++ b/crates/server/src/routes/service.rs @@ -1,19 +1,28 @@ use axum::{ - extract::{Path, State}, + extract::{Path, Query, State}, response::{IntoResponse, Response}, routing::{get, put}, Json, Router, }; use axum_macros::debug_handler; +use serde::Deserialize; use serde_json::json; use tracing::error; use crate::{ auth::Claims, - models::service::{Service, ServiceForCreate, ServiceForUpdate}, + models::{ + log::Log, + service::{Service, ServiceForCreate, ServiceForUpdate}, + }, AppState, }; +#[derive(Deserialize)] +struct Pagination { + limit: Option, +} + #[debug_handler] async fn add_service( _: Claims, @@ -109,9 +118,35 @@ async fn list_services(State(state): State) -> Response { .into_response() } +#[debug_handler] +async fn list_service_logs( + //_: Claims, + State(state): State, + Path(service_id): Path, + pagination: Query, +) -> Response { + match Log::list(&state.pool, service_id, pagination.limit).await { + Ok(logs) => Response::builder() + .header("Content-Type", "application/json") + .body(json!({ "logs": logs }).to_string()) + .unwrap() + .into_response(), + Err(e) => { + error!("{e}"); + Response::builder() + .header("Content-Type", "application/json") + .status(500) + .body(json!({ "message": "Internal server error" }).to_string()) + .unwrap() + .into_response() + } + } +} + pub fn routes(state: AppState) -> Router { Router::new() - .route("/service", get(list_services).post(add_service)) - .route("/service/:id", put(update_service).get(get_service)) + .route("/services", get(list_services).post(add_service)) + .route("/services/:id", put(update_service).get(get_service)) + .route("/services/:id/logs", get(list_service_logs)) .with_state(state) }