Read admin lookup maps under client lock

This commit is contained in:
Brandon McGinty (chatgpt)
2026-08-09 18:30:46 -04:00
committed by Brandon McGinty
parent 7ebe764d82
commit 98a29a6470
2 changed files with 48 additions and 22 deletions
+34 -22
View File
@@ -83,7 +83,9 @@ func (b *Barnard) OpenAdminMenu() {
if b.adminTargetChan != nil { if b.adminTargetChan != nil {
b.adminTargetChan.RequestPermission() b.adminTargetChan.RequestPermission()
} }
if root := b.Client.Channels[0]; root != nil && root != b.adminTargetChan { var root *gumble.Channel
b.Client.Do(func() { root = b.Client.Channels[0] })
if root != nil && root != b.adminTargetChan {
root.RequestPermission() root.RequestPermission()
} }
b.UiAdmin.Rebuild() b.UiAdmin.Rebuild()
@@ -964,39 +966,47 @@ func (b *Barnard) findOrCreateACLRule(subjectType, subject string) *gumble.ACLRu
} }
} }
func (b *Barnard) findUser(token string) *gumble.User { func (b *Barnard) findUser(token string) (found *gumble.User) {
if b.Client == nil { if b.Client == nil {
return nil return nil
} }
if session, err := strconv.ParseUint(token, 10, 32); err == nil { b.Client.Do(func() {
if user := b.Client.Users[uint32(session)]; user != nil { if session, err := strconv.ParseUint(token, 10, 32); err == nil {
return user found = b.Client.Users[uint32(session)]
if found != nil {
return
}
} }
} for _, user := range b.Client.Users {
for _, user := range b.Client.Users { if strings.EqualFold(user.Name, token) {
if strings.EqualFold(user.Name, token) { found = user
return user return
}
} }
} })
return nil return found
} }
func (b *Barnard) findChannel(token string) *gumble.Channel { func (b *Barnard) findChannel(token string) (found *gumble.Channel) {
if b.Client == nil { if b.Client == nil {
return nil return nil
} }
token = strings.TrimSpace(token) token = strings.TrimSpace(token)
if id, err := strconv.ParseUint(token, 10, 32); err == nil { b.Client.Do(func() {
if channel := b.Client.Channels[uint32(id)]; channel != nil { if id, err := strconv.ParseUint(token, 10, 32); err == nil {
return channel found = b.Client.Channels[uint32(id)]
if found != nil {
return
}
} }
} for _, channel := range b.Client.Channels {
for _, channel := range b.Client.Channels { if strings.EqualFold(channel.Name, token) {
if strings.EqualFold(channel.Name, token) { found = channel
return channel return
}
} }
} })
return nil return found
} }
func (b *Barnard) findRegisteredUser(token string) *gumble.RegisteredUser { func (b *Barnard) findRegisteredUser(token string) *gumble.RegisteredUser {
@@ -1019,7 +1029,9 @@ func (b *Barnard) adminCanRoot(permission gumble.Permission) bool {
if b.Client == nil { if b.Client == nil {
return true return true
} }
return b.adminCanChannel(b.Client.Channels[0], permission) var root *gumble.Channel
b.Client.Do(func() { root = b.Client.Channels[0] })
return b.adminCanChannel(root, permission)
} }
func (b *Barnard) adminCanChannel(channel *gumble.Channel, permission gumble.Permission) bool { func (b *Barnard) adminCanChannel(channel *gumble.Channel, permission gumble.Permission) bool {
+14
View File
@@ -7,6 +7,20 @@ import (
"git.stormux.org/storm/barnard/uiterm" "git.stormux.org/storm/barnard/uiterm"
) )
// Regression: admin lookup helpers read Client.Users and Client.Channels while
// TCP handlers could mutate those maps.
func TestAdminLookupUsesClientSnapshot(t *testing.T) {
user := &gumble.User{Session: 7, Name: "Guest"}
channel := &gumble.Channel{ID: 4, Name: "Room"}
b := &Barnard{Client: &gumble.Client{Users: gumble.Users{7: user}, Channels: gumble.Channels{4: channel}}}
if b.findUser("guest") != user || b.findUser("7") != user {
t.Fatal("user lookup failed")
}
if b.findChannel("room") != channel || b.findChannel("4") != channel {
t.Fatal("channel lookup failed")
}
}
func TestParseToggleState(t *testing.T) { func TestParseToggleState(t *testing.T) {
tests := []struct { tests := []struct {
name string name string