mirror of https://github.com/buster-so/buster.git
Implement chat access checks for metrics and dashboards
- Added functions to check if a user has access to metrics and dashboards through associated chats. - Updated permission handling in `get_metric_data_handler`, `get_metric_for_dashboard_handler`, and `get_metric_handler` to include chat access checks. - Enhanced error handling for cases where users lack access to both dashboards and chats. - Updated `asset_access_checks` to include new chat access functions and modified the public interface in `lib.rs` accordingly.
This commit is contained in:
parent
ec2a630496
commit
308c87b202
|
@ -147,48 +147,61 @@ pub async fn get_dashboard_handler(
|
|||
tracing::debug!(dashboard_id = %dashboard_id, user_id = %user.id, ?permission, "Granting access via direct permission.");
|
||||
}
|
||||
} else {
|
||||
// No sufficient direct/admin permission, check public access rules
|
||||
tracing::debug!(dashboard_id = %dashboard_id, "Insufficient direct/admin permission. Checking public access rules.");
|
||||
if !dashboard_file.publicly_accessible {
|
||||
tracing::warn!(dashboard_id = %dashboard_id, user_id = %user.id, "Permission denied (not public, insufficient direct permission).");
|
||||
return Err(anyhow!("You don't have permission to view this dashboard"));
|
||||
}
|
||||
tracing::debug!(dashboard_id = %dashboard_id, "Dashboard is publicly accessible.");
|
||||
|
||||
// Check if the public access has expired
|
||||
if let Some(expiry_date) = dashboard_file.public_expiry_date {
|
||||
tracing::debug!(dashboard_id = %dashboard_id, ?expiry_date, "Checking expiry date");
|
||||
if expiry_date < chrono::Utc::now() {
|
||||
tracing::warn!(dashboard_id = %dashboard_id, "Public access expired");
|
||||
return Err(anyhow!("Public access to this dashboard has expired"));
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a password is required
|
||||
tracing::debug!(dashboard_id = %dashboard_id, has_password = dashboard_file.public_password.is_some(), "Checking password requirement");
|
||||
if let Some(required_password) = &dashboard_file.public_password {
|
||||
tracing::debug!(dashboard_id = %dashboard_id, "Password required. Checking provided password.");
|
||||
match password {
|
||||
Some(provided_password) => {
|
||||
if provided_password != *required_password {
|
||||
// Incorrect password provided
|
||||
tracing::warn!(dashboard_id = %dashboard_id, user_id = %user.id, "Incorrect public password provided");
|
||||
return Err(anyhow!("Incorrect password for public access"));
|
||||
}
|
||||
// Correct password provided, grant CanView via public access
|
||||
tracing::debug!(dashboard_id = %dashboard_id, user_id = %user.id, "Correct public password provided. Granting CanView.");
|
||||
permission = AssetPermissionRole::CanView;
|
||||
}
|
||||
None => {
|
||||
// Password required but none provided
|
||||
tracing::warn!(dashboard_id = %dashboard_id, user_id = %user.id, "Public password required but none provided");
|
||||
return Err(anyhow!("public_password required for this dashboard"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Publicly accessible, not expired, and no password required
|
||||
tracing::debug!(dashboard_id = %dashboard_id, "Public access granted (no password required).");
|
||||
// No sufficient direct/admin permission, check if user has access via a chat
|
||||
tracing::debug!(dashboard_id = %dashboard_id, "Insufficient direct/admin permission. Checking chat access.");
|
||||
|
||||
let has_chat_access = sharing::check_dashboard_chat_access(dashboard_id, &user.id)
|
||||
.await
|
||||
.unwrap_or(false);
|
||||
|
||||
if has_chat_access {
|
||||
// User has access to a chat containing this dashboard, grant CanView
|
||||
tracing::debug!(dashboard_id = %dashboard_id, user_id = %user.id, "User has access via chat. Granting CanView.");
|
||||
permission = AssetPermissionRole::CanView;
|
||||
} else {
|
||||
// No chat access either, check public access rules
|
||||
tracing::debug!(dashboard_id = %dashboard_id, "No chat access. Checking public access rules.");
|
||||
if !dashboard_file.publicly_accessible {
|
||||
tracing::warn!(dashboard_id = %dashboard_id, user_id = %user.id, "Permission denied (not public, no chat access, insufficient direct permission).");
|
||||
return Err(anyhow!("You don't have permission to view this dashboard"));
|
||||
}
|
||||
tracing::debug!(dashboard_id = %dashboard_id, "Dashboard is publicly accessible.");
|
||||
|
||||
// Check if the public access has expired
|
||||
if let Some(expiry_date) = dashboard_file.public_expiry_date {
|
||||
tracing::debug!(dashboard_id = %dashboard_id, ?expiry_date, "Checking expiry date");
|
||||
if expiry_date < chrono::Utc::now() {
|
||||
tracing::warn!(dashboard_id = %dashboard_id, "Public access expired");
|
||||
return Err(anyhow!("Public access to this dashboard has expired"));
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a password is required
|
||||
tracing::debug!(dashboard_id = %dashboard_id, has_password = dashboard_file.public_password.is_some(), "Checking password requirement");
|
||||
if let Some(required_password) = &dashboard_file.public_password {
|
||||
tracing::debug!(dashboard_id = %dashboard_id, "Password required. Checking provided password.");
|
||||
match password {
|
||||
Some(provided_password) => {
|
||||
if provided_password != *required_password {
|
||||
// Incorrect password provided
|
||||
tracing::warn!(dashboard_id = %dashboard_id, user_id = %user.id, "Incorrect public password provided");
|
||||
return Err(anyhow!("Incorrect password for public access"));
|
||||
}
|
||||
// Correct password provided, grant CanView via public access
|
||||
tracing::debug!(dashboard_id = %dashboard_id, user_id = %user.id, "Correct public password provided. Granting CanView.");
|
||||
permission = AssetPermissionRole::CanView;
|
||||
}
|
||||
None => {
|
||||
// Password required but none provided
|
||||
tracing::warn!(dashboard_id = %dashboard_id, user_id = %user.id, "Public password required but none provided");
|
||||
return Err(anyhow!("public_password required for this dashboard"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Publicly accessible, not expired, and no password required
|
||||
tracing::debug!(dashboard_id = %dashboard_id, "Public access granted (no password required).");
|
||||
permission = AssetPermissionRole::CanView;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -100,9 +100,40 @@ pub async fn get_metric_data_handler(
|
|||
}
|
||||
}
|
||||
} else {
|
||||
// No dashboard access, return the original permission error
|
||||
tracing::warn!("No dashboard association found for metric. Returning original error.");
|
||||
return Err(e);
|
||||
// No dashboard access, check if user has access via a chat
|
||||
tracing::info!("No dashboard association found. Checking chat access.");
|
||||
let has_chat_access = sharing::check_metric_chat_access(&request.metric_id, &user.id)
|
||||
.await
|
||||
.unwrap_or(false);
|
||||
|
||||
if has_chat_access {
|
||||
// User has access to a chat containing this metric
|
||||
tracing::info!("Found associated chat with user access. Fetching metric with chat context.");
|
||||
match get_metric_for_dashboard_handler(
|
||||
&request.metric_id,
|
||||
&user,
|
||||
request.version_number,
|
||||
request.password.clone(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(metric_via_chat) => {
|
||||
tracing::debug!(
|
||||
"Successfully retrieved metric via chat association."
|
||||
);
|
||||
metric_via_chat // Use this metric definition
|
||||
}
|
||||
Err(fetch_err) => {
|
||||
// If fetching via chat fails unexpectedly, return that error
|
||||
tracing::error!("Failed to fetch metric via chat context: {}", fetch_err);
|
||||
return Err(fetch_err);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No dashboard or chat access, return the original permission error
|
||||
tracing::warn!("No dashboard or chat association found for metric. Returning original error.");
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Error was not permission-related, return original error
|
||||
|
|
|
@ -169,48 +169,61 @@ pub async fn get_metric_for_dashboard_handler(
|
|||
tracing::debug!(metric_id = %metric_id, user_id = %user.id, "User has access via dashboard. Granting CanView.");
|
||||
permission = AssetPermissionRole::CanView;
|
||||
} else {
|
||||
// No dashboard access, check public access rules
|
||||
tracing::debug!(metric_id = %metric_id, "No dashboard access. Checking public access rules.");
|
||||
if !metric_file.publicly_accessible {
|
||||
tracing::warn!(metric_id = %metric_id, user_id = %user.id, "Permission denied (not public, no dashboard access, insufficient direct permission).");
|
||||
return Err(anyhow!("You don't have permission to view this metric"));
|
||||
}
|
||||
tracing::debug!(metric_id = %metric_id, "Metric is publicly accessible.");
|
||||
|
||||
// Check if the public access has expired
|
||||
if let Some(expiry_date) = metric_file.public_expiry_date {
|
||||
tracing::debug!(metric_id = %metric_id, ?expiry_date, "Checking expiry date");
|
||||
if expiry_date < chrono::Utc::now() {
|
||||
tracing::warn!(metric_id = %metric_id, "Public access expired");
|
||||
return Err(anyhow!("Public access to this metric has expired"));
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a password is required
|
||||
tracing::debug!(metric_id = %metric_id, has_password = metric_file.public_password.is_some(), "Checking password requirement");
|
||||
if let Some(required_password) = &metric_file.public_password {
|
||||
tracing::debug!(metric_id = %metric_id, "Password required. Checking provided password.");
|
||||
match password {
|
||||
Some(provided_password) => {
|
||||
if provided_password != *required_password {
|
||||
// Incorrect password provided
|
||||
tracing::warn!(metric_id = %metric_id, user_id = %user.id, "Incorrect public password provided");
|
||||
return Err(anyhow!("Incorrect password for public access"));
|
||||
}
|
||||
// Correct password provided, grant CanView via public access
|
||||
tracing::debug!(metric_id = %metric_id, user_id = %user.id, "Correct public password provided. Granting CanView.");
|
||||
permission = AssetPermissionRole::CanView;
|
||||
}
|
||||
None => {
|
||||
// Password required but none provided
|
||||
tracing::warn!(metric_id = %metric_id, user_id = %user.id, "Public password required but none provided");
|
||||
return Err(anyhow!("public_password required for this metric"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Publicly accessible, not expired, and no password required
|
||||
tracing::debug!(metric_id = %metric_id, "Public access granted (no password required).");
|
||||
// No dashboard access, check if user has access via a chat
|
||||
tracing::debug!(metric_id = %metric_id, "No dashboard access. Checking chat access.");
|
||||
|
||||
let has_chat_access = sharing::check_metric_chat_access(metric_id, &user.id)
|
||||
.await
|
||||
.unwrap_or(false);
|
||||
|
||||
if has_chat_access {
|
||||
// User has access to a chat containing this metric, grant CanView
|
||||
tracing::debug!(metric_id = %metric_id, user_id = %user.id, "User has access via chat. Granting CanView.");
|
||||
permission = AssetPermissionRole::CanView;
|
||||
} else {
|
||||
// No chat access either, check public access rules
|
||||
tracing::debug!(metric_id = %metric_id, "No chat access. Checking public access rules.");
|
||||
if !metric_file.publicly_accessible {
|
||||
tracing::warn!(metric_id = %metric_id, user_id = %user.id, "Permission denied (not public, no dashboard/chat access, insufficient direct permission).");
|
||||
return Err(anyhow!("You don't have permission to view this metric"));
|
||||
}
|
||||
tracing::debug!(metric_id = %metric_id, "Metric is publicly accessible.");
|
||||
|
||||
// Check if the public access has expired
|
||||
if let Some(expiry_date) = metric_file.public_expiry_date {
|
||||
tracing::debug!(metric_id = %metric_id, ?expiry_date, "Checking expiry date");
|
||||
if expiry_date < chrono::Utc::now() {
|
||||
tracing::warn!(metric_id = %metric_id, "Public access expired");
|
||||
return Err(anyhow!("Public access to this metric has expired"));
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a password is required
|
||||
tracing::debug!(metric_id = %metric_id, has_password = metric_file.public_password.is_some(), "Checking password requirement");
|
||||
if let Some(required_password) = &metric_file.public_password {
|
||||
tracing::debug!(metric_id = %metric_id, "Password required. Checking provided password.");
|
||||
match password {
|
||||
Some(provided_password) => {
|
||||
if provided_password != *required_password {
|
||||
// Incorrect password provided
|
||||
tracing::warn!(metric_id = %metric_id, user_id = %user.id, "Incorrect public password provided");
|
||||
return Err(anyhow!("Incorrect password for public access"));
|
||||
}
|
||||
// Correct password provided, grant CanView via public access
|
||||
tracing::debug!(metric_id = %metric_id, user_id = %user.id, "Correct public password provided. Granting CanView.");
|
||||
permission = AssetPermissionRole::CanView;
|
||||
}
|
||||
None => {
|
||||
// Password required but none provided
|
||||
tracing::warn!(metric_id = %metric_id, user_id = %user.id, "Public password required but none provided");
|
||||
return Err(anyhow!("public_password required for this metric"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Publicly accessible, not expired, and no password required
|
||||
tracing::debug!(metric_id = %metric_id, "Public access granted (no password required).");
|
||||
permission = AssetPermissionRole::CanView;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -167,48 +167,61 @@ pub async fn get_metric_handler(
|
|||
tracing::debug!(metric_id = %metric_id, user_id = %user.id, "User has access via dashboard. Granting CanView.");
|
||||
permission = AssetPermissionRole::CanView;
|
||||
} else {
|
||||
// No dashboard access, check public access rules
|
||||
tracing::debug!(metric_id = %metric_id, "No dashboard access. Checking public access rules.");
|
||||
if !metric_file.publicly_accessible {
|
||||
tracing::warn!(metric_id = %metric_id, user_id = %user.id, "Permission denied (not public, no dashboard access, insufficient direct permission).");
|
||||
return Err(anyhow!("You don't have permission to view this metric"));
|
||||
}
|
||||
tracing::debug!(metric_id = %metric_id, "Metric is publicly accessible.");
|
||||
|
||||
// Check if the public access has expired
|
||||
if let Some(expiry_date) = metric_file.public_expiry_date {
|
||||
tracing::debug!(metric_id = %metric_id, ?expiry_date, "Checking expiry date");
|
||||
if expiry_date < chrono::Utc::now() {
|
||||
tracing::warn!(metric_id = %metric_id, "Public access expired");
|
||||
return Err(anyhow!("Public access to this metric has expired"));
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a password is required
|
||||
tracing::debug!(metric_id = %metric_id, has_password = metric_file.public_password.is_some(), "Checking password requirement");
|
||||
if let Some(required_password) = &metric_file.public_password {
|
||||
tracing::debug!(metric_id = %metric_id, "Password required. Checking provided password.");
|
||||
match password {
|
||||
Some(provided_password) => {
|
||||
if provided_password != *required_password {
|
||||
// Incorrect password provided
|
||||
tracing::warn!(metric_id = %metric_id, user_id = %user.id, "Incorrect public password provided");
|
||||
return Err(anyhow!("Incorrect password for public access"));
|
||||
}
|
||||
// Correct password provided, grant CanView via public access
|
||||
tracing::debug!(metric_id = %metric_id, user_id = %user.id, "Correct public password provided. Granting CanView.");
|
||||
permission = AssetPermissionRole::CanView;
|
||||
}
|
||||
None => {
|
||||
// Password required but none provided
|
||||
tracing::warn!(metric_id = %metric_id, user_id = %user.id, "Public password required but none provided");
|
||||
return Err(anyhow!("public_password required for this metric"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Publicly accessible, not expired, and no password required
|
||||
tracing::debug!(metric_id = %metric_id, "Public access granted (no password required).");
|
||||
// No dashboard access, check if user has access via a chat
|
||||
tracing::debug!(metric_id = %metric_id, "No dashboard access. Checking chat access.");
|
||||
|
||||
let has_chat_access = sharing::check_metric_chat_access(metric_id, &user.id)
|
||||
.await
|
||||
.unwrap_or(false);
|
||||
|
||||
if has_chat_access {
|
||||
// User has access to a chat containing this metric, grant CanView
|
||||
tracing::debug!(metric_id = %metric_id, user_id = %user.id, "User has access via chat. Granting CanView.");
|
||||
permission = AssetPermissionRole::CanView;
|
||||
} else {
|
||||
// No chat access either, check public access rules
|
||||
tracing::debug!(metric_id = %metric_id, "No chat access. Checking public access rules.");
|
||||
if !metric_file.publicly_accessible {
|
||||
tracing::warn!(metric_id = %metric_id, user_id = %user.id, "Permission denied (not public, no dashboard/chat access, insufficient direct permission).");
|
||||
return Err(anyhow!("You don't have permission to view this metric"));
|
||||
}
|
||||
tracing::debug!(metric_id = %metric_id, "Metric is publicly accessible.");
|
||||
|
||||
// Check if the public access has expired
|
||||
if let Some(expiry_date) = metric_file.public_expiry_date {
|
||||
tracing::debug!(metric_id = %metric_id, ?expiry_date, "Checking expiry date");
|
||||
if expiry_date < chrono::Utc::now() {
|
||||
tracing::warn!(metric_id = %metric_id, "Public access expired");
|
||||
return Err(anyhow!("Public access to this metric has expired"));
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a password is required
|
||||
tracing::debug!(metric_id = %metric_id, has_password = metric_file.public_password.is_some(), "Checking password requirement");
|
||||
if let Some(required_password) = &metric_file.public_password {
|
||||
tracing::debug!(metric_id = %metric_id, "Password required. Checking provided password.");
|
||||
match password {
|
||||
Some(provided_password) => {
|
||||
if provided_password != *required_password {
|
||||
// Incorrect password provided
|
||||
tracing::warn!(metric_id = %metric_id, user_id = %user.id, "Incorrect public password provided");
|
||||
return Err(anyhow!("Incorrect password for public access"));
|
||||
}
|
||||
// Correct password provided, grant CanView via public access
|
||||
tracing::debug!(metric_id = %metric_id, user_id = %user.id, "Correct public password provided. Granting CanView.");
|
||||
permission = AssetPermissionRole::CanView;
|
||||
}
|
||||
None => {
|
||||
// Password required but none provided
|
||||
tracing::warn!(metric_id = %metric_id, user_id = %user.id, "Public password required but none provided");
|
||||
return Err(anyhow!("public_password required for this metric"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Publicly accessible, not expired, and no password required
|
||||
tracing::debug!(metric_id = %metric_id, "Public access granted (no password required).");
|
||||
permission = AssetPermissionRole::CanView;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,6 +117,172 @@ pub async fn check_metric_dashboard_access(
|
|||
Ok(has_public_access.is_some())
|
||||
}
|
||||
|
||||
/// Checks if a user has access to a metric through any associated chat.
|
||||
///
|
||||
/// This function is used to implement permission cascading from chats to metrics.
|
||||
/// If a user has access to any chat containing the metric, they get at least CanView permission.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `metric_id` - UUID of the metric to check
|
||||
/// * `user_id` - UUID of the user to check permissions for
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Result<bool>` - True if the user has access to any chat containing the metric, false otherwise
|
||||
pub async fn check_metric_chat_access(
|
||||
metric_id: &Uuid,
|
||||
user_id: &Uuid,
|
||||
) -> Result<bool, diesel::result::Error> {
|
||||
let mut conn = get_pg_pool().get().await.map_err(|e| {
|
||||
diesel::result::Error::DatabaseError(
|
||||
diesel::result::DatabaseErrorKind::UnableToSendCommand,
|
||||
Box::new(e.to_string()),
|
||||
)
|
||||
})?;
|
||||
|
||||
// Check if user has access to any chat containing this metric
|
||||
let has_chat_access = database::schema::messages_to_files::table
|
||||
.inner_join(
|
||||
database::schema::messages::table
|
||||
.on(database::schema::messages::id.eq(database::schema::messages_to_files::message_id)),
|
||||
)
|
||||
.inner_join(
|
||||
database::schema::chats::table
|
||||
.on(database::schema::chats::id.eq(database::schema::messages::chat_id)),
|
||||
)
|
||||
.inner_join(
|
||||
asset_permissions::table.on(
|
||||
asset_permissions::asset_id.eq(database::schema::chats::id)
|
||||
.and(asset_permissions::asset_type.eq(AssetType::Chat))
|
||||
.and(asset_permissions::identity_id.eq(user_id))
|
||||
.and(asset_permissions::identity_type.eq(IdentityType::User))
|
||||
.and(asset_permissions::deleted_at.is_null())
|
||||
),
|
||||
)
|
||||
.filter(database::schema::messages_to_files::file_id.eq(metric_id))
|
||||
.filter(database::schema::messages_to_files::deleted_at.is_null())
|
||||
.filter(database::schema::messages::deleted_at.is_null())
|
||||
.filter(database::schema::chats::deleted_at.is_null())
|
||||
.select(database::schema::chats::id)
|
||||
.first::<Uuid>(&mut conn)
|
||||
.await
|
||||
.optional()?;
|
||||
|
||||
if has_chat_access.is_some() {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
// Now check if metric belongs to any PUBLIC chat
|
||||
let now = chrono::Utc::now();
|
||||
let has_public_chat_access = database::schema::messages_to_files::table
|
||||
.inner_join(
|
||||
database::schema::messages::table
|
||||
.on(database::schema::messages::id.eq(database::schema::messages_to_files::message_id)),
|
||||
)
|
||||
.inner_join(
|
||||
database::schema::chats::table
|
||||
.on(database::schema::chats::id.eq(database::schema::messages::chat_id)),
|
||||
)
|
||||
.filter(database::schema::messages_to_files::file_id.eq(metric_id))
|
||||
.filter(database::schema::messages_to_files::deleted_at.is_null())
|
||||
.filter(database::schema::messages::deleted_at.is_null())
|
||||
.filter(database::schema::chats::deleted_at.is_null())
|
||||
.filter(database::schema::chats::publicly_accessible.eq(true))
|
||||
.filter(
|
||||
database::schema::chats::public_expiry_date
|
||||
.is_null()
|
||||
.or(database::schema::chats::public_expiry_date.gt(now)),
|
||||
)
|
||||
.select(database::schema::chats::id)
|
||||
.first::<Uuid>(&mut conn)
|
||||
.await
|
||||
.optional()?;
|
||||
|
||||
Ok(has_public_chat_access.is_some())
|
||||
}
|
||||
|
||||
/// Checks if a user has access to a dashboard through any associated chat.
|
||||
///
|
||||
/// This function is used to implement permission cascading from chats to dashboards.
|
||||
/// If a user has access to any chat containing the dashboard, they get at least CanView permission.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `dashboard_id` - UUID of the dashboard to check
|
||||
/// * `user_id` - UUID of the user to check permissions for
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Result<bool>` - True if the user has access to any chat containing the dashboard, false otherwise
|
||||
pub async fn check_dashboard_chat_access(
|
||||
dashboard_id: &Uuid,
|
||||
user_id: &Uuid,
|
||||
) -> Result<bool, diesel::result::Error> {
|
||||
let mut conn = get_pg_pool().get().await.map_err(|e| {
|
||||
diesel::result::Error::DatabaseError(
|
||||
diesel::result::DatabaseErrorKind::UnableToSendCommand,
|
||||
Box::new(e.to_string()),
|
||||
)
|
||||
})?;
|
||||
|
||||
// Check if user has access to any chat containing this dashboard
|
||||
let has_chat_access = database::schema::messages_to_files::table
|
||||
.inner_join(
|
||||
database::schema::messages::table
|
||||
.on(database::schema::messages::id.eq(database::schema::messages_to_files::message_id)),
|
||||
)
|
||||
.inner_join(
|
||||
database::schema::chats::table
|
||||
.on(database::schema::chats::id.eq(database::schema::messages::chat_id)),
|
||||
)
|
||||
.inner_join(
|
||||
asset_permissions::table.on(
|
||||
asset_permissions::asset_id.eq(database::schema::chats::id)
|
||||
.and(asset_permissions::asset_type.eq(AssetType::Chat))
|
||||
.and(asset_permissions::identity_id.eq(user_id))
|
||||
.and(asset_permissions::identity_type.eq(IdentityType::User))
|
||||
.and(asset_permissions::deleted_at.is_null())
|
||||
),
|
||||
)
|
||||
.filter(database::schema::messages_to_files::file_id.eq(dashboard_id))
|
||||
.filter(database::schema::messages_to_files::deleted_at.is_null())
|
||||
.filter(database::schema::messages::deleted_at.is_null())
|
||||
.filter(database::schema::chats::deleted_at.is_null())
|
||||
.select(database::schema::chats::id)
|
||||
.first::<Uuid>(&mut conn)
|
||||
.await
|
||||
.optional()?;
|
||||
|
||||
if has_chat_access.is_some() {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
// Now check if dashboard belongs to any PUBLIC chat
|
||||
let now = chrono::Utc::now();
|
||||
let has_public_chat_access = database::schema::messages_to_files::table
|
||||
.inner_join(
|
||||
database::schema::messages::table
|
||||
.on(database::schema::messages::id.eq(database::schema::messages_to_files::message_id)),
|
||||
)
|
||||
.inner_join(
|
||||
database::schema::chats::table
|
||||
.on(database::schema::chats::id.eq(database::schema::messages::chat_id)),
|
||||
)
|
||||
.filter(database::schema::messages_to_files::file_id.eq(dashboard_id))
|
||||
.filter(database::schema::messages_to_files::deleted_at.is_null())
|
||||
.filter(database::schema::messages::deleted_at.is_null())
|
||||
.filter(database::schema::chats::deleted_at.is_null())
|
||||
.filter(database::schema::chats::publicly_accessible.eq(true))
|
||||
.filter(
|
||||
database::schema::chats::public_expiry_date
|
||||
.is_null()
|
||||
.or(database::schema::chats::public_expiry_date.gt(now)),
|
||||
)
|
||||
.select(database::schema::chats::id)
|
||||
.first::<Uuid>(&mut conn)
|
||||
.await
|
||||
.optional()?;
|
||||
|
||||
Ok(has_public_chat_access.is_some())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -19,4 +19,4 @@ pub use types::{
|
|||
SerializableAssetPermission, UserInfo,
|
||||
};
|
||||
pub use user_lookup::find_user_by_email;
|
||||
pub use asset_access_checks::{check_permission_access, check_metric_dashboard_access};
|
||||
pub use asset_access_checks::{check_permission_access, check_metric_dashboard_access, check_metric_chat_access, check_dashboard_chat_access};
|
||||
|
|
Loading…
Reference in New Issue