mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-11-02 11:15:03 +03:00
fix(inbounds): delete an inbound's dependent rows on every delete path
The node sync's sweep of an inbound the node stopped reporting deleted the inbound but left its host rows, and the depleted-clients delete left its sub-balancer references. SQLite hands a freed inbound id out again once the table empties, so a node's host overrides could bind to a new inbound it never hosted and point that inbound's subscribers at an address, port and TLS settings the node chose. delInbound's cleanup moves into deleteInboundRow (detach clients, delete the inbound, its host rows and its sub-balancer references), which the sweep and the depleted-clients delete now call as well.
This commit is contained in:
@@ -1689,31 +1689,9 @@ func (s *InboundService) delInbound(id int) (bool, func(), error) {
|
||||
}
|
||||
|
||||
if err := runSerializedTx(func(tx *gorm.DB) error {
|
||||
if err := s.clientService.DetachInbound(tx, id); err != nil {
|
||||
if err := s.deleteInboundRow(tx, id); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Delete(model.Inbound{}, id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := database.DeleteHosts(tx, "inbound_id = ?", id); err != nil {
|
||||
return err
|
||||
}
|
||||
// Drop the deleted inbound from any sub-balancer that selects it; a
|
||||
// dangling id would emit a member no subscriber can resolve (#5648).
|
||||
var balancers []model.SubBalancer
|
||||
if err := tx.Find(&balancers).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
for i := range balancers {
|
||||
before := balancers[i].InboundIds
|
||||
balancers[i].InboundIds = slices.DeleteFunc(before, func(b int) bool { return b == id })
|
||||
if len(balancers[i].InboundIds) == len(before) {
|
||||
continue
|
||||
}
|
||||
if err := tx.Save(&balancers[i]).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if loadErr == nil && ib.NodeID != nil {
|
||||
return (&NodeService{}).MarkNodeDirtyTx(tx, *ib.NodeID)
|
||||
}
|
||||
@@ -1749,6 +1727,37 @@ func (s *InboundService) delInbound(id int) (bool, func(), error) {
|
||||
return needRestart, nodePush, nil
|
||||
}
|
||||
|
||||
// deleteInboundRow removes an inbound and every row keyed by its id; SQLite
|
||||
// hands a freed id out again, so anything left behind binds to the next inbound.
|
||||
func (s *InboundService) deleteInboundRow(tx *gorm.DB, id int) error {
|
||||
if err := s.clientService.DetachInbound(tx, id); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Delete(model.Inbound{}, id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := database.DeleteHosts(tx, "inbound_id = ?", id); err != nil {
|
||||
return err
|
||||
}
|
||||
// Drop the deleted inbound from any sub-balancer that selects it; a
|
||||
// dangling id would emit a member no subscriber can resolve (#5648).
|
||||
var balancers []model.SubBalancer
|
||||
if err := tx.Find(&balancers).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
for i := range balancers {
|
||||
before := balancers[i].InboundIds
|
||||
balancers[i].InboundIds = slices.DeleteFunc(before, func(b int) bool { return b == id })
|
||||
if len(balancers[i].InboundIds) == len(before) {
|
||||
continue
|
||||
}
|
||||
if err := tx.Save(&balancers[i]).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type BulkDelInboundResult struct {
|
||||
Deleted int `json:"deleted"`
|
||||
Skipped []BulkDelInboundReport `json:"skipped,omitempty"`
|
||||
|
||||
Reference in New Issue
Block a user