types: make CheckTarget.String() unambiguous by always emitting all fields
The previous implementation skipped empty fields, which meant targets
differing only in which fields were populated could produce the same
string (e.g. {UserId:"A"} and {DomainId:"A"} both gave "A"). This
caused key collisions when the string was used in storage index keys.
This commit is contained in:
parent
2cd323beed
commit
6493589bb4
2 changed files with 10 additions and 16 deletions
|
|
@ -21,7 +21,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -66,19 +65,11 @@ func (t CheckTarget) Scope() CheckScopeType {
|
||||||
return CheckScopeUser
|
return CheckScopeUser
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a stable string representation of the target.
|
// String returns a stable, unambiguous string representation of the target.
|
||||||
|
// All three fields are always present (even when empty) so that different
|
||||||
|
// targets never produce the same string.
|
||||||
func (t CheckTarget) String() string {
|
func (t CheckTarget) String() string {
|
||||||
var parts []string
|
return t.UserId + "/" + t.DomainId + "/" + t.ServiceId
|
||||||
if t.UserId != "" {
|
|
||||||
parts = append(parts, t.UserId)
|
|
||||||
}
|
|
||||||
if t.DomainId != "" {
|
|
||||||
parts = append(parts, t.DomainId)
|
|
||||||
}
|
|
||||||
if t.ServiceId != "" {
|
|
||||||
parts = append(parts, t.ServiceId)
|
|
||||||
}
|
|
||||||
return strings.Join(parts, "/")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckerAvailability declares on which scopes a checker can operate.
|
// CheckerAvailability declares on which scopes a checker can operate.
|
||||||
|
|
|
||||||
|
|
@ -148,10 +148,13 @@ func TestCheckTarget_String(t *testing.T) {
|
||||||
target CheckTarget
|
target CheckTarget
|
||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{CheckTarget{}, ""},
|
{CheckTarget{}, "//"},
|
||||||
{CheckTarget{UserId: "u1"}, "u1"},
|
{CheckTarget{UserId: "u1"}, "u1//"},
|
||||||
{CheckTarget{UserId: "u1", DomainId: "d1"}, "u1/d1"},
|
{CheckTarget{UserId: "u1", DomainId: "d1"}, "u1/d1/"},
|
||||||
{CheckTarget{UserId: "u1", DomainId: "d1", ServiceId: "s1"}, "u1/d1/s1"},
|
{CheckTarget{UserId: "u1", DomainId: "d1", ServiceId: "s1"}, "u1/d1/s1"},
|
||||||
|
// Ensure different targets with different empty fields don't collide.
|
||||||
|
{CheckTarget{DomainId: "d1"}, "/d1/"},
|
||||||
|
{CheckTarget{ServiceId: "s1"}, "//s1"},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
if got := tt.target.String(); got != tt.want {
|
if got := tt.target.String(); got != tt.want {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue