mirror of https://github.com/buster-so/buster.git
514 lines
19 KiB
Rust
514 lines
19 KiB
Rust
use anyhow::Result;
|
|
use chrono::Utc;
|
|
use database::enums::{AssetPermissionRole, AssetType};
|
|
use database::helpers::metric_files::{
|
|
fetch_metric_file_with_permissions, fetch_metric_files_with_permissions,
|
|
};
|
|
use database::models::{Collection, CollectionToAsset, MetricFileToDashboardFile};
|
|
use diesel::prelude::*;
|
|
use diesel_async::RunQueryDsl;
|
|
use tokio;
|
|
use uuid::Uuid;
|
|
|
|
use database::test_utils::{TestDb, insert_test_metric_file, insert_test_dashboard_file, insert_test_permission, cleanup_test_data};
|
|
|
|
/// Tests the fetch_metric_file_with_permissions function with direct permission
|
|
#[tokio::test]
|
|
async fn test_metric_file_direct_permission() -> Result<()> {
|
|
// Initialize test environment
|
|
let test_db = TestDb::new().await?;
|
|
|
|
// Create test user and file
|
|
let user = test_db.create_test_user().await?;
|
|
let owner_id = user.id;
|
|
let metric_file = test_db.create_test_metric_file(&owner_id).await?;
|
|
let metric_id = metric_file.id;
|
|
|
|
// Insert the test metric file
|
|
insert_test_metric_file(&metric_file).await?;
|
|
|
|
// Test cases with different permission roles
|
|
for role in [
|
|
AssetPermissionRole::Owner,
|
|
AssetPermissionRole::FullAccess,
|
|
AssetPermissionRole::CanEdit,
|
|
AssetPermissionRole::CanFilter,
|
|
AssetPermissionRole::CanView,
|
|
] {
|
|
// Create and insert permission
|
|
let permission = test_db
|
|
.create_asset_permission(&metric_id, AssetType::MetricFile, &owner_id, role)
|
|
.await?;
|
|
insert_test_permission(&permission).await?;
|
|
|
|
// Fetch file with permissions
|
|
let result = fetch_metric_file_with_permissions(&metric_id, &owner_id).await?;
|
|
|
|
// Assert file is found and has correct permission
|
|
assert!(result.is_some(), "Metric file should be found");
|
|
let file_with_permission = result.unwrap();
|
|
assert_eq!(file_with_permission.metric_file.id, metric_id);
|
|
assert_eq!(file_with_permission.permission, Some(role));
|
|
}
|
|
|
|
// Clean up
|
|
cleanup_test_data(&[metric_id]).await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Tests the fetch_metric_file_with_permissions function when no permission exists
|
|
#[tokio::test]
|
|
async fn test_metric_file_no_permission() -> Result<()> {
|
|
// Initialize test environment
|
|
let test_db = TestDb::new().await?;
|
|
|
|
// Create test user and file
|
|
let user = test_db.create_test_user().await?;
|
|
let owner_id = user.id;
|
|
let metric_file = test_db.create_test_metric_file(&owner_id).await?;
|
|
let metric_id = metric_file.id;
|
|
|
|
// Insert the test metric file
|
|
insert_test_metric_file(&metric_file).await?;
|
|
|
|
// Fetch file with permissions (no permission exists)
|
|
let result = fetch_metric_file_with_permissions(&metric_id, &Uuid::new_v4()).await?;
|
|
|
|
// Assert file is found but has no permission
|
|
assert!(result.is_some(), "Metric file should be found");
|
|
let file_with_permission = result.unwrap();
|
|
assert_eq!(file_with_permission.metric_file.id, metric_id);
|
|
assert_eq!(file_with_permission.permission, None);
|
|
|
|
// Clean up
|
|
cleanup_test_data(&[metric_id]).await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Tests the fetch_metric_file_with_permissions function with public accessibility
|
|
#[tokio::test]
|
|
async fn test_metric_file_public_access() -> Result<()> {
|
|
// Initialize test environment
|
|
let test_db = TestDb::new().await?;
|
|
|
|
// Create test user and file
|
|
let user = test_db.create_test_user().await?;
|
|
let owner_id = user.id;
|
|
let mut metric_file = test_db.create_test_metric_file(&owner_id).await?;
|
|
|
|
// Make the file publicly accessible
|
|
metric_file.publicly_accessible = true;
|
|
metric_file.publicly_enabled_by = Some(owner_id);
|
|
metric_file.public_expiry_date = Some(Utc::now() + chrono::Duration::days(1));
|
|
|
|
let metric_id = metric_file.id;
|
|
|
|
// Insert the test metric file
|
|
insert_test_metric_file(&metric_file).await?;
|
|
|
|
// Fetch file with permissions for a random user (no direct permission)
|
|
let random_user_id = Uuid::new_v4();
|
|
let result = fetch_metric_file_with_permissions(&metric_id, &random_user_id).await?;
|
|
|
|
// Assert file is found and has CanView permission due to public access
|
|
assert!(result.is_some(), "Metric file should be found");
|
|
let file_with_permission = result.unwrap();
|
|
assert_eq!(file_with_permission.metric_file.id, metric_id);
|
|
assert_eq!(file_with_permission.permission, Some(AssetPermissionRole::CanView));
|
|
|
|
// Clean up
|
|
cleanup_test_data(&[metric_id]).await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Tests the fetch_metric_file_with_permissions function with expired public accessibility
|
|
#[tokio::test]
|
|
async fn test_metric_file_expired_public_access() -> Result<()> {
|
|
// Initialize test environment
|
|
let test_db = TestDb::new().await?;
|
|
|
|
// Create test user and file
|
|
let user = test_db.create_test_user().await?;
|
|
let owner_id = user.id;
|
|
let mut metric_file = test_db.create_test_metric_file(&owner_id).await?;
|
|
|
|
// Make the file publicly accessible but expired
|
|
metric_file.publicly_accessible = true;
|
|
metric_file.publicly_enabled_by = Some(owner_id);
|
|
metric_file.public_expiry_date = Some(Utc::now() - chrono::Duration::days(1)); // Expired
|
|
|
|
let metric_id = metric_file.id;
|
|
|
|
// Insert the test metric file
|
|
insert_test_metric_file(&metric_file).await?;
|
|
|
|
// Fetch file with permissions for a random user (no direct permission)
|
|
let random_user_id = Uuid::new_v4();
|
|
let result = fetch_metric_file_with_permissions(&metric_id, &random_user_id).await?;
|
|
|
|
// Assert file is found but has no permission (public access expired)
|
|
assert!(result.is_some(), "Metric file should be found");
|
|
let file_with_permission = result.unwrap();
|
|
assert_eq!(file_with_permission.metric_file.id, metric_id);
|
|
assert_eq!(file_with_permission.permission, None);
|
|
|
|
// Clean up
|
|
cleanup_test_data(&[metric_id]).await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Tests the fetch_metric_files_with_permissions function for multiple files
|
|
#[tokio::test]
|
|
async fn test_fetch_multiple_metric_files() -> Result<()> {
|
|
// Initialize test environment
|
|
let test_db = TestDb::new().await?;
|
|
|
|
// Create test user and files
|
|
let user = test_db.create_test_user().await?;
|
|
let owner_id = user.id;
|
|
|
|
// Create and insert three test metric files with different permissions
|
|
let metric_file1 = test_db.create_test_metric_file(&owner_id).await?;
|
|
let metric_id1 = metric_file1.id;
|
|
insert_test_metric_file(&metric_file1).await?;
|
|
|
|
let mut metric_file2 = test_db.create_test_metric_file(&owner_id).await?;
|
|
metric_file2.publicly_accessible = true;
|
|
metric_file2.public_expiry_date = Some(Utc::now() + chrono::Duration::days(1));
|
|
let metric_id2 = metric_file2.id;
|
|
insert_test_metric_file(&metric_file2).await?;
|
|
|
|
let metric_file3 = test_db.create_test_metric_file(&owner_id).await?;
|
|
let metric_id3 = metric_file3.id;
|
|
insert_test_metric_file(&metric_file3).await?;
|
|
|
|
// Create and insert permissions
|
|
let permission1 = test_db
|
|
.create_asset_permission(&metric_id1, AssetType::MetricFile, &owner_id, AssetPermissionRole::CanEdit)
|
|
.await?;
|
|
insert_test_permission(&permission1).await?;
|
|
|
|
let permission3 = test_db
|
|
.create_asset_permission(&metric_id3, AssetType::MetricFile, &owner_id, AssetPermissionRole::CanView)
|
|
.await?;
|
|
insert_test_permission(&permission3).await?;
|
|
|
|
// Fetch multiple files with permissions
|
|
let ids = vec![metric_id1, metric_id2, metric_id3];
|
|
let results = fetch_metric_files_with_permissions(&ids, &owner_id).await?;
|
|
|
|
// Assert correct permissions for each file
|
|
assert_eq!(results.len(), 3, "Should return 3 files");
|
|
|
|
// Find each file in results and check its permission
|
|
for result in &results {
|
|
if result.metric_file.id == metric_id1 {
|
|
assert_eq!(result.permission, Some(AssetPermissionRole::CanEdit));
|
|
} else if result.metric_file.id == metric_id2 {
|
|
assert_eq!(result.permission, Some(AssetPermissionRole::CanView)); // Public file
|
|
} else if result.metric_file.id == metric_id3 {
|
|
assert_eq!(result.permission, Some(AssetPermissionRole::CanView));
|
|
} else {
|
|
panic!("Unexpected file ID in results");
|
|
}
|
|
}
|
|
|
|
// Clean up
|
|
cleanup_test_data(&ids).await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Tests access to a metric file through dashboard permissions
|
|
/// This test specifically checks that a user with access to a dashboard can view
|
|
/// metrics associated with that dashboard
|
|
#[tokio::test]
|
|
async fn test_metric_file_dashboard_access() -> Result<()> {
|
|
// Initialize test environment
|
|
let test_db = TestDb::new().await?;
|
|
let mut conn = test_db.get_conn().await?;
|
|
|
|
// Create test users and files
|
|
let user = test_db.create_test_user().await?;
|
|
let owner_id = user.id;
|
|
let viewer_id = Uuid::new_v4(); // Another user who will have access to dashboard but not directly to metric
|
|
|
|
// Create metric and dashboard files
|
|
let metric_file = test_db.create_test_metric_file(&owner_id).await?;
|
|
let metric_id = metric_file.id;
|
|
insert_test_metric_file(&metric_file).await?;
|
|
|
|
let dashboard_file = test_db.create_test_dashboard_file(&owner_id).await?;
|
|
let dashboard_id = dashboard_file.id;
|
|
insert_test_dashboard_file(&dashboard_file).await?;
|
|
|
|
// Create association between metric and dashboard
|
|
let metric_to_dashboard = MetricFileToDashboardFile {
|
|
metric_file_id: metric_id,
|
|
dashboard_file_id: dashboard_id,
|
|
created_at: Utc::now(),
|
|
updated_at: Utc::now(),
|
|
deleted_at: None,
|
|
created_by: owner_id,
|
|
};
|
|
|
|
// Insert association
|
|
diesel::insert_into(database::schema::metric_files_to_dashboard_files::table)
|
|
.values(&metric_to_dashboard)
|
|
.execute(&mut conn)
|
|
.await?;
|
|
|
|
// Give viewer permission to dashboard but not to metric
|
|
let dashboard_permission = test_db
|
|
.create_asset_permission(&dashboard_id, AssetType::DashboardFile, &viewer_id, AssetPermissionRole::CanView)
|
|
.await?;
|
|
insert_test_permission(&dashboard_permission).await?;
|
|
|
|
// Fetch metric file with permissions as viewer
|
|
let result = fetch_metric_file_with_permissions(&metric_id, &viewer_id).await?;
|
|
|
|
// Assert viewer can view metric through dashboard permission
|
|
assert!(result.is_some(), "Metric file should be found");
|
|
let file_with_permission = result.unwrap();
|
|
assert_eq!(file_with_permission.metric_file.id, metric_id);
|
|
assert_eq!(file_with_permission.permission, Some(AssetPermissionRole::CanView));
|
|
|
|
// Clean up
|
|
cleanup_test_data(&[metric_id, dashboard_id]).await?;
|
|
|
|
// Delete metric-to-dashboard association
|
|
diesel::delete(database::schema::metric_files_to_dashboard_files::table)
|
|
.filter(database::schema::metric_files_to_dashboard_files::metric_file_id.eq(metric_id))
|
|
.execute(&mut conn)
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Tests access to a metric file through collection permissions
|
|
#[tokio::test]
|
|
async fn test_metric_file_collection_access() -> Result<()> {
|
|
// Initialize test environment
|
|
let test_db = TestDb::new().await?;
|
|
let mut conn = test_db.get_conn().await?;
|
|
|
|
// Create test users and files
|
|
let user = test_db.create_test_user().await?;
|
|
let owner_id = user.id;
|
|
let viewer_id = Uuid::new_v4(); // Another user who will have access to collection but not directly to metric
|
|
|
|
// Create metric file
|
|
let metric_file = test_db.create_test_metric_file(&owner_id).await?;
|
|
let metric_id = metric_file.id;
|
|
insert_test_metric_file(&metric_file).await?;
|
|
|
|
// Create collection
|
|
let collection_id = Uuid::new_v4();
|
|
let collection = Collection {
|
|
id: collection_id,
|
|
name: format!("Test Collection {}", test_db.test_id),
|
|
description: Some("Test collection description".to_string()),
|
|
created_by: owner_id,
|
|
updated_by: owner_id,
|
|
created_at: Utc::now(),
|
|
updated_at: Utc::now(),
|
|
deleted_at: None,
|
|
organization_id: test_db.organization_id,
|
|
};
|
|
|
|
// Insert collection
|
|
diesel::insert_into(database::schema::collections::table)
|
|
.values(&collection)
|
|
.execute(&mut conn)
|
|
.await?;
|
|
|
|
// Create association between metric and collection
|
|
let collection_to_asset = CollectionToAsset {
|
|
collection_id,
|
|
asset_id: metric_id,
|
|
asset_type: AssetType::MetricFile,
|
|
created_at: Utc::now(),
|
|
updated_at: Utc::now(),
|
|
deleted_at: None,
|
|
created_by: owner_id,
|
|
updated_by: owner_id,
|
|
};
|
|
|
|
// Insert association
|
|
diesel::insert_into(database::schema::collections_to_assets::table)
|
|
.values(&collection_to_asset)
|
|
.execute(&mut conn)
|
|
.await?;
|
|
|
|
// Give viewer permission to collection but not to metric
|
|
let collection_permission = test_db
|
|
.create_asset_permission(&collection_id, AssetType::Collection, &viewer_id, AssetPermissionRole::CanEdit)
|
|
.await?;
|
|
insert_test_permission(&collection_permission).await?;
|
|
|
|
// Fetch metric file with permissions as viewer
|
|
let result = fetch_metric_file_with_permissions(&metric_id, &viewer_id).await?;
|
|
|
|
// Assert viewer can view metric through collection permission
|
|
assert!(result.is_some(), "Metric file should be found");
|
|
let file_with_permission = result.unwrap();
|
|
assert_eq!(file_with_permission.metric_file.id, metric_id);
|
|
assert_eq!(file_with_permission.permission, Some(AssetPermissionRole::CanEdit));
|
|
|
|
// Clean up
|
|
cleanup_test_data(&[metric_id]).await?;
|
|
|
|
// Delete collection and associations
|
|
diesel::delete(database::schema::collections_to_assets::table)
|
|
.filter(database::schema::collections_to_assets::collection_id.eq(collection_id))
|
|
.execute(&mut conn)
|
|
.await?;
|
|
|
|
diesel::delete(database::schema::collections::table)
|
|
.filter(database::schema::collections::id.eq(collection_id))
|
|
.execute(&mut conn)
|
|
.await?;
|
|
|
|
diesel::delete(database::schema::asset_permissions::table)
|
|
.filter(database::schema::asset_permissions::asset_id.eq(collection_id))
|
|
.execute(&mut conn)
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Tests permission hierarchy when multiple permissions exist
|
|
#[tokio::test]
|
|
async fn test_metric_file_permission_hierarchy() -> Result<()> {
|
|
// Initialize test environment
|
|
let test_db = TestDb::new().await?;
|
|
let mut conn = test_db.get_conn().await?;
|
|
|
|
// Create test users and files
|
|
let user = test_db.create_test_user().await?;
|
|
let owner_id = user.id;
|
|
|
|
// Create metric file
|
|
let metric_file = test_db.create_test_metric_file(&owner_id).await?;
|
|
let metric_id = metric_file.id;
|
|
insert_test_metric_file(&metric_file).await?;
|
|
|
|
// Create collection
|
|
let collection_id = Uuid::new_v4();
|
|
let collection = Collection {
|
|
id: collection_id,
|
|
name: format!("Test Collection {}", test_db.test_id),
|
|
description: Some("Test collection description".to_string()),
|
|
created_by: owner_id,
|
|
updated_by: owner_id,
|
|
created_at: Utc::now(),
|
|
updated_at: Utc::now(),
|
|
deleted_at: None,
|
|
organization_id: test_db.organization_id,
|
|
};
|
|
|
|
// Insert collection
|
|
diesel::insert_into(database::schema::collections::table)
|
|
.values(&collection)
|
|
.execute(&mut conn)
|
|
.await?;
|
|
|
|
// Create association between metric and collection
|
|
let collection_to_asset = CollectionToAsset {
|
|
collection_id,
|
|
asset_id: metric_id,
|
|
asset_type: AssetType::MetricFile,
|
|
created_at: Utc::now(),
|
|
updated_at: Utc::now(),
|
|
deleted_at: None,
|
|
created_by: owner_id,
|
|
updated_by: owner_id,
|
|
};
|
|
|
|
// Insert association
|
|
diesel::insert_into(database::schema::collections_to_assets::table)
|
|
.values(&collection_to_asset)
|
|
.execute(&mut conn)
|
|
.await?;
|
|
|
|
// Create dashboard file
|
|
let dashboard_file = test_db.create_test_dashboard_file(&owner_id).await?;
|
|
let dashboard_id = dashboard_file.id;
|
|
insert_test_dashboard_file(&dashboard_file).await?;
|
|
|
|
// Create association between metric and dashboard
|
|
let metric_to_dashboard = MetricFileToDashboardFile {
|
|
metric_file_id: metric_id,
|
|
dashboard_file_id: dashboard_id,
|
|
created_at: Utc::now(),
|
|
updated_at: Utc::now(),
|
|
deleted_at: None,
|
|
created_by: owner_id,
|
|
};
|
|
|
|
// Insert association
|
|
diesel::insert_into(database::schema::metric_files_to_dashboard_files::table)
|
|
.values(&metric_to_dashboard)
|
|
.execute(&mut conn)
|
|
.await?;
|
|
|
|
// Give user multiple permissions to test hierarchy
|
|
|
|
// Direct permission - CanFilter
|
|
let direct_permission = test_db
|
|
.create_asset_permission(&metric_id, AssetType::MetricFile, &owner_id, AssetPermissionRole::CanFilter)
|
|
.await?;
|
|
insert_test_permission(&direct_permission).await?;
|
|
|
|
// Collection permission - CanEdit (higher than direct)
|
|
let collection_permission = test_db
|
|
.create_asset_permission(&collection_id, AssetType::Collection, &owner_id, AssetPermissionRole::CanEdit)
|
|
.await?;
|
|
insert_test_permission(&collection_permission).await?;
|
|
|
|
// Dashboard permission - CanView (lower than others)
|
|
let dashboard_permission = test_db
|
|
.create_asset_permission(&dashboard_id, AssetType::DashboardFile, &owner_id, AssetPermissionRole::CanView)
|
|
.await?;
|
|
insert_test_permission(&dashboard_permission).await?;
|
|
|
|
// Fetch metric file with permissions
|
|
let result = fetch_metric_file_with_permissions(&metric_id, &owner_id).await?;
|
|
|
|
// Assert the highest permission level is used (collection's CanEdit)
|
|
assert!(result.is_some(), "Metric file should be found");
|
|
let file_with_permission = result.unwrap();
|
|
assert_eq!(file_with_permission.metric_file.id, metric_id);
|
|
assert_eq!(file_with_permission.permission, Some(AssetPermissionRole::CanEdit));
|
|
|
|
// Clean up
|
|
cleanup_test_data(&[metric_id, dashboard_id]).await?;
|
|
|
|
// Delete collections and associations
|
|
diesel::delete(database::schema::collections_to_assets::table)
|
|
.filter(database::schema::collections_to_assets::collection_id.eq(collection_id))
|
|
.execute(&mut conn)
|
|
.await?;
|
|
|
|
diesel::delete(database::schema::collections::table)
|
|
.filter(database::schema::collections::id.eq(collection_id))
|
|
.execute(&mut conn)
|
|
.await?;
|
|
|
|
diesel::delete(database::schema::asset_permissions::table)
|
|
.filter(database::schema::asset_permissions::asset_id.eq(collection_id))
|
|
.execute(&mut conn)
|
|
.await?;
|
|
|
|
// Delete metric-to-dashboard association
|
|
diesel::delete(database::schema::metric_files_to_dashboard_files::table)
|
|
.filter(database::schema::metric_files_to_dashboard_files::metric_file_id.eq(metric_id))
|
|
.execute(&mut conn)
|
|
.await?;
|
|
|
|
Ok(())
|
|
} |