summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSanto Cariotti <santo@dcariotti.me>2022-09-22 15:08:54 +0000
committerSanto Cariotti <santo@dcariotti.me>2022-09-22 15:08:54 +0000
commitb4764fc85c36f5cac6a2a43413da8ad374519fd8 (patch)
tree10e6dad556277e8c7c4cf0eab31143ea3fc5d4b6
parenta30bcf0f0f32d6b1c822c631cf22fa9b13a5616a (diff)
Delete model uploads
-rw-r--r--src/models/model.rs36
-rw-r--r--src/routes/model.rs45
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),
+ }
+}