Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions internal/dao/kb.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,12 @@ func (dao *KnowledgebaseDAO) GetDetail(kbID string) (*entity.KnowledgebaseDetail
func (dao *KnowledgebaseDAO) Accessible(kbID, userID string) bool {
var count int64
err := DB.Table("knowledgebase").
Joins("JOIN user_tenant ON user_tenant.tenant_id = knowledgebase.tenant_id").
Where("knowledgebase.id = ? AND user_tenant.user_id = ? AND knowledgebase.status = ?",
kbID, userID, string(entity.StatusValid)).
Joins("LEFT JOIN user_tenant ON user_tenant.tenant_id = knowledgebase.tenant_id AND user_tenant.user_id = ?", userID).
Where(`knowledgebase.id = ? AND knowledgebase.status = ? AND (
knowledgebase.created_by = ? OR
knowledgebase.tenant_id = ? OR
(knowledgebase.permission = ? AND user_tenant.user_id IS NOT NULL)
)`, kbID, string(entity.StatusValid), userID, userID, string(entity.TenantPermissionTeam)).
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
Count(&count).Error

if err != nil {
Expand Down
96 changes: 86 additions & 10 deletions internal/dao/kb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ func setupKBTestDB(t *testing.T) *gorm.DB {
t.Fatalf("failed to open sqlite: %v", err)
}

// Migrate knowledgebase table
if err := db.AutoMigrate(&entity.Knowledgebase{}); err != nil {
// Migrate tables needed by KB access checks.
if err := db.AutoMigrate(&entity.Knowledgebase{}, &entity.UserTenant{}); err != nil {
t.Fatalf("failed to migrate: %v", err)
}

Expand All @@ -47,21 +47,39 @@ func setupKBTestDB(t *testing.T) *gorm.DB {
func testKnowledgebase(t *testing.T, db *gorm.DB, id string, docNum, tokenNum, chunkNum int64) *entity.Knowledgebase {
t.Helper()
kb := &entity.Knowledgebase{
ID: id,
TenantID: "tenant-1",
Name: "test-kb-" + id,
EmbdID: "embd-1",
DocNum: docNum,
TokenNum: tokenNum,
ChunkNum: chunkNum,
Status: stringPtr(string(entity.StatusValid)),
ID: id,
TenantID: "tenant-1",
Name: "test-kb-" + id,
EmbdID: "embd-1",
CreatedBy: "tenant-1",
Permission: string(entity.TenantPermissionMe),
DocNum: docNum,
TokenNum: tokenNum,
ChunkNum: chunkNum,
Status: stringPtr(string(entity.StatusValid)),
}
if err := db.Create(kb).Error; err != nil {
t.Fatalf("failed to create test kb: %v", err)
}
return kb
}

func testUserTenant(t *testing.T, db *gorm.DB, id, userID, tenantID string) {
t.Helper()
status := string(entity.StatusValid)
userTenant := &entity.UserTenant{
ID: id,
UserID: userID,
TenantID: tenantID,
Role: "normal",
InvitedBy: tenantID,
Status: &status,
}
if err := db.Create(userTenant).Error; err != nil {
t.Fatalf("failed to create test user_tenant: %v", err)
}
}

func stringPtr(s string) *string {
return &s
}
Expand Down Expand Up @@ -119,3 +137,61 @@ func TestKnowledgebaseDAO_DecreaseDocumentNum_ZeroDecrement(t *testing.T) {
t.Fatalf("chunk_num should be unchanged: expected 15, got %d", kb.ChunkNum)
}
}

func TestKnowledgebaseDAO_AccessibleAllowsOwnerForPrivateKnowledgebase(t *testing.T) {
db := setupKBTestDB(t)
pushDB(t, db)
dao := NewKnowledgebaseDAO()

testKnowledgebase(t, db, "kb-private", 0, 0, 0)

if !dao.Accessible("kb-private", "tenant-1") {
t.Fatal("owner should access a private knowledgebase")
}
}

func TestKnowledgebaseDAO_AccessibleRejectsTenantMemberForPrivateKnowledgebase(t *testing.T) {
db := setupKBTestDB(t)
pushDB(t, db)
dao := NewKnowledgebaseDAO()

testKnowledgebase(t, db, "kb-private", 0, 0, 0)
testUserTenant(t, db, "ut-1", "member-1", "tenant-1")

if dao.Accessible("kb-private", "member-1") {
t.Fatal("tenant member should not access a private knowledgebase")
}
}

func TestKnowledgebaseDAO_AccessibleAllowsTenantMemberForTeamKnowledgebase(t *testing.T) {
db := setupKBTestDB(t)
pushDB(t, db)
dao := NewKnowledgebaseDAO()

kb := testKnowledgebase(t, db, "kb-team", 0, 0, 0)
kb.Permission = string(entity.TenantPermissionTeam)
if err := db.Save(kb).Error; err != nil {
t.Fatalf("failed to update test kb permission: %v", err)
}
testUserTenant(t, db, "ut-1", "member-1", "tenant-1")

if !dao.Accessible("kb-team", "member-1") {
t.Fatal("tenant member should access a team knowledgebase")
}
}

func TestKnowledgebaseDAO_AccessibleRejectsUnrelatedUserForTeamKnowledgebase(t *testing.T) {
db := setupKBTestDB(t)
pushDB(t, db)
dao := NewKnowledgebaseDAO()

kb := testKnowledgebase(t, db, "kb-team", 0, 0, 0)
kb.Permission = string(entity.TenantPermissionTeam)
if err := db.Save(kb).Error; err != nil {
t.Fatalf("failed to update test kb permission: %v", err)
}

if dao.Accessible("kb-team", "stranger-1") {
t.Fatal("unrelated user should not access a team knowledgebase")
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.