Compare commits

..

2 commits

Author SHA1 Message Date
javadtgh
958ea09d50
Merge 3b262cf180 into b65ec83c39 2025-09-29 20:09:29 +03:30
konstpic
b65ec83c39
fix: fix delete method (#3569)
Some checks failed
Release 3X-UI / build (386) (push) Has been cancelled
Release 3X-UI / build (amd64) (push) Has been cancelled
Release 3X-UI / build (arm64) (push) Has been cancelled
Release 3X-UI / build (armv5) (push) Has been cancelled
Release 3X-UI / build (armv6) (push) Has been cancelled
Release 3X-UI / build (armv7) (push) Has been cancelled
Release 3X-UI / build (s390x) (push) Has been cancelled
Release 3X-UI / Build for Windows (push) Has been cancelled
Co-authored-by: Пичугин Константин <k.pichugin@comagic.dev>
2025-09-29 18:16:46 +02:00

View file

@ -214,7 +214,7 @@ func (j *LdapSyncJob) batchSetEnable(ib *model.Inbound, emails []string, enable
return return
} }
// Подготовка JSON для массового обновления // Prepare JSON for mass update
clients := make([]model.Client, 0, len(emails)) clients := make([]model.Client, 0, len(emails))
for _, email := range emails { for _, email := range emails {
clients = append(clients, model.Client{ clients = append(clients, model.Client{
@ -238,7 +238,7 @@ func (j *LdapSyncJob) batchSetEnable(ib *model.Inbound, emails []string, enable
j.xrayService.SetToNeedRestart() j.xrayService.SetToNeedRestart()
} }
// deleteClientsNotInLDAP performs batch deletion of clients not in LDAP // deleteClientsNotInLDAP deletes clients not in LDAP using batches and a single restart
func (j *LdapSyncJob) deleteClientsNotInLDAP(inboundTag string, ldapEmails map[string]struct{}) { func (j *LdapSyncJob) deleteClientsNotInLDAP(inboundTag string, ldapEmails map[string]struct{}) {
inbounds, err := j.inboundService.GetAllInbounds() inbounds, err := j.inboundService.GetAllInbounds()
if err != nil { if err != nil {
@ -246,22 +246,24 @@ func (j *LdapSyncJob) deleteClientsNotInLDAP(inboundTag string, ldapEmails map[s
return return
} }
batchSize := 50 // clients in 1 batch
restartNeeded := false
for _, ib := range inbounds { for _, ib := range inbounds {
if ib.Tag != inboundTag { if ib.Tag != inboundTag {
continue continue
} }
clients, err := j.inboundService.GetClients(ib) clients, err := j.inboundService.GetClients(ib)
if err != nil { if err != nil {
logger.Warningf("Failed to get clients for inbound %s: %v", ib.Tag, err)
continue continue
} }
// Сбор клиентов для удаления // Collect clients for deletion
toDelete := []model.Client{} toDelete := []model.Client{}
for _, c := range clients { for _, c := range clients {
if _, ok := ldapEmails[c.Email]; !ok { if _, ok := ldapEmails[c.Email]; !ok {
// Use appropriate field depending on protocol toDelete = append(toDelete, c)
client := model.Client{Email: c.Email, ID: c.ID, Password: c.Password}
toDelete = append(toDelete, client)
} }
} }
@ -269,21 +271,47 @@ func (j *LdapSyncJob) deleteClientsNotInLDAP(inboundTag string, ldapEmails map[s
continue continue
} }
payload := &model.Inbound{ // Delete in batches
Id: ib.Id, for i := 0; i < len(toDelete); i += batchSize {
Settings: j.clientsToJSON(toDelete), end := i + batchSize
} if end > len(toDelete) {
end = len(toDelete)
}
batch := toDelete[i:end]
if _, err := j.inboundService.DelInboundClient(payload.Id, payload.Settings); err != nil { for _, c := range batch {
logger.Warningf("Batch delete failed for inbound %s: %v", ib.Tag, err) var clientKey string
} else { switch ib.Protocol {
logger.Infof("Batch deleted %d clients from inbound %s", len(toDelete), ib.Tag) case model.Trojan:
j.xrayService.SetToNeedRestart() clientKey = c.Password
case model.Shadowsocks:
clientKey = c.Email
default: // vless/vmess
clientKey = c.ID
}
if _, err := j.inboundService.DelInboundClient(ib.Id, clientKey); err != nil {
logger.Warningf("Failed to delete client %s from inbound id=%d(tag=%s): %v",
c.Email, ib.Id, ib.Tag, err)
} else {
logger.Infof("Deleted client %s from inbound id=%d(tag=%s)",
c.Email, ib.Id, ib.Tag)
// do not restart here
restartNeeded = true
}
}
} }
} }
// One time after all batches
if restartNeeded {
j.xrayService.SetToNeedRestart()
logger.Info("Xray restart scheduled after batch deletion")
}
} }
// clientsToJSON сериализует массив клиентов в JSON
// clientsToJSON serializes an array of clients to JSON
func (j *LdapSyncJob) clientsToJSON(clients []model.Client) string { func (j *LdapSyncJob) clientsToJSON(clients []model.Client) string {
b := strings.Builder{} b := strings.Builder{}
b.WriteString("{\"clients\":[") b.WriteString("{\"clients\":[")