mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-09-02 16:37:14 +00:00
fix(node): fully delete clients on nodes instead of only detaching them
Deleting a client on the master propagated to nodes via the detach endpoint, which removes the client from that one inbound's settings but deliberately keeps the client record. The node ended up with an orphaned record that kept showing in its Clients view; the master and node could never converge on a delete. Full-delete and detach intent now travel separately: the Runtime interface gains DeleteClient, which on Remote hits the node's panel/api/clients/del endpoint (record, attachments, traffic; repeat calls for a client on several inbounds of the same node are swallowed as idempotent "not found"). Delete/DeleteByEmail/BulkDelete use it for node inbounds, while Detach/BulkDetach keep the inbound-scoped detach RPC so removing a client from one inbound never wipes it node-wide (the #5543 guarantee is preserved and covered by tests). Bulk deletes above the fold threshold still converge membership via reconcile; their leftover node records can be cleaned with the node's delete-orphans action. Closes #5797
This commit is contained in:
@@ -831,7 +831,7 @@ func (s *ClientService) UpdateInboundClient(inboundSvc *InboundService, data *mo
|
||||
return needRestart, nil
|
||||
}
|
||||
|
||||
func (s *ClientService) DelInboundClientByEmail(inboundSvc *InboundService, inboundId int, email string, keepTraffic bool) (bool, error) {
|
||||
func (s *ClientService) DelInboundClientByEmail(inboundSvc *InboundService, inboundId int, email string, keepTraffic bool, fullDelete bool) (bool, error) {
|
||||
defer lockInbound(inboundId).Unlock()
|
||||
|
||||
oldInbound, err := inboundSvc.GetInbound(inboundId)
|
||||
@@ -972,9 +972,17 @@ func (s *ClientService) DelInboundClientByEmail(inboundSvc *InboundService, inbo
|
||||
} else {
|
||||
// Node inbound: propagate the delete regardless of the enable flag —
|
||||
// the node's own DB still carries a disabled client and would
|
||||
// resurrect it on the next snapshot otherwise.
|
||||
// resurrect it on the next snapshot otherwise. A full client delete
|
||||
// must remove the node's client record too, not just detach it from
|
||||
// this inbound (#5797).
|
||||
if push {
|
||||
if err1 := rt.DeleteUser(context.Background(), oldInbound, email); err1 != nil {
|
||||
var err1 error
|
||||
if fullDelete {
|
||||
err1 = rt.DeleteClient(context.Background(), email)
|
||||
} else {
|
||||
err1 = rt.DeleteUser(context.Background(), oldInbound, email)
|
||||
}
|
||||
if err1 != nil {
|
||||
logger.Warning("Error in deleting client on", rt.Name(), ":", err1)
|
||||
} else {
|
||||
advancePushedInbound(rt, prevSettings, oldInbound)
|
||||
|
||||
Reference in New Issue
Block a user