diff options
| author | Santo Cariotti <santo@dcariotti.me> | 2022-09-23 18:45:39 +0000 |
|---|---|---|
| committer | Santo Cariotti <santo@dcariotti.me> | 2022-09-23 18:45:39 +0000 |
| commit | 7cb5079e1d8e5fbd3659ff0d6115ad6d0f1960b1 (patch) | |
| tree | 8e8db991ca3ae972722ca7fcde036454e9cca2d7 | |
| parent | b4764fc85c36f5cac6a2a43413da8ad374519fd8 (diff) | |
Edit model
| -rw-r--r-- | src/models/model.rs | 29 | ||||
| -rw-r--r-- | src/routes/model.rs | 87 |
2 files changed, 89 insertions, 27 deletions
diff --git a/src/models/model.rs b/src/models/model.rs index 9d463b1..0a9ea0a 100644 --- a/src/models/model.rs +++ b/src/models/model.rs @@ -122,6 +122,35 @@ impl Model { Ok(rec) } + /// Edit a model + pub async fn edit(id: i32, model: Model) -> Result<Model, AppError> { + let pool = unsafe { get_client() }; + + model + .validate() + .map_err(|error| AppError::BadRequest(error.to_string()))?; + + let rec: Model = sqlx::query_as( + r#" + UPDATE models SET name = $1, description = $2, duration = $3, height = $4, weight = $5, printer = $6, material = $7, updated = $8 + WHERE id = $9 + RETURNING * + "#) + .bind(model.name) + .bind(model.description) + .bind(model.duration) + .bind(model.height) + .bind(model.weight) + .bind(model.printer) + .bind(model.material) + .bind(model.updated) + .bind(id) + .fetch_one(pool) + .await?; + + Ok(rec) + } + /// Returns the model with id = `model_id` pub async fn find_by_id(model_id: i32) -> Result<ModelUser, AppError> { let pool = unsafe { get_client() }; diff --git a/src/routes/model.rs b/src/routes/model.rs index e40b31e..d19c6df 100644 --- a/src/routes/model.rs +++ b/src/routes/model.rs @@ -21,7 +21,7 @@ use serde::Serialize; pub fn create_route() -> Router { Router::new() .route("/", get(list_models).post(create_model)) - .route("/:id", get(get_model).delete(delete_model)) + .route("/:id", get(get_model).delete(delete_model).put(edit_model)) .route("/:id/upload", post(upload_model_file)) .route("/:id/upload/:uid", delete(delete_model_file)) } @@ -70,12 +70,8 @@ async fn get_model(Path(model_id): Path<i32>) -> Result<Json<ModelUser>, AppErro } } -/// Upload a file for a model -async fn upload_model_file( - claims: Claims, - Path(model_id): Path<i32>, - ContentLengthLimit(multipart): ContentLengthLimit<Multipart, { 1024 * 1024 }>, -) -> Result<Json<ModelUpload>, AppError> { +/// The owner or a staffer can delete a model +async fn delete_model(claims: Claims, Path(model_id): Path<i32>) -> Result<StatusCode, AppError> { let model = match Model::find_by_id(model_id).await { Ok(model) => model, Err(_) => { @@ -83,24 +79,30 @@ async fn upload_model_file( } }; - if model.author_id() != claims.user_id { - return Err(AppError::Unauthorized); - } + let user = User::find_by_id(claims.user_id).await?; - let allowed_extensions = vec!["stl", "obj", "png", "jpg", "jpeg", "gif", "webp", "blend"]; + let uploads: Vec<String> = model.list_upload_filepaths().await.unwrap(); - match upload(multipart, allowed_extensions, None).await { - Ok(saved_file) => { - let model_file = ModelUpload::create(ModelUpload::new(saved_file, model_id)).await?; + if !(model.author_id() == user.id || user.is_staff.unwrap()) { + return Err(AppError::Unauthorized); + } - Ok(Json(model_file)) - } - Err(e) => Err(e), + // If the model has been deleted, remove all old uploads from the file system + if Model::delete(model_id).await.is_ok() { + uploads + .iter() + .for_each(|path: &String| delete_upload(path).unwrap_or_default()); } + + Ok(StatusCode::NO_CONTENT) } -/// The owner or a staffer can delete a model -async fn delete_model(claims: Claims, Path(model_id): Path<i32>) -> Result<StatusCode, AppError> { +/// The owner or a staffer can edit a model +async fn edit_model( + Json(payload): Json<ModelCreate>, + claims: Claims, + Path(model_id): Path<i32>, +) -> Result<Json<ModelUser>, AppError> { let model = match Model::find_by_id(model_id).await { Ok(model) => model, Err(_) => { @@ -110,20 +112,51 @@ async fn delete_model(claims: Claims, Path(model_id): Path<i32>) -> Result<Statu let user = User::find_by_id(claims.user_id).await?; - let uploads: Vec<String> = model.list_upload_filepaths().await.unwrap(); - if !(model.author_id() == user.id || user.is_staff.unwrap()) { return Err(AppError::Unauthorized); } - // If the model has been deleted, remove all old uploads from the file system - if Model::delete(model_id).await.is_ok() { - uploads - .iter() - .for_each(|path: &String| delete_upload(path).unwrap_or_default()); + let model_body = Model::new( + payload.name, + payload.description, + payload.duration, + payload.height, + payload.weight, + payload.printer, + payload.material, + claims.user_id, + ); + Model::edit(model.id, model_body).await?; + Ok(Json(model)) +} + +/// Upload a file for a model +async fn upload_model_file( + claims: Claims, + Path(model_id): Path<i32>, + ContentLengthLimit(multipart): ContentLengthLimit<Multipart, { 1024 * 1024 }>, +) -> Result<Json<ModelUpload>, AppError> { + let model = match Model::find_by_id(model_id).await { + Ok(model) => model, + Err(_) => { + return Err(AppError::NotFound("Model not found".to_string())); + } + }; + + if model.author_id() != claims.user_id { + return Err(AppError::Unauthorized); } - Ok(StatusCode::NO_CONTENT) + let allowed_extensions = vec!["stl", "obj", "png", "jpg", "jpeg", "gif", "webp", "blend"]; + + match upload(multipart, allowed_extensions, None).await { + Ok(saved_file) => { + let model_file = ModelUpload::create(ModelUpload::new(saved_file, model_id)).await?; + + Ok(Json(model_file)) + } + Err(e) => Err(e), + } } /// The owner or a staffer can delete a model upload |
