107 lines
3.2 KiB
Go
107 lines
3.2 KiB
Go
package data
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
|
|
"kra/internal/biz"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type dataScopeRecord struct {
|
|
ID uint `gorm:"primaryKey"`
|
|
DeptID uint
|
|
CreatedBy uint
|
|
Name string
|
|
}
|
|
|
|
func (dataScopeRecord) TableName() string { return "business_scope_records" }
|
|
|
|
func newDataScopeTestDB(t *testing.T) *gorm.DB {
|
|
t.Helper()
|
|
db, err := openWithDriver("sqlite", "file:"+t.Name()+"?mode=memory&cache=shared")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := db.AutoMigrate(&dataScopeRecord{}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
registerDataScopeCallbacks(db, nil)
|
|
sqlDB, err := db.DB()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Cleanup(func() { _ = sqlDB.Close() })
|
|
return db
|
|
}
|
|
|
|
func TestDataScopeCallbacksFailClosedAndAllowExplicitSystemBypass(t *testing.T) {
|
|
db := newDataScopeTestDB(t)
|
|
seed := []dataScopeRecord{
|
|
{DeptID: 10, CreatedBy: 7, Name: "visible"},
|
|
{DeptID: 20, CreatedBy: 8, Name: "hidden"},
|
|
{DeptID: 0, CreatedBy: 9, Name: "unassigned"},
|
|
}
|
|
if err := db.Set("data_scope:skip", true).Create(&seed).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
var rows []dataScopeRecord
|
|
if err := db.WithContext(context.Background()).Find(&rows).Error; !errors.Is(err, errDataScopeRequired) {
|
|
t.Fatalf("query without data scope error = %v", err)
|
|
}
|
|
|
|
invalidCtx := biz.NewDataScopeContext(context.Background(), biz.DataScope{UserID: 7, AuthorityID: 1, Scope: 1, All: false})
|
|
if err := db.WithContext(invalidCtx).Find(&rows).Error; !errors.Is(err, errInvalidDataScope) {
|
|
t.Fatalf("query with invalid data scope error = %v", err)
|
|
}
|
|
|
|
scopedCtx := biz.NewDataScopeContext(context.Background(), biz.DataScope{UserID: 7, AuthorityID: 1, Scope: 3, DepartmentIDs: []uint{10}})
|
|
rows = nil
|
|
if err := db.WithContext(scopedCtx).Order("id").Find(&rows).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(rows) != 1 || rows[0].Name != "visible" {
|
|
t.Fatalf("scoped query rows = %+v", rows)
|
|
}
|
|
|
|
emptyCtx := biz.NewDataScopeContext(context.Background(), biz.DataScope{UserID: 7, AuthorityID: 1, Scope: 5})
|
|
rows = nil
|
|
if err := db.WithContext(emptyCtx).Find(&rows).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(rows) != 0 {
|
|
t.Fatalf("empty custom scope exposed rows: %+v", rows)
|
|
}
|
|
|
|
rows = nil
|
|
if err := db.Set("data_scope:skip", true).Order("id").Find(&rows).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(rows) != len(seed) {
|
|
t.Fatalf("explicit system bypass rows = %d, want %d", len(rows), len(seed))
|
|
}
|
|
}
|
|
|
|
func TestDataScopeCreateRequiresIdentityAndStampsOwnership(t *testing.T) {
|
|
db := newDataScopeTestDB(t)
|
|
if err := db.Create(&dataScopeRecord{Name: "missing"}).Error; !errors.Is(err, errDataScopeRequired) {
|
|
t.Fatalf("create without data scope error = %v", err)
|
|
}
|
|
|
|
ctx := biz.NewDataScopeContext(context.Background(), biz.DataScope{UserID: 7, AuthorityID: 1, Scope: 3, PrimaryDeptID: 10, DepartmentIDs: []uint{10}})
|
|
created := dataScopeRecord{Name: "owned", DeptID: 999, CreatedBy: 999}
|
|
if err := db.WithContext(ctx).Create(&created).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var stored dataScopeRecord
|
|
if err := db.Set("data_scope:skip", true).First(&stored, created.ID).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if stored.DeptID != 10 || stored.CreatedBy != 7 {
|
|
t.Fatalf("stamped ownership = dept:%d user:%d, want 10/7", stored.DeptID, stored.CreatedBy)
|
|
}
|
|
}
|