Преглед изворни кода

fix(clients): drop tombstone gate that blocked re-import after delete

ClientService.Delete tombstones a just-deleted email for 90s to keep a
late node snapshot from resurrecting it. The same check was also gating
the create branch of SyncInbound — which silently dropped clients on any
legitimate re-add (delete inbound + re-import within 90s left the
clients table empty even though settings.clients carried the rows).

The snapshot-side caller in setRemoteTraffic already filters tombstoned
emails before handing the list to SyncInbound, so removing the duplicate
check inside SyncInbound preserves the protection where it's needed and
unblocks user-initiated re-imports.

While here, mirror the addInbound shape in importInbound (NodeID=0→nil
normalisation, early return on error, broadcastInboundsUpdate) and fan
out a notifyClientsChanged from add/del/update/import so an open Clients
page picks up settings.clients reconciliation without a manual refresh.
MHSanaei пре 20 часа
родитељ
комит
6185db586a
2 измењених фајлова са 15 додато и 7 уклоњено
  1. 15 4
      web/controller/inbound.go
  2. 0 3
      web/service/client.go

+ 15 - 4
web/controller/inbound.go

@@ -166,6 +166,7 @@ func (a *InboundController) addInbound(c *gin.Context) {
 		a.xrayService.SetToNeedRestart()
 	}
 	a.broadcastInboundsUpdate(user.Id)
+	notifyClientsChanged()
 }
 
 // delInbound deletes an inbound configuration by its ID.
@@ -186,6 +187,7 @@ func (a *InboundController) delInbound(c *gin.Context) {
 	}
 	user := session.GetLoginUser(c)
 	a.broadcastInboundsUpdate(user.Id)
+	notifyClientsChanged()
 }
 
 // updateInbound updates an existing inbound configuration.
@@ -221,6 +223,7 @@ func (a *InboundController) updateInbound(c *gin.Context) {
 	}
 	user := session.GetLoginUser(c)
 	a.broadcastInboundsUpdate(user.Id)
+	notifyClientsChanged()
 }
 
 // setInboundEnable flips only the enable flag of an inbound. This is a
@@ -299,6 +302,9 @@ func (a *InboundController) importInbound(c *gin.Context) {
 	user := session.GetLoginUser(c)
 	inbound.Id = 0
 	inbound.UserId = user.Id
+	if inbound.NodeID != nil && *inbound.NodeID == 0 {
+		inbound.NodeID = nil
+	}
 	if inbound.Tag == "" {
 		if inbound.Listen == "" || inbound.Listen == "0.0.0.0" || inbound.Listen == "::" || inbound.Listen == "::0" {
 			inbound.Tag = fmt.Sprintf("inbound-%v", inbound.Port)
@@ -312,12 +318,17 @@ func (a *InboundController) importInbound(c *gin.Context) {
 		inbound.ClientStats[index].Enable = true
 	}
 
-	needRestart := false
-	inbound, needRestart, err = a.inboundService.AddInbound(inbound)
-	jsonMsgObj(c, I18nWeb(c, "pages.inbounds.toasts.inboundCreateSuccess"), inbound, err)
-	if err == nil && needRestart {
+	inbound, needRestart, err := a.inboundService.AddInbound(inbound)
+	if err != nil {
+		jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
+		return
+	}
+	jsonMsgObj(c, I18nWeb(c, "pages.inbounds.toasts.inboundCreateSuccess"), inbound, nil)
+	if needRestart {
 		a.xrayService.SetToNeedRestart()
 	}
+	a.broadcastInboundsUpdate(user.Id)
+	notifyClientsChanged()
 }
 
 // resolveHost mirrors what sub.SubService.ResolveRequest does for the host

+ 0 - 3
web/service/client.go

@@ -208,9 +208,6 @@ func (s *ClientService) SyncInbound(tx *gorm.DB, inboundId int, clients []model.
 			return err
 		}
 		if errors.Is(err, gorm.ErrRecordNotFound) {
-			if isClientEmailTombstoned(email) {
-				continue
-			}
 			if err := tx.Create(incoming).Error; err != nil {
 				return err
 			}