diff --git a/handlers/user.go b/handlers/user.go index 1e0b8b4748..fe371b2603 100644 --- a/handlers/user.go +++ b/handlers/user.go @@ -1853,11 +1853,8 @@ func internUserNotificationsSubscribe(event, filter string, threshold float64, w return false } - isPkey := searchPubkeyExactRE.MatchString(filter) - filterLen := len(filter) - - if filterLen != 0 && !isPkey { - errMsg := fmt.Errorf("error invalid pubkey characters or length") + if !isValidSubscriptionFilter(eventName, filter) { + errMsg := fmt.Errorf("error invalid filter, not pubkey or client") errFields := map[string]interface{}{ "filter": filter, "filter_len": len(filter)} @@ -1888,6 +1885,7 @@ func internUserNotificationsSubscribe(event, filter string, threshold float64, w // rocketpool thresholds are free } + filterLen := len(filter) if filterLen == 0 && !strings.HasPrefix(string(eventName), "monitoring_") && !strings.HasPrefix(string(eventName), "rocketpool_") { // no filter = add all my watched validators myValidators, err2 := db.GetTaggedValidators(filterWatchlist) if err2 != nil { @@ -2032,11 +2030,8 @@ func internUserNotificationsUnsubscribe(event, filter string, w http.ResponseWri return false } - isPkey := searchPubkeyExactRE.MatchString(filter) - filterLen := len(filter) - - if filterLen != 0 && !isPkey { - errMsg := fmt.Errorf("error invalid pubkey characters or length") + if !isValidSubscriptionFilter(eventName, filter) { + errMsg := fmt.Errorf("error invalid filter, not pubkey or client") errFields := map[string]interface{}{ "filter": filter, "filter_len": len(filter)} @@ -2053,6 +2048,7 @@ func internUserNotificationsUnsubscribe(event, filter string, w http.ResponseWri Network: utils.GetNetwork(), } + filterLen := len(filter) if filterLen == 0 && !strings.HasPrefix(string(eventName), "monitoring_") && !strings.HasPrefix(string(eventName), "rocketpool_") { // no filter = add all my watched validators myValidators, err2 := db.GetTaggedValidators(filterWatchlist) @@ -2120,11 +2116,8 @@ func UserNotificationsUnsubscribe(w http.ResponseWriter, r *http.Request) { return } - isPkey := searchPubkeyExactRE.MatchString(filter) - filterLen := len(filter) - - if filterLen != 0 && !isPkey { - errMsg := fmt.Errorf("error invalid pubkey characters or length") + if !isValidSubscriptionFilter(eventName, filter) { + errMsg := fmt.Errorf("error invalid filter, not pubkey or client") errFields := map[string]interface{}{ "filter": filter, "filter_len": len(filter)} @@ -2134,6 +2127,7 @@ func UserNotificationsUnsubscribe(w http.ResponseWriter, r *http.Request) { return } + filterLen := len(filter) if filterLen == 0 && !types.IsUserIndexed(eventName) { // no filter = add all my watched validators filter := db.WatchlistFilter{ @@ -2182,6 +2176,27 @@ func UserNotificationsUnsubscribe(w http.ResponseWriter, r *http.Request) { OKResponse(w, r) } +func isValidSubscriptionFilter(eventName types.EventName, filter string) bool { + ethClients := []string{"geth", "nethermind", "besu", "erigon", "teku", "prysm", "nimbus", "lighthouse", "lodestar", "rocketpool", "mev-boost"} + + isPkey := searchPubkeyExactRE.MatchString(filter) + + isClientName := false + for _, str := range ethClients { + if str == filter { + isClientName = true + break + } + } + + isClient := false + if eventName == types.EthClientUpdateEventName && isClientName { + isClient = true + } + + return len(filter) == 0 || isPkey || isClient +} + func UserNotificationsUnsubscribeByHash(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") q := r.URL.Query()