Skip to content

Commit

Permalink
feat(gateway): block project delete on db or secrets
Browse files Browse the repository at this point in the history
  • Loading branch information
oddgrd committed Oct 23, 2023
1 parent f7ad5d8 commit d597007
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 13 deletions.
6 changes: 3 additions & 3 deletions common/src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use strum::{Display, EnumString};
#[cfg(feature = "openapi")]
use utoipa::ToSchema;

#[derive(Clone, Copy, Debug, Deserialize, Serialize, Eq, PartialEq)]
#[derive(Clone, Copy, Debug, Deserialize, Serialize, Eq, PartialEq, Hash)]
#[serde(rename_all = "lowercase")]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[cfg_attr(feature = "openapi", schema(as = shuttle_common::database::Type))]
Expand All @@ -14,7 +14,7 @@ pub enum Type {
Shared(SharedEngine),
}

#[derive(Clone, Copy, Debug, Deserialize, Display, Serialize, EnumString, Eq, PartialEq)]
#[derive(Clone, Copy, Debug, Deserialize, Display, Serialize, EnumString, Eq, PartialEq, Hash)]
#[serde(rename_all = "lowercase")]
#[strum(serialize_all = "lowercase")]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
Expand All @@ -24,7 +24,7 @@ pub enum AwsRdsEngine {
MariaDB,
}

#[derive(Clone, Copy, Debug, Deserialize, Display, Serialize, EnumString, Eq, PartialEq)]
#[derive(Clone, Copy, Debug, Deserialize, Display, Serialize, EnumString, Eq, PartialEq, Hash)]
#[serde(rename_all = "lowercase")]
#[strum(serialize_all = "lowercase")]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
Expand Down
13 changes: 8 additions & 5 deletions common/src/models/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub enum ErrorKind {
OwnProjectAlreadyExists(String),
ProjectNotReady,
ProjectUnavailable,
ProjectHasDatabase,
ProjectHasResources(Vec<String>),
ProjectHasRunningDeployment,
CustomDomainNotFound,
InvalidCustomDomain,
Expand Down Expand Up @@ -86,10 +86,13 @@ impl From<ErrorKind> for ApiError {
StatusCode::FORBIDDEN,
"A deployment is running. Stop it with `cargo shuttle stop` first."
),
ErrorKind::ProjectHasDatabase => (
StatusCode::FORBIDDEN,
"Project has database resources. Use `cargo shuttle resource list` and `cargo shuttle resource delete <type>` to delete them."
),
ErrorKind::ProjectHasResources(resources) => {
let resources = resources.join(", ");
return Self {
message: format!("Project has resources: {}. Use `cargo shuttle resource list` and `cargo shuttle resource delete <type>` to delete them.", resources),
status_code: StatusCode::FORBIDDEN.as_u16(),
}
}
ErrorKind::InvalidProjectName => (
StatusCode::BAD_REQUEST,
r#"
Expand Down
2 changes: 1 addition & 1 deletion common/src/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub struct Response {
pub data: Value,
}

#[derive(Clone, Copy, Debug, Deserialize, Serialize, Eq, PartialEq)]
#[derive(Clone, Copy, Debug, Deserialize, Serialize, Eq, PartialEq, Hash)]
#[serde(rename_all = "lowercase")]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[cfg_attr(feature = "openapi", schema(as = shuttle_common::resource::Type))]
Expand Down
21 changes: 17 additions & 4 deletions gateway/src/api/latest.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::collections::HashSet;
use std::io::Cursor;
use std::net::SocketAddr;
use std::ops::Sub;
Expand Down Expand Up @@ -361,11 +362,23 @@ async fn delete_project(
let resources: Vec<shuttle_common::resource::Response> =
serde_json::from_slice(&body_bytes)
.map_err(|e| Error::source(ErrorKind::Internal, e))?;
if resources

let resources = resources
.into_iter()
.any(|s| matches!(s.r#type, shuttle_common::resource::Type::Database(_)))
{
return Err(Error::from_kind(ErrorKind::ProjectHasDatabase));
.filter(|resource| {
matches!(
resource.r#type,
shuttle_common::resource::Type::Database(_)
| shuttle_common::resource::Type::Secrets
)
})
.map(|resource| resource.r#type.to_string())
.collect::<HashSet<_>>()
.into_iter()
.collect::<Vec<_>>();

if !resources.is_empty() {
return Err(Error::from_kind(ErrorKind::ProjectHasResources(resources)));
}
}

Expand Down

0 comments on commit d597007

Please sign in to comment.