mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-04 16:09:05 +00:00
fix(dashboards): scope annotation-panel delete to the caller's dashboard (#14263)
This commit is contained in:
@@ -303,7 +303,13 @@ pub async fn delete_annotation_panels(
|
||||
if panels.is_empty() {
|
||||
return MetaHttpResponse::bad_request("panels cannot be empty".to_string());
|
||||
}
|
||||
match timed_annotations::delete_timed_annotation_panels(&timed_annotation_id, panels).await {
|
||||
match timed_annotations::delete_timed_annotation_panels(
|
||||
&dashboard_id,
|
||||
&timed_annotation_id,
|
||||
panels,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(_) => (StatusCode::OK, "").into_response(),
|
||||
Err(e) => {
|
||||
log::error!("Error deleting timed annotation panels: {e}");
|
||||
|
||||
@@ -95,13 +95,19 @@ pub async fn update_timed_annotations(
|
||||
|
||||
#[tracing::instrument]
|
||||
pub async fn delete_timed_annotation_panels(
|
||||
dashboard_id: &str,
|
||||
timed_annotation_id: &str,
|
||||
panels: Vec<String>,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
if panels.is_empty() {
|
||||
return Err(anyhow::anyhow!("panels cannot be empty"));
|
||||
}
|
||||
table::timed_annotation_panels::delete_many_panels(timed_annotation_id, panels.clone()).await?;
|
||||
table::timed_annotation_panels::delete_many_panels_in_dashboard(
|
||||
dashboard_id,
|
||||
timed_annotation_id,
|
||||
panels.clone(),
|
||||
)
|
||||
.await?;
|
||||
#[cfg(feature = "enterprise")]
|
||||
super_cluster::emit_timed_annotation_panels_delete_event(timed_annotation_id, panels).await?;
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
use config::ider;
|
||||
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter, Set, TransactionTrait};
|
||||
|
||||
use super::entity::timed_annotation_panels;
|
||||
use super::entity::{dashboards, timed_annotation_panels, timed_annotations};
|
||||
use crate::{
|
||||
db::{get_orm_client_ro, get_orm_client_rw},
|
||||
errors,
|
||||
@@ -62,6 +62,8 @@ pub async fn insert_many_panels(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Unscoped: only for replaying a delete the originating cluster already authorized. Callers
|
||||
/// serving a user request must use [`delete_many_panels_in_dashboard`].
|
||||
pub async fn delete_many_panels(
|
||||
timed_annotation_id: &str,
|
||||
panel_ids: Vec<String>,
|
||||
@@ -83,3 +85,38 @@ pub async fn delete_many_panels(
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Removes panel associations only when the annotation belongs to the given dashboard.
|
||||
pub async fn delete_many_panels_in_dashboard(
|
||||
dashboard_id: &str,
|
||||
timed_annotation_id: &str,
|
||||
panel_ids: Vec<String>,
|
||||
) -> Result<(), errors::Error> {
|
||||
if panel_ids.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let client = get_orm_client_rw().await;
|
||||
let dashboard_record = dashboards::Entity::find()
|
||||
.filter(dashboards::Column::DashboardId.eq(dashboard_id))
|
||||
.one(client)
|
||||
.await?
|
||||
.ok_or_else(|| {
|
||||
errors::Error::DbError(errors::DbError::KeyNotExists(format!(
|
||||
"Dashboard '{dashboard_id}' not found"
|
||||
)))
|
||||
})?;
|
||||
|
||||
timed_annotations::Entity::find()
|
||||
.filter(timed_annotations::Column::Id.eq(timed_annotation_id))
|
||||
.filter(timed_annotations::Column::DashboardId.eq(dashboard_record.id))
|
||||
.one(client)
|
||||
.await?
|
||||
.ok_or_else(|| {
|
||||
errors::Error::DbError(errors::DbError::KeyNotExists(format!(
|
||||
"TimedAnnotation with ID {timed_annotation_id} not found in dashboard {dashboard_id}"
|
||||
)))
|
||||
})?;
|
||||
|
||||
delete_many_panels(timed_annotation_id, panel_ids).await
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user