diff options
| author | Santo Cariotti <santo@dcariotti.me> | 2022-09-26 15:42:08 +0000 |
|---|---|---|
| committer | Santo Cariotti <santo@dcariotti.me> | 2022-09-26 15:42:08 +0000 |
| commit | ac985c0a5e269ec82329868bbdfc3d15afb6b055 (patch) | |
| tree | ae069fb8c65e2b14f5d359b69fb4e79a6c89a3d6 | |
| parent | dfbee1cebc8c6ca6b09c55f9c576c15a4f7b9979 (diff) | |
Filter warnings by model_id
| -rw-r--r-- | src/models/warning.rs | 71 | ||||
| -rw-r--r-- | src/routes/warning.rs | 65 |
2 files changed, 126 insertions, 10 deletions
diff --git a/src/models/warning.rs b/src/models/warning.rs index 200f671..f6a4963 100644 --- a/src/models/warning.rs +++ b/src/models/warning.rs @@ -23,6 +23,18 @@ pub struct WarningCreate { pub note: String, } +/// Payload used for warning filtering +#[derive(Deserialize)] +pub struct WarningFilterPayload { + pub model_id: i32, +} + +/// Struct used as argument for filtering by the backend +pub struct WarningFilter { + pub model_id: i32, + pub user_id: Option<i32>, +} + impl Warning { /// Create a warning means create an object which has an `user_id` (creator of the warning), a /// `model_id` (suspect model) and a `note` @@ -119,4 +131,63 @@ impl Warning { Ok(rec) } + + /// Filter warnings. Pass a `WarningFilter` argument + pub async fn filter(page: i64, args: WarningFilter) -> Result<Vec<Warning>, AppError> { + let pool = unsafe { get_client() }; + + let query = r#" + SELECT * FROM warnings WHERE model_id = $1 + "#; + + let rows: Vec<Warning> = match args.user_id { + Some(id) => { + sqlx::query_as(&format!(r#"{} AND user_id = $2 LIMIT $3 OFFSET $4"#, query)) + .bind(args.model_id) + .bind(id) + .bind(CONFIG.page_limit) + .bind(CONFIG.page_limit * page) + .fetch_all(pool) + .await? + } + None => { + sqlx::query_as(&format!(r#"{} LIMIT $2 OFFSET $3"#, query)) + .bind(args.model_id) + .bind(CONFIG.page_limit) + .bind(CONFIG.page_limit * page) + .fetch_all(pool) + .await? + } + }; + + Ok(rows) + } + + /// Return the number of filtered warnings. + pub async fn count_by_model_id(args: WarningFilter) -> Result<i64, AppError> { + let pool = unsafe { get_client() }; + + let query = r#" + SELECT COUNT(id) as count FROM warnings WHERE model_id = $1 + "#; + + let cursor = match args.user_id { + Some(id) => { + sqlx::query(&format!(r#"{} AND user_id = $2"#, query)) + .bind(args.model_id) + .bind(id) + .fetch_one(pool) + .await? + } + None => { + sqlx::query(&format!(r#"{}"#, query)) + .bind(args.model_id) + .fetch_one(pool) + .await? + } + }; + + let count: i64 = cursor.try_get(0).unwrap(); + Ok(count) + } } diff --git a/src/routes/warning.rs b/src/routes/warning.rs index 1870843..3a8573e 100644 --- a/src/routes/warning.rs +++ b/src/routes/warning.rs @@ -4,23 +4,22 @@ use crate::{ auth::Claims, model::Model, user::User, - warning::{Warning, WarningCreate}, + warning::{Warning, WarningCreate, WarningFilter, WarningFilterPayload}, }, pagination::{Pagination, WarningPagination}, routes::JsonCreate, }; -use axum::{extract::Query, routing::get, Json, Router}; -use serde::Serialize; +use axum::{ + extract::Query, + routing::{get, post}, + Json, Router, +}; /// Create routes for `/v1/warnings/` namespace pub fn create_route() -> Router { - Router::new().route("/", get(list_warnings).post(create_warning)) -} - -#[derive(Serialize)] -struct WarningPagination { - count: i64, - results: Vec<Warning>, + Router::new() + .route("/", get(list_warnings).post(create_warning)) + .route("/filter", post(filter_warnings)) } /// List warnings. A staffer can see everything. @@ -62,3 +61,49 @@ async fn create_warning( Ok(JsonCreate(warning_new)) } + +/// Apply a filter to warnings list +async fn filter_warnings( + Json(payload): Json<WarningFilterPayload>, + pagination: Query<Pagination>, + claims: Claims, +) -> Result<Json<WarningPagination>, AppError> { + let page = pagination.0.page.unwrap_or_default(); + + let user = User::find_by_id(claims.user_id).await?; + + let (results, count) = match user.is_staff.unwrap() { + true => ( + Warning::filter( + page, + WarningFilter { + model_id: payload.model_id, + user_id: None, + }, + ) + .await?, + Warning::count_by_model_id(WarningFilter { + model_id: payload.model_id, + user_id: None, + }) + .await?, + ), + false => ( + Warning::filter( + page, + WarningFilter { + model_id: payload.model_id, + user_id: Some(user.id), + }, + ) + .await?, + Warning::count_by_model_id(WarningFilter { + model_id: payload.model_id, + user_id: Some(user.id), + }) + .await?, + ), + }; + + Ok(Json(WarningPagination { count, results })) +} |
