package system import ( "context" "kra/internal/biz/system" "strings" "testing" "kra/internal/config" ) func newPolicyTestData(t *testing.T) *Data { t.Helper() db, err := openWithDriver("sqlite", "file:"+t.Name()+"?mode=memory&cache=shared") if err != nil { t.Fatal(err) } if err := db.AutoMigrate(&apiPO{}, &casbinRulePO{}, &authorityPO{}, &authorityAPIPO{}); err != nil { t.Fatal(err) } data := &Data{ gormDB: newReloadableDB(db, nil), runtime: config.NewStore( &config.Config{ Data: &config.Data{Database: &config.Database{Driver: "sqlite"}}, Admin: &config.Admin{System: &config.System{UseStrictAuth: true}}, }, ), } t.Cleanup(func() { data.gormDB.close() }) return data } func apiPolicyUintPointer(value uint) *uint { return &value } func TestSetPolicyPathsStrictRootRequiresRegisteredAPI(t *testing.T) { data := newPolicyTestData(t) ctx := system.NewActorContext(context.Background(), system.Actor{AuthorityID: 888}) if err := data.gormDB.WithContext(ctx).Create(&[]authorityPO{ {AuthorityID: 888, ParentID: apiPolicyUintPointer(0)}, {AuthorityID: 999, ParentID: apiPolicyUintPointer(888)}, }).Error; err != nil { t.Fatal(err) } if err := data.gormDB.WithContext(ctx).Create(&apiPO{Path: "/known", Method: "POST"}).Error; err != nil { t.Fatal(err) } err := (&apiRepo{data: data}).SetPolicyPaths(ctx, 999, []*system.API{{Path: "/unknown", Method: "POST"}}) if err == nil || !strings.Contains(err.Error(), "存在api不在权限列表中") { t.Fatalf("unregistered root assignment error = %v", err) } if err := (&apiRepo{data: data}).SetPolicyPaths(ctx, 999, []*system.API{{Path: "/known", Method: "POST"}}); err != nil { t.Fatal(err) } } func TestSetPolicyPathsStrictChildRejectsStalePolicy(t *testing.T) { data := newPolicyTestData(t) ctx := system.NewActorContext(context.Background(), system.Actor{AuthorityID: 1001}) if err := data.gormDB.WithContext(ctx).Create(&[]authorityPO{ {AuthorityID: 888, ParentID: apiPolicyUintPointer(0)}, {AuthorityID: 1001, ParentID: apiPolicyUintPointer(888)}, {AuthorityID: 1002, ParentID: apiPolicyUintPointer(1001)}, }).Error; err != nil { t.Fatal(err) } if err := data.gormDB.WithContext(ctx).Create(&apiPO{Path: "/known", Method: "POST"}).Error; err != nil { t.Fatal(err) } if err := data.gormDB.WithContext(ctx).Create(&[]casbinRulePO{ newPolicyRule(1001, "/known", "POST"), newPolicyRule(1001, "/stale", "POST"), }).Error; err != nil { t.Fatal(err) } err := (&apiRepo{data: data}).SetPolicyPaths(ctx, 1002, []*system.API{{Path: "/stale", Method: "POST"}}) if err == nil || !strings.Contains(err.Error(), "存在api不在权限列表中") { t.Fatalf("stale child assignment error = %v", err) } if err := (&apiRepo{data: data}).SetPolicyPaths(ctx, 1002, []*system.API{{Path: "/known", Method: "POST"}}); err != nil { t.Fatal(err) } } func TestSetPolicyPathsUsesCompatibleDedupeKey(t *testing.T) { data := newPolicyTestData(t) ctx := system.NewActorContext(context.Background(), system.Actor{AuthorityID: 888}) if err := data.gormDB.WithContext(ctx).Create(&[]authorityPO{ {AuthorityID: 888, ParentID: apiPolicyUintPointer(0)}, {AuthorityID: 999, ParentID: apiPolicyUintPointer(888)}, }).Error; err != nil { t.Fatal(err) } if err := data.gormDB.WithContext(ctx).Create(&[]apiPO{ {Path: "/a", Method: "BC"}, {Path: "/aB", Method: "C"}, }).Error; err != nil { t.Fatal(err) } if err := (&apiRepo{data: data}).SetPolicyPaths(ctx, 999, []*system.API{ {Path: "/a", Method: "BC"}, {Path: "/aB", Method: "C"}, }); err != nil { t.Fatal(err) } rows, err := policyRowsForAuthority(data.gormDB.WithContext(ctx), 999) if err != nil { t.Fatal(err) } if len(rows) != 1 || rows[0].V1 != "/a" || rows[0].V2 != "BC" { t.Fatalf("deduplicated policies = %#v, want only the first concatenated-key match", rows) } } func TestCheckPolicyStore(t *testing.T) { data := newPolicyTestData(t) repo := &apiRepo{data: data} if err := repo.CheckPolicyStore(context.Background()); err != nil { t.Fatalf("CheckPolicyStore returned error for migrated table: %v", err) } if err := data.gormDB.WithContext(context.Background()).Migrator().DropTable(&casbinRulePO{}); err != nil { t.Fatal(err) } if err := repo.CheckPolicyStore(context.Background()); err == nil { t.Fatal("CheckPolicyStore succeeded after casbin_rule was dropped") } } func TestSetAPIRolesStrictOnlyChangesManagedAuthorities(t *testing.T) { data := newPolicyTestData(t) db := data.gormDB.WithContext(context.Background()) rootID, actorID, childID, siblingID := uint(888), uint(2001), uint(2002), uint(3001) if err := db.Create(&[]authorityPO{ {AuthorityID: rootID, ParentID: apiPolicyUintPointer(0)}, {AuthorityID: actorID, ParentID: &rootID}, {AuthorityID: childID, ParentID: &actorID}, {AuthorityID: siblingID, ParentID: &rootID}, }).Error; err != nil { t.Fatal(err) } if err := db.Create(&apiPO{Path: "/known", Method: "POST"}).Error; err != nil { t.Fatal(err) } if err := db.Create(&[]casbinRulePO{ newPolicyRule(actorID, "/known", "POST"), newPolicyRule(siblingID, "/known", "POST"), }).Error; err != nil { t.Fatal(err) } ctx := system.NewActorContext(context.Background(), system.Actor{AuthorityID: actorID}) repo := &apiRepo{data: data} if err := repo.SetAPIRoles(ctx, "/known", "POST", []uint{siblingID}); err == nil { t.Fatal("SetAPIRoles() accepted an out-of-scope authority") } if err := repo.SetAPIRoles(ctx, "/known", "POST", []uint{childID}); err != nil { t.Fatalf("SetAPIRoles() rejected a managed authority: %v", err) } if exists, err := policyExists(db, siblingID, "/known", "POST"); err != nil || !exists { t.Fatalf("out-of-scope policy exists=%v err=%v, want preserved", exists, err) } if exists, err := policyExists(db, childID, "/known", "POST"); err != nil || !exists { t.Fatalf("managed policy exists=%v err=%v, want added", exists, err) } }