mirror of
https://github.com/moghtech/komodo.git
synced 2026-09-07 08:00:54 +00:00
validate attached resources by name / id
This commit is contained in:
Generated
+4
-4
@@ -2399,18 +2399,18 @@ checksum = "ffa94c2e5674923c67d7f3dfce1279507b191e10eb064881b46ed3e1256e5ca6"
|
||||
|
||||
[[package]]
|
||||
name = "partial_derive2"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4eac44820a8c7e50b7ba6926c388adc05b9a1f41b22a9b18e273fb39d4f892f2"
|
||||
checksum = "2eecafa276875fa10fbbcbcc2c93d08e9e302627600afe99a2b000dfa68e478d"
|
||||
dependencies = [
|
||||
"partial_derive2_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "partial_derive2_derive"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad412582e4972654640acf910d4c85e2ba14a547fbcec5b8ddb944d82adec1e1"
|
||||
checksum = "5a543253c8df8d6377ba82d06c5de2d96bf336ade75588ca537d3de083ce2b5c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ derive_empty_traits = "0.1.0"
|
||||
merge_config_files = "0.1.3"
|
||||
termination_signal = "0.1.3"
|
||||
async_timing_util = "0.1.14"
|
||||
partial_derive2 = "0.2.1"
|
||||
partial_derive2 = "0.2.2"
|
||||
derive_variants = "0.1.3"
|
||||
resolver_api = "0.1.6"
|
||||
parse_csl = "0.1.0"
|
||||
|
||||
@@ -107,7 +107,7 @@ impl Resolve<RunBuild, User> for State {
|
||||
});
|
||||
|
||||
let build_id = build.id.clone();
|
||||
|
||||
|
||||
let inner = || async move {
|
||||
update.id = add_update(update.clone()).await?;
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ use crate::{
|
||||
impl Resolve<CreateBuild, User> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
CreateBuild { name, config }: CreateBuild,
|
||||
CreateBuild { name, mut config }: CreateBuild,
|
||||
user: User,
|
||||
) -> anyhow::Result<Build> {
|
||||
let name = to_monitor_name(&name);
|
||||
@@ -44,9 +44,10 @@ impl Resolve<CreateBuild, User> for State {
|
||||
return Err(anyhow!("valid ObjectIds cannot be used as names"));
|
||||
}
|
||||
if let Some(builder_id) = &config.builder_id {
|
||||
Builder::get_resource_check_permissions(builder_id, &user, PermissionLevel::Read)
|
||||
let builder = Builder::get_resource_check_permissions(builder_id, &user, PermissionLevel::Read)
|
||||
.await
|
||||
.context("cannot create build using this builder. user must have at least read permissions on the builder.")?;
|
||||
config.builder_id = Some(builder.id)
|
||||
}
|
||||
let start_ts = monitor_timestamp();
|
||||
let build = Build {
|
||||
@@ -112,7 +113,9 @@ impl Resolve<CopyBuild, User> for State {
|
||||
PermissionLevel::Write,
|
||||
)
|
||||
.await?;
|
||||
Builder::get_resource_check_permissions(&config.builder_id, &user, PermissionLevel::Read).await.context("cannot create build using this builder. user must have at least read permissions on the builder.")?;
|
||||
Builder::get_resource_check_permissions(&config.builder_id, &user, PermissionLevel::Read)
|
||||
.await
|
||||
.context("cannot create build using this builder. user must have at least read permissions on the builder.")?;
|
||||
let start_ts = monitor_timestamp();
|
||||
let build = Build {
|
||||
id: Default::default(),
|
||||
@@ -233,7 +236,10 @@ impl Resolve<UpdateBuild, User> for State {
|
||||
|
||||
let inner = || async move {
|
||||
if let Some(builder_id) = &config.builder_id {
|
||||
Builder::get_resource_check_permissions(builder_id, &user, PermissionLevel::Read).await.context("cannot create build using this builder. user must have at least read permissions on the builder.")?;
|
||||
let builder = Builder::get_resource_check_permissions(builder_id, &user, PermissionLevel::Read)
|
||||
.await
|
||||
.context("cannot create build using this builder. user must have at least read permissions on the builder.")?;
|
||||
config.builder_id = Some(builder.id)
|
||||
}
|
||||
|
||||
if let Some(build_args) = &mut config.build_args {
|
||||
|
||||
@@ -40,7 +40,7 @@ use crate::{
|
||||
impl Resolve<CreateDeployment, User> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
CreateDeployment { name, config }: CreateDeployment,
|
||||
CreateDeployment { name, mut config }: CreateDeployment,
|
||||
user: User,
|
||||
) -> anyhow::Result<Deployment> {
|
||||
let name = to_monitor_name(&name);
|
||||
@@ -49,18 +49,23 @@ impl Resolve<CreateDeployment, User> for State {
|
||||
}
|
||||
if let Some(server_id) = &config.server_id {
|
||||
if !server_id.is_empty() {
|
||||
Server::get_resource_check_permissions(server_id, &user, PermissionLevel::Write)
|
||||
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, .. }) =
|
||||
if let Some(DeploymentImage::Build { build_id, version }) =
|
||||
&config.image
|
||||
{
|
||||
if !build_id.is_empty() {
|
||||
Build::get_resource_check_permissions(build_id, &user, PermissionLevel::Read)
|
||||
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(),
|
||||
});
|
||||
}
|
||||
}
|
||||
let start_ts = monitor_timestamp();
|
||||
|
||||
@@ -3,10 +3,17 @@ use std::str::FromStr;
|
||||
use anyhow::{anyhow, Context};
|
||||
use async_trait::async_trait;
|
||||
use monitor_client::{
|
||||
api::write::*,
|
||||
api::{execute::Execution, write::*},
|
||||
entities::{
|
||||
monitor_timestamp, permission::PermissionLevel,
|
||||
procedure::Procedure, to_monitor_name, update::Log, user::User,
|
||||
build::Build,
|
||||
deployment::Deployment,
|
||||
monitor_timestamp,
|
||||
permission::PermissionLevel,
|
||||
procedure::{Procedure, ProcedureConfig},
|
||||
repo::Repo,
|
||||
server::Server,
|
||||
update::Log,
|
||||
user::User,
|
||||
Operation,
|
||||
},
|
||||
};
|
||||
@@ -31,13 +38,17 @@ use crate::{
|
||||
impl Resolve<CreateProcedure, User> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
CreateProcedure { name, config }: CreateProcedure,
|
||||
CreateProcedure { name, mut config }: CreateProcedure,
|
||||
user: User,
|
||||
) -> anyhow::Result<CreateProcedureResponse> {
|
||||
if ObjectId::from_str(&name).is_ok() {
|
||||
return Err(anyhow!("valid ObjectIds cannot be used as names"));
|
||||
}
|
||||
|
||||
let start_ts = monitor_timestamp();
|
||||
|
||||
validate_procedure_config(&mut config, &user).await?;
|
||||
|
||||
let procedure = Procedure {
|
||||
id: Default::default(),
|
||||
name,
|
||||
@@ -84,6 +95,130 @@ impl Resolve<CreateProcedure, User> for State {
|
||||
}
|
||||
}
|
||||
|
||||
async fn validate_procedure_config(
|
||||
config: &mut ProcedureConfig,
|
||||
user: &User,
|
||||
) -> anyhow::Result<()> {
|
||||
let execs = match config {
|
||||
ProcedureConfig::Sequence(execs) => execs,
|
||||
ProcedureConfig::Parallel(execs) => execs,
|
||||
};
|
||||
for exec in execs {
|
||||
match &mut exec.execution {
|
||||
Execution::None(_) => {}
|
||||
Execution::RunProcedure(data) => {
|
||||
let procedure = Procedure::get_resource_check_permissions(
|
||||
&data.procedure,
|
||||
user,
|
||||
PermissionLevel::Execute,
|
||||
)
|
||||
.await?;
|
||||
data.procedure = procedure.id;
|
||||
}
|
||||
Execution::RunBuild(data) => {
|
||||
let build = Build::get_resource_check_permissions(
|
||||
&data.build,
|
||||
user,
|
||||
PermissionLevel::Execute,
|
||||
)
|
||||
.await?;
|
||||
data.build = build.id;
|
||||
}
|
||||
Execution::Deploy(data) => {
|
||||
let deployment = Deployment::get_resource_check_permissions(
|
||||
&data.deployment,
|
||||
user,
|
||||
PermissionLevel::Execute,
|
||||
)
|
||||
.await?;
|
||||
data.deployment = deployment.id;
|
||||
}
|
||||
Execution::StartContainer(data) => {
|
||||
let deployment = Deployment::get_resource_check_permissions(
|
||||
&data.deployment,
|
||||
user,
|
||||
PermissionLevel::Execute,
|
||||
)
|
||||
.await?;
|
||||
data.deployment = deployment.id;
|
||||
}
|
||||
Execution::StopContainer(data) => {
|
||||
let deployment = Deployment::get_resource_check_permissions(
|
||||
&data.deployment,
|
||||
user,
|
||||
PermissionLevel::Execute,
|
||||
)
|
||||
.await?;
|
||||
data.deployment = deployment.id;
|
||||
}
|
||||
Execution::StopAllContainers(data) => {
|
||||
let server = Server::get_resource_check_permissions(
|
||||
&data.server,
|
||||
user,
|
||||
PermissionLevel::Execute,
|
||||
)
|
||||
.await?;
|
||||
data.server = server.id;
|
||||
}
|
||||
Execution::RemoveContainer(data) => {
|
||||
let deployment = Deployment::get_resource_check_permissions(
|
||||
&data.deployment,
|
||||
user,
|
||||
PermissionLevel::Execute,
|
||||
)
|
||||
.await?;
|
||||
data.deployment = deployment.id;
|
||||
}
|
||||
Execution::CloneRepo(data) => {
|
||||
let repo = Repo::get_resource_check_permissions(
|
||||
&data.repo,
|
||||
user,
|
||||
PermissionLevel::Execute,
|
||||
)
|
||||
.await?;
|
||||
data.repo = repo.id;
|
||||
}
|
||||
Execution::PullRepo(data) => {
|
||||
let repo = Repo::get_resource_check_permissions(
|
||||
&data.repo,
|
||||
user,
|
||||
PermissionLevel::Execute,
|
||||
)
|
||||
.await?;
|
||||
data.repo = repo.id;
|
||||
}
|
||||
Execution::PruneDockerNetworks(data) => {
|
||||
let server = Server::get_resource_check_permissions(
|
||||
&data.server,
|
||||
user,
|
||||
PermissionLevel::Execute,
|
||||
)
|
||||
.await?;
|
||||
data.server = server.id;
|
||||
}
|
||||
Execution::PruneDockerImages(data) => {
|
||||
let server = Server::get_resource_check_permissions(
|
||||
&data.server,
|
||||
user,
|
||||
PermissionLevel::Execute,
|
||||
)
|
||||
.await?;
|
||||
data.server = server.id;
|
||||
}
|
||||
Execution::PruneDockerContainers(data) => {
|
||||
let server = Server::get_resource_check_permissions(
|
||||
&data.server,
|
||||
user,
|
||||
PermissionLevel::Execute,
|
||||
)
|
||||
.await?;
|
||||
data.server = server.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<CopyProcedure, User> for State {
|
||||
async fn resolve(
|
||||
@@ -91,7 +226,6 @@ impl Resolve<CopyProcedure, User> for State {
|
||||
CopyProcedure { name, id }: CopyProcedure,
|
||||
user: User,
|
||||
) -> anyhow::Result<CopyProcedureResponse> {
|
||||
let name = to_monitor_name(&name);
|
||||
let Procedure {
|
||||
config,
|
||||
description,
|
||||
|
||||
@@ -37,7 +37,7 @@ use crate::{
|
||||
impl Resolve<CreateRepo, User> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
CreateRepo { name, config }: CreateRepo,
|
||||
CreateRepo { name, mut config }: CreateRepo,
|
||||
user: User,
|
||||
) -> anyhow::Result<Repo> {
|
||||
let name = to_monitor_name(&name);
|
||||
@@ -46,13 +46,14 @@ impl Resolve<CreateRepo, User> for State {
|
||||
}
|
||||
if let Some(server_id) = &config.server_id {
|
||||
if !server_id.is_empty() {
|
||||
Server::get_resource_check_permissions(
|
||||
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);
|
||||
}
|
||||
}
|
||||
let start_ts = monitor_timestamp();
|
||||
|
||||
@@ -37,7 +37,7 @@ const STATE_PREFIX_LENGTH: usize = 20;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct RedirectQuery {
|
||||
pub redirect: Option<String>,
|
||||
pub redirect: Option<String>,
|
||||
}
|
||||
|
||||
pub async fn auth_request(
|
||||
|
||||
@@ -4,9 +4,11 @@ use monitor_client::entities::update::{Update, UpdateListItem};
|
||||
use tokio::sync::{broadcast, Mutex};
|
||||
|
||||
/// A channel sending (build_id, update_id)
|
||||
pub fn build_cancel_channel() -> &'static BroadcastChannel<(String, Update)> {
|
||||
static BUILD_CANCEL_CHANNEL: OnceLock<BroadcastChannel<(String, Update)>> =
|
||||
OnceLock::new();
|
||||
pub fn build_cancel_channel(
|
||||
) -> &'static BroadcastChannel<(String, Update)> {
|
||||
static BUILD_CANCEL_CHANNEL: OnceLock<
|
||||
BroadcastChannel<(String, Update)>,
|
||||
> = OnceLock::new();
|
||||
BUILD_CANCEL_CHANNEL.get_or_init(|| BroadcastChannel::new(100))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,59 +1,38 @@
|
||||
[[procedure]]
|
||||
name = "redeploy-v1"
|
||||
description = "builds v1 core / frontend, and redeploys them"
|
||||
name = "build-deploy-monitor-v1"
|
||||
description = "builds v1 core / frontend, then redeploys them"
|
||||
config.type = "Sequence"
|
||||
|
||||
[[procedure.config.data]]
|
||||
id = ""
|
||||
enabled = true
|
||||
|
||||
|
||||
# Deploys
|
||||
execution.type = "RunProcedure"
|
||||
execution.params.procedure = "build-monitor-v1"
|
||||
[[procedure.config.data]]
|
||||
enabled = true
|
||||
execution.type = "RunProcedure"
|
||||
execution.params.procedure = "deploy-monitor-v1"
|
||||
|
||||
[[procedure]]
|
||||
name = "deploy-v1"
|
||||
name = "deploy-monitor-v1"
|
||||
description = "deploys v1 core / frontend"
|
||||
config.type = "Parallel"
|
||||
[[procedure.config.data]]
|
||||
id = "deploy-v1-core"
|
||||
enabled = true
|
||||
execution.type = "Deploy"
|
||||
execution.params.deployment = "monitor-core-v1"
|
||||
[[procedure.config.data]]
|
||||
id = "deploy-v1-frontend"
|
||||
enabled = true
|
||||
execution.type = "Deploy"
|
||||
execution.params.deployment = "monitor-frontend-v1"
|
||||
|
||||
[[procedure]]
|
||||
name = "deploy-v1-core"
|
||||
config.type = "Execution"
|
||||
config.data.type = "Deploy"
|
||||
config.data.params.deployment = "monitor-core-v1"
|
||||
|
||||
[[procedure]]
|
||||
name = "deploy-v1-frontend"
|
||||
config.type = "Execution"
|
||||
config.data.type = "Deploy"
|
||||
config.data.params.deployment = "monitor-frontend-v1"
|
||||
|
||||
# Builds
|
||||
|
||||
[[procedure]]
|
||||
name = "build-v1"
|
||||
name = "build-monitor-v1"
|
||||
description = "builds v1 core / frontend"
|
||||
config.type = "Parallel"
|
||||
[[procedure.config.data]]
|
||||
id = "build-v1-core"
|
||||
enabled = true
|
||||
execution.type = "RunBuild"
|
||||
execution.params.build = "monitor-core-v1"
|
||||
[[procedure.config.data]]
|
||||
id = "build-v1-frontend"
|
||||
enabled = true
|
||||
|
||||
[[procedure]]
|
||||
name = "build-v1-core"
|
||||
config.type = "Execution"
|
||||
config.data.type = "RunBuild"
|
||||
config.data.params.build = "monitor-core-v1"
|
||||
|
||||
[[procedure]]
|
||||
name = "build-v1-frontend"
|
||||
config.type = "Execution"
|
||||
config.data.type = "RunBuild"
|
||||
config.data.params.build = "monitor-frontend-v1"
|
||||
execution.type = "RunBuild"
|
||||
execution.params.build = "monitor-frontend-v1"
|
||||
|
||||
@@ -28,6 +28,8 @@ pub async fn run_sync(path: &Path) -> anyhow::Result<()> {
|
||||
|
||||
let resources = resource_file::read_resources(path)?;
|
||||
|
||||
println!("{resources:#?}");
|
||||
|
||||
let (server_updates, server_creates) =
|
||||
Server::get_updates(resources.servers)?;
|
||||
let (deployment_updates, deployment_creates) =
|
||||
@@ -112,7 +114,8 @@ pub trait ResourceSync {
|
||||
|
||||
if !to_create.is_empty() {
|
||||
println!(
|
||||
"\nTO CREATE: {}",
|
||||
"\n{} TO CREATE: {}",
|
||||
Self::display(),
|
||||
to_create
|
||||
.iter()
|
||||
.map(|item| item.name.as_str())
|
||||
@@ -123,7 +126,8 @@ pub trait ResourceSync {
|
||||
|
||||
if !to_update.is_empty() {
|
||||
println!(
|
||||
"\nTO UPDATE: {}",
|
||||
"\n{} TO UPDATE: {}",
|
||||
Self::display(),
|
||||
to_update
|
||||
.iter()
|
||||
.map(|(_, item)| item.name.as_str())
|
||||
|
||||
@@ -62,6 +62,7 @@ fn read_resources_recursive(
|
||||
resources.builders.extend(more.builders);
|
||||
resources.repos.extend(more.repos);
|
||||
resources.alerters.extend(more.alerters);
|
||||
resources.procedures.extend(more.procedures);
|
||||
Ok(())
|
||||
} else if res.is_dir() {
|
||||
let directory = fs::read_dir(path)
|
||||
|
||||
@@ -41,6 +41,7 @@ pub type _PartialBuildConfig = PartialBuildConfig;
|
||||
#[partial_from]
|
||||
pub struct BuildConfig {
|
||||
#[serde(default, alias = "builder")]
|
||||
#[partial_attr(serde(alias = "builder"))]
|
||||
#[builder(default)]
|
||||
pub builder_id: String,
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ pub type _PartialDeploymentConfig = PartialDeploymentConfig;
|
||||
#[partial_from]
|
||||
pub struct DeploymentConfig {
|
||||
#[serde(default, alias = "server")]
|
||||
#[partial_attr(serde(alias = "server"))]
|
||||
#[builder(default)]
|
||||
pub server_id: String,
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ pub type _PartialRepoConfig = PartialRepoConfig;
|
||||
#[partial_from]
|
||||
pub struct RepoConfig {
|
||||
#[serde(default, alias = "server")]
|
||||
#[partial_attr(serde(alias = "server"))]
|
||||
#[builder(default)]
|
||||
pub server_id: String,
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ impl User {
|
||||
pub enum UserConfig {
|
||||
/// User that logs in with username / password
|
||||
Local { password: String },
|
||||
|
||||
|
||||
/// User that logs in via Google Oauth
|
||||
Google { google_id: String, avatar: String },
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ export const ServerSelector = ({
|
||||
);
|
||||
|
||||
export const DeploymentConfig = ({ id }: { id: string }) => {
|
||||
const config = useRead("GetDeployment", { id }).data?.config;
|
||||
const config = useRead("GetDeployment", { deployment: id }).data?.config;
|
||||
const [update, set] = useState<Partial<Types.DeploymentConfig>>({});
|
||||
const { mutate } = useWrite("UpdateDeployment");
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import { BuildComponents } from "@components/resources/build";
|
||||
import { RepoComponents } from "@components/resources/repo";
|
||||
import { BuilderComponents } from "@components/resources/builder";
|
||||
import { AlerterComponents } from "@components/resources/alerter";
|
||||
import { ProcedureComponents } from "@components/resources/procedure/index2";
|
||||
import { ProcedureComponents } from "@components/resources/procedure/index";
|
||||
import { TagsSummary } from "@components/dashboard/tags";
|
||||
import { ApiKeysSummary } from "@components/dashboard/api-keys";
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Page } from "@components/layouts";
|
||||
import { ConfirmButton, CopyButton } from "@components/util";
|
||||
import { useInvalidate, useRead, useWrite } from "@lib/hooks";
|
||||
import { fmt_date, fmt_date_with_minutes } from "@lib/utils";
|
||||
import { fmt_date } from "@lib/utils";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
|
||||
Reference in New Issue
Block a user