diff options
| -rw-r--r-- | src/models/model.rs | 38 | ||||
| -rw-r--r-- | src/models/user.rs | 19 | ||||
| -rw-r--r-- | src/routes/model.rs | 6 | ||||
| -rw-r--r-- | src/routes/user.rs | 21 |
4 files changed, 79 insertions, 5 deletions
diff --git a/src/models/model.rs b/src/models/model.rs index 0a9ea0a..60a6814 100644 --- a/src/models/model.rs +++ b/src/models/model.rs @@ -198,6 +198,32 @@ impl Model { Ok(rows) } + /// List author's models + pub async fn list_from_author(page: i64, author: i32) -> Result<Vec<ModelUser>, AppError> { + let pool = unsafe { get_client() }; + let rows: Vec<ModelUser> = sqlx::query_as( + r#" + SELECT + models.*, + json_build_object('id', users.id, 'email', users.email, 'username', users.username, 'is_staff', users.is_staff, 'avatar', users.avatar) as author, + json_agg(uploads.*) filter (where uploads.* is not null) as uploads + FROM models + JOIN users ON users.id = models.author_id + LEFT JOIN uploads ON uploads.model_id = models.id + WHERE author_id = $1 + GROUP BY models.id, users.id + ORDER BY id DESC + LIMIT $2 OFFSET $3 + "#) + .bind(author) + .bind(CONFIG.page_limit) + .bind(CONFIG.page_limit * page) + .fetch_all(pool) + .await?; + + Ok(rows) + } + /// Delete a model pub async fn delete(model_id: i32) -> Result<(), AppError> { let pool = unsafe { get_client() }; @@ -224,6 +250,18 @@ impl Model { let count: i64 = cursor.try_get(0).unwrap(); Ok(count) } + + /// Return the number of author models + pub async fn count_filter_by_author(author: i32) -> Result<i64, AppError> { + let pool = unsafe { get_client() }; + let cursor = sqlx::query(r#"SELECT COUNT(id) as count FROM models WHERE author_id = $1"#) + .bind(author) + .fetch_one(pool) + .await?; + + let count: i64 = cursor.try_get(0).unwrap(); + Ok(count) + } } impl ModelUser { diff --git a/src/models/user.rs b/src/models/user.rs index c4debf5..7c08075 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -1,4 +1,9 @@ -use crate::{config::CONFIG, db::get_client, errors::AppError}; +use crate::{ + config::CONFIG, + db::get_client, + errors::AppError, + models::model::{Model, ModelUser}, +}; use serde::{Deserialize, Serialize}; use serde_with::{serde_as, NoneAsEmptyString}; @@ -170,7 +175,7 @@ impl User { } impl UserList { - // Edit an user + /// Edit an user pub async fn edit_avatar(&mut self, avatar: Option<String>) -> Result<(), AppError> { let pool = unsafe { get_client() }; sqlx::query( @@ -187,4 +192,14 @@ impl UserList { Ok(()) } + + /// Get all models created by an user + pub async fn get_models(&self, page: i64) -> Result<Vec<ModelUser>, AppError> { + Model::list_from_author(page, self.id).await + } + + /// Returns the number of models for an user + pub async fn count_models(&self) -> Result<i64, AppError> { + Model::count_filter_by_author(self.id).await + } } diff --git a/src/routes/model.rs b/src/routes/model.rs index b510ade..16468d0 100644 --- a/src/routes/model.rs +++ b/src/routes/model.rs @@ -27,9 +27,9 @@ pub fn create_route() -> Router { } #[derive(Serialize)] -struct ModelPagination { - count: i64, - results: Vec<ModelUser>, +pub struct ModelPagination { + pub count: i64, + pub results: Vec<ModelUser>, } /// List models. diff --git a/src/routes/user.rs b/src/routes/user.rs index 4904531..172007a 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -6,6 +6,7 @@ use crate::{ user::{User, UserList}, }, pagination::Pagination, + routes::model::ModelPagination, }; use axum::{ extract::{ContentLengthLimit, Multipart, Path, Query}, @@ -21,6 +22,7 @@ pub fn create_route() -> Router { .route("/me", get(get_me)) .route("/me/avatar", put(edit_my_avatar).delete(delete_my_avatar)) .route("/:id", get(get_user)) + .route("/:id/models", get(get_user_models)) } #[derive(Serialize)] @@ -108,3 +110,22 @@ async fn get_user(Path(user_id): Path<i32>) -> Result<Json<UserList>, AppError> Err(_) => Err(AppError::NotFound("User not found".to_string())), } } + +/// Get user models list +async fn get_user_models( + Path(user_id): Path<i32>, + pagination: Query<Pagination>, +) -> Result<Json<ModelPagination>, AppError> { + let user = match User::find_by_id(user_id).await { + Ok(user) => user, + Err(_) => { + return Err(AppError::NotFound("User not found".to_string())); + } + }; + + let page = pagination.0.page.unwrap_or_default(); + let results = user.get_models(page).await?; + let count = user.count_models().await?; + + Ok(Json(ModelPagination { count, results })) +} |
