mirror of https://github.com/buster-so/buster.git
enhancement_dashboard_collections
This commit is contained in:
parent
d5bd1d2ab4
commit
74a2c4a493
|
@ -8,14 +8,15 @@ use futures::future::join_all;
|
|||
use middleware::AuthenticatedUser;
|
||||
use serde_json::Value;
|
||||
use serde_yaml;
|
||||
use tokio::task::JoinHandle;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::dashboards::types::BusterShareIndividual;
|
||||
use crate::dashboards::types::{BusterShareIndividual, DashboardCollection};
|
||||
use crate::metrics::{get_metric_handler, BusterMetric, Version};
|
||||
use database::enums::{AssetPermissionRole, AssetType, IdentityType, Verification};
|
||||
use database::helpers::dashboard_files::fetch_dashboard_file_with_permission;
|
||||
use database::pool::get_pg_pool;
|
||||
use database::schema::{asset_permissions, dashboard_files, users};
|
||||
use database::schema::{asset_permissions, collections, collections_to_assets, dashboard_files, users};
|
||||
use database::types::VersionHistory;
|
||||
use sharing::check_permission_access;
|
||||
|
||||
|
@ -50,6 +51,28 @@ struct AssetPermissionInfo {
|
|||
name: Option<String>,
|
||||
}
|
||||
|
||||
/// Fetches collections that the dashboard belongs to
|
||||
async fn fetch_associated_collections_for_dashboard(dashboard_id: Uuid) -> Result<Vec<DashboardCollection>> {
|
||||
let mut conn = get_pg_pool().get().await?;
|
||||
|
||||
let associated_collections = collections_to_assets::table
|
||||
.inner_join(collections::table.on(collections::id.eq(collections_to_assets::collection_id)))
|
||||
.filter(collections_to_assets::asset_id.eq(dashboard_id))
|
||||
.filter(collections_to_assets::asset_type.eq(AssetType::DashboardFile))
|
||||
.filter(collections::deleted_at.is_null()) // Ensure collection isn't deleted
|
||||
.select((collections::id, collections::name))
|
||||
.load::<(Uuid, String)>(&mut conn)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|(id, name)| DashboardCollection {
|
||||
id: id.to_string(),
|
||||
name
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(associated_collections)
|
||||
}
|
||||
|
||||
pub async fn get_dashboard_handler(
|
||||
dashboard_id: &Uuid,
|
||||
user: &AuthenticatedUser,
|
||||
|
@ -217,6 +240,13 @@ pub async fn get_dashboard_handler(
|
|||
Err(_) => None,
|
||||
};
|
||||
|
||||
// Clone dashboard_id for use in spawned task
|
||||
let d_id = *dashboard_id;
|
||||
|
||||
// Spawn task to fetch collections concurrently
|
||||
let collections_handle: JoinHandle<Result<Vec<DashboardCollection>>> =
|
||||
tokio::spawn(async move { fetch_associated_collections_for_dashboard(d_id).await });
|
||||
|
||||
// Construct the dashboard using content values where available
|
||||
let dashboard = BusterDashboard {
|
||||
config,
|
||||
|
@ -235,6 +265,22 @@ pub async fn get_dashboard_handler(
|
|||
file_name: dashboard_file.file_name,
|
||||
};
|
||||
|
||||
// Await collections result
|
||||
let collections_result = collections_handle.await;
|
||||
|
||||
// Handle collections result
|
||||
let collections = match collections_result {
|
||||
Ok(Ok(c)) => c,
|
||||
Ok(Err(e)) => {
|
||||
tracing::error!("Failed to fetch associated collections for dashboard {}: {}", dashboard_id, e);
|
||||
vec![]
|
||||
}
|
||||
Err(e) => { // JoinError
|
||||
tracing::error!("Task join error fetching collections for dashboard {}: {}", dashboard_id, e);
|
||||
vec![]
|
||||
}
|
||||
};
|
||||
|
||||
Ok(BusterDashboardResponse {
|
||||
access: dashboard_with_permission
|
||||
.permission
|
||||
|
@ -245,7 +291,7 @@ pub async fn get_dashboard_handler(
|
|||
.permission
|
||||
.unwrap_or(AssetPermissionRole::Owner),
|
||||
public_password: None,
|
||||
collections: vec![], // Empty collections for now
|
||||
collections, // Now populated with associated collections
|
||||
// New sharing fields
|
||||
individual_permissions,
|
||||
publicly_accessible: dashboard_file.publicly_accessible,
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::common::{
|
|||
assertions::response::assert_api_ok,
|
||||
};
|
||||
use chrono::Utc;
|
||||
use database::enums::{AssetPermissionRole, AssetTypeEnum, IdentityTypeEnum};
|
||||
use database::enums::{AssetPermissionRole, AssetType, AssetTypeEnum, IdentityTypeEnum};
|
||||
use diesel::{ExpressionMethods, QueryDsl};
|
||||
use diesel_async::RunQueryDsl;
|
||||
|
||||
|
@ -25,6 +25,9 @@ async fn test_get_dashboard_with_sharing_info() {
|
|||
// Add public sharing
|
||||
enable_public_sharing(&env, dashboard_id, user_id).await;
|
||||
|
||||
// Create a collection and add the dashboard to it
|
||||
let collection_id = create_collection_and_add_dashboard(&env, dashboard_id, user_id).await;
|
||||
|
||||
// Test GET request
|
||||
let response = client
|
||||
.get(&format!("/api/v1/dashboards/{}", dashboard_id))
|
||||
|
@ -48,6 +51,12 @@ async fn test_get_dashboard_with_sharing_info() {
|
|||
assert_eq!(permission["email"], "test2@example.com");
|
||||
assert_eq!(permission["role"], "viewer");
|
||||
assert_eq!(permission["name"], "Test User 2");
|
||||
|
||||
// Check collections
|
||||
assert_eq!(data["collections"].as_array().unwrap().len(), 1);
|
||||
let collection = &data["collections"][0];
|
||||
assert_eq!(collection["id"], collection_id.to_string());
|
||||
assert_eq!(collection["name"], "Test Collection");
|
||||
}
|
||||
|
||||
// Helper functions to set up the test data
|
||||
|
@ -141,4 +150,44 @@ async fn enable_public_sharing(env: &TestEnv, dashboard_id: Uuid, user_id: Uuid)
|
|||
.execute(&mut conn)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
async fn create_collection_and_add_dashboard(env: &TestEnv, dashboard_id: Uuid, user_id: Uuid) -> Uuid {
|
||||
let mut conn = env.db_pool.get().await.unwrap();
|
||||
|
||||
// Get organization ID
|
||||
let org_id = Uuid::parse_str("00000000-0000-0000-0000-000000000100").unwrap();
|
||||
|
||||
// Create a collection
|
||||
let collection_id = Uuid::parse_str("00000000-0000-0000-0000-000000000030").unwrap();
|
||||
|
||||
diesel::sql_query(r#"
|
||||
INSERT INTO collections (id, name, description, created_by, updated_by, organization_id)
|
||||
VALUES ($1, $2, $3, $4, $4, $5)
|
||||
ON CONFLICT DO NOTHING
|
||||
"#)
|
||||
.bind::<diesel::sql_types::Uuid, _>(collection_id)
|
||||
.bind::<diesel::sql_types::Text, _>("Test Collection")
|
||||
.bind::<diesel::sql_types::Text, _>("Test Collection Description")
|
||||
.bind::<diesel::sql_types::Uuid, _>(user_id)
|
||||
.bind::<diesel::sql_types::Uuid, _>(org_id)
|
||||
.execute(&mut conn)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Add the dashboard to the collection
|
||||
diesel::sql_query(r#"
|
||||
INSERT INTO collections_to_assets (collection_id, asset_id, asset_type, created_by, updated_by)
|
||||
VALUES ($1, $2, $3, $4, $4)
|
||||
ON CONFLICT DO NOTHING
|
||||
"#)
|
||||
.bind::<diesel::sql_types::Uuid, _>(collection_id)
|
||||
.bind::<diesel::sql_types::Uuid, _>(dashboard_id)
|
||||
.bind::<diesel::sql_types::Text, _>(AssetType::DashboardFile.to_string())
|
||||
.bind::<diesel::sql_types::Uuid, _>(user_id)
|
||||
.execute(&mut conn)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
collection_id
|
||||
}
|
Loading…
Reference in New Issue