ok filtering the chats and hiding shareWithChannel for now

This commit is contained in:
dal 2025-07-18 11:32:33 -06:00
parent 0dd82ab1d1
commit d7d4ab6401
No known key found for this signature in database
GPG Key ID: 16F4B0E1E9F61122
4 changed files with 356 additions and 6 deletions

View File

@ -78,7 +78,7 @@ pub async fn list_chats_handler(
request: ListChatsRequest,
user: &AuthenticatedUser,
) -> Result<Vec<ChatListItem>> {
use database::schema::{asset_permissions, chats, messages, users};
use database::schema::{asset_permissions, chats, messages, users, user_favorites};
let mut conn = get_pg_pool().get().await?;
@ -152,7 +152,29 @@ pub async fn list_chats_handler(
// Get user's organization IDs
let user_org_ids: Vec<Uuid> = user.organizations.iter().map(|org| org.id).collect();
// Get user's favorited chat IDs
let favorited_chat_ids: Vec<Uuid> = if !request.admin_view {
asset_permissions::table
.filter(asset_permissions::identity_id.eq(user.id))
.filter(asset_permissions::asset_type.eq(AssetType::Chat))
.filter(asset_permissions::identity_type.eq(IdentityType::User))
.filter(asset_permissions::deleted_at.is_null())
.select(asset_permissions::asset_id)
.union(
user_favorites::table
.filter(user_favorites::user_id.eq(user.id))
.filter(user_favorites::asset_type.eq(AssetType::Chat))
.filter(user_favorites::deleted_at.is_null())
.select(user_favorites::asset_id)
)
.load::<Uuid>(&mut conn)
.await?
} else {
Vec::new()
};
// Second query: Get workspace-shared chats that the user doesn't have direct access to
// but has either contributed to or favorited
let workspace_shared_chats = if !request.admin_view && !user_org_ids.is_empty() {
chats::table
.inner_join(users::table.on(chats::created_by.eq(users::id)))
@ -173,6 +195,24 @@ pub async fn list_chats_handler(
))
)
)
// Only include if user has contributed (created or updated a message) or favorited
.filter(
// User has favorited the chat
chats::id.eq_any(&favorited_chat_ids)
.or(
// User has created a message in the chat
diesel::dsl::exists(
messages::table
.filter(messages::chat_id.eq(chats::id))
.filter(messages::created_by.eq(user.id))
.filter(messages::deleted_at.is_null())
)
)
.or(
// User has updated the chat
chats::updated_by.eq(user.id)
)
)
.filter(
diesel::dsl::exists(
messages::table

View File

@ -0,0 +1,309 @@
use anyhow::Result;
use database::{
enums::{AssetType, WorkspaceSharing},
models::{Chat, Message, UserFavorite},
pool::get_pg_pool,
schema::{chats, messages, user_favorites},
tests::common::db::{TestDb, TestSetup},
};
use diesel::prelude::*;
use diesel_async::RunQueryDsl;
use handlers::chats::{list_chats_handler, ListChatsRequest};
use middleware::UserOrganization;
use uuid::Uuid;
#[tokio::test]
async fn test_workspace_shared_chats_filtered_without_contribution() -> Result<()> {
let setup = TestSetup::new(None).await?;
let mut conn = setup.db.diesel_conn().await?;
// Create another user in the same organization
let other_user = setup.db.create_user("other@example.com", "Other User").await?;
// Create a workspace-shared chat by the other user
let shared_chat = Chat {
id: Uuid::new_v4(),
title: "Shared Chat".to_string(),
organization_id: setup.organization.id,
created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(),
deleted_at: None,
created_by: other_user.id,
updated_by: other_user.id,
publicly_accessible: false,
publicly_enabled_by: None,
public_expiry_date: None,
most_recent_file_id: None,
most_recent_file_type: None,
most_recent_version_number: None,
workspace_sharing: WorkspaceSharing::CanView,
workspace_sharing_enabled_by: Some(other_user.id),
workspace_sharing_enabled_at: Some(chrono::Utc::now()),
};
diesel::insert_into(chats::table)
.values(&shared_chat)
.execute(&mut conn)
.await?;
// Create a message in the chat by the other user
let message = Message {
id: Uuid::new_v4(),
request_message: Some("Test message".to_string()),
response_messages: serde_json::json!({}),
reasoning: serde_json::json!({}),
title: "Test".to_string(),
raw_llm_messages: serde_json::json!({}),
final_reasoning_message: None,
chat_id: shared_chat.id,
created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(),
deleted_at: None,
created_by: other_user.id,
feedback: None,
is_completed: true,
post_processing_message: None,
};
diesel::insert_into(messages::table)
.values(&message)
.execute(&mut conn)
.await?;
// List chats for the test user - should NOT see the shared chat
let request = ListChatsRequest {
page: Some(1),
page_size: 10,
admin_view: false,
};
let auth_user = middleware::AuthenticatedUser {
id: setup.user.id,
email: setup.user.email.clone(),
name: setup.user.name.clone(),
organizations: vec![UserOrganization {
id: setup.organization.id,
name: setup.organization.name.clone(),
}],
};
let result = list_chats_handler(request, &auth_user).await?;
// Should not see the shared chat since user hasn't contributed
assert_eq!(result.len(), 0);
// Clean up
setup.db.cleanup().await?;
Ok(())
}
#[tokio::test]
async fn test_workspace_shared_chats_visible_with_contribution() -> Result<()> {
let setup = TestSetup::new(None).await?;
let mut conn = setup.db.diesel_conn().await?;
// Create another user in the same organization
let other_user = setup.db.create_user("other@example.com", "Other User").await?;
// Create a workspace-shared chat by the other user
let shared_chat = Chat {
id: Uuid::new_v4(),
title: "Shared Chat With Contribution".to_string(),
organization_id: setup.organization.id,
created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(),
deleted_at: None,
created_by: other_user.id,
updated_by: other_user.id,
publicly_accessible: false,
publicly_enabled_by: None,
public_expiry_date: None,
most_recent_file_id: None,
most_recent_file_type: None,
most_recent_version_number: None,
workspace_sharing: WorkspaceSharing::CanView,
workspace_sharing_enabled_by: Some(other_user.id),
workspace_sharing_enabled_at: Some(chrono::Utc::now()),
};
diesel::insert_into(chats::table)
.values(&shared_chat)
.execute(&mut conn)
.await?;
// Create a message by the other user
let message1 = Message {
id: Uuid::new_v4(),
request_message: Some("Other user message".to_string()),
response_messages: serde_json::json!({}),
reasoning: serde_json::json!({}),
title: "Test".to_string(),
raw_llm_messages: serde_json::json!({}),
final_reasoning_message: None,
chat_id: shared_chat.id,
created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(),
deleted_at: None,
created_by: other_user.id,
feedback: None,
is_completed: true,
post_processing_message: None,
};
diesel::insert_into(messages::table)
.values(&message1)
.execute(&mut conn)
.await?;
// Create a message by the test user (contribution)
let message2 = Message {
id: Uuid::new_v4(),
request_message: Some("Test user message".to_string()),
response_messages: serde_json::json!({}),
reasoning: serde_json::json!({}),
title: "Test".to_string(),
raw_llm_messages: serde_json::json!({}),
final_reasoning_message: None,
chat_id: shared_chat.id,
created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(),
deleted_at: None,
created_by: setup.user.id, // Test user contributes
feedback: None,
is_completed: true,
post_processing_message: None,
};
diesel::insert_into(messages::table)
.values(&message2)
.execute(&mut conn)
.await?;
// List chats for the test user - should see the shared chat
let request = ListChatsRequest {
page: Some(1),
page_size: 10,
admin_view: false,
};
let auth_user = middleware::AuthenticatedUser {
id: setup.user.id,
email: setup.user.email.clone(),
name: setup.user.name.clone(),
organizations: vec![UserOrganization {
id: setup.organization.id,
name: setup.organization.name.clone(),
}],
};
let result = list_chats_handler(request, &auth_user).await?;
// Should see the shared chat since user has contributed
assert_eq!(result.len(), 1);
assert_eq!(result[0].name, "Shared Chat With Contribution");
// Clean up
setup.db.cleanup().await?;
Ok(())
}
#[tokio::test]
async fn test_workspace_shared_chats_visible_when_favorited() -> Result<()> {
let setup = TestSetup::new(None).await?;
let mut conn = setup.db.diesel_conn().await?;
// Create another user in the same organization
let other_user = setup.db.create_user("other@example.com", "Other User").await?;
// Create a workspace-shared chat by the other user
let shared_chat = Chat {
id: Uuid::new_v4(),
title: "Favorited Shared Chat".to_string(),
organization_id: setup.organization.id,
created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(),
deleted_at: None,
created_by: other_user.id,
updated_by: other_user.id,
publicly_accessible: false,
publicly_enabled_by: None,
public_expiry_date: None,
most_recent_file_id: None,
most_recent_file_type: None,
most_recent_version_number: None,
workspace_sharing: WorkspaceSharing::CanView,
workspace_sharing_enabled_by: Some(other_user.id),
workspace_sharing_enabled_at: Some(chrono::Utc::now()),
};
diesel::insert_into(chats::table)
.values(&shared_chat)
.execute(&mut conn)
.await?;
// Create a message by the other user
let message = Message {
id: Uuid::new_v4(),
request_message: Some("Other user message".to_string()),
response_messages: serde_json::json!({}),
reasoning: serde_json::json!({}),
title: "Test".to_string(),
raw_llm_messages: serde_json::json!({}),
final_reasoning_message: None,
chat_id: shared_chat.id,
created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(),
deleted_at: None,
created_by: other_user.id,
feedback: None,
is_completed: true,
post_processing_message: None,
};
diesel::insert_into(messages::table)
.values(&message)
.execute(&mut conn)
.await?;
// Add the chat to user's favorites
let favorite = UserFavorite {
user_id: setup.user.id,
asset_id: shared_chat.id,
asset_type: AssetType::Chat,
order_index: 0,
created_at: chrono::Utc::now(),
deleted_at: None,
};
diesel::insert_into(user_favorites::table)
.values(&favorite)
.execute(&mut conn)
.await?;
// List chats for the test user - should see the shared chat
let request = ListChatsRequest {
page: Some(1),
page_size: 10,
admin_view: false,
};
let auth_user = middleware::AuthenticatedUser {
id: setup.user.id,
email: setup.user.email.clone(),
name: setup.user.name.clone(),
organizations: vec![UserOrganization {
id: setup.organization.id,
name: setup.organization.name.clone(),
}],
};
let result = list_chats_handler(request, &auth_user).await?;
// Should see the shared chat since user has favorited it
assert_eq!(result.len(), 1);
assert_eq!(result[0].name, "Favorited Shared Chat");
// Clean up
setup.db.cleanup().await?;
Ok(())
}

View File

@ -33,3 +33,4 @@ pub mod sharing;
pub mod metrics;
pub mod dashboards;
pub mod collections;
pub mod chats_list_filter_test;

View File

@ -231,11 +231,11 @@ const SlackSharingPermissions = React.memo(() => {
value: 'shareWithWorkspace',
secondaryLabel: 'All workspace members will have access to any chat created from any channel.'
},
{
label: 'Channel',
value: 'shareWithChannel',
secondaryLabel: 'All channel members will have access to any chat created from that channel.'
},
// {
// label: 'Channel',
// value: 'shareWithChannel',
// secondaryLabel: 'All channel members will have access to any chat created from that channel.'
// },
{
label: 'None',
value: 'noSharing',