mirror of
https://github.com/moghtech/komodo.git
synced 2026-10-27 00:00:35 +00:00
CloseAlert
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::{Context, anyhow};
|
||||
use database::mungos::mongodb::bson::{doc, oid::ObjectId};
|
||||
use komodo_client::{api::write::CloseAlert, entities::NoData};
|
||||
use reqwest::StatusCode;
|
||||
use resolver_api::Resolve;
|
||||
use serror::AddStatusCodeError;
|
||||
|
||||
use crate::{api::write::WriteArgs, state::db_client};
|
||||
|
||||
impl Resolve<WriteArgs> for CloseAlert {
|
||||
async fn resolve(
|
||||
self,
|
||||
WriteArgs { user: admin }: &WriteArgs,
|
||||
) -> Result<Self::Response, Self::Error> {
|
||||
if !admin.admin {
|
||||
return Err(
|
||||
anyhow!("This call is admin only")
|
||||
.status_code(StatusCode::FORBIDDEN),
|
||||
);
|
||||
}
|
||||
db_client()
|
||||
.alerts
|
||||
.update_one(
|
||||
doc! { "_id": ObjectId::from_str(&self.id)? },
|
||||
doc! { "$set": { "resolved": true } },
|
||||
)
|
||||
.await
|
||||
.context("Failed to close Alert on database")?;
|
||||
Ok(NoData {})
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ use crate::auth::auth_request;
|
||||
use super::Variant;
|
||||
|
||||
mod action;
|
||||
mod alert;
|
||||
mod alerter;
|
||||
mod build;
|
||||
mod builder;
|
||||
@@ -200,6 +201,9 @@ pub enum WriteRequest {
|
||||
CreateOnboardingKey(CreateOnboardingKey),
|
||||
UpdateOnboardingKey(UpdateOnboardingKey),
|
||||
DeleteOnboardingKey(DeleteOnboardingKey),
|
||||
|
||||
// ==== ALERT ====
|
||||
CloseAlert(CloseAlert),
|
||||
}
|
||||
|
||||
pub fn router() -> Router {
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
use derive_empty_traits::EmptyTraits;
|
||||
use resolver_api::Resolve;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use typeshare::typeshare;
|
||||
|
||||
use crate::{api::write::KomodoWriteRequest, entities::NoData};
|
||||
|
||||
//
|
||||
|
||||
/// **Admin only.** Close the Alert at the given id.
|
||||
/// Response: [NoData]
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Debug, Clone, Serialize, Deserialize, Resolve, EmptyTraits,
|
||||
)]
|
||||
#[empty_traits(KomodoWriteRequest)]
|
||||
#[response(NoData)]
|
||||
#[error(serror::Error)]
|
||||
pub struct CloseAlert {
|
||||
/// The id of the Alert to close.
|
||||
pub id: String,
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
mod action;
|
||||
mod alert;
|
||||
mod alerter;
|
||||
mod api_key;
|
||||
mod build;
|
||||
@@ -19,6 +20,7 @@ mod user_group;
|
||||
mod variable;
|
||||
|
||||
pub use action::*;
|
||||
pub use alert::*;
|
||||
pub use alerter::*;
|
||||
pub use api_key::*;
|
||||
pub use build::*;
|
||||
|
||||
@@ -331,6 +331,9 @@ export type WriteResponses = {
|
||||
CreateOnboardingKey: Types.CreateOnboardingKeyResponse;
|
||||
UpdateOnboardingKey: Types.UpdateOnboardingKeyResponse;
|
||||
DeleteOnboardingKey: Types.DeleteOnboardingKeyResponse;
|
||||
|
||||
// ==== ALERT ====
|
||||
CloseAlert: Types.NoData;
|
||||
};
|
||||
|
||||
export type ExecuteResponses = {
|
||||
|
||||
@@ -4603,6 +4603,15 @@ export interface CloneRepo {
|
||||
repo: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* **Admin only.** Close the Alert at the given id.
|
||||
* Response: [NoData]
|
||||
*/
|
||||
export interface CloseAlert {
|
||||
/** The id of the Alert to close. */
|
||||
id: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports matching resources, and writes to the target sync's resource file. Response: [Update]
|
||||
*
|
||||
@@ -9139,7 +9148,8 @@ export type WriteRequest =
|
||||
| { type: "DeleteDockerRegistryAccount", params: DeleteDockerRegistryAccount }
|
||||
| { type: "CreateOnboardingKey", params: CreateOnboardingKey }
|
||||
| { type: "UpdateOnboardingKey", params: UpdateOnboardingKey }
|
||||
| { type: "DeleteOnboardingKey", params: DeleteOnboardingKey };
|
||||
| { type: "DeleteOnboardingKey", params: DeleteOnboardingKey }
|
||||
| { type: "CloseAlert", params: CloseAlert };
|
||||
|
||||
export type WsLoginMessage =
|
||||
| { type: "Jwt", params: {
|
||||
|
||||
+1
@@ -246,6 +246,7 @@ export type WriteResponses = {
|
||||
CreateOnboardingKey: Types.CreateOnboardingKeyResponse;
|
||||
UpdateOnboardingKey: Types.UpdateOnboardingKeyResponse;
|
||||
DeleteOnboardingKey: Types.DeleteOnboardingKeyResponse;
|
||||
CloseAlert: Types.NoData;
|
||||
};
|
||||
export type ExecuteResponses = {
|
||||
StartContainer: Types.Update;
|
||||
|
||||
Vendored
+11
@@ -4484,6 +4484,14 @@ export interface CloneRepo {
|
||||
/** Id or name */
|
||||
repo: string;
|
||||
}
|
||||
/**
|
||||
* **Admin only.** Close the Alert at the given id.
|
||||
* Response: [NoData]
|
||||
*/
|
||||
export interface CloseAlert {
|
||||
/** The id of the Alert to close. */
|
||||
id: string;
|
||||
}
|
||||
/**
|
||||
* Exports matching resources, and writes to the target sync's resource file. Response: [Update]
|
||||
*
|
||||
@@ -9265,6 +9273,9 @@ export type WriteRequest = {
|
||||
} | {
|
||||
type: "DeleteOnboardingKey";
|
||||
params: DeleteOnboardingKey;
|
||||
} | {
|
||||
type: "CloseAlert";
|
||||
params: CloseAlert;
|
||||
};
|
||||
export type WsLoginMessage = {
|
||||
type: "Jwt";
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
import { ResourceLink } from "@components/resources/common";
|
||||
import { useRead } from "@lib/hooks";
|
||||
import { useInvalidate, useRead, useUser, useWrite } from "@lib/hooks";
|
||||
import { UsableResource } from "@types";
|
||||
import { Button } from "@ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTrigger,
|
||||
} from "@ui/dialog";
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTrigger } from "@ui/dialog";
|
||||
import { useState } from "react";
|
||||
import { AlertLevel } from ".";
|
||||
import { fmt_date_with_minutes } from "@lib/formatting";
|
||||
@@ -18,6 +13,9 @@ import {
|
||||
} from "@lib/color";
|
||||
import { MonacoEditor } from "@components/monaco";
|
||||
import { Types } from "komodo_client";
|
||||
import { ConfirmButton } from "@components/util";
|
||||
import { X } from "lucide-react";
|
||||
import { useToast } from "@ui/use-toast";
|
||||
|
||||
export const AlertDetailsDialog = ({ id }: { id: string }) => {
|
||||
const [open, set] = useState(false);
|
||||
@@ -40,66 +38,83 @@ export const AlertDetailsDialogContent = ({
|
||||
}: {
|
||||
alert: Types.Alert | undefined;
|
||||
onClose: () => void;
|
||||
}) => (
|
||||
<>
|
||||
{alert && (
|
||||
<DialogContent className="w-[90vw] max-w-[900px]">
|
||||
{alert && (
|
||||
<>
|
||||
<DialogHeader>
|
||||
{alert && (
|
||||
<div className="flex items-center gap-4">
|
||||
<ResourceLink
|
||||
type={alert.target.type as UsableResource}
|
||||
id={alert.target.id}
|
||||
onClick={onClose}
|
||||
/>
|
||||
<div className="text-muted-foreground">
|
||||
{fmt_date_with_minutes(new Date(alert.ts))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</DialogHeader>
|
||||
<DialogDescription>
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex gap-4 items-center">
|
||||
{/** Alert type */}
|
||||
<div className="flex gap-2">
|
||||
<div className="text-muted-foreground">type:</div>{" "}
|
||||
{alert.data.type}
|
||||
</div>
|
||||
}) => {
|
||||
const { toast } = useToast();
|
||||
const isAdmin = useUser().data?.admin ?? false;
|
||||
const inv = useInvalidate();
|
||||
const { mutate: close_alert, isPending: closePending } = useWrite(
|
||||
"CloseAlert",
|
||||
{
|
||||
onSuccess: () => {
|
||||
inv(["ListAlerts"], ["GetAlert"]);
|
||||
toast({ title: "Closed alert." });
|
||||
onClose();
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
{/** Resolved */}
|
||||
<div className="flex gap-2">
|
||||
<div className="text-muted-foreground">status:</div>{" "}
|
||||
<div
|
||||
className={text_color_class_by_intention(
|
||||
alert.resolved
|
||||
? "Good"
|
||||
: alert_level_intention(alert.level)
|
||||
)}
|
||||
>
|
||||
{alert.resolved ? "RESOLVED" : "OPEN"}
|
||||
</div>
|
||||
</div>
|
||||
if (!alert) return null;
|
||||
|
||||
{/** Level */}
|
||||
<div className="flex gap-2 text-muted-foreground">
|
||||
level: <AlertLevel level={alert.level} />
|
||||
</div>
|
||||
</div>
|
||||
return (
|
||||
<DialogContent className="w-[90vw] max-w-[900px]">
|
||||
<DialogHeader>
|
||||
<div className="flex items-center gap-4">
|
||||
<ResourceLink
|
||||
type={alert.target.type as UsableResource}
|
||||
id={alert.target.id}
|
||||
onClick={onClose}
|
||||
/>
|
||||
<div className="text-muted-foreground">
|
||||
{fmt_date_with_minutes(new Date(alert.ts))}
|
||||
</div>
|
||||
</div>
|
||||
</DialogHeader>
|
||||
<DialogDescription>
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex gap-4 items-center">
|
||||
{/** Alert type */}
|
||||
<div className="flex gap-2">
|
||||
<div className="text-muted-foreground">type:</div>{" "}
|
||||
{alert.data.type}
|
||||
</div>
|
||||
|
||||
{/** Alert data */}
|
||||
<MonacoEditor
|
||||
value={JSON.stringify(alert.data.data, undefined, 2)}
|
||||
language="json"
|
||||
readOnly
|
||||
/>
|
||||
{/** Resolved */}
|
||||
<div className="flex gap-2">
|
||||
<div className="text-muted-foreground">status:</div>{" "}
|
||||
<div
|
||||
className={text_color_class_by_intention(
|
||||
alert.resolved ? "Good" : alert_level_intention(alert.level)
|
||||
)}
|
||||
>
|
||||
{alert.resolved ? "RESOLVED" : "OPEN"}
|
||||
</div>
|
||||
</DialogDescription>
|
||||
</>
|
||||
)}
|
||||
</DialogContent>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
</div>
|
||||
|
||||
{/** Level */}
|
||||
<div className="flex gap-2 text-muted-foreground">
|
||||
level: <AlertLevel level={alert.level} />
|
||||
</div>
|
||||
|
||||
{isAdmin && (
|
||||
<ConfirmButton
|
||||
title="Close"
|
||||
icon={<X className="w-4 h-4" />}
|
||||
variant="destructive"
|
||||
className="max-w-[120px]"
|
||||
onClick={() => close_alert({ id: alert?._id?.$oid! })}
|
||||
loading={closePending}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/** Alert data */}
|
||||
<MonacoEditor
|
||||
value={JSON.stringify(alert.data.data, undefined, 2)}
|
||||
language="json"
|
||||
readOnly
|
||||
/>
|
||||
</div>
|
||||
</DialogDescription>
|
||||
</DialogContent>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user