fix(multi-node): scope remote client update/delete to one inbound (#4892)

UpdateUser and DeleteUser hit the node's email-based full-client endpoints, which fanned out to every inbound the client had on the node: editing a client wiped flow on the node's other inbounds, and detaching one node inbound deleted the client from all of them.

Make both inbound-scoped, mirroring AddClient. DeleteUser now detaches the resolved remote inbound id; UpdateUser passes an inboundIds scope so the node updates only that inbound.
This commit is contained in:
MHSanaei
2026-06-04 16:45:40 +02:00
parent a07c7b7f4e
commit db86007ab8
3 changed files with 51 additions and 13 deletions

View File

@@ -3,6 +3,8 @@ package controller
import (
"encoding/json"
"fmt"
"strconv"
"strings"
"time"
"github.com/mhsanaei/3x-ui/v3/database/model"
@@ -16,6 +18,21 @@ func notifyClientsChanged() {
websocket.BroadcastInvalidate(websocket.MessageTypeClients)
}
func parseInboundIdsQuery(raw string) []int {
raw = strings.TrimSpace(raw)
if raw == "" {
return nil
}
parts := strings.Split(raw, ",")
ids := make([]int, 0, len(parts))
for _, p := range parts {
if id, err := strconv.Atoi(strings.TrimSpace(p)); err == nil {
ids = append(ids, id)
}
}
return ids
}
type ClientController struct {
clientService service.ClientService
inboundService service.InboundService
@@ -129,7 +146,8 @@ func (a *ClientController) update(c *gin.Context) {
jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
return
}
needRestart, err := a.clientService.UpdateByEmail(&a.inboundService, email, updated)
inboundFilter := parseInboundIdsQuery(c.Query("inboundIds"))
needRestart, err := a.clientService.UpdateByEmail(&a.inboundService, email, updated, inboundFilter...)
if err != nil {
jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
return