diff options
Diffstat (limited to 'server/src/main.rs')
| -rw-r--r-- | server/src/main.rs | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/server/src/main.rs b/server/src/main.rs index 019f28f..f07c372 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -46,6 +46,8 @@ struct Db(sqlx::MySqlPool); reviews, review, review_id, + review_del, + review_id_del, users, user_key_add, user_key_get, @@ -633,6 +635,114 @@ async fn get_review_from_id( Ok(Json(review)) } +#[allow(clippy::too_many_arguments)] +async fn del_review( + mut db: Connection<Db>, + roots: &State<git_root::Roots>, + session: auth::Session, + projectid: &str, + reviewid: u64, + state: u8, + owner: &str, + branch: &str, +) -> Result<&'static str, Custom<&'static str>> { + let state = api_model::ReviewState::try_from(state).unwrap(); + + if owner != session.user_id + && project_check_maintainer(&mut db, session, projectid) + .await + .is_err() + { + return Err(Custom( + Status::Unauthorized, + "Not owner of review or maintainer of project", + )); + } + + match state { + api_model::ReviewState::Draft | api_model::ReviewState::Dropped => {} + api_model::ReviewState::Open | api_model::ReviewState::Closed => { + return Err(Custom(Status::BadRequest, "Review is open or closed")); + } + } + + roots + .del_branch(projectid, branch) + .map_err(|_| Custom(Status::InternalServerError, "git error")) + .await?; + + sqlx::query!( + "DELETE FROM reviews WHERE project=? AND id=?", + projectid, + reviewid + ) + .execute(&mut **db) + .await + .unwrap(); + + Ok("") +} + +async fn del_review_from_branch( + mut db: Connection<Db>, + roots: &State<git_root::Roots>, + session: auth::Session, + projectid: &str, + branch: &str, +) -> Result<&'static str, Custom<&'static str>> { + let (id, state, owner) = sqlx::query!( + "SELECT id,state,owner FROM reviews WHERE project=? AND branch=?", + projectid, + branch + ) + .fetch_one(&mut **db) + .map_ok(|r| (r.id, r.state, r.owner)) + .map_err(|_| Custom(Status::NotFound, "No such review")) + .await?; + + del_review( + db, + roots, + session, + projectid, + id, + state, + owner.as_str(), + branch, + ) + .await +} + +async fn del_review_from_id( + mut db: Connection<Db>, + roots: &State<git_root::Roots>, + session: auth::Session, + projectid: &str, + reviewid: u64, +) -> Result<&'static str, Custom<&'static str>> { + let (state, branch, owner) = sqlx::query!( + "SELECT state,branch,owner FROM reviews WHERE project=? AND id=?", + projectid, + reviewid + ) + .fetch_one(&mut **db) + .map_ok(|r| (r.state, r.branch, r.owner)) + .map_err(|_| Custom(Status::NotFound, "No such review")) + .await?; + + del_review( + db, + roots, + session, + projectid, + reviewid, + state, + owner.as_str(), + branch.as_str(), + ) + .await +} + #[utoipa::path( responses( (status = 200, description = "Get review", body = api_model::Review), @@ -665,6 +775,47 @@ async fn review_encoded_path( #[utoipa::path( responses( + (status = 200, description = "Review deleted"), + (status = 400, description = "Review is open or closed"), + (status = 401, description = "Not owner of review or maintainer of project"), + (status = 404, description = "No such review"), + ), + security( + ("session" = []), + ), +)] +#[delete("/review/<projectid>/<branch..>")] +async fn review_del( + db: Connection<Db>, + roots: &State<git_root::Roots>, + session: auth::Session, + projectid: &str, + branch: PathBuf, +) -> Result<&'static str, Custom<&'static str>> { + del_review_from_branch( + db, + roots, + session, + projectid, + branch.as_path().to_str().unwrap(), + ) + .await +} + +// Backup for the above. Matches if <branch> ends up encoded (with / as %2f) +#[delete("/review/<projectid>/<branch>", rank = 1)] +async fn review_encoded_path_del( + db: Connection<Db>, + roots: &State<git_root::Roots>, + session: auth::Session, + projectid: &str, + branch: &str, +) -> Result<&'static str, Custom<&'static str>> { + del_review_from_branch(db, roots, session, projectid, branch).await +} + +#[utoipa::path( + responses( (status = 200, description = "Get review", body = api_model::Review), (status = 404, description = "No such review"), ), @@ -684,6 +835,28 @@ async fn review_id( #[utoipa::path( responses( + (status = 200, description = "Remove deleted"), + (status = 400, description = "Review is open or closed"), + (status = 401, description = "Not owner of review or maintainer of project"), + (status = 404, description = "No such review"), + ), + security( + ("session" = []), + ), +)] +#[delete("/review/<projectid>?<reviewid>")] +async fn review_id_del( + db: Connection<Db>, + roots: &State<git_root::Roots>, + session: auth::Session, + projectid: &str, + reviewid: u64, +) -> Result<&'static str, Custom<&'static str>> { + del_review_from_id(db, roots, session, projectid, reviewid).await +} + +#[utoipa::path( + responses( (status = 200, description = "Get all users", body = api_model::Users), ), security( @@ -941,8 +1114,11 @@ fn rocket_from_config(figment: Figment) -> Rocket<Build> { project_user_del, reviews, review, + review_del, review_encoded_path, + review_encoded_path_del, review_id, + review_id_del, users, user_key_add, user_key_get, |
