package bm import ( "context" "errors" "testing" "git.golem15.com/golem15/summercms/modules/backpack" "git.golem15.com/golem15/summercms/modules/compass" "gorm.io/gorm" ) // watchPlugin builds jz.bm on an app with a published (fake) database // unless noDB, and the given materials channel check. func watchPlugin(t *testing.T, noDB bool, watch func(context.Context, *gorm.DB, uint, uint) (bool, error)) *Plugin { t.Helper() cfg, err := compass.Open(compass.Options{Dir: t.TempDir(), Environ: []string{"SUMMER_ENV=testing"}}) if err != nil { t.Fatal(err) } app := backpack.New(cfg) if !noDB { if err := app.Publish[*gorm.DB](&gorm.DB{}); err != nil { t.Fatal(err) } } return &Plugin{app: app, watchMaterial: watch} } func TestAuthorizeMaterial(t *testing.T) { ctx := context.Background() type call struct{ userID, id uint } var calls []call watch := func(_ context.Context, _ *gorm.DB, userID, id uint) (bool, error) { calls = append(calls, call{userID, id}) switch userID { case 7: return true, nil case 13: return false, errors.New("database down") } return false, nil } p := watchPlugin(t, false, watch) if res := p.authorizeMaterial(ctx, 7, "materials:5"); !res.Allowed { t.Errorf("manager on materials:5 denied: %s", res.Reason()) } if len(calls) != 1 || calls[0] != (call{7, 5}) { t.Errorf("seam calls %v, want [{7 5}]", calls) } for _, ch := range []string{"materials:5abc", "materials:05", "materials:0", "materials:5:x", "presence:materials:5", "materials:", "materials"} { calls = nil res := p.authorizeMaterial(ctx, 7, ch) if res.Allowed { t.Errorf("%q allowed", ch) } if res.Reason() != "malformed material channel" { t.Errorf("%q: reason %q", ch, res.Reason()) } if len(calls) != 0 { t.Errorf("%q called the seam: %v", ch, calls) } } if res := p.authorizeMaterial(ctx, 13, "materials:5"); res.Allowed || res.Reason() != "material lookup failed" { t.Errorf("seam error: allowed %v, reason %q", res.Allowed, res.Reason()) } if res := p.authorizeMaterial(ctx, 8, "materials:5"); res.Allowed || res.Reason() != "not the material's manager" { t.Errorf("non-manager: allowed %v, reason %q", res.Allowed, res.Reason()) } calls = nil noDB := watchPlugin(t, true, watch) if res := noDB.authorizeMaterial(ctx, 7, "materials:5"); res.Allowed || res.Reason() != "database unavailable" { t.Errorf("no database: allowed %v, reason %q", res.Allowed, res.Reason()) } if len(calls) != 0 { t.Errorf("no database called the seam: %v", calls) } }