mirror of
https://github.com/moghtech/komodo.git
synced 2026-08-03 08:56:41 -05:00
create permissioned delete routes
This commit is contained in:
+89
-23
@@ -1,45 +1,74 @@
|
||||
use anyhow::{anyhow, Context};
|
||||
use anyhow::anyhow;
|
||||
use async_timing_util::unix_timestamp_ms;
|
||||
use axum::{routing::post, Extension, Json, Router};
|
||||
use axum::{
|
||||
extract::Path,
|
||||
routing::{delete, post},
|
||||
Extension, Json, Router,
|
||||
};
|
||||
use db::DbExtension;
|
||||
use helpers::handle_anyhow_error;
|
||||
use types::{Build, Operation, PermissionLevel, Update, UpdateTarget};
|
||||
use mungos::Deserialize;
|
||||
use types::{traits::Permissioned, Build, Log, Operation, PermissionLevel, Update, UpdateTarget};
|
||||
|
||||
use crate::{auth::RequestUserExtension, ws::update};
|
||||
|
||||
use super::add_update;
|
||||
use super::{add_update, PeripheryExtension};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct BuildId {
|
||||
id: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct CreateBuildBody {
|
||||
name: String,
|
||||
server_id: String,
|
||||
}
|
||||
|
||||
pub fn router() -> Router {
|
||||
Router::new().route(
|
||||
"/create",
|
||||
post(|db, user, update_ws, build| async {
|
||||
create(db, user, update_ws, build)
|
||||
.await
|
||||
.map_err(handle_anyhow_error)
|
||||
}),
|
||||
)
|
||||
Router::new()
|
||||
.route(
|
||||
"/create",
|
||||
post(|db, user, update_ws, build| async {
|
||||
create(db, user, update_ws, build)
|
||||
.await
|
||||
.map_err(handle_anyhow_error)
|
||||
}),
|
||||
)
|
||||
.route(
|
||||
"/delete/:id",
|
||||
delete(|db, user, update_ws, periphery, build_id| async {
|
||||
delete_one(db, user, update_ws, periphery, build_id)
|
||||
.await
|
||||
.map_err(handle_anyhow_error)
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
impl Into<Build> for CreateBuildBody {
|
||||
fn into(self) -> Build {
|
||||
Build {
|
||||
name: self.name,
|
||||
server_id: self.server_id,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn create(
|
||||
Extension(db): DbExtension,
|
||||
Extension(user): RequestUserExtension,
|
||||
Extension(update_ws): update::UpdateWsSenderExtension,
|
||||
Json(mut build): Json<Build>,
|
||||
Json(build): Json<CreateBuildBody>,
|
||||
) -> anyhow::Result<()> {
|
||||
let build_server = db
|
||||
.servers
|
||||
.find_one_by_id(&build.server_id)
|
||||
.await
|
||||
.context("failed at query to find server")?
|
||||
.ok_or(anyhow!("did not find server with server_id given on build"))?;
|
||||
let permissions = *build_server.permissions.get(&user.id).ok_or(anyhow!(
|
||||
"user does not have permissions to create build on this server"
|
||||
))?;
|
||||
if permissions != PermissionLevel::Write {
|
||||
let server = db.get_server(&build.server_id).await?;
|
||||
let permissions = server.get_user_permissions(&user.id);
|
||||
if !user.is_admin && permissions != PermissionLevel::Write {
|
||||
return Err(anyhow!(
|
||||
"user does not have permissions to create build on this server"
|
||||
));
|
||||
}
|
||||
let mut build: Build = build.into();
|
||||
build.permissions = [(user.id.clone(), PermissionLevel::Write)]
|
||||
.into_iter()
|
||||
.collect();
|
||||
@@ -55,3 +84,40 @@ async fn create(
|
||||
};
|
||||
add_update(update, &db, &update_ws).await
|
||||
}
|
||||
|
||||
async fn delete_one(
|
||||
Extension(db): DbExtension,
|
||||
Extension(user): RequestUserExtension,
|
||||
Extension(update_ws): update::UpdateWsSenderExtension,
|
||||
Extension(periphery): PeripheryExtension,
|
||||
Path(BuildId { id }): Path<BuildId>,
|
||||
) -> anyhow::Result<()> {
|
||||
let build = db.get_build(&id).await?;
|
||||
let permissions = build.get_user_permissions(&user.id);
|
||||
if permissions != PermissionLevel::Write {
|
||||
return Err(anyhow!(
|
||||
"user does not have permissions to delete build {} ({id})",
|
||||
build.name
|
||||
));
|
||||
}
|
||||
let start_ts = unix_timestamp_ms() as i64;
|
||||
let server = db.get_server(&build.server_id).await?;
|
||||
// clean up anything left by the build (delete the repo)
|
||||
db.builds.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 build {} on server {}",
|
||||
build.name, server.name
|
||||
)),
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
add_update(update, &db, &update_ws).await
|
||||
}
|
||||
|
||||
+39
-10
@@ -1,6 +1,10 @@
|
||||
use anyhow::{anyhow, Context};
|
||||
use async_timing_util::unix_timestamp_ms;
|
||||
use axum::{routing::post, Extension, Json, Router};
|
||||
use axum::{
|
||||
extract::Path,
|
||||
routing::{delete, post},
|
||||
Extension, Json, Router,
|
||||
};
|
||||
use db::DbExtension;
|
||||
use helpers::handle_anyhow_error;
|
||||
use mungos::Deserialize;
|
||||
@@ -13,10 +17,16 @@ use crate::{auth::RequestUserExtension, ws::update};
|
||||
use super::{add_update, PeripheryExtension};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct DeploymentIdBody {
|
||||
pub struct DeploymentId {
|
||||
id: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct CreateDeploymentBody {
|
||||
name: String,
|
||||
server_id: String,
|
||||
}
|
||||
|
||||
pub fn router() -> Router {
|
||||
Router::new()
|
||||
.route(
|
||||
@@ -28,21 +38,39 @@ pub fn router() -> Router {
|
||||
}),
|
||||
)
|
||||
.route(
|
||||
"/delete",
|
||||
post(|db, user, update_ws, periphery, deployment_id| async {
|
||||
delete(db, user, update_ws, periphery, deployment_id)
|
||||
"/delete/:id",
|
||||
delete(|db, user, update_ws, periphery, deployment_id| async {
|
||||
delete_one(db, user, update_ws, periphery, deployment_id)
|
||||
.await
|
||||
.map_err(handle_anyhow_error)
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
impl Into<Deployment> for CreateDeploymentBody {
|
||||
fn into(self) -> Deployment {
|
||||
Deployment {
|
||||
name: self.name,
|
||||
server_id: self.server_id,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn create(
|
||||
Extension(db): DbExtension,
|
||||
Extension(user): RequestUserExtension,
|
||||
Extension(update_ws): update::UpdateWsSenderExtension,
|
||||
Json(mut deployment): Json<Deployment>,
|
||||
Json(deployment): Json<CreateDeploymentBody>,
|
||||
) -> anyhow::Result<()> {
|
||||
let server = db.get_server(&deployment.server_id).await?;
|
||||
let permissions = server.get_user_permissions(&user.id);
|
||||
if permissions != PermissionLevel::Write {
|
||||
return Err(anyhow!(
|
||||
"user does not have permissions to create deployment on this server"
|
||||
));
|
||||
}
|
||||
let mut deployment: Deployment = deployment.into();
|
||||
deployment.permissions = [(user.id.clone(), PermissionLevel::Write)]
|
||||
.into_iter()
|
||||
.collect();
|
||||
@@ -63,22 +91,23 @@ async fn create(
|
||||
add_update(update, &db, &update_ws).await
|
||||
}
|
||||
|
||||
async fn delete(
|
||||
async fn delete_one(
|
||||
Extension(db): DbExtension,
|
||||
Extension(user): RequestUserExtension,
|
||||
Extension(update_ws): update::UpdateWsSenderExtension,
|
||||
Extension(periphery): PeripheryExtension,
|
||||
Json(DeploymentIdBody { id }): Json<DeploymentIdBody>,
|
||||
Path(DeploymentId { id }): Path<DeploymentId>,
|
||||
) -> 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}"
|
||||
"user does not have permissions to delete deployment {} ({id})",
|
||||
deployment.name
|
||||
));
|
||||
}
|
||||
let server = db.get_server(&deployment.server_id).await?;
|
||||
let start_ts = unix_timestamp_ms() as i64;
|
||||
let server = db.get_server(&deployment.server_id).await?;
|
||||
let log = periphery
|
||||
.container_remove(&server, &deployment.name)
|
||||
.await?;
|
||||
|
||||
+71
-20
@@ -2,20 +2,32 @@ use anyhow::{anyhow, Context};
|
||||
use async_timing_util::unix_timestamp_ms;
|
||||
use axum::{
|
||||
extract::Path,
|
||||
routing::{get, post},
|
||||
routing::{delete, get, post},
|
||||
Extension, Json, Router,
|
||||
};
|
||||
use db::DbExtension;
|
||||
use helpers::handle_anyhow_error;
|
||||
use mungos::Deserialize;
|
||||
use types::{
|
||||
traits::Permissioned, Operation, PermissionLevel, Server, SystemStats, Update, UpdateTarget,
|
||||
traits::Permissioned, Log, Operation, PermissionLevel, Server, SystemStats, Update,
|
||||
UpdateTarget,
|
||||
};
|
||||
|
||||
use crate::{auth::RequestUserExtension, ws::update};
|
||||
|
||||
use super::{add_update, PeripheryExtension};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ServerId {
|
||||
id: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct CreateServerBody {
|
||||
name: String,
|
||||
address: String,
|
||||
}
|
||||
|
||||
pub fn router() -> Router {
|
||||
Router::new()
|
||||
.route(
|
||||
@@ -31,9 +43,17 @@ pub fn router() -> Router {
|
||||
}),
|
||||
)
|
||||
.route(
|
||||
"/stats/:server_id",
|
||||
get(|db, user, periphery, path| async {
|
||||
stats(db, user, periphery, path)
|
||||
"/delete/:id",
|
||||
delete(|db, user, update_ws, server_id| async {
|
||||
delete_one(db, user, update_ws, server_id)
|
||||
.await
|
||||
.map_err(handle_anyhow_error)
|
||||
}),
|
||||
)
|
||||
.route(
|
||||
"/stats/:id",
|
||||
get(|db, user, periphery, server_id| async {
|
||||
stats(db, user, periphery, server_id)
|
||||
.await
|
||||
.map_err(handle_anyhow_error)
|
||||
}),
|
||||
@@ -54,10 +74,7 @@ async fn list(
|
||||
if user.is_admin {
|
||||
true
|
||||
} else {
|
||||
let permissions = *s
|
||||
.permissions
|
||||
.get(&user.id)
|
||||
.unwrap_or(&PermissionLevel::None);
|
||||
let permissions = s.get_user_permissions(&user.id);
|
||||
permissions != PermissionLevel::None
|
||||
}
|
||||
})
|
||||
@@ -66,12 +83,28 @@ async fn list(
|
||||
Ok(Json(servers))
|
||||
}
|
||||
|
||||
impl Into<Server> for CreateServerBody {
|
||||
fn into(self) -> Server {
|
||||
Server {
|
||||
name: self.name,
|
||||
address: self.address,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn create(
|
||||
Extension(db): DbExtension,
|
||||
Extension(user): RequestUserExtension,
|
||||
Extension(update_ws): update::UpdateWsSenderExtension,
|
||||
Json(mut server): Json<Server>,
|
||||
Json(server): Json<CreateServerBody>,
|
||||
) -> anyhow::Result<()> {
|
||||
if !user.is_admin {
|
||||
return Err(anyhow!(
|
||||
"user does not have permissions to add server (not admin)"
|
||||
));
|
||||
}
|
||||
let mut server: Server = server.into();
|
||||
server.permissions = [(user.id.clone(), PermissionLevel::Write)]
|
||||
.into_iter()
|
||||
.collect();
|
||||
@@ -92,23 +125,41 @@ async fn create(
|
||||
add_update(update, &db, &update_ws).await
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct GetStatsPath {
|
||||
server_id: String,
|
||||
async fn delete_one(
|
||||
Extension(db): DbExtension,
|
||||
Extension(user): RequestUserExtension,
|
||||
Extension(update_ws): update::UpdateWsSenderExtension,
|
||||
Path(ServerId { id }): Path<ServerId>,
|
||||
) -> anyhow::Result<()> {
|
||||
let server = db.get_server(&id).await?;
|
||||
let permissions = server.get_user_permissions(&user.id);
|
||||
if !user.is_admin && permissions != PermissionLevel::Write {
|
||||
return Err(anyhow!(
|
||||
"user does not have permissions to delete server {} ({id})",
|
||||
server.name
|
||||
));
|
||||
}
|
||||
let start_ts = unix_timestamp_ms() as i64;
|
||||
db.deployments.delete_one(&id).await?;
|
||||
let update = Update {
|
||||
target: UpdateTarget::System,
|
||||
operation: Operation::DeleteServer,
|
||||
start_ts,
|
||||
end_ts: Some(unix_timestamp_ms() as i64),
|
||||
operator: user.id.clone(),
|
||||
log: vec![Log::simple(format!("deleted server {}", server.name))],
|
||||
..Default::default()
|
||||
};
|
||||
add_update(update, &db, &update_ws).await
|
||||
}
|
||||
|
||||
async fn stats(
|
||||
Extension(db): DbExtension,
|
||||
Extension(user): RequestUserExtension,
|
||||
Extension(periphery): PeripheryExtension,
|
||||
Path(GetStatsPath { server_id }): Path<GetStatsPath>,
|
||||
Path(ServerId { id }): Path<ServerId>,
|
||||
) -> anyhow::Result<Json<SystemStats>> {
|
||||
let server = db
|
||||
.servers
|
||||
.find_one_by_id(&server_id)
|
||||
.await
|
||||
.context("failed at query to get server")?
|
||||
.ok_or(anyhow!("failed to find server with id {server_id}"))?;
|
||||
let server = db.get_server(&id).await?;
|
||||
let permissions = server.get_user_permissions(&user.id);
|
||||
if permissions == PermissionLevel::None {
|
||||
return Err(anyhow!("user does not have permissions on this server"));
|
||||
|
||||
Reference in New Issue
Block a user