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 return false
} }
// Try canonical match first: "platform:id" format // Try canonical match first: "platform:id" format.
if platform, id, ok := ParseCanonicalID(allowed); ok { // Skip when allowed starts with "@" — that indicates a username
// Only treat as canonical if the platform portion looks like a known platform name // (e.g., Matrix user IDs like "@alice:matrix.org"), not a canonical ID.
// (not a pure-numeric string, which could be a compound ID) if !strings.HasPrefix(allowed, "@") {
if !isNumeric(platform) { if platform, id, ok := ParseCanonicalID(allowed); ok {
candidate := BuildCanonicalID(platform, id) // Only treat as canonical if the platform portion looks like a known platform name
if candidate != "" && sender.CanonicalID != "" { // (not a pure-numeric string, which could be a compound ID)
return strings.EqualFold(sender.CanonicalID, candidate) 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 return true
} }
// Match against Username only when explicitly requested via "@username" // Match against Username only when explicitly requested via "@username".
if isAtUsername && sender.Username != "" && sender.Username == trimmed { // 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 return true
} }

View file

@ -78,6 +78,14 @@ func TestMatchAllowed(t *testing.T) {
Username: "carol", 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 { tests := []struct {
name string name string
sender bus.SenderInfo sender bus.SenderInfo
@ -223,6 +231,25 @@ func TestMatchAllowed(t *testing.T) {
allowed: " 123456 ", allowed: " 123456 ",
want: true, 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 { for _, tt := range tests {