package classes_test import ( "context" "errors" "testing" "git.golem15.com/jakub/sm-bm-plugin/classes" "gorm.io/gorm" ) // members is an injected group check: user 7 is in studenci, user 9 is in // moderatorzy only, user 13 makes the check fail. func members(_ context.Context, _ *gorm.DB, userID uint, group string) (bool, error) { switch { case userID == 13: return false, errors.New("database down") case group == "studenci": return userID == 7, nil case group == "moderatorzy": return userID == 9 || userID == 7, nil } return false, nil } func TestChatAccess(t *testing.T) { db := func() *gorm.DB { return &gorm.DB{} } access := classes.NewChatAccess(db, "studenci", members) ctx := t.Context() for _, c := range []struct { name string userID uint contextType string contextID uint want bool }{ {"member of bm/1", 7, "bm", 1, true}, {"other context type", 7, "channel", 1, false}, {"other context id", 7, "bm", 2, false}, {"non-member", 8, "bm", 1, false}, {"moderator only", 9, "bm", 1, false}, {"check fails", 13, "bm", 1, false}, {"no user", 0, "bm", 1, false}, } { if got := access.CanAccessContext(ctx, c.userID, c.contextType, c.contextID); got != c.want { t.Errorf("%s: CanAccessContext = %v, want %v", c.name, got, c.want) } if access.CanManageContext(ctx, c.userID, c.contextType, c.contextID) { t.Errorf("%s: CanManageContext = true; nobody creates channels", c.name) } } noDB := classes.NewChatAccess(func() *gorm.DB { return nil }, "studenci", members) if noDB.CanAccessContext(ctx, 7, "bm", 1) { t.Error("CanAccessContext without a database = true, want false") } nilFunc := classes.NewChatAccess(nil, "studenci", members) if nilFunc.CanAccessContext(ctx, 7, "bm", 1) { t.Error("CanAccessContext without a database func = true, want false") } noGroup := classes.NewChatAccess(db, "", members) if noGroup.CanAccessContext(ctx, 7, "bm", 1) { t.Error("CanAccessContext without a chat group = true, want false") } } func TestChatContext(t *testing.T) { ctx := t.Context() c := classes.NewChatContext(&gorm.DB{}, "studenci", "moderatorzy").WithMembership(members) if c.ID() != classes.ChatContextID || c.ID() != 1 || c.Type() != "bm" { t.Errorf("context = %s/%d, want bm/1", c.Type(), c.ID()) } if !c.ChatEnabled() || c.GroupName() != "ogólny" { t.Errorf("ChatEnabled %v GroupName %q", c.ChatEnabled(), c.GroupName()) } if c.BroadcastChannel() != "chat:context:1" { t.Errorf("BroadcastChannel = %q, want chat:context:1", c.BroadcastChannel()) } for _, id := range []uint{7, 9, 8} { if ok, err := c.CanOverseeChats(ctx, id); ok || err != nil { t.Errorf("CanOverseeChats(%d) = %v, %v; nobody oversees", id, ok, err) } } if ok, err := c.HasMember(ctx, 7); !ok || err != nil { t.Errorf("HasMember(7) = %v, %v, want true", ok, err) } if ok, err := c.HasMember(ctx, 9); ok || err != nil { t.Errorf("HasMember(9) = %v, %v, want false (moderator group only)", ok, err) } if ok, _ := c.HasMember(ctx, 0); ok { t.Error("HasMember(0) = true") } if _, err := c.HasMember(ctx, 13); err == nil { t.Error("HasMember with a failing check returned no error") } if !c.CanActFor(ctx, 7, 7) || c.CanActFor(ctx, 7, 8) { t.Error("CanActFor is not self-only") } load := classes.ChatContextLoader(func() string { return "studenci" }, func() string { return "moderatorzy" }) if got, err := load(ctx, &gorm.DB{}, 2); got != nil || err != nil { t.Errorf("loader(2) = %v, %v, want nil, nil", got, err) } got, err := load(ctx, &gorm.DB{}, 1) if err != nil || got == nil || got.ID() != 1 || got.Type() != "bm" { t.Errorf("loader(1) = %v, %v, want the bm/1 context", got, err) } }