Merge branch 'evals' of https://github.com/buster-so/buster into evals

This commit is contained in:
Nate Kelley 2025-04-17 11:39:32 -06:00
commit 45b431ce3c
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
11 changed files with 66 additions and 19 deletions

View File

@ -72,7 +72,7 @@ Example `lib.rs`:
//! This library provides... //! This library provides...
// Re-export common workspace types if needed // Re-export common workspace types if needed
pub use common_types::{Result, Error}; pub use anyhow::{Result, Error};
pub mod models; pub mod models;
pub mod utils; pub mod utils;
@ -91,7 +91,7 @@ pub use models::{ImportantType, AnotherType};
Example `errors.rs`: Example `errors.rs`:
```rust ```rust
use thiserror::Error; use thiserror::Error;
use common_types::Error as WorkspaceError; use anyhow::Error as WorkspaceError;
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum Error { pub enum Error {

View File

@ -9,6 +9,7 @@ members = [
"libs/sharing", "libs/sharing",
"libs/sql_analyzer", "libs/sql_analyzer",
"libs/search", "libs/search",
"libs/dataset_security",
] ]
resolver = "2" resolver = "2"

View File

@ -72,7 +72,7 @@ Example `lib.rs`:
//! This library provides... //! This library provides...
// Re-export common workspace types if needed // Re-export common workspace types if needed
pub use common_types::{Result, Error}; pub use anyhow::{Result, Error};
pub mod models; pub mod models;
pub mod utils; pub mod utils;
@ -91,7 +91,7 @@ pub use models::{ImportantType, AnotherType};
Example `errors.rs`: Example `errors.rs`:
```rust ```rust
use thiserror::Error; use thiserror::Error;
use common_types::Error as WorkspaceError; use anyhow::Error as WorkspaceError;
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum Error { pub enum Error {

View File

@ -0,0 +1,20 @@
[package]
name = "dataset_security"
version = "0.1.0"
edition = "2021"
[dependencies]
# Workspace dependencies
anyhow = { workspace = true }
diesel = { workspace = true }
diesel-async = { workspace = true }
uuid = { workspace = true }
tracing = { workspace = true }
# Internal workspace dependencies
database = { path = "../database" }
# Development dependencies
[dev-dependencies]
tokio = { workspace = true }
# Add other workspace dev dependencies as needed

View File

@ -1,3 +1,5 @@
//! Library for handling dataset security and permissions.
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use diesel::{BoolExpressionMethods, ExpressionMethods, JoinOnDsl, QueryDsl}; use diesel::{BoolExpressionMethods, ExpressionMethods, JoinOnDsl, QueryDsl};
use diesel_async::RunQueryDsl; use diesel_async::RunQueryDsl;
@ -7,8 +9,11 @@ use database::{
pool::{get_pg_pool, PgPool}, pool::{get_pg_pool, PgPool},
models::Dataset, models::Dataset,
schema::{ schema::{
datasets, datasets_to_permission_groups, permission_groups, datasets,
permission_groups_to_identities, teams_to_users, datasets_to_permission_groups,
permission_groups,
permission_groups_to_identities,
teams_to_users,
}, },
}; };
@ -23,6 +28,8 @@ pub async fn get_permissioned_datasets(
Err(e) => return Err(anyhow!("Unable to get connection from pool: {}", e)), Err(e) => return Err(anyhow!("Unable to get connection from pool: {}", e)),
}; };
// TODO: Add logic to check if user is admin, if so, return all datasets
let datasets = match datasets::table let datasets = match datasets::table
.select(datasets::all_columns) .select(datasets::all_columns)
.inner_join( .inner_join(

View File

@ -115,9 +115,9 @@ pub async fn list_chats_handler(
); );
} }
// Order by creation date descending and apply pagination // Order by updated date descending and apply pagination
query = query query = query
.order_by(chats::created_at.desc()) .order_by(chats::updated_at.desc())
.offset(offset as i64) .offset(offset as i64)
.limit((request.page_size + 1) as i64); .limit((request.page_size + 1) as i64);

View File

@ -2879,7 +2879,7 @@ fn generate_file_response_values(filtered_files: &[CompletedFileInfo]) -> Vec<Va
filter_version_id: None, filter_version_id: None,
metadata: Some(vec![BusterChatResponseFileMetadata { metadata: Some(vec![BusterChatResponseFileMetadata {
status: "completed".to_string(), status: "completed".to_string(),
message: format!("Created new {} file.", file_info.file_type), message: format!("Created new {} file", file_info.file_type),
timestamp: Some(Utc::now().timestamp()), timestamp: Some(Utc::now().timestamp()),
}]), }]),
}; };

View File

