diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e71365dfd..da0a31b027 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ For details about compatibility between different releases, see the **Commitment ### Fixed - Resolve scroll jumps when selecting different tabs of a table in the Console. +- `BatchGetGatewayConnectionStats` RPC rights check in certain cases. ### Security diff --git a/pkg/identityserver/gateway_access.go b/pkg/identityserver/gateway_access.go index 5229fb4eaa..5c4ad4c6d0 100644 --- a/pkg/identityserver/gateway_access.go +++ b/pkg/identityserver/gateway_access.go @@ -537,7 +537,7 @@ type gatewayBatchAccess struct { } var ( - errEmtpyRequest = errors.DefineInvalidArgument( + errEmptyRequest = errors.DefineInvalidArgument( "empty_request", "empty request", ) @@ -555,7 +555,7 @@ func (gba *gatewayBatchAccess) AssertRights( // Sanitize request. required := req.Required.Unique() if len(required.GetRights()) == 0 { - return nil, errEmtpyRequest.New() + return nil, errEmptyRequest.New() } // Check that the request is checking only gateway rights. diff --git a/pkg/identityserver/rights.go b/pkg/identityserver/rights.go index 6850da8e7b..a20ea60f8f 100644 --- a/pkg/identityserver/rights.go +++ b/pkg/identityserver/rights.go @@ -252,6 +252,9 @@ func (is *IdentityServer) assertGatewayRights( // nolint:gocyclo return errInsufficientRights.New() } + // If the caller has specified the identifiers multiple times, deduplicate them. + gtwIDs = uniqueIdentifiers(gtwIDs) + return is.store.Transact(ctx, func(ctx context.Context, st store.Store) error { gtws, err := st.FindGateways(ctx, gtwIDs, []string{"ids", "status_public", "location_public"}) if err != nil { @@ -316,6 +319,9 @@ func (is *IdentityServer) assertGatewayRights( // nolint:gocyclo } entityIDs = append(entityIDs, gtwID.GetEntityIdentifiers().IDString()) } + if len(entityIDs) == 0 { + return nil + } membershipChains, err := st.FindAccountMembershipChains( ctx, ouID, @@ -341,3 +347,16 @@ func (is *IdentityServer) assertGatewayRights( // nolint:gocyclo return nil }) } + +func uniqueIdentifiers[T ttnpb.IDStringer](ids []T) []T { + m := make(map[string]struct{}, len(ids)) + result := make([]T, 0, len(ids)) + for _, id := range ids { + if _, ok := m[id.IDString()]; ok { + continue + } + m[id.IDString()] = struct{}{} + result = append(result, id) + } + return result +}