|
@@ -493,12 +493,14 @@ func (s *ClientService) Delete(inboundSvc *InboundService, id int, keepTraffic b
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
needRestart := false
|
|
needRestart := false
|
|
|
|
|
+ var delErrs []error
|
|
|
for _, ibId := range inboundIds {
|
|
for _, ibId := range inboundIds {
|
|
|
if _, getErr := inboundSvc.GetInbound(ibId); getErr != nil {
|
|
if _, getErr := inboundSvc.GetInbound(ibId); getErr != nil {
|
|
|
if errors.Is(getErr, gorm.ErrRecordNotFound) {
|
|
if errors.Is(getErr, gorm.ErrRecordNotFound) {
|
|
|
continue
|
|
continue
|
|
|
}
|
|
}
|
|
|
- return needRestart, getErr
|
|
|
|
|
|
|
+ delErrs = append(delErrs, fmt.Errorf("inbound %d: %w", ibId, getErr))
|
|
|
|
|
+ continue
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Always delete by email — the client's stable identity. This removes
|
|
// Always delete by email — the client's stable identity. This removes
|
|
@@ -515,12 +517,18 @@ func (s *ClientService) Delete(inboundSvc *InboundService, id int, keepTraffic b
|
|
|
if errors.Is(delErr, ErrClientNotInInbound) {
|
|
if errors.Is(delErr, ErrClientNotInInbound) {
|
|
|
continue
|
|
continue
|
|
|
}
|
|
}
|
|
|
- return needRestart, delErr
|
|
|
|
|
|
|
+ delErrs = append(delErrs, fmt.Errorf("inbound %d: %w", ibId, delErr))
|
|
|
|
|
+ continue
|
|
|
}
|
|
}
|
|
|
if nr {
|
|
if nr {
|
|
|
needRestart = true
|
|
needRestart = true
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ // A failed inbound still holds the client in its settings JSON: keep the
|
|
|
|
|
+ // record so the next delete retries exactly the leftovers, and report it.
|
|
|
|
|
+ if len(delErrs) > 0 {
|
|
|
|
|
+ return needRestart, errors.Join(delErrs...)
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
db := database.GetDB()
|
|
db := database.GetDB()
|
|
|
if err := db.Transaction(func(tx *gorm.DB) error {
|
|
if err := db.Transaction(func(tx *gorm.DB) error {
|
|
@@ -668,18 +676,23 @@ func (s *ClientService) DeleteByEmail(inboundSvc *InboundService, email string,
|
|
|
return false, common.NewError(fmt.Sprintf("client %q not found in any inbound or client record", email))
|
|
return false, common.NewError(fmt.Sprintf("client %q not found in any inbound or client record", email))
|
|
|
}
|
|
}
|
|
|
needRestart := false
|
|
needRestart := false
|
|
|
|
|
+ var delErrs []error
|
|
|
for _, ibId := range inboundIds {
|
|
for _, ibId := range inboundIds {
|
|
|
nr, delErr := s.DelInboundClientByEmail(inboundSvc, ibId, email, false, true)
|
|
nr, delErr := s.DelInboundClientByEmail(inboundSvc, ibId, email, false, true)
|
|
|
if delErr != nil {
|
|
if delErr != nil {
|
|
|
if errors.Is(delErr, ErrClientNotInInbound) {
|
|
if errors.Is(delErr, ErrClientNotInInbound) {
|
|
|
continue
|
|
continue
|
|
|
}
|
|
}
|
|
|
- return needRestart, delErr
|
|
|
|
|
|
|
+ delErrs = append(delErrs, fmt.Errorf("inbound %d: %w", ibId, delErr))
|
|
|
|
|
+ continue
|
|
|
}
|
|
}
|
|
|
if nr {
|
|
if nr {
|
|
|
needRestart = true
|
|
needRestart = true
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ if len(delErrs) > 0 {
|
|
|
|
|
+ return needRestart, errors.Join(delErrs...)
|
|
|
|
|
+ }
|
|
|
if !keepTraffic {
|
|
if !keepTraffic {
|
|
|
db := database.GetDB()
|
|
db := database.GetDB()
|
|
|
if err := db.Where("email = ?", email).Delete(&xray.ClientTraffic{}).Error; err != nil {
|
|
if err := db.Where("email = ?", email).Delete(&xray.ClientTraffic{}).Error; err != nil {
|