diff --git a/pkg/identity/identity.go b/pkg/identity/identity.go index 045725a8d..383dabd0b 100644 --- a/pkg/identity/identity.go +++ b/pkg/identity/identity.go @@ -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 } diff --git a/pkg/identity/identity_test.go b/pkg/identity/identity_test.go index c60402d19..d643f8820 100644 --- a/pkg/identity/identity_test.go +++ b/pkg/identity/identity_test.go @@ -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 {