@ -24,6 +24,9 @@ pub struct LogListItem {
pub created_by_name: String, pub created_by_name: String,
pub created_by_avatar: Option<String>, pub created_by_avatar: Option<String>,
pub last_edited: String, pub last_edited: String,
pub most_recent_file_id: Option<String>,
pub most_recent_file_type: Option<String>,
pub most_recent_version_number: Option<i32>,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
@ -47,6 +50,9 @@ struct ChatWithUser {
pub created_at: DateTime<Utc>, pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>, pub updated_at: DateTime<Utc>,
pub created_by: Uuid, pub created_by: Uuid,
pub most_recent_file_id: Option<Uuid>,
pub most_recent_file_type: Option<String>,
pub most_recent_version_number: Option<i32>,
// User fields // User fields
pub user_name: Option<String>, pub user_name: Option<String>,
pub user_attributes: Value, pub user_attributes: Value,
@ -62,7 +68,7 @@ struct ChatWithUser {
pub async fn list_logs_handler( pub async fn list_logs_handler(
request: ListLogsRequest, request: ListLogsRequest,
organization_id: Uuid, organization_id: Uuid,
) -> Result<Vec<LogListItem>, anyhow::Error> { ) -> Result<ListLogsResponse, anyhow::Error> {
use database::schema::{chats, users}; use database::schema::{chats, users};
let mut conn = get_pg_pool().get().await?; let mut conn = get_pg_pool().get().await?;
@ -78,9 +84,9 @@ pub async fn list_logs_handler(
let page = request.page.unwrap_or(1); let page = request.page.unwrap_or(1);
let offset = (page - 1) * request.page_size; let offset = (page - 1) * request.page_size;
// Order by creation date descending and apply pagination // Order by updated date descending and apply pagination
query = query query = query
.order_by(chats::created_at.desc()) .order_by(chats::updated_at.desc())
.offset(offset as i64) .offset(offset as i64)
.limit((request.page_size + 1) as i64); .limit((request.page_size + 1) as i64);
@ -92,6 +98,9 @@ pub async fn list_logs_handler(
chats::created_at, chats::created_at,
chats::updated_at, chats::updated_at,
chats::created_by, chats::created_by,
chats::most_recent_file_id,
chats::most_recent_file_type,
chats::most_recent_version_number,
users::name.nullable(), users::name.nullable(),
users::attributes, users::attributes,
)) ))
@ -120,16 +129,19 @@ pub async fn list_logs_handler(
created_by_name: chat.user_name.unwrap_or_else(|| "Unknown".to_string()), created_by_name: chat.user_name.unwrap_or_else(|| "Unknown".to_string()),
created_by_avatar, created_by_avatar,
last_edited: chat.updated_at.to_rfc3339(), last_edited: chat.updated_at.to_rfc3339(),
most_recent_file_id: chat.most_recent_file_id.map(|id| id.to_string()),
most_recent_file_type: chat.most_recent_file_type,
most_recent_version_number: chat.most_recent_version_number,
} }
}) })
.collect(); .collect();
// Create pagination info // Create pagination info
let _pagination = PaginationInfo { let pagination = PaginationInfo {
has_more, has_more,
next_page: if has_more { Some(page + 1) } else { None }, next_page: if has_more { Some(page + 1) } else { None },
total_items: items.len() as i32, total_items: items.len() as i32,
}; };
Ok(items) Ok(ListLogsResponse { items, pagination })
} }

View File

@ -50,7 +50,13 @@ middleware = { path = "../libs/middleware" }
sharing = { path = "../libs/sharing" } sharing = { path = "../libs/sharing" }
search = { path = "../libs/search" } search = { path = "../libs/search" }
# Workspace Libraries
dataset_security = { path = "../libs/dataset_security" }
[dev-dependencies] [dev-dependencies]
mockito = { workspace = true } mockito = { workspace = true }
tokio-test = { workspace = true } tokio-test = { workspace = true }
async-trait = { workspace = true } async-trait = { workspace = true }
# Add the new dependency
# dataset_security = { path = "../libs/dataset_security" }

View File

@ -36,7 +36,7 @@ pub async fn list_logs_route(
}; };
match list_logs_handler(request, organization_id).await { match list_logs_handler(request, organization_id).await {
Ok(response) => Ok(ApiResponse::JsonData(response)), Ok(response) => Ok(ApiResponse::JsonData(response.items)),
Err(e) => { Err(e) => {
tracing::error!("Error listing logs: {}", e); tracing::error!("Error listing logs: {}", e);
Err((StatusCode::INTERNAL_SERVER_ERROR, "Failed to list logs")) Err((StatusCode::INTERNAL_SERVER_ERROR, "Failed to list logs"))

View File

@ -4,7 +4,6 @@ use diesel::{BoolExpressionMethods, ExpressionMethods, JoinOnDsl, QueryDsl};
use indexmap::IndexMap; use indexmap::IndexMap;
use query_engine::data_source_query_routes::query_engine::query_engine; use query_engine::data_source_query_routes::query_engine::query_engine;
use query_engine::data_types::DataType; use query_engine::data_types::DataType;
use rayon::iter::ParallelIterator;
use reqwest::StatusCode; use reqwest::StatusCode;
use uuid::Uuid; use uuid::Uuid;
@ -18,9 +17,11 @@ use database::{
types::DataMetadata, types::DataMetadata,
}; };
use crate::{routes::rest::ApiResponse, utils::dataset_security::has_dataset_access}; use dataset_security::has_dataset_access;
use middleware::AuthenticatedUser; use middleware::AuthenticatedUser;
use crate::routes::rest::ApiResponse;
const MAX_UNIQUE_VALUES: usize = 100; const MAX_UNIQUE_VALUES: usize = 100;
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]