test: cover the chat access policy and bootstrap guards
ChatAccess admits only chat-group members to context bm/1 and manages nothing; the chat context oversees nothing and its loader knows only id 1; /chat and /chat/members need a caller and a database. The migration count rises to 15 for the chat group seed.
This commit is contained in:
107
classes/chat_context_test.go
Normal file
107
classes/chat_context_test.go
Normal file
@@ -0,0 +1,107 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user