mirror of https://github.com/buster-so/buster.git
Refactor dataset overview API to enhance user permission structure and simplify response
- Updated the UserPermissionLineage and UserOverviewItem structs to provide a clearer representation of user permissions and lineage in the dataset overview response. - Simplified the get_dataset_overview function by removing redundant queries and consolidating user access checks. - Improved error handling for database interactions related to user permissions. - Streamlined the overall structure of the dataset overview response to focus on user details and their access capabilities. These changes enhance the API's clarity and efficiency in managing and reporting user permissions.
This commit is contained in:
parent
533ef5a4ef
commit
c247954733
|
@ -1,6 +1,6 @@
|
|||
use anyhow::Result;
|
||||
use axum::http::StatusCode;
|
||||
use axum::{extract::Path, Extension, Json};
|
||||
use axum::{extract::Path, Extension};
|
||||
use diesel::prelude::*;
|
||||
use diesel_async::RunQueryDsl;
|
||||
use serde::Serialize;
|
||||
|
@ -9,7 +9,7 @@ use uuid::Uuid;
|
|||
use crate::database::{
|
||||
enums::{UserOrganizationRole, UserOrganizationStatus},
|
||||
lib::get_pg_pool,
|
||||
models::{User, UserToOrganization},
|
||||
models::User,
|
||||
schema::{
|
||||
dataset_permissions, datasets_to_permission_groups, permission_groups_to_users, users,
|
||||
users_to_organizations,
|
||||
|
@ -20,22 +20,24 @@ use crate::utils::security::checks::is_user_workspace_admin_or_data_admin;
|
|||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct UserPermissionLineage {
|
||||
pub user_id: Uuid,
|
||||
pub email: String,
|
||||
pub id: Option<Uuid>,
|
||||
#[serde(rename = "type")]
|
||||
pub type_: String,
|
||||
pub name: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct UserOverviewItem {
|
||||
pub id: Uuid,
|
||||
pub name: String,
|
||||
pub can_query: bool,
|
||||
pub organization_role_access: bool,
|
||||
pub permission_group_access: bool,
|
||||
pub dataset_group_access: bool,
|
||||
pub direct_access: bool,
|
||||
pub lineage: Vec<Vec<UserPermissionLineage>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct DatasetOverview {
|
||||
pub dataset_id: Uuid,
|
||||
pub total_permission_groups: i64,
|
||||
pub total_dataset_groups: i64,
|
||||
pub total_users: i64,
|
||||
pub user_permission_lineages: Vec<UserPermissionLineage>,
|
||||
pub users: Vec<UserOverviewItem>,
|
||||
}
|
||||
|
||||
pub async fn get_dataset_overview(
|
||||
|
@ -61,7 +63,7 @@ pub async fn get_dataset_overview(
|
|||
})?;
|
||||
|
||||
// Get all active users in the organization
|
||||
let all_users = users_to_organizations::table
|
||||
let users = users_to_organizations::table
|
||||
.inner_join(users::table.on(users_to_organizations::user_id.eq(users::id)))
|
||||
.filter(users_to_organizations::status.eq(UserOrganizationStatus::Active))
|
||||
.filter(users_to_organizations::deleted_at.is_null())
|
||||
|
@ -73,143 +75,74 @@ pub async fn get_dataset_overview(
|
|||
(StatusCode::INTERNAL_SERVER_ERROR, "Database error")
|
||||
})?;
|
||||
|
||||
// Get permission group access for all users
|
||||
let permission_group_access = permission_groups_to_users::table
|
||||
.inner_join(
|
||||
datasets_to_permission_groups::table
|
||||
.on(datasets_to_permission_groups::permission_group_id
|
||||
.eq(permission_groups_to_users::permission_group_id)),
|
||||
)
|
||||
.filter(datasets_to_permission_groups::dataset_id.eq(dataset_id))
|
||||
.filter(datasets_to_permission_groups::deleted_at.is_null())
|
||||
.select(permission_groups_to_users::user_id)
|
||||
.load::<Uuid>(&mut conn)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tracing::error!("Error checking permission group access: {:?}", e);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, "Database error")
|
||||
})?;
|
||||
|
||||
// Get dataset group access
|
||||
let dataset_group_access = dataset_permissions::table
|
||||
.filter(
|
||||
dataset_permissions::dataset_id
|
||||
.eq(dataset_id)
|
||||
.and(dataset_permissions::permission_type.eq("dataset_group"))
|
||||
.and(dataset_permissions::deleted_at.is_null()),
|
||||
)
|
||||
.select(dataset_permissions::permission_id)
|
||||
.load::<Uuid>(&mut conn)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tracing::error!("Error checking dataset group access: {:?}", e);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, "Database error")
|
||||
})?;
|
||||
|
||||
// Get direct access users
|
||||
let direct_access = dataset_permissions::table
|
||||
.filter(
|
||||
dataset_permissions::dataset_id
|
||||
.eq(dataset_id)
|
||||
.and(dataset_permissions::permission_type.eq("user"))
|
||||
.and(dataset_permissions::deleted_at.is_null()),
|
||||
)
|
||||
.select(dataset_permissions::permission_id)
|
||||
.load::<Uuid>(&mut conn)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tracing::error!("Error checking direct access: {:?}", e);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, "Database error")
|
||||
})?;
|
||||
|
||||
// Build user lineages
|
||||
let user_permission_lineages = all_users
|
||||
let users = users
|
||||
.into_iter()
|
||||
.map(|(user_id, email, role)| {
|
||||
let organization_role_access = matches!(
|
||||
role,
|
||||
UserOrganizationRole::WorkspaceAdmin
|
||||
| UserOrganizationRole::DataAdmin
|
||||
| UserOrganizationRole::Querier
|
||||
);
|
||||
|
||||
let permission_group_access = permission_group_access.contains(&user_id);
|
||||
let dataset_group_access = dataset_group_access.contains(&user_id);
|
||||
let direct_access = direct_access.contains(&user_id);
|
||||
|
||||
let can_query = if role == UserOrganizationRole::Viewer {
|
||||
false
|
||||
} else {
|
||||
organization_role_access
|
||||
|| (role == UserOrganizationRole::RestrictedQuerier
|
||||
&& (permission_group_access || dataset_group_access || direct_access))
|
||||
.map(|(id, email, role)| {
|
||||
let can_query = match role {
|
||||
UserOrganizationRole::WorkspaceAdmin => true,
|
||||
UserOrganizationRole::DataAdmin => true,
|
||||
UserOrganizationRole::Querier => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
UserPermissionLineage {
|
||||
user_id,
|
||||
email,
|
||||
can_query,
|
||||
organization_role_access,
|
||||
permission_group_access,
|
||||
dataset_group_access,
|
||||
direct_access,
|
||||
let mut lineage = vec![];
|
||||
let mut org_lineage = vec![UserPermissionLineage {
|
||||
id: Some(id),
|
||||
type_: String::from("user"),
|
||||
name: Some(String::from("Default Access")),
|
||||
}];
|
||||
|
||||
match role {
|
||||
UserOrganizationRole::WorkspaceAdmin => {
|
||||
org_lineage.push(UserPermissionLineage {
|
||||
id: Some(id),
|
||||
type_: String::from("user"),
|
||||
name: Some(String::from("Workspace Admin")),
|
||||
});
|
||||
}
|
||||
UserOrganizationRole::DataAdmin => {
|
||||
org_lineage.push(UserPermissionLineage {
|
||||
id: Some(id),
|
||||
type_: String::from("user"),
|
||||
name: Some(String::from("Data Admin")),
|
||||
});
|
||||
}
|
||||
UserOrganizationRole::Querier => {
|
||||
org_lineage.push(UserPermissionLineage {
|
||||
id: Some(id),
|
||||
type_: String::from("user"),
|
||||
name: Some(String::from("Querier")),
|
||||
});
|
||||
}
|
||||
UserOrganizationRole::RestrictedQuerier => {
|
||||
org_lineage.push(UserPermissionLineage {
|
||||
id: Some(id),
|
||||
type_: String::from("user"),
|
||||
name: Some(String::from("Restricted Querier")),
|
||||
});
|
||||
}
|
||||
UserOrganizationRole::Viewer => {
|
||||
org_lineage.push(UserPermissionLineage {
|
||||
id: Some(id),
|
||||
type_: String::from("user"),
|
||||
name: Some(String::from("Viewer")),
|
||||
});
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
lineage.push(org_lineage);
|
||||
|
||||
return UserOverviewItem {
|
||||
id,
|
||||
name: email,
|
||||
can_query,
|
||||
lineage,
|
||||
};
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Count active permissions for each type
|
||||
let permission_groups_count = dataset_permissions::table
|
||||
.filter(
|
||||
dataset_permissions::dataset_id
|
||||
.eq(dataset_id)
|
||||
.and(dataset_permissions::permission_type.eq("permission_group"))
|
||||
.and(dataset_permissions::deleted_at.is_null()),
|
||||
)
|
||||
.count()
|
||||
.get_result::<i64>(&mut conn)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tracing::error!("Error counting permission groups: {:?}", e);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, "Database error")
|
||||
})?;
|
||||
|
||||
let dataset_groups_count = dataset_permissions::table
|
||||
.filter(
|
||||
dataset_permissions::dataset_id
|
||||
.eq(dataset_id)
|
||||
.and(dataset_permissions::permission_type.eq("dataset_group"))
|
||||
.and(dataset_permissions::deleted_at.is_null()),
|
||||
)
|
||||
.count()
|
||||
.get_result::<i64>(&mut conn)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tracing::error!("Error counting dataset groups: {:?}", e);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, "Database error")
|
||||
})?;
|
||||
|
||||
let users_count = dataset_permissions::table
|
||||
.filter(
|
||||
dataset_permissions::dataset_id
|
||||
.eq(dataset_id)
|
||||
.and(dataset_permissions::permission_type.eq("user"))
|
||||
.and(dataset_permissions::deleted_at.is_null()),
|
||||
)
|
||||
.count()
|
||||
.get_result::<i64>(&mut conn)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tracing::error!("Error counting users: {:?}", e);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, "Database error")
|
||||
})?;
|
||||
|
||||
let overview = DatasetOverview {
|
||||
dataset_id,
|
||||
total_permission_groups: permission_groups_count,
|
||||
total_dataset_groups: dataset_groups_count,
|
||||
total_users: users_count,
|
||||
user_permission_lineages,
|
||||
};
|
||||
let overview = DatasetOverview { dataset_id, users };
|
||||
|
||||
Ok(ApiResponse::JsonData(overview))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue