From 6b81a3cb99bc109726282d3e661f6b5ac5dde4c2 Mon Sep 17 00:00:00 2001 From: Santo Cariotti Date: Sun, 14 Mar 2021 22:20:35 +0100 Subject: feat: add DELETE method --- README.md | 1 + src/repository/models.rs | 32 +++++++++++++++++++++++++++ src/repository/routes.rs | 57 +++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 84 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e4b8d22..93de202 100644 --- a/README.md +++ b/README.md @@ -11,4 +11,5 @@ PG.HOST= PG.PORT= PG.DBNAME= PG.POOL.MAX_SIZE= +SECRET_KEY= ``` diff --git a/src/repository/models.rs b/src/repository/models.rs index c480cbe..bcddcf1 100644 --- a/src/repository/models.rs +++ b/src/repository/models.rs @@ -59,4 +59,36 @@ impl Repository { }), } } + + /// Find a repository and delete it, but before check if "Authorization" + /// matches with SECRET_KEY + pub async fn delete( + pool: Pool, + id: &Uuid, + ) -> Result { + let client = get_client(pool.clone()).await.unwrap(); + let statement = client + .prepare( + " + DELETE FROM repository + WHERE id=$1 + RETURNING * + ", + ) + .await?; + + let repo = client + .query_opt(&statement, &[&id]) + .await? + .map(|row| Repository::from_row_ref(&row).unwrap()); + + match repo { + Some(repo) => Ok(repo), + None => Err(AppError { + error_type: AppErrorType::NotFoundError, + cause: None, + message: Some("Repository not found".to_string()), + }), + } + } } diff --git a/src/repository/routes.rs b/src/repository/routes.rs index c13af7f..54bb35d 100644 --- a/src/repository/routes.rs +++ b/src/repository/routes.rs @@ -1,9 +1,11 @@ use crate::config::AppState; -use crate::errors::AppErrorResponse; +use crate::errors::{AppError, AppErrorResponse, AppErrorType}; use crate::helpers::uuid_from_string; use crate::repository::models::Repository; -use actix_web::{web, HttpResponse, Responder}; +use actix_web::http::header; +use actix_web::{web, HttpRequest, HttpResponse, Responder}; use slog::info; +use std::env; use uuid::Uuid; /// Endpoint used for retrieve all repositories @@ -41,9 +43,52 @@ async fn get_repo( .map_err(|e| e) } +/// Endpoint used for delete repository. +/// It uses a SECRET_KEY used like an API key +async fn delete_repo( + req: HttpRequest, + state: web::Data, + id: web::Path<(String,)>, +) -> impl Responder { + let uuid: Uuid = uuid_from_string(&id.0); + match req.headers().get(header::AUTHORIZATION) { + Some(x) + if x.to_str().unwrap() + != env::var("SECRET_KEY").unwrap_or("".to_string()) => + { + info!(state.log, "DELETE /repo/{}/ 401", id.0); + return Err(AppError { + error_type: AppErrorType::AuthorizationError, + message: Some( + "You must provide a valid Authorization".to_string(), + ), + cause: None, + }); + } + Some(_) => {} + None => { + info!(state.log, "DELETE /repo/{}/ 400", id.0); + return Ok(HttpResponse::BadRequest().body("")); + } + }; + + let result = Repository::delete(state.pool.clone(), &uuid).await; + info!(state.log, "DELETE /repo/{}/", id.0); + + result + .map(|_| HttpResponse::NoContent().body("")) + .map_err(|e| e) +} + +/// Routes for repository. TODO: create endpoint for UPDATE method pub fn config(cfg: &mut web::ServiceConfig) { - cfg.service(web::resource("/repo{_:/?}").route(web::get().to(index))) - .service( - web::resource("/repo/{id}{_:/?}").route(web::get().to(get_repo)), - ); + cfg.service( + web::scope("/repo") + .service(web::resource("{_:/?}").route(web::get().to(index))) + .service( + web::resource("/{id}{_:/?}") + .route(web::get().to(get_repo)) + .route(web::delete().to(delete_repo)), + ), + ); } -- cgit v1.2.3-18-g5258