mirror of
https://github.com/moghtech/komodo.git
synced 2026-03-12 02:18:32 -05:00
delete deployment
This commit is contained in:
8
.vscode/tasks.json
vendored
8
.vscode/tasks.json
vendored
@@ -68,6 +68,14 @@
|
||||
"cwd": "${workspaceFolder}/cli"
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "cargo",
|
||||
"command": "publish",
|
||||
"label": "publish types",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/lib/types"
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"command": "docker build -t monitor_periphery -f Dockerfile.periphery .",
|
||||
|
||||
@@ -1,23 +1,40 @@
|
||||
use anyhow::Context;
|
||||
use anyhow::{anyhow, Context};
|
||||
use async_timing_util::unix_timestamp_ms;
|
||||
use axum::{routing::post, Extension, Json, Router};
|
||||
use db::DbExtension;
|
||||
use helpers::handle_anyhow_error;
|
||||
use types::{Deployment, Operation, PermissionLevel, Update, UpdateTarget};
|
||||
use mungos::Deserialize;
|
||||
use types::{
|
||||
traits::Permissioned, Deployment, Log, Operation, PermissionLevel, Update, UpdateTarget,
|
||||
};
|
||||
|
||||
use crate::{auth::RequestUserExtension, ws::update};
|
||||
|
||||
use super::add_update;
|
||||
use super::{add_update, PeripheryExtension};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct DeploymentIdBody {
|
||||
id: String,
|
||||
}
|
||||
|
||||
pub fn router() -> Router {
|
||||
Router::new().route(
|
||||
"/create",
|
||||
post(|db, user, update_ws, deployment| async {
|
||||
create(db, user, update_ws, deployment)
|
||||
.await
|
||||
.map_err(handle_anyhow_error)
|
||||
}),
|
||||
)
|
||||
Router::new()
|
||||
.route(
|
||||
"/create",
|
||||
post(|db, user, update_ws, deployment| async {
|
||||
create(db, user, update_ws, deployment)
|
||||
.await
|
||||
.map_err(handle_anyhow_error)
|
||||
}),
|
||||
)
|
||||
.route(
|
||||
"/delete",
|
||||
post(|db, user, update_ws, periphery, deployment_id| async {
|
||||
delete(db, user, update_ws, periphery, deployment_id)
|
||||
.await
|
||||
.map_err(handle_anyhow_error)
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
async fn create(
|
||||
@@ -45,3 +62,41 @@ async fn create(
|
||||
};
|
||||
add_update(update, &db, &update_ws).await
|
||||
}
|
||||
|
||||
async fn delete(
|
||||
Extension(db): DbExtension,
|
||||
Extension(user): RequestUserExtension,
|
||||
Extension(update_ws): update::UpdateWsSenderExtension,
|
||||
Extension(periphery): PeripheryExtension,
|
||||
Json(DeploymentIdBody { id }): Json<DeploymentIdBody>,
|
||||
) -> anyhow::Result<()> {
|
||||
let deployment = db.get_deployment(&id).await?;
|
||||
let permissions = deployment.get_user_permissions(&user.id);
|
||||
if permissions != PermissionLevel::Write {
|
||||
return Err(anyhow!(
|
||||
"user does not have permissions to delete deployment {id}"
|
||||
));
|
||||
}
|
||||
let server = db.get_server(&deployment.server_id).await?;
|
||||
let start_ts = unix_timestamp_ms() as i64;
|
||||
let log = periphery
|
||||
.container_remove(&server, &deployment.name)
|
||||
.await?;
|
||||
db.deployments.delete_one(&id).await?;
|
||||
let update = Update {
|
||||
target: UpdateTarget::System,
|
||||
operation: Operation::DeleteDeployment,
|
||||
start_ts,
|
||||
end_ts: Some(unix_timestamp_ms() as i64),
|
||||
operator: user.id.clone(),
|
||||
log: vec![
|
||||
log,
|
||||
Log::simple(format!(
|
||||
"deleted deployment {} on server {}",
|
||||
deployment.name, server.name
|
||||
)),
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
add_update(update, &db, &update_ws).await
|
||||
}
|
||||
|
||||
@@ -8,9 +8,11 @@ use axum::{
|
||||
use db::DbExtension;
|
||||
use helpers::handle_anyhow_error;
|
||||
use mungos::Deserialize;
|
||||
use types::{Operation, PermissionLevel, Server, SystemStats, Update, UpdateTarget};
|
||||
use types::{
|
||||
traits::Permissioned, Operation, PermissionLevel, Server, SystemStats, Update, UpdateTarget,
|
||||
};
|
||||
|
||||
use crate::{auth::RequestUserExtension, helpers::get_user_permissions, ws::update};
|
||||
use crate::{auth::RequestUserExtension, ws::update};
|
||||
|
||||
use super::{add_update, PeripheryExtension};
|
||||
|
||||
@@ -107,7 +109,7 @@ async fn stats(
|
||||
.await
|
||||
.context("failed at query to get server")?
|
||||
.ok_or(anyhow!("failed to find server with id {server_id}"))?;
|
||||
let permissions = get_user_permissions(&user.id, &server.permissions);
|
||||
let permissions = server.get_user_permissions(&user.id);
|
||||
if permissions == PermissionLevel::None {
|
||||
return Err(anyhow!("user does not have permissions on this server"));
|
||||
}
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
use types::{PermissionLevel, PermissionsMap};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! response {
|
||||
($x:expr) => {
|
||||
Ok::<_, (axum::http::StatusCode, String)>($x)
|
||||
};
|
||||
}
|
||||
|
||||
pub fn get_user_permissions(user_id: &str, permissions: &PermissionsMap) -> PermissionLevel {
|
||||
*permissions.get(user_id).unwrap_or(&PermissionLevel::None)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::{anyhow, Context};
|
||||
use anyhow::anyhow;
|
||||
use axum::{
|
||||
extract::{
|
||||
ws::{Message, WebSocket},
|
||||
@@ -23,10 +23,7 @@ use tokio::{
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use types::{PermissionLevel, Update, UpdateTarget, User};
|
||||
|
||||
use crate::{
|
||||
auth::{JwtClient, JwtExtension},
|
||||
helpers::get_user_permissions,
|
||||
};
|
||||
use crate::auth::{JwtClient, JwtExtension};
|
||||
|
||||
pub type UpdateWsSender = Arc<Mutex<Sender<Update>>>;
|
||||
pub type UpdateWsSenderExtension = Extension<UpdateWsSender>;
|
||||
@@ -192,54 +189,32 @@ async fn user_can_see_update(
|
||||
if user.admin {
|
||||
return Ok(());
|
||||
}
|
||||
match update_target {
|
||||
UpdateTarget::System => {
|
||||
if user.admin {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(anyhow!("user not admin, can't recieve system updates"))
|
||||
}
|
||||
}
|
||||
let (permissions, target) = match update_target {
|
||||
UpdateTarget::Server(server_id) => {
|
||||
let server = db_client
|
||||
.servers
|
||||
.find_one_by_id(server_id)
|
||||
.await
|
||||
.context(format!("failed at query to get server at {server_id}"))?
|
||||
.ok_or(anyhow!("did not server with id {server_id}"))?;
|
||||
if get_user_permissions(user_id, &server.permissions) != PermissionLevel::None {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(anyhow!("user does not have permissions on server"))
|
||||
}
|
||||
let permissions = db_client
|
||||
.get_user_permission_on_server(user_id, server_id)
|
||||
.await?;
|
||||
(permissions, "server")
|
||||
}
|
||||
UpdateTarget::Deployment(deployment_id) => {
|
||||
let deployment = db_client
|
||||
.deployments
|
||||
.find_one_by_id(deployment_id)
|
||||
.await
|
||||
.context(format!(
|
||||
"failed at query to get deployment at {deployment_id}"
|
||||
))?
|
||||
.ok_or(anyhow!("did not deployment with id {deployment_id}"))?;
|
||||
if get_user_permissions(user_id, &deployment.permissions) != PermissionLevel::None {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(anyhow!("user does not have permissions on deployment"))
|
||||
}
|
||||
let permissions = db_client
|
||||
.get_user_permission_on_deployment(user_id, deployment_id)
|
||||
.await?;
|
||||
(permissions, "deployment")
|
||||
}
|
||||
UpdateTarget::Build(build_id) => {
|
||||
let build = db_client
|
||||
.builds
|
||||
.find_one_by_id(build_id)
|
||||
.await
|
||||
.context(format!("failed at query to get build at {build_id}"))?
|
||||
.ok_or(anyhow!("did not build with id {build_id}"))?;
|
||||
if get_user_permissions(user_id, &build.permissions) != PermissionLevel::None {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(anyhow!("user does not have permissions on build"))
|
||||
}
|
||||
let permissions = db_client
|
||||
.get_user_permission_on_build(user_id, build_id)
|
||||
.await?;
|
||||
(permissions, "build")
|
||||
}
|
||||
UpdateTarget::System => {
|
||||
return Err(anyhow!("user not admin, can't recieve system updates"))
|
||||
}
|
||||
};
|
||||
if permissions != PermissionLevel::None {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(anyhow!("user does not have permissions on {target}"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
use std::{sync::Arc, time::Duration};
|
||||
|
||||
use anyhow::{anyhow, Context};
|
||||
use axum::Extension;
|
||||
use collections::{
|
||||
builds_collection, deployments_collection, procedures_collection, servers_collection,
|
||||
updates_collection, users_collection,
|
||||
};
|
||||
use mungos::{Collection, Mungos};
|
||||
use types::{Build, Deployment, MongoConfig, Procedure, Server, Update, User};
|
||||
use types::{Build, Deployment, MongoConfig, PermissionLevel, Procedure, Server, Update, User};
|
||||
|
||||
mod collections;
|
||||
|
||||
@@ -49,4 +50,78 @@ impl DbClient {
|
||||
};
|
||||
Extension(Arc::new(client))
|
||||
}
|
||||
|
||||
pub async fn get_deployment(&self, deployment_id: &str) -> anyhow::Result<Deployment> {
|
||||
let deployment = self
|
||||
.deployments
|
||||
.find_one_by_id(deployment_id)
|
||||
.await
|
||||
.context(format!(
|
||||
"failed at mongo query for deployment {deployment_id}"
|
||||
))?
|
||||
.ok_or(anyhow!("deployment at {deployment_id} doesn't exist"))?;
|
||||
Ok(deployment)
|
||||
}
|
||||
|
||||
pub async fn get_user_permission_on_deployment(
|
||||
&self,
|
||||
user_id: &str,
|
||||
deployment_id: &str,
|
||||
) -> anyhow::Result<PermissionLevel> {
|
||||
let permissions = *self
|
||||
.get_deployment(deployment_id)
|
||||
.await?
|
||||
.permissions
|
||||
.get(user_id)
|
||||
.unwrap_or_default();
|
||||
Ok(permissions)
|
||||
}
|
||||
|
||||
pub async fn get_build(&self, build_id: &str) -> anyhow::Result<Build> {
|
||||
let build = self
|
||||
.builds
|
||||
.find_one_by_id(build_id)
|
||||
.await
|
||||
.context(format!("failed at mongo query for build {build_id}"))?
|
||||
.ok_or(anyhow!("build at {build_id} doesn't exist"))?;
|
||||
Ok(build)
|
||||
}
|
||||
|
||||
pub async fn get_user_permission_on_build(
|
||||
&self,
|
||||
user_id: &str,
|
||||
build_id: &str,
|
||||
) -> anyhow::Result<PermissionLevel> {
|
||||
let permissions = *self
|
||||
.get_build(build_id)
|
||||
.await?
|
||||
.permissions
|
||||
.get(user_id)
|
||||
.unwrap_or_default();
|
||||
Ok(permissions)
|
||||
}
|
||||
|
||||
pub async fn get_server(&self, server_id: &str) -> anyhow::Result<Server> {
|
||||
let server = self
|
||||
.servers
|
||||
.find_one_by_id(server_id)
|
||||
.await
|
||||
.context(format!("failed at mongo query for server {server_id}"))?
|
||||
.ok_or(anyhow!("server at {server_id} doesn't exist"))?;
|
||||
Ok(server)
|
||||
}
|
||||
|
||||
pub async fn get_user_permission_on_server(
|
||||
&self,
|
||||
user_id: &str,
|
||||
server_id: &str,
|
||||
) -> anyhow::Result<PermissionLevel> {
|
||||
let permissions = *self
|
||||
.get_server(server_id)
|
||||
.await?
|
||||
.permissions
|
||||
.get(user_id)
|
||||
.unwrap_or_default();
|
||||
Ok(permissions)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
use std::{collections::HashMap, path::PathBuf};
|
||||
|
||||
use async_timing_util::Timelength;
|
||||
use async_timing_util::{unix_timestamp_ms, Timelength};
|
||||
use mungos::ObjectId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum_macros::{Display, EnumString};
|
||||
|
||||
pub mod traits;
|
||||
|
||||
pub const PERIPHERY_BUILDER_BUSY: &str = "builder is busy";
|
||||
|
||||
pub type UserId = String;
|
||||
@@ -227,6 +229,19 @@ pub struct Log {
|
||||
pub end_ts: i64,
|
||||
}
|
||||
|
||||
impl Log {
|
||||
pub fn simple(msg: String) -> Log {
|
||||
let ts = unix_timestamp_ms() as i64;
|
||||
Log {
|
||||
stdout: msg,
|
||||
success: true,
|
||||
start_ts: ts,
|
||||
end_ts: ts,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct Command {
|
||||
pub path: String,
|
||||
@@ -458,6 +473,18 @@ pub enum PermissionLevel {
|
||||
Write,
|
||||
}
|
||||
|
||||
impl Default for PermissionLevel {
|
||||
fn default() -> Self {
|
||||
PermissionLevel::None
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for &PermissionLevel {
|
||||
fn default() -> Self {
|
||||
&PermissionLevel::None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Display, EnumString, PartialEq, Hash, Eq, Clone, Copy)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
|
||||
27
lib/types/src/traits.rs
Normal file
27
lib/types/src/traits.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
use crate::{Build, Deployment, PermissionLevel, PermissionsMap, Server};
|
||||
|
||||
pub trait Permissioned {
|
||||
fn permissions_map(&self) -> &PermissionsMap;
|
||||
|
||||
fn get_user_permissions(&self, user_id: &str) -> PermissionLevel {
|
||||
*self.permissions_map().get(user_id).unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
impl Permissioned for Deployment {
|
||||
fn permissions_map(&self) -> &PermissionsMap {
|
||||
&self.permissions
|
||||
}
|
||||
}
|
||||
|
||||
impl Permissioned for Build {
|
||||
fn permissions_map(&self) -> &PermissionsMap {
|
||||
&self.permissions
|
||||
}
|
||||
}
|
||||
|
||||
impl Permissioned for Server {
|
||||
fn permissions_map(&self) -> &PermissionsMap {
|
||||
&self.permissions
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user