diff options
| author | Santo Cariotti <santo@dcariotti.me> | 2022-09-22 15:08:54 +0000 |
|---|---|---|
| committer | Santo Cariotti <santo@dcariotti.me> | 2022-09-22 15:08:54 +0000 |
| commit | b4764fc85c36f5cac6a2a43413da8ad374519fd8 (patch) | |
| tree | 10e6dad556277e8c7c4cf0eab31143ea3fc5d4b6 /src | |
| parent | a30bcf0f0f32d6b1c822c631cf22fa9b13a5616a (diff) | |
Delete model uploads
Diffstat (limited to 'src')
| -rw-r--r-- | src/models/model.rs | 36 | ||||
| -rw-r--r-- | src/routes/model.rs | 45 |
2 files changed, 78 insertions, 3 deletions
diff --git a/src/models/model.rs b/src/models/model.rs index 469356f..9d463b1 100644 --- a/src/models/model.rs +++ b/src/models/model.rs @@ -59,8 +59,8 @@ pub struct ModelUser { #[derive(Deserialize, Serialize, sqlx::FromRow)] pub struct ModelUpload { id: i32, - model_id: i32, - filepath: String, + pub model_id: i32, + pub filepath: String, created: NaiveDateTime, } @@ -270,4 +270,36 @@ impl ModelUpload { Ok(rec) } + + /// Returns the model upload with id = `upload_id` + pub async fn find_by_id(id: i32) -> Result<ModelUpload, AppError> { + let pool = unsafe { get_client() }; + + let rec: ModelUpload = sqlx::query_as( + r#" + SELECT * FROM uploads WHERE id = $1 + "#, + ) + .bind(id) + .fetch_one(pool) + .await?; + + Ok(rec) + } + + /// Delete a model upload + pub async fn delete(upload_id: i32) -> Result<(), AppError> { + let pool = unsafe { get_client() }; + + sqlx::query( + r#" + DELETE FROM uploads WHERE id = $1 + "#, + ) + .bind(upload_id) + .execute(pool) + .await?; + + Ok(()) + } } diff --git a/src/routes/model.rs b/src/routes/model.rs index 0572977..e40b31e 100644 --- a/src/routes/model.rs +++ b/src/routes/model.rs @@ -12,7 +12,7 @@ use crate::{ use axum::{ extract::{ContentLengthLimit, Multipart, Path, Query}, http::StatusCode, - routing::{get, post}, + routing::{delete, get, post}, Json, Router, }; use serde::Serialize; @@ -23,6 +23,7 @@ pub fn create_route() -> Router { .route("/", get(list_models).post(create_model)) .route("/:id", get(get_model).delete(delete_model)) .route("/:id/upload", post(upload_model_file)) + .route("/:id/upload/:uid", delete(delete_model_file)) } #[derive(Serialize)] @@ -124,3 +125,45 @@ async fn delete_model(claims: Claims, Path(model_id): Path<i32>) -> Result<Statu Ok(StatusCode::NO_CONTENT) } + +/// The owner or a staffer can delete a model upload +async fn delete_model_file( + claims: Claims, + Path(model_id): Path<i32>, + Path(upload_id): Path<i32>, +) -> Result<StatusCode, AppError> { + let model = match Model::find_by_id(model_id).await { + Ok(model) => model, + Err(_) => { + return Err(AppError::NotFound("Model not found".to_string())); + } + }; + + let user = User::find_by_id(claims.user_id).await?; + + if !(model.author_id() == user.id || user.is_staff.unwrap()) { + return Err(AppError::Unauthorized); + } + + let upload = match ModelUpload::find_by_id(upload_id).await { + Ok(upload) => upload, + Err(_) => { + return Err(AppError::NotFound("Upload not found".to_string())); + } + }; + + if upload.model_id != model.id { + return Err(AppError::NotFound("Upload not found".to_string())); + } + + let filepath = upload.filepath.clone(); + + match ModelUpload::delete(upload_id).await { + Ok(_) => { + delete_upload(&filepath)?; + + return Ok(StatusCode::NO_CONTENT); + } + Err(e) => Err(e), + } +} |
