summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/models/model.rs29
-rw-r--r--src/routes/model.rs87
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