mirror of
https://github.com/moghtech/komodo.git
synced 2026-09-08 00:01:07 +00:00
implement some alerter crud
This commit is contained in:
@@ -4,6 +4,7 @@ use anyhow::{anyhow, Context};
|
||||
use monitor_types::{
|
||||
busy::Busy,
|
||||
entities::{
|
||||
alerter::Alerter,
|
||||
build::Build,
|
||||
builder::Builder,
|
||||
deployment::{Deployment, DockerContainerState},
|
||||
@@ -304,6 +305,45 @@ impl State {
|
||||
Ok(repo.get_user_permissions(user_id))
|
||||
}
|
||||
|
||||
pub async fn get_alerter(&self, alerter_id: &str) -> anyhow::Result<Alerter> {
|
||||
self.db
|
||||
.alerters
|
||||
.find_one_by_id(alerter_id)
|
||||
.await?
|
||||
.context(format!("did not find any alerter with id {alerter_id}"))
|
||||
}
|
||||
|
||||
pub async fn get_alerter_check_permissions(
|
||||
&self,
|
||||
alerter_id: &str,
|
||||
user: &RequestUser,
|
||||
permission_level: PermissionLevel,
|
||||
) -> anyhow::Result<Alerter> {
|
||||
let alerter = self
|
||||
.db
|
||||
.alerters
|
||||
.find_one_by_id(alerter_id)
|
||||
.await?
|
||||
.context(format!("did not find any alerter with id {alerter_id}"))?;
|
||||
let permissions = alerter.get_user_permissions(&user.id);
|
||||
if user.is_admin || permissions >= permission_level {
|
||||
Ok(alerter)
|
||||
} else {
|
||||
Err(anyhow!(
|
||||
"user does not have required permissions on this alerter"
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_user_permission_on_alerter(
|
||||
&self,
|
||||
user_id: &str,
|
||||
alerter_id: &str,
|
||||
) -> anyhow::Result<PermissionLevel> {
|
||||
let alerter = self.get_alerter(alerter_id).await?;
|
||||
Ok(alerter.get_user_permissions(user_id))
|
||||
}
|
||||
|
||||
pub async fn send_update(&self, update: Update) -> anyhow::Result<()> {
|
||||
self.update.sender.lock().await.send(update)?;
|
||||
Ok(())
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
use anyhow::Context;
|
||||
use async_trait::async_trait;
|
||||
use monitor_types::{
|
||||
entities::alerter::Alerter,
|
||||
entities::{
|
||||
alerter::Alerter,
|
||||
update::{Log, ResourceTarget, Update},
|
||||
Operation, PermissionLevel,
|
||||
},
|
||||
monitor_timestamp,
|
||||
requests::write::{CopyAlerter, CreateAlerter, DeleteAlerter, UpdateAlerter},
|
||||
};
|
||||
use resolver_api::Resolve;
|
||||
@@ -14,7 +20,51 @@ impl Resolve<CreateAlerter, RequestUser> for State {
|
||||
CreateAlerter { name, config }: CreateAlerter,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Alerter> {
|
||||
todo!()
|
||||
let start_ts = monitor_timestamp();
|
||||
let is_default = self.db.alerters.find_one(None, None).await?.is_none();
|
||||
let alerter = Alerter {
|
||||
id: Default::default(),
|
||||
name,
|
||||
created_at: start_ts,
|
||||
updated_at: start_ts,
|
||||
permissions: [(user.id.clone(), PermissionLevel::Update)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
description: Default::default(),
|
||||
tags: Default::default(),
|
||||
is_default,
|
||||
config: config.into(),
|
||||
};
|
||||
let alerter_id = self
|
||||
.db
|
||||
.alerters
|
||||
.create_one(alerter)
|
||||
.await
|
||||
.context("failed to add alerter to db")?;
|
||||
let alerter = self.get_alerter(&alerter_id).await?;
|
||||
let update = Update {
|
||||
target: ResourceTarget::Alerter(alerter_id),
|
||||
operation: Operation::CreateAlerter,
|
||||
start_ts,
|
||||
end_ts: monitor_timestamp().into(),
|
||||
operator: user.id.clone(),
|
||||
success: true,
|
||||
logs: vec![
|
||||
Log::simple(
|
||||
"create alerter",
|
||||
format!(
|
||||
"created alerter\nid: {}\nname: {}",
|
||||
alerter.id, alerter.name
|
||||
),
|
||||
),
|
||||
Log::simple("config", format!("{:#?}", alerter.config)),
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
self.add_update(update).await?;
|
||||
|
||||
Ok(alerter)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ impl Resolve<CreateBuilder, RequestUser> for State {
|
||||
.builders
|
||||
.create_one(builder)
|
||||
.await
|
||||
.context("failed to add build to db")?;
|
||||
.context("failed to add builder to db")?;
|
||||
let builder = self.get_builder(&builder_id).await?;
|
||||
let update = Update {
|
||||
target: ResourceTarget::Builder(builder_id),
|
||||
|
||||
@@ -222,6 +222,28 @@ impl Resolve<UpdateUserPermissionsOnTarget, RequestUser> for State {
|
||||
user.username, permission, repo.name
|
||||
)
|
||||
}
|
||||
ResourceTarget::Alerter(id) => {
|
||||
let alerter = self
|
||||
.db
|
||||
.alerters
|
||||
.find_one_by_id(id)
|
||||
.await
|
||||
.context("failed at find alerter query")?
|
||||
.ok_or(anyhow!("failed to find a alerter with id {id}"))?;
|
||||
self.db
|
||||
.alerters
|
||||
.update_one(
|
||||
id,
|
||||
mungos::Update::Set(doc! {
|
||||
format!("permissions.{}", user_id): permission.to_string()
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
format!(
|
||||
"user {} given {} permissions on alerter {}",
|
||||
user.username, permission, alerter.name
|
||||
)
|
||||
}
|
||||
};
|
||||
let mut update = Update {
|
||||
operation: Operation::UpdateUserPermissionsOnTarget,
|
||||
|
||||
+10
-24
@@ -10,7 +10,7 @@ use axum::{
|
||||
};
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use monitor_types::entities::{
|
||||
update::{ResourceTarget, Update},
|
||||
update::{ResourceTarget, Update, ResourceTargetVariant},
|
||||
user::User,
|
||||
PermissionLevel,
|
||||
};
|
||||
@@ -170,46 +170,32 @@ impl State {
|
||||
let permissions = self
|
||||
.get_user_permission_on_server(user_id, server_id)
|
||||
.await?;
|
||||
(permissions, "server")
|
||||
(permissions, ResourceTargetVariant::Server)
|
||||
}
|
||||
ResourceTarget::Deployment(deployment_id) => {
|
||||
let permissions = self
|
||||
.get_user_permission_on_deployment(user_id, deployment_id)
|
||||
.await?;
|
||||
(permissions, "deployment")
|
||||
(permissions, ResourceTargetVariant::Deployment)
|
||||
}
|
||||
ResourceTarget::Build(build_id) => {
|
||||
let permissions = self.get_user_permission_on_build(user_id, build_id).await?;
|
||||
(permissions, "build")
|
||||
(permissions, ResourceTargetVariant::Build)
|
||||
}
|
||||
ResourceTarget::Builder(builder_id) => {
|
||||
let permissions = self
|
||||
.get_user_permission_on_builder(user_id, builder_id)
|
||||
.await?;
|
||||
(permissions, "builder")
|
||||
(permissions, ResourceTargetVariant::Builder)
|
||||
}
|
||||
ResourceTarget::Repo(repo_id) => {
|
||||
let permissions = self.get_user_permission_on_repo(user_id, repo_id).await?;
|
||||
(permissions, "repo")
|
||||
(permissions, ResourceTargetVariant::Repo)
|
||||
}
|
||||
ResourceTarget::Alerter(alerter_id) => {
|
||||
let permissions = self.get_user_permission_on_alerter(user_id, alerter_id).await?;
|
||||
(permissions, ResourceTargetVariant::Alerter)
|
||||
}
|
||||
// UpdateTarget::Procedure(procedure_id) => {
|
||||
// let permissions = db_client
|
||||
// .get_user_permission_on_procedure(user_id, procedure_id)
|
||||
// .await?;
|
||||
// (permissions, "procedure")
|
||||
// }
|
||||
// UpdateTarget::Group(group_id) => {
|
||||
// let permissions = db_client
|
||||
// .get_user_permission_on_group(user_id, group_id)
|
||||
// .await?;
|
||||
// (permissions, "group")
|
||||
// }
|
||||
// UpdateTarget::Command(command_id) => {
|
||||
// let permissions = db_client
|
||||
// .get_user_permission_on_command(user_id, command_id)
|
||||
// .await?;
|
||||
// (permissions, "command")
|
||||
// }
|
||||
ResourceTarget::System => {
|
||||
return Err(anyhow!("user not admin, can't recieve system updates"))
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ pub struct Alerter {
|
||||
|
||||
#[serde(default)]
|
||||
#[builder(default)]
|
||||
pub default_alerter: bool,
|
||||
pub is_default: bool,
|
||||
|
||||
pub config: AlerterConfig,
|
||||
}
|
||||
@@ -76,6 +76,40 @@ pub enum PartialAlerterConfig {
|
||||
Slack(_PartialSlackAlerterConfig),
|
||||
}
|
||||
|
||||
impl From<PartialAlerterConfig> for AlerterConfig {
|
||||
fn from(value: PartialAlerterConfig) -> AlerterConfig {
|
||||
match value {
|
||||
PartialAlerterConfig::Custom(config) => AlerterConfig::Custom(config.into()),
|
||||
PartialAlerterConfig::Slack(config) => AlerterConfig::Slack(config.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AlerterConfig {
|
||||
pub fn merge_partial(self, partial: PartialAlerterConfig) -> AlerterConfig {
|
||||
match partial {
|
||||
PartialAlerterConfig::Custom(partial) => match self {
|
||||
AlerterConfig::Custom(config) => {
|
||||
let config = CustomAlerterConfig {
|
||||
url: partial.url.unwrap_or(config.url),
|
||||
};
|
||||
AlerterConfig::Custom(config)
|
||||
}
|
||||
_ => AlerterConfig::Custom(partial.into()),
|
||||
},
|
||||
PartialAlerterConfig::Slack(partial) => match self {
|
||||
AlerterConfig::Slack(config) => {
|
||||
let config = SlackAlerterConfig {
|
||||
url: partial.url.unwrap_or(config.url),
|
||||
};
|
||||
AlerterConfig::Slack(config)
|
||||
}
|
||||
_ => AlerterConfig::Slack(partial.into()),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Builder, Partial)]
|
||||
#[partial_derive(Serialize, Deserialize, Debug, Clone)]
|
||||
@@ -84,6 +118,14 @@ pub struct CustomAlerterConfig {
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
impl From<PartialCustomAlerterConfig> for CustomAlerterConfig {
|
||||
fn from(value: PartialCustomAlerterConfig) -> CustomAlerterConfig {
|
||||
CustomAlerterConfig {
|
||||
url: value.url.unwrap_or(String::from("http://localhost:7000")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Builder, Partial)]
|
||||
#[partial_derive(Serialize, Deserialize, Debug, Clone)]
|
||||
@@ -91,3 +133,13 @@ pub struct CustomAlerterConfig {
|
||||
pub struct SlackAlerterConfig {
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
impl From<PartialSlackAlerterConfig> for SlackAlerterConfig {
|
||||
fn from(value: PartialSlackAlerterConfig) -> SlackAlerterConfig {
|
||||
SlackAlerterConfig {
|
||||
url: value.url.unwrap_or(String::from(
|
||||
"https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,9 +59,6 @@ pub struct Build {
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Builder, Partial, MungosIndexed)]
|
||||
#[partial_derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[skip_serializing_none]
|
||||
#[doc_index(doc! { "builder.type": 1 })]
|
||||
#[sparse_doc_index(doc! { "builder.params.server_id": 1 })]
|
||||
#[sparse_doc_index(doc! { "builder.params.builder_id": 1 })]
|
||||
pub struct BuildConfig {
|
||||
pub builder: BuildBuilderConfig,
|
||||
|
||||
@@ -162,6 +159,9 @@ pub struct BuildActionState {
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, MungosIndexed, EnumVariants)]
|
||||
#[variant_derive(Serialize, Deserialize, Debug, Clone, Copy, Display, EnumString)]
|
||||
#[serde(tag = "type", content = "params")]
|
||||
#[doc_index(doc! { "type": 1 })]
|
||||
#[sparse_doc_index(doc! { "params.server_id": 1 })]
|
||||
#[sparse_doc_index(doc! { "params.builder_id": 1 })]
|
||||
pub enum BuildBuilderConfig {
|
||||
Server { server_id: String },
|
||||
Builder { builder_id: String },
|
||||
|
||||
@@ -55,8 +55,6 @@ pub struct Deployment {
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Builder, Partial, MungosIndexed)]
|
||||
#[partial_derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[skip_serializing_none]
|
||||
#[doc_index(doc! { "image.type": 1 })]
|
||||
#[sparse_doc_index(doc! { "image.params.build_id": 1 })]
|
||||
pub struct DeploymentConfig {
|
||||
#[serde(default)]
|
||||
#[builder(default)]
|
||||
@@ -166,6 +164,8 @@ impl From<PartialDeploymentConfig> for DeploymentConfig {
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, MungosIndexed, EnumVariants)]
|
||||
#[variant_derive(Serialize, Deserialize, Debug, Clone, Copy, Display, EnumString)]
|
||||
#[doc_index(doc! { "type": 1 })]
|
||||
#[sparse_doc_index(doc! { "params.build_id": 1 })]
|
||||
#[serde(tag = "type", content = "params")]
|
||||
pub enum DeploymentImage {
|
||||
Image { image: String },
|
||||
|
||||
@@ -301,21 +301,10 @@ pub enum Operation {
|
||||
CloneRepo,
|
||||
PullRepo,
|
||||
|
||||
// // procedure
|
||||
// CreateProcedure,
|
||||
// UpdateProcedure,
|
||||
// DeleteProcedure,
|
||||
|
||||
// // command
|
||||
// CreateCommand,
|
||||
// UpdateCommand,
|
||||
// DeleteCommand,
|
||||
// RunCommand,
|
||||
|
||||
// // group
|
||||
// CreateGroup,
|
||||
// UpdateGroup,
|
||||
// DeleteGroup,
|
||||
// alerter
|
||||
CreateAlerter,
|
||||
UpdateAlerter,
|
||||
DeleteAlerter,
|
||||
|
||||
// user
|
||||
UpdateUserPermissions,
|
||||
|
||||
@@ -8,7 +8,8 @@ use typeshare::typeshare;
|
||||
use crate::{entities::Operation, monitor_timestamp, MongoId, I64};
|
||||
|
||||
use super::{
|
||||
build::Build, builder::Builder, deployment::Deployment, repo::Repo, server::Server, Version,
|
||||
alerter::Alerter, build::Build, builder::Builder, deployment::Deployment, repo::Repo,
|
||||
server::Server, Version,
|
||||
};
|
||||
|
||||
#[typeshare]
|
||||
@@ -109,6 +110,7 @@ pub enum ResourceTarget {
|
||||
Deployment(String),
|
||||
Server(String),
|
||||
Repo(String),
|
||||
Alerter(String),
|
||||
}
|
||||
|
||||
impl From<&Build> for ResourceTarget {
|
||||
@@ -141,6 +143,12 @@ impl From<&Builder> for ResourceTarget {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Alerter> for ResourceTarget {
|
||||
fn from(alerter: &Alerter) -> Self {
|
||||
Self::Alerter(alerter.id.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Serialize,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::entities::{
|
||||
build::Build, builder::Builder, deployment::Deployment, repo::Repo, server::Server,
|
||||
PermissionLevel, PermissionsMap,
|
||||
alerter::Alerter, build::Build, builder::Builder, deployment::Deployment, repo::Repo,
|
||||
server::Server, PermissionLevel, PermissionsMap,
|
||||
};
|
||||
|
||||
pub trait Permissioned {
|
||||
@@ -40,3 +40,9 @@ impl Permissioned for Repo {
|
||||
&self.permissions
|
||||
}
|
||||
}
|
||||
|
||||
impl Permissioned for Alerter {
|
||||
fn permissions_map(&self) -> &PermissionsMap {
|
||||
&self.permissions
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user