fix: filtered total
This commit is contained in:
@@ -35,6 +35,7 @@
|
|||||||
pkg-config
|
pkg-config
|
||||||
sqlite
|
sqlite
|
||||||
gemini-cli
|
gemini-cli
|
||||||
|
claude-code
|
||||||
biome
|
biome
|
||||||
sqlx-cli
|
sqlx-cli
|
||||||
typos
|
typos
|
||||||
|
|||||||
@@ -325,21 +325,19 @@ pub async fn list_logs(
|
|||||||
State(state): State<Arc<AppContext>>,
|
State(state): State<Arc<AppContext>>,
|
||||||
Query(params): Query<ListLogsParams>,
|
Query(params): Query<ListLogsParams>,
|
||||||
) -> Result<Json<PaginatedRequestLogs>, (StatusCode, Json<ApiError>)> {
|
) -> Result<Json<PaginatedRequestLogs>, (StatusCode, Json<ApiError>)> {
|
||||||
match (
|
match db::repositories::logs::list(
|
||||||
db::repositories::logs::list(
|
&state.db,
|
||||||
&state.db,
|
params.method.as_deref(),
|
||||||
params.method.as_deref(),
|
params.search.as_deref(),
|
||||||
params.search.as_deref(),
|
params.limit,
|
||||||
params.limit,
|
params
|
||||||
params
|
.limit
|
||||||
.limit
|
.map(|limit| limit * (params.page.unwrap_or(1) - 1)),
|
||||||
.map(|limit| limit * (params.page.unwrap_or(1) - 1)),
|
)
|
||||||
)
|
.await
|
||||||
.await,
|
{
|
||||||
db::repositories::logs::total(&state.db).await,
|
Ok((logs, total)) => Ok(Json(PaginatedRequestLogs { total, data: logs })),
|
||||||
) {
|
Err(e) => {
|
||||||
(Ok(logs), Ok(total)) => Ok(Json(PaginatedRequestLogs { total, data: logs })),
|
|
||||||
(Err(e), _) | (_, Err(e)) => {
|
|
||||||
error!("Failed to list logs: {}", e);
|
error!("Failed to list logs: {}", e);
|
||||||
Err((
|
Err((
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
|||||||
@@ -1,26 +1,23 @@
|
|||||||
use crate::db::models::{InterceptionAction, RequestLog};
|
use crate::db::models::{InterceptionAction, RequestLog};
|
||||||
use sqlx::{QueryBuilder, SqlitePool};
|
use sqlx::{QueryBuilder, SqlitePool};
|
||||||
|
|
||||||
pub async fn total(pool: &SqlitePool) -> anyhow::Result<usize> {
|
|
||||||
Ok(
|
|
||||||
sqlx::query_scalar::<_, i64>("SELECT COUNT(*) FROM request_logs;")
|
|
||||||
.fetch_one(pool)
|
|
||||||
.await? as usize,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn list(
|
pub async fn list(
|
||||||
pool: &SqlitePool,
|
pool: &SqlitePool,
|
||||||
method: Option<&str>,
|
method: Option<&str>,
|
||||||
search: Option<&str>,
|
search: Option<&str>,
|
||||||
limit: Option<usize>,
|
limit: Option<usize>,
|
||||||
offset: Option<usize>,
|
offset: Option<usize>,
|
||||||
) -> anyhow::Result<Vec<RequestLog>> {
|
) -> anyhow::Result<(Vec<RequestLog>, usize)> {
|
||||||
|
let mut tx = pool.begin().await?;
|
||||||
let mut builder: QueryBuilder<sqlx::Sqlite> = QueryBuilder::new("SELECT * FROM request_logs");
|
let mut builder: QueryBuilder<sqlx::Sqlite> = QueryBuilder::new("SELECT * FROM request_logs");
|
||||||
|
let mut total_builder: QueryBuilder<sqlx::Sqlite> =
|
||||||
|
QueryBuilder::new("SELECT COUNT(*) FROM request_logs");
|
||||||
|
|
||||||
if let Some(method_val) = method {
|
if let Some(method_val) = method {
|
||||||
builder.push(" WHERE method = ");
|
builder.push(" WHERE method = ");
|
||||||
builder.push_bind(method_val);
|
builder.push_bind(method_val);
|
||||||
|
total_builder.push(" WHERE method = ");
|
||||||
|
total_builder.push_bind(method_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(search_val) = search {
|
if let Some(search_val) = search {
|
||||||
@@ -32,8 +29,18 @@ pub async fn list(
|
|||||||
}
|
}
|
||||||
builder.push_bind(pattern.clone());
|
builder.push_bind(pattern.clone());
|
||||||
builder.push(" OR response_body LIKE ");
|
builder.push(" OR response_body LIKE ");
|
||||||
builder.push_bind(pattern);
|
builder.push_bind(pattern.clone());
|
||||||
builder.push(")");
|
builder.push(")");
|
||||||
|
|
||||||
|
if method.is_some() {
|
||||||
|
total_builder.push(" AND (request_body LIKE ");
|
||||||
|
} else {
|
||||||
|
total_builder.push(" WHERE (request_body LIKE ");
|
||||||
|
}
|
||||||
|
total_builder.push_bind(pattern.clone());
|
||||||
|
total_builder.push(" OR response_body LIKE ");
|
||||||
|
total_builder.push_bind(pattern);
|
||||||
|
total_builder.push(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(limit) = limit {
|
if let Some(limit) = limit {
|
||||||
@@ -49,14 +56,22 @@ pub async fn list(
|
|||||||
builder.push(" ORDER BY created_at DESC");
|
builder.push(" ORDER BY created_at DESC");
|
||||||
|
|
||||||
let query = builder.build_query_as();
|
let query = builder.build_query_as();
|
||||||
Ok(query.fetch_all(pool).await?)
|
let logs = query.fetch_all(&mut *tx).await?;
|
||||||
|
let total = builder
|
||||||
|
.build_query_scalar::<i64>()
|
||||||
|
.fetch_one(&mut *tx)
|
||||||
|
.await? as usize;
|
||||||
|
tx.commit().await?;
|
||||||
|
Ok((logs, total))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn list_methods(pool: &SqlitePool) -> anyhow::Result<Vec<String>> {
|
pub async fn list_methods(pool: &SqlitePool) -> anyhow::Result<Vec<String>> {
|
||||||
Ok(
|
Ok(
|
||||||
sqlx::query_scalar::<_, String>("SELECT DISTINCT method FROM request_logs ORDER BY method;")
|
sqlx::query_scalar::<_, String>(
|
||||||
.fetch_all(pool)
|
"SELECT DISTINCT method FROM request_logs ORDER BY method;",
|
||||||
.await?
|
)
|
||||||
|
.fetch_all(pool)
|
||||||
|
.await?,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -198,7 +198,8 @@ async fn process_response(body: String, method: &str, ctx: &Arc<AppContext>) ->
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let modified_body_str = serde_json::to_string(&response_value).expect("serialization succeeded");
|
let modified_body_str =
|
||||||
|
serde_json::to_string(&response_value).expect("serialization succeeded");
|
||||||
let encrypted = ctx.cryptor.encrypt(modified_body_str.clone());
|
let encrypted = ctx.cryptor.encrypt(modified_body_str.clone());
|
||||||
let final_ = action.map(|action| (modified_body_str.clone(), action));
|
let final_ = action.map(|action| (modified_body_str.clone(), action));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user