From 3492eb312638be0b106de5af07d3ced466511e3f Mon Sep 17 00:00:00 2001 From: mbecker20 Date: Wed, 27 Mar 2024 05:54:15 -0700 Subject: [PATCH] validate --- bin/core/src/api/execute/build.rs | 4 +- bin/core/src/api/read/builder.rs | 4 +- bin/core/src/api/write/builder.rs | 34 +++++++- bin/core/src/api/write/deployment.rs | 111 ++++++++++++------------- bin/core/src/api/write/repo.rs | 49 ++++++----- bin/core/src/helpers/resource.rs | 2 +- client/core/rs/src/entities/builder.rs | 6 +- 7 files changed, 120 insertions(+), 90 deletions(-) diff --git a/bin/core/src/api/execute/build.rs b/bin/core/src/api/execute/build.rs index f05f1b367..31ce5d60b 100644 --- a/bin/core/src/api/execute/build.rs +++ b/bin/core/src/api/execute/build.rs @@ -298,10 +298,10 @@ async fn get_build_builder( Builder::get_resource(&build.config.builder_id).await?; match builder.config { BuilderConfig::Server(config) => { - if config.id.is_empty() { + if config.server_id.is_empty() { return Err(anyhow!("build has not configured a builder")); } - let server = Server::get_resource(&config.id).await?; + let server = Server::get_resource(&config.server_id).await?; let periphery = periphery_client(&server)?; Ok(( periphery, diff --git a/bin/core/src/api/read/builder.rs b/bin/core/src/api/read/builder.rs index 0c1d90e18..c7e08fcdd 100644 --- a/bin/core/src/api/read/builder.rs +++ b/bin/core/src/api/read/builder.rs @@ -111,7 +111,9 @@ impl Resolve for State { BuilderConfig::Server(config) => { let res = self .resolve( - read::GetAvailableAccounts { server: config.id }, + read::GetAvailableAccounts { + server: config.server_id, + }, user, ) .await?; diff --git a/bin/core/src/api/write/builder.rs b/bin/core/src/api/write/builder.rs index e2a568c71..30f1a9e60 100644 --- a/bin/core/src/api/write/builder.rs +++ b/bin/core/src/api/write/builder.rs @@ -5,9 +5,12 @@ use async_trait::async_trait; use monitor_client::{ api::write::*, entities::{ - builder::Builder, + builder::{ + Builder, PartialBuilderConfig, PartialServerBuilderConfig, + }, monitor_timestamp, permission::PermissionLevel, + server::Server, update::{Log, ResourceTarget, Update}, user::User, Operation, @@ -29,17 +32,40 @@ use crate::{ state::State, }; +async fn validate_config( + config: &mut PartialBuilderConfig, + user: &User, +) -> anyhow::Result<()> { + match config { + PartialBuilderConfig::Server(PartialServerBuilderConfig { + server_id: Some(server_id), + }) if !server_id.is_empty() => { + let server = Server::get_resource_check_permissions( + server_id, + user, + PermissionLevel::Write, + ) + .await?; + *server_id = server.id; + } + _ => {} + } + Ok(()) +} + #[async_trait] impl Resolve for State { async fn resolve( &self, - CreateBuilder { name, config }: CreateBuilder, + CreateBuilder { name, mut config }: CreateBuilder, user: User, ) -> anyhow::Result { let start_ts = monitor_timestamp(); if ObjectId::from_str(&name).is_ok() { return Err(anyhow!("valid ObjectIds cannot be used as names")); } + validate_config(&mut config, &user).await?; + let builder = Builder { id: Default::default(), name, @@ -205,7 +231,7 @@ impl Resolve for State { impl Resolve for State { async fn resolve( &self, - UpdateBuilder { id, config }: UpdateBuilder, + UpdateBuilder { id, mut config }: UpdateBuilder, user: User, ) -> anyhow::Result { let builder = Builder::get_resource_check_permissions( @@ -215,6 +241,8 @@ impl Resolve for State { ) .await?; + validate_config(&mut config, &user).await?; + let mut update = Update { target: ResourceTarget::Builder(id.clone()), operation: Operation::UpdateBuilder, diff --git a/bin/core/src/api/write/deployment.rs b/bin/core/src/api/write/deployment.rs index 67d5ce5cc..fce089c38 100644 --- a/bin/core/src/api/write/deployment.rs +++ b/bin/core/src/api/write/deployment.rs @@ -7,7 +7,10 @@ use monitor_client::{ entities::{ all_logs_success, build::Build, - deployment::{Deployment, DeploymentImage, DockerContainerState}, + deployment::{ + Deployment, DeploymentImage, DockerContainerState, + PartialDeploymentConfig, + }, monitor_timestamp, permission::PermissionLevel, server::Server, @@ -36,6 +39,55 @@ use crate::{ state::{action_states, State}, }; +async fn validate_config( + config: &mut PartialDeploymentConfig, + user: &User, +) -> anyhow::Result<()> { + if let Some(server_id) = &config.server_id { + if !server_id.is_empty() { + let server = Server::get_resource_check_permissions(server_id, user, PermissionLevel::Write) + .await + .context("cannot create deployment on this server. user must have update permissions on the server to perform this action.")?; + config.server_id = Some(server.id); + } + } + if let Some(DeploymentImage::Build { build_id, version }) = + &config.image + { + if !build_id.is_empty() { + let build = Build::get_resource_check_permissions(build_id, user, PermissionLevel::Read) + .await + .context("cannot create deployment with this build attached. user must have at least read permissions on the build to perform this action.")?; + config.image = Some(DeploymentImage::Build { + build_id: build.id, + version: version.clone(), + }); + } + } + if let Some(volumes) = &mut config.volumes { + volumes.retain(|v| { + !empty_or_only_spaces(&v.local) + && !empty_or_only_spaces(&v.container) + }) + } + if let Some(ports) = &mut config.ports { + ports.retain(|v| { + !empty_or_only_spaces(&v.local) + && !empty_or_only_spaces(&v.container) + }) + } + if let Some(environment) = &mut config.environment { + environment.retain(|v| { + !empty_or_only_spaces(&v.variable) + && !empty_or_only_spaces(&v.value) + }) + } + if let Some(extra_args) = &mut config.extra_args { + extra_args.retain(|v| !empty_or_only_spaces(v)) + } + Ok(()) +} + #[async_trait] impl Resolve for State { async fn resolve( @@ -47,27 +99,7 @@ impl Resolve for State { if ObjectId::from_str(&name).is_ok() { return Err(anyhow!("valid ObjectIds cannot be used as names")); } - if let Some(server_id) = &config.server_id { - if !server_id.is_empty() { - let server = Server::get_resource_check_permissions(server_id, &user, PermissionLevel::Write) - .await - .context("cannot create deployment on this server. user must have update permissions on the server to perform this action.")?; - config.server_id = Some(server.id); - } - } - if let Some(DeploymentImage::Build { build_id, version }) = - &config.image - { - if !build_id.is_empty() { - let build = Build::get_resource_check_permissions(build_id, &user, PermissionLevel::Read) - .await - .context("cannot create deployment with this build attached. user must have at least read permissions on the build to perform this action.")?; - config.image = Some(DeploymentImage::Build { - build_id: build.id, - version: version.clone(), - }); - } - } + validate_config(&mut config, &user).await?; let start_ts = monitor_timestamp(); let deployment = Deployment { id: Default::default(), @@ -333,40 +365,7 @@ impl Resolve for State { let inner = || async move { let start_ts = monitor_timestamp(); - if let Some(server_id) = &config.server_id { - Server::get_resource_check_permissions(server_id, &user, PermissionLevel::Write) - .await - .context("cannot create deployment on this server. user must have update permissions on the server to perform this action.")?; - } - if let Some(DeploymentImage::Build { build_id, .. }) = - &config.image - { - Build::get_resource_check_permissions(build_id, &user, PermissionLevel::Read) - .await - .context("cannot create deployment with this build attached. user must have at least read permissions on the build to perform this action.")?; - } - - if let Some(volumes) = &mut config.volumes { - volumes.retain(|v| { - !empty_or_only_spaces(&v.local) - && !empty_or_only_spaces(&v.container) - }) - } - if let Some(ports) = &mut config.ports { - ports.retain(|v| { - !empty_or_only_spaces(&v.local) - && !empty_or_only_spaces(&v.container) - }) - } - if let Some(environment) = &mut config.environment { - environment.retain(|v| { - !empty_or_only_spaces(&v.variable) - && !empty_or_only_spaces(&v.value) - }) - } - if let Some(extra_args) = &mut config.extra_args { - extra_args.retain(|v| !empty_or_only_spaces(v)) - } + validate_config(&mut config, &user).await?; update_one_by_id( &db_client().await.deployments, diff --git a/bin/core/src/api/write/repo.rs b/bin/core/src/api/write/repo.rs index 24c3eca0d..e033c835a 100644 --- a/bin/core/src/api/write/repo.rs +++ b/bin/core/src/api/write/repo.rs @@ -7,7 +7,7 @@ use monitor_client::{ entities::{ monitor_timestamp, permission::PermissionLevel, - repo::Repo, + repo::{PartialRepoConfig, Repo}, server::Server, to_monitor_name, update::{Log, ResourceTarget, Update}, @@ -33,6 +33,26 @@ use crate::{ state::{action_states, State}, }; +async fn validate_config( + config: &mut PartialRepoConfig, + user: &User, +) -> anyhow::Result<()> { + match &config.server_id { + Some(server_id) if !server_id.is_empty() => { + let server = Server::get_resource_check_permissions( + server_id, + &user, + PermissionLevel::Write, + ) + .await + .context("cannot create repo on this server. user must have update permissions on the server.")?; + config.server_id = Some(server.id); + } + _ => {} + } + Ok(()) +} + #[async_trait] impl Resolve for State { async fn resolve( @@ -44,18 +64,7 @@ impl Resolve for State { if ObjectId::from_str(&name).is_ok() { return Err(anyhow!("valid ObjectIds cannot be used as names")); } - if let Some(server_id) = &config.server_id { - if !server_id.is_empty() { - let server = Server::get_resource_check_permissions( - server_id, - &user, - PermissionLevel::Write, - ) - .await - .context("cannot create repo on this server. user must have update permissions on the server.")?; - config.server_id = Some(server.id); - } - } + validate_config(&mut config, &user).await?; let start_ts = monitor_timestamp(); let repo = Repo { id: Default::default(), @@ -283,20 +292,10 @@ impl Resolve for State { impl Resolve for State { async fn resolve( &self, - UpdateRepo { id, config }: UpdateRepo, + UpdateRepo { id, mut config }: UpdateRepo, user: User, ) -> anyhow::Result { - if let Some(server_id) = &config.server_id { - if !server_id.is_empty() { - Server::get_resource_check_permissions( - server_id, - &user, - PermissionLevel::Write, - ) - .await - .context("cannot move repo to this server. user must have update permissions on the server.")?; - } - } + validate_config(&mut config, &user).await?; let repo = Repo::get_resource_check_permissions( &id, diff --git a/bin/core/src/helpers/resource.rs b/bin/core/src/helpers/resource.rs index 9b27a48c2..b5a665658 100644 --- a/bin/core/src/helpers/resource.rs +++ b/bin/core/src/helpers/resource.rs @@ -419,7 +419,7 @@ impl StateResource for Builder { ) -> anyhow::Result { let (provider, instance_type) = match builder.config { BuilderConfig::Server(config) => { - ("server".to_string(), Some(config.id)) + ("server".to_string(), Some(config.server_id)) } BuilderConfig::Aws(config) => { ("aws ec2".to_string(), Some(config.instance_type)) diff --git a/client/core/rs/src/entities/builder.rs b/client/core/rs/src/entities/builder.rs index 9adbee870..78d67b7d9 100644 --- a/client/core/rs/src/entities/builder.rs +++ b/client/core/rs/src/entities/builder.rs @@ -87,7 +87,7 @@ impl BuilderConfig { PartialBuilderConfig::Server(partial) => match self { BuilderConfig::Server(config) => { let config = ServerBuilderConfig { - id: partial.id.unwrap_or(config.id), + server_id: partial.server_id.unwrap_or(config.server_id), }; BuilderConfig::Server(config) } @@ -137,7 +137,9 @@ impl BuilderConfig { #[skip_serializing_none] #[partial_from] pub struct ServerBuilderConfig { - pub id: String, + #[serde(alias = "server")] + #[partial_attr(serde(alias = "server"))] + pub server_id: String, } #[typeshare]