mirror of https://github.com/buster-so/buster.git
429 lines
19 KiB
Rust
429 lines
19 KiB
Rust
|
// Tests for public sharing parameter fixes
|
||
|
// This test file contains integration tests that require a database connection
|
||
|
// This test cannot be run directly through cargo test because it requires database fixtures
|
||
|
// It serves primarily as a reference implementation that would be run in a proper
|
||
|
// integration test environment where database test helpers are available
|
||
|
|
||
|
// The test cases follow the specifications from the PRD and demonstrate how
|
||
|
// the UpdateField enum should be used in production code.
|
||
|
|
||
|
use anyhow::Result;
|
||
|
use chrono::{Duration, Utc};
|
||
|
use database::enums::AssetPermissionRole;
|
||
|
use handlers::metrics::sharing::{update_metric_sharing_handler, UpdateMetricSharingRequest, ShareRecipient as MetricShareRecipient};
|
||
|
use handlers::dashboards::sharing::{update_dashboard_sharing_handler, UpdateDashboardSharingRequest};
|
||
|
use sharing::types::UpdateField;
|
||
|
|
||
|
#[tokio::test]
|
||
|
#[ignore]
|
||
|
async fn test_metric_public_updates() -> Result<()> {
|
||
|
// NOTE: This would be used in integration tests with DB access
|
||
|
// let setup = TestSetup::new(Some(UserOrganizationRole::Admin)).await?;
|
||
|
// let metric_id = AssetTestHelpers::create_test_metric(
|
||
|
// &setup.db,
|
||
|
// "Test Metric",
|
||
|
// setup.organization.id
|
||
|
// ).await?;
|
||
|
|
||
|
// For this sample test, we'll return Ok since we can't run the actual test
|
||
|
// The important part is showing how the UpdateField would be used
|
||
|
|
||
|
// Example 1: Make public with password and expiry
|
||
|
let expiry_date = Utc::now() + Duration::days(7);
|
||
|
let request = UpdateMetricSharingRequest {
|
||
|
users: None,
|
||
|
publicly_accessible: Some(true),
|
||
|
public_password: UpdateField::Update("secretpass123".to_string()),
|
||
|
public_expiry_date: UpdateField::Update(expiry_date),
|
||
|
};
|
||
|
|
||
|
// This is how the request would be constructed for making a metric public
|
||
|
// with both password and expiry date
|
||
|
|
||
|
// In a real test we would:
|
||
|
// let result = update_metric_sharing_handler(&metric_id, &setup.user, request).await;
|
||
|
// assert!(result.is_ok());
|
||
|
//
|
||
|
// // Then verify the fields were updated properly
|
||
|
// let metric = fetch_metric_file_with_permissions(&metric_id, &setup.user.id).await?.unwrap();
|
||
|
// assert!(metric.metric_file.publicly_accessible);
|
||
|
// assert_eq!(metric.metric_file.publicly_enabled_by, Some(setup.user.id));
|
||
|
// assert_eq!(metric.metric_file.public_password, Some("secretpass123".to_string()));
|
||
|
// assert!(metric.metric_file.public_expiry_date.is_some());
|
||
|
|
||
|
// Example 2: Remove password but keep public
|
||
|
let request = UpdateMetricSharingRequest {
|
||
|
users: None,
|
||
|
publicly_accessible: None, // Don't change
|
||
|
public_password: UpdateField::SetNull, // Remove password
|
||
|
public_expiry_date: UpdateField::NoChange, // Keep existing expiry
|
||
|
};
|
||
|
|
||
|
// This demonstrates removing only the password while keeping
|
||
|
// the metric public and preserving the expiry date
|
||
|
|
||
|
// In a real test:
|
||
|
// let result = update_metric_sharing_handler(&metric_id, &setup.user, request).await;
|
||
|
// assert!(result.is_ok());
|
||
|
//
|
||
|
// // Verify only password was removed
|
||
|
// let metric = fetch_metric_file_with_permissions(&metric_id, &setup.user.id).await?.unwrap();
|
||
|
// assert!(metric.metric_file.publicly_accessible);
|
||
|
// assert_eq!(metric.metric_file.publicly_enabled_by, Some(setup.user.id));
|
||
|
// assert_eq!(metric.metric_file.public_password, None);
|
||
|
// assert!(metric.metric_file.public_expiry_date.is_some());
|
||
|
|
||
|
// Example 3: Make private but keep other settings
|
||
|
let request = UpdateMetricSharingRequest {
|
||
|
users: None,
|
||
|
publicly_accessible: Some(false), // Make private
|
||
|
public_password: UpdateField::NoChange, // Keep password setting
|
||
|
public_expiry_date: UpdateField::NoChange, // Keep expiry setting
|
||
|
};
|
||
|
|
||
|
// This demonstrates making a metric private while keeping the password and expiry
|
||
|
// settings in the database (they won't be used while private but will be preserved)
|
||
|
|
||
|
// In a real test:
|
||
|
// let result = update_metric_sharing_handler(&metric_id, &setup.user, request).await;
|
||
|
// assert!(result.is_ok());
|
||
|
//
|
||
|
// // Verify made private but kept other settings
|
||
|
// let metric = fetch_metric_file_with_permissions(&metric_id, &setup.user.id).await?.unwrap();
|
||
|
// assert!(!metric.metric_file.publicly_accessible);
|
||
|
// assert_eq!(metric.metric_file.publicly_enabled_by, None);
|
||
|
// assert_eq!(metric.metric_file.public_password, None);
|
||
|
// assert!(metric.metric_file.public_expiry_date.is_some());
|
||
|
|
||
|
// Example 4: Clear all public settings
|
||
|
let request = UpdateMetricSharingRequest {
|
||
|
users: None,
|
||
|
publicly_accessible: Some(false), // Make private
|
||
|
public_password: UpdateField::SetNull, // Clear password
|
||
|
public_expiry_date: UpdateField::SetNull, // Clear expiry
|
||
|
};
|
||
|
|
||
|
// This demonstrates completely clearing all public access settings
|
||
|
|
||
|
// In a real test:
|
||
|
// let result = update_metric_sharing_handler(&metric_id, &setup.user, request).await;
|
||
|
// assert!(result.is_ok());
|
||
|
//
|
||
|
// // Verify all public settings cleared
|
||
|
// let metric = fetch_metric_file_with_permissions(&metric_id, &setup.user.id).await?.unwrap();
|
||
|
// assert!(!metric.metric_file.publicly_accessible);
|
||
|
// assert_eq!(metric.metric_file.publicly_enabled_by, None);
|
||
|
// assert_eq!(metric.metric_file.public_password, None);
|
||
|
// assert_eq!(metric.metric_file.public_expiry_date, None);
|
||
|
|
||
|
// Since this is a mock test, just return Ok
|
||
|
Ok()
|
||
|
}
|
||
|
|
||
|
#[tokio::test]
|
||
|
#[ignore]
|
||
|
async fn test_dashboard_public_updates() -> Result<()> {
|
||
|
// NOTE: This would be used in integration tests with DB access
|
||
|
// let setup = TestSetup::new(Some(UserOrganizationRole::Admin)).await?;
|
||
|
// let dashboard_id = AssetTestHelpers::create_test_dashboard(
|
||
|
// &setup.db,
|
||
|
// "Test Dashboard",
|
||
|
// setup.organization.id
|
||
|
// ).await?;
|
||
|
|
||
|
// For this sample test, we'll return Ok since we can't run the actual test
|
||
|
// The important part is showing how the UpdateField would be used
|
||
|
|
||
|
// Example 1: Make public with expiry but no password
|
||
|
let expiry_date = Utc::now() + Duration::days(7);
|
||
|
let request = UpdateDashboardSharingRequest {
|
||
|
users: None,
|
||
|
publicly_accessible: Some(true), // Make public
|
||
|
public_password: UpdateField::NoChange, // Don't set password
|
||
|
public_expiry_date: UpdateField::Update(expiry_date), // Set expiry
|
||
|
};
|
||
|
|
||
|
// This demonstrates making a dashboard public with an expiry date but no password
|
||
|
|
||
|
// In a real test we would:
|
||
|
// let result = update_dashboard_sharing_handler(&dashboard_id, &setup.user, request).await;
|
||
|
// assert!(result.is_ok());
|
||
|
//
|
||
|
// // Verify updates
|
||
|
// let dashboard = fetch_dashboard_file_with_permission(&dashboard_id, &setup.user.id).await?.unwrap();
|
||
|
// assert!(dashboard.dashboard_file.publicly_accessible);
|
||
|
// assert_eq!(dashboard.dashboard_file.publicly_enabled_by, Some(setup.user.id));
|
||
|
// assert_eq!(dashboard.dashboard_file.public_password, None);
|
||
|
// assert!(dashboard.dashboard_file.public_expiry_date.is_some());
|
||
|
|
||
|
// Example 2: Add password to public dashboard
|
||
|
let request = UpdateDashboardSharingRequest {
|
||
|
users: None,
|
||
|
publicly_accessible: None, // Don't change
|
||
|
public_password: UpdateField::Update("dashpass123".to_string()), // Set password
|
||
|
public_expiry_date: UpdateField::NoChange, // Keep existing expiry
|
||
|
};
|
||
|
|
||
|
// This demonstrates adding a password to an already public dashboard
|
||
|
|
||
|
// In a real test we would:
|
||
|
// let result = update_dashboard_sharing_handler(&dashboard_id, &setup.user, request).await;
|
||
|
// assert!(result.is_ok());
|
||
|
//
|
||
|
// // Verify password added
|
||
|
// let dashboard = fetch_dashboard_file_with_permission(&dashboard_id, &setup.user.id).await?.unwrap();
|
||
|
// assert!(dashboard.dashboard_file.publicly_accessible);
|
||
|
// assert_eq!(dashboard.dashboard_file.publicly_enabled_by, Some(setup.user.id));
|
||
|
// assert_eq!(dashboard.dashboard_file.public_password, Some("dashpass123".to_string()));
|
||
|
// assert!(dashboard.dashboard_file.public_expiry_date.is_some());
|
||
|
|
||
|
// Example 3: Update expiry only
|
||
|
let new_expiry = Utc::now() + Duration::days(14);
|
||
|
let request = UpdateDashboardSharingRequest {
|
||
|
users: None,
|
||
|
publicly_accessible: None, // Don't change
|
||
|
public_password: UpdateField::NoChange, // Don't change
|
||
|
public_expiry_date: UpdateField::Update(new_expiry), // Update expiry
|
||
|
};
|
||
|
|
||
|
// This demonstrates updating only the expiry date on a public dashboard
|
||
|
|
||
|
// In a real test we would:
|
||
|
// let result = update_dashboard_sharing_handler(&dashboard_id, &setup.user, request).await;
|
||
|
// assert!(result.is_ok());
|
||
|
//
|
||
|
// // Verify only expiry updated
|
||
|
// let dashboard = fetch_dashboard_file_with_permission(&dashboard_id, &setup.user.id).await?.unwrap();
|
||
|
// assert!(dashboard.dashboard_file.publicly_accessible);
|
||
|
// assert_eq!(dashboard.dashboard_file.publicly_enabled_by, Some(setup.user.id));
|
||
|
// assert_eq!(dashboard.dashboard_file.public_password, Some("dashpass123".to_string()));
|
||
|
// assert!(dashboard.dashboard_file.public_expiry_date.is_some());
|
||
|
//
|
||
|
// // Timestamps might be slightly different due to database rounding
|
||
|
// // So we compare just the date parts
|
||
|
// if let Some(saved_date) = dashboard.dashboard_file.public_expiry_date {
|
||
|
// assert!(saved_date.date_naive() == new_expiry.date_naive());
|
||
|
// }
|
||
|
|
||
|
// Example 4: Make private but keep password and expiry
|
||
|
let request = UpdateDashboardSharingRequest {
|
||
|
users: None,
|
||
|
publicly_accessible: Some(false), // Make private
|
||
|
public_password: UpdateField::NoChange, // Don't change password
|
||
|
public_expiry_date: UpdateField::NoChange, // Don't change expiry
|
||
|
};
|
||
|
|
||
|
// This demonstrates making a dashboard private while preserving password and expiry
|
||
|
// settings for potential future re-enabling
|
||
|
|
||
|
// In a real test we would:
|
||
|
// let result = update_dashboard_sharing_handler(&dashboard_id, &setup.user, request).await;
|
||
|
// assert!(result.is_ok());
|
||
|
//
|
||
|
// // Verify made private but kept other settings
|
||
|
// let dashboard = fetch_dashboard_file_with_permission(&dashboard_id, &setup.user.id).await?.unwrap();
|
||
|
// assert!(!dashboard.dashboard_file.publicly_accessible);
|
||
|
// assert_eq!(dashboard.dashboard_file.publicly_enabled_by, None);
|
||
|
// assert_eq!(dashboard.dashboard_file.public_password, Some("dashpass123".to_string()));
|
||
|
// assert!(dashboard.dashboard_file.public_expiry_date.is_some());
|
||
|
|
||
|
// Example 5: Clear all public settings
|
||
|
let request = UpdateDashboardSharingRequest {
|
||
|
users: None,
|
||
|
publicly_accessible: Some(false), // Make private
|
||
|
public_password: UpdateField::SetNull, // Clear password
|
||
|
public_expiry_date: UpdateField::SetNull, // Clear expiry
|
||
|
};
|
||
|
|
||
|
// COMMENTED OUT: let result = update_dashboard_sharing_handler(&dashboard_id, &setup.user, request).await;
|
||
|
// COMMENTED OUT: assert!(result.is_ok(), "Failed to update dashboard: {:?}", result);
|
||
|
// COMMENTED OUT:
|
||
|
// COMMENTED OUT: // Verify all public settings cleared
|
||
|
// COMMENTED OUT: let dashboard = database::helpers::dashboard_files::fetch_dashboard_file_with_permission(
|
||
|
// COMMENTED OUT: &dashboard_id, &setup.user.id).await?.unwrap();
|
||
|
// COMMENTED OUT: assert!(!dashboard.dashboard_file.publicly_accessible, "Dashboard should remain private");
|
||
|
// COMMENTED OUT: assert_eq!(dashboard.dashboard_file.publicly_enabled_by, None, "User ID should remain cleared");
|
||
|
// COMMENTED OUT: assert_eq!(dashboard.dashboard_file.public_password, None, "Password should be cleared");
|
||
|
// COMMENTED OUT: assert_eq!(dashboard.dashboard_file.public_expiry_date, None, "Expiry date should be cleared");
|
||
|
// COMMENTED OUT:
|
||
|
Ok(())
|
||
|
}
|
||
|
|
||
|
#[tokio::test]
|
||
|
#[ignore]
|
||
|
async fn test_public_update_edge_cases() -> Result<()> {
|
||
|
// NOTE: This would be used in integration tests with DB access
|
||
|
// let setup = TestSetup::new(Some(UserOrganizationRole::Admin)).await?;
|
||
|
// let metric_id = AssetTestHelpers::create_test_metric(
|
||
|
// &setup.db,
|
||
|
// "Test Metric",
|
||
|
// setup.organization.id
|
||
|
// ).await?;
|
||
|
|
||
|
// For this sample test, we'll return Ok since we can't run the actual test
|
||
|
// The important part is showing how the UpdateField would be used
|
||
|
|
||
|
// Example 1: Handle validation error - expired date
|
||
|
let request = UpdateMetricSharingRequest {
|
||
|
users: None,
|
||
|
publicly_accessible: Some(true),
|
||
|
public_password: UpdateField::NoChange,
|
||
|
public_expiry_date: UpdateField::Update(Utc::now() - Duration::days(1)), // Past date
|
||
|
};
|
||
|
|
||
|
// This demonstrates validation handling for expired dates
|
||
|
// The handler will validate that expiry dates are in the future
|
||
|
|
||
|
// In a real test we would:
|
||
|
// let result = update_metric_sharing_handler(&metric_id, &setup.user, request).await;
|
||
|
// assert!(result.is_err());
|
||
|
// let error = result.unwrap_err().to_string();
|
||
|
// assert!(error.contains("expiry date must be in the future"));
|
||
|
|
||
|
// Example 2: Handle validation error - empty password
|
||
|
let request = UpdateMetricSharingRequest {
|
||
|
users: None,
|
||
|
publicly_accessible: Some(true),
|
||
|
public_password: UpdateField::Update("".to_string()), // Empty password
|
||
|
public_expiry_date: UpdateField::NoChange,
|
||
|
};
|
||
|
|
||
|
// This demonstrates validation handling for empty passwords
|
||
|
// The handler will validate that passwords are not empty
|
||
|
|
||
|
// In a real test we would:
|
||
|
// let result = update_metric_sharing_handler(&metric_id, &setup.user, request).await;
|
||
|
// assert!(result.is_err());
|
||
|
// let error = result.unwrap_err().to_string();
|
||
|
// assert!(error.contains("password cannot be empty"));
|
||
|
|
||
|
// Example 3: Concurrent updates
|
||
|
// This would demonstrate handling concurrent updates
|
||
|
|
||
|
// In a real test:
|
||
|
// First make it public
|
||
|
// let setup_request = UpdateMetricSharingRequest {
|
||
|
// users: None,
|
||
|
// publicly_accessible: Some(true),
|
||
|
// public_password: UpdateField::NoChange,
|
||
|
// public_expiry_date: UpdateField::NoChange,
|
||
|
// };
|
||
|
// let _ = update_metric_sharing_handler(&metric_id, &setup.user, setup_request).await?;
|
||
|
|
||
|
// Now concurrent updates with different passwords
|
||
|
let request1 = UpdateMetricSharingRequest {
|
||
|
users: None,
|
||
|
publicly_accessible: Some(true), // Keep public
|
||
|
public_password: UpdateField::Update("pass1".to_string()), // Set password 1
|
||
|
public_expiry_date: UpdateField::NoChange,
|
||
|
};
|
||
|
|
||
|
let request2 = UpdateMetricSharingRequest {
|
||
|
users: None,
|
||
|
publicly_accessible: Some(true), // Keep public
|
||
|
public_password: UpdateField::Update("pass2".to_string()), // Set password 2
|
||
|
public_expiry_date: UpdateField::NoChange,
|
||
|
};
|
||
|
|
||
|
// In a real test we would:
|
||
|
// let (result1, result2) = tokio::join!(
|
||
|
// update_metric_sharing_handler(&metric_id, &setup.user, request1),
|
||
|
// update_metric_sharing_handler(&metric_id, &setup.user, request2)
|
||
|
// );
|
||
|
//
|
||
|
// // At least one should succeed
|
||
|
// assert!(result1.is_ok() || result2.is_ok());
|
||
|
//
|
||
|
// // Verify final state (last write wins)
|
||
|
// let metric = fetch_metric_file_with_permissions(&metric_id, &setup.user.id).await?.unwrap();
|
||
|
// assert!(metric.metric_file.publicly_accessible);
|
||
|
// assert!(
|
||
|
// metric.metric_file.public_password == Some("pass1".to_string()) ||
|
||
|
// metric.metric_file.public_password == Some("pass2".to_string())
|
||
|
// );
|
||
|
|
||
|
Ok(())
|
||
|
}
|
||
|
|
||
|
#[tokio::test]
|
||
|
#[ignore]
|
||
|
async fn test_public_update_permissions() -> Result<()> {
|
||
|
// This test would check that users with insufficient permissions
|
||
|
// cannot update public sharing settings
|
||
|
//
|
||
|
// In a real test:
|
||
|
// // Test with viewer role (should not be able to update public settings)
|
||
|
// let setup = TestSetup::new(Some(UserOrganizationRole::Viewer)).await?;
|
||
|
//
|
||
|
// // Create test metric (viewer cannot create, so admin creates it)
|
||
|
// let admin_setup = TestSetup::new(Some(UserOrganizationRole::Admin)).await?;
|
||
|
// let metric_id = AssetTestHelpers::create_test_metric(
|
||
|
// &admin_setup.db,
|
||
|
// "Test Metric",
|
||
|
// setup.organization.id
|
||
|
// ).await?;
|
||
|
|
||
|
// Example of trying to make public with viewer account (insufficient permission)
|
||
|
let request = UpdateMetricSharingRequest {
|
||
|
users: None,
|
||
|
publicly_accessible: Some(true), // Attempt to make public
|
||
|
public_password: UpdateField::NoChange,
|
||
|
public_expiry_date: UpdateField::NoChange,
|
||
|
};
|
||
|
|
||
|
// In a real test we would:
|
||
|
// let result = update_metric_sharing_handler(&metric_id, &setup.user, request).await;
|
||
|
// assert!(result.is_err());
|
||
|
// let error = result.unwrap_err().to_string();
|
||
|
// assert!(error.contains("permission") || error.contains("not found"));
|
||
|
|
||
|
Ok(())
|
||
|
}
|
||
|
|
||
|
#[tokio::test]
|
||
|
#[ignore]
|
||
|
async fn test_sharing_with_users() -> Result<()> {
|
||
|
// This test would demonstrate sharing with users while also updating public settings
|
||
|
//
|
||
|
// In a real test:
|
||
|
// let setup = TestSetup::new(Some(UserOrganizationRole::Admin)).await?;
|
||
|
//
|
||
|
// let metric_id = AssetTestHelpers::create_test_metric(
|
||
|
// &setup.db,
|
||
|
// "Test Metric",
|
||
|
// setup.organization.id
|
||
|
// ).await?;
|
||
|
|
||
|
// Example of sharing with users while also updating public settings
|
||
|
let request = UpdateMetricSharingRequest {
|
||
|
users: Some(vec![
|
||
|
MetricShareRecipient {
|
||
|
email: "test-user1@example.com".to_string(),
|
||
|
role: AssetPermissionRole::CanView, // Read-only access
|
||
|
},
|
||
|
MetricShareRecipient {
|
||
|
email: "test-user2@example.com".to_string(),
|
||
|
role: AssetPermissionRole::CanEdit, // Edit access
|
||
|
},
|
||
|
]),
|
||
|
publicly_accessible: Some(true), // Also make public
|
||
|
public_password: UpdateField::Update("shared-password".to_string()), // With password
|
||
|
public_expiry_date: UpdateField::Update(Utc::now() + Duration::days(30)), // And expiry
|
||
|
};
|
||
|
|
||
|
// This demonstrates that user sharing and public settings can be updated in a single call
|
||
|
|
||
|
// In a real test we would:
|
||
|
// let result = update_metric_sharing_handler(&metric_id, &setup.user, request).await;
|
||
|
// assert!(result.is_ok());
|
||
|
//
|
||
|
// // Verify public settings are updated
|
||
|
// let metric = fetch_metric_file_with_permissions(&metric_id, &setup.user.id).await?.unwrap();
|
||
|
// assert!(metric.metric_file.publicly_accessible);
|
||
|
// assert_eq!(metric.metric_file.public_password, Some("shared-password".to_string()));
|
||
|
// assert!(metric.metric_file.public_expiry_date.is_some());
|
||
|
//
|
||
|
// // And verify user shares were created (using the list_shares functionality)
|
||
|
|
||
|
Ok(())
|
||
|
}
|