implement some alerter crud

This commit is contained in:
mbecker20
2023-07-10 05:10:13 +00:00
parent f1101cae5a
commit 54df0af48e
11 changed files with 204 additions and 51 deletions
+40
View File
@@ -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(())
+52 -2
View File
@@ -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)
}
}
+1 -1
View File
@@ -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),
+22
View File
@@ -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
View File
@@ -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"))
}
+53 -1
View File
@@ -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",
)),
}
}
}
+3 -3
View File
@@ -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 },
+2 -2
View File
@@ -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 },
+4 -15
View File
@@ -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,
+9 -1
View File
@@ -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,
+8 -2
View File
@@ -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
}
}