Files
zitadel/internal/execution/target/router.go
Gayathri Vijayan 95eb51f802 fix(actionsV2): executing request/response type for 'all' condition (#11071)
# Which Problems Are Solved

In actions v2, when the condition `all` is chosen, or a specific method
is not specified for a service action, the actions are not executed.

# How the Problems Are Solved

The wildcard suffix `.*` is used only for event groups. As global
`requests`, `responses` or `services with no specified method` do not
have this suffix, they were bypassing the prefix-match check. This check
therefore does not apply to action types other than `event`

This issue is fixed by removing the `e.ID == "event"` condition when
prefix-matching execution IDs to not exclude other action types
(`request`, `response`, etc).

# Additional Changes
N/A

# Additional Context

- Closes #10895

---------

Co-authored-by: Livio Spring <livio.a@gmail.com>
(cherry picked from commit a1bfdeb257)
2025-12-08 07:39:16 +01:00

71 lines
1.6 KiB
Go

package target
import (
"slices"
"strings"
)
type element struct {
ID string `json:"id"`
Targets []Target `json:"targets,omitempty"`
}
type Router []element
func NewRouter(targets []Target) Router {
m := make(map[string][]Target)
for _, t := range targets {
m[t.GetExecutionID()] = append(m[t.GetExecutionID()], t)
}
router := make(Router, 0, len(m))
for id, targets := range m {
router = append(router, element{
ID: id,
Targets: targets,
})
}
slices.SortFunc(router, func(a, b element) int {
return strings.Compare(a.ID, b.ID)
})
return router
}
// Get execution targets by exact match of the executionID
func (r Router) Get(executionID string) ([]Target, bool) {
i, ok := slices.BinarySearchFunc(r, executionID, func(a element, b string) int {
return strings.Compare(a.ID, b)
})
if ok {
return r[i].Targets, true
}
return nil, false
}
// GetEventBestMatch returns the best matching execution targets for an event.
// The following match priority is used:
// 1. Exact match
// 2. Longest matching prefix (with wildcard suffix .* for events)
func (r Router) GetEventBestMatch(executionID string) ([]Target, bool) {
t, ok := r.Get(executionID)
if ok {
return t, true
}
var bestMatch element
for _, e := range r {
if strings.HasPrefix(executionID, e.ID) {
bestMatch, ok = e, true
}
// .* is suffixed for "all" condition on events
cut, has := strings.CutSuffix(e.ID, ".*")
if has && strings.HasPrefix(executionID, cut) {
bestMatch, ok = e, true
}
}
return bestMatch.Targets, ok
}
func (r Router) IsZero() bool {
return len(r) == 0
}