fix: skip canonical ID parsing for @-prefixed allow_from entries

Matrix user IDs (@user:server) were incorrectly parsed as canonical
IDs (platform:id), causing allow_from matching to always fail.

Skip canonical parsing when the entry starts with '@', and match
PlatformID/Username against the original value (with '@') for
platforms like Matrix where IDs include '@'.

Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
liaoyinglong 2026-03-30 16:14:38 +08:00
parent 5e1b6a3971
commit 05b1915278
2 changed files with 54 additions and 13 deletions

View file

@ -44,18 +44,22 @@ func MatchAllowed(sender bus.SenderInfo, allowed string) bool {
return false
}
// Try canonical match first: "platform:id" format
if platform, id, ok := ParseCanonicalID(allowed); ok {
// Only treat as canonical if the platform portion looks like a known platform name
// (not a pure-numeric string, which could be a compound ID)
if !isNumeric(platform) {
candidate := BuildCanonicalID(platform, id)
if candidate != "" && sender.CanonicalID != "" {
return strings.EqualFold(sender.CanonicalID, candidate)
// Try canonical match first: "platform:id" format.
// Skip when allowed starts with "@" — that indicates a username
// (e.g., Matrix user IDs like "@alice:matrix.org"), not a canonical ID.
if !strings.HasPrefix(allowed, "@") {
if platform, id, ok := ParseCanonicalID(allowed); ok {
// Only treat as canonical if the platform portion looks like a known platform name
// (not a pure-numeric string, which could be a compound ID)
if !isNumeric(platform) {
candidate := BuildCanonicalID(platform, id)
if candidate != "" && sender.CanonicalID != "" {
return strings.EqualFold(sender.CanonicalID, candidate)
}
// If sender has no canonical ID, try matching platform + platformID
return strings.EqualFold(platform, sender.Platform) &&
sender.PlatformID == id
}
// If sender has no canonical ID, try matching platform + platformID
return strings.EqualFold(platform, sender.Platform) &&
sender.PlatformID == id
}
}
@ -78,8 +82,18 @@ func MatchAllowed(sender bus.SenderInfo, allowed string) bool {
return true
}
// Match against Username only when explicitly requested via "@username"
if isAtUsername && sender.Username != "" && sender.Username == trimmed {
// Match against Username only when explicitly requested via "@username".
// Compare against both the trimmed value and the original allowed value,
// because some platforms (e.g., Matrix) include "@" in their user IDs.
if isAtUsername && sender.Username != "" {
if sender.Username == trimmed || sender.Username == allowed {
return true
}
}
// Also try matching PlatformID against the original "@..." value
// for platforms where PlatformID itself contains "@" (e.g., Matrix "@user:server").
if isAtUsername && sender.PlatformID != "" && sender.PlatformID == allowed {
return true
}

View file

@ -78,6 +78,14 @@ func TestMatchAllowed(t *testing.T) {
Username: "carol",
}
matrixSender := bus.SenderInfo{
Platform: "matrix",
PlatformID: "@example:matrix.org",
CanonicalID: "matrix:@example:matrix.org",
Username: "@example:matrix.org",
DisplayName: "@example:matrix.org",
}
tests := []struct {
name string
sender bus.SenderInfo
@ -223,6 +231,25 @@ func TestMatchAllowed(t *testing.T) {
allowed: " 123456 ",
want: true,
},
// Matrix user ID format "@user:server"
{
name: "matrix user ID matches via @username",
sender: matrixSender,
allowed: "@example:matrix.org",
want: true,
},
{
name: "matrix canonical format also works",
sender: matrixSender,
allowed: "matrix:@example:matrix.org",
want: true,
},
{
name: "matrix user ID wrong user does not match",
sender: matrixSender,
allowed: "@other:matrix.org",
want: false,
},
}
for _, tt := range tests {