Przeglądaj źródła

fix(groups): report changed bulk moves without restarting xray (#6199)

n0ctal 18 godzin temu
rodzic
commit
0496c23a26

+ 0 - 1
internal/web/controller/group.go

@@ -148,7 +148,6 @@ func (a *GroupController) bulkAdd(c *gin.Context) {
 		return
 	}
 	jsonObj(c, gin.H{"affected": affected}, nil)
-	a.xrayService.SetToNeedRestart()
 	notifyClientsChanged()
 }
 

+ 42 - 0
internal/web/service/client_group_bulk_test.go

@@ -0,0 +1,42 @@
+package service
+
+import (
+	"testing"
+
+	"github.com/mhsanaei/3x-ui/v3/internal/database"
+	"github.com/mhsanaei/3x-ui/v3/internal/database/model"
+)
+
+func TestAddToGroupReportsOnlyChangedRecordsIncludingNull(t *testing.T) {
+	setupConflictDB(t)
+	db := database.GetDB()
+	if err := db.Create(&model.ClientGroup{Name: "paid"}).Error; err != nil {
+		t.Fatalf("create group: %v", err)
+	}
+	rows := []model.ClientRecord{
+		{Email: "same@example", UUID: "same", Group: "paid"},
+		{Email: "other@example", UUID: "other", Group: "free"},
+		{Email: "null@example", UUID: "null"},
+	}
+	if err := db.Create(&rows).Error; err != nil {
+		t.Fatalf("create clients: %v", err)
+	}
+	if err := db.Model(&model.ClientRecord{}).Where("email = ?", "null@example").UpdateColumn("group_name", nil).Error; err != nil {
+		t.Fatalf("set NULL group: %v", err)
+	}
+
+	got, err := (&ClientService{}).AddToGroup([]string{"same@example", "other@example", "null@example", "missing@example"}, "paid")
+	if err != nil {
+		t.Fatalf("AddToGroup: %v", err)
+	}
+	if got != 2 {
+		t.Fatalf("affected = %d, want 2 changed records", got)
+	}
+	got, err = (&ClientService{}).AddToGroup([]string{"same@example", "other@example", "null@example"}, "paid")
+	if err != nil {
+		t.Fatalf("second AddToGroup: %v", err)
+	}
+	if got != 0 {
+		t.Fatalf("second affected = %d, want 0", got)
+	}
+}

+ 11 - 5
internal/web/service/client_groups.go

@@ -234,7 +234,9 @@ func (s *ClientService) AddToGroup(emails []string, group string) (int, error) {
 	var records []model.ClientRecord
 	for _, batch := range chunkStrings(emails, sqlInChunk) {
 		var rows []model.ClientRecord
-		if err := db.Where("email IN ?", batch).Find(&rows).Error; err != nil {
+		if err := db.Where("email IN ?", batch).
+			Where("group_name IS NULL OR group_name <> ?", group).
+			Find(&rows).Error; err != nil {
 			return 0, err
 		}
 		records = append(records, rows...)
@@ -248,13 +250,17 @@ func (s *ClientService) AddToGroup(emails []string, group string) (int, error) {
 	}
 
 	tx := db.Begin()
+	var affected int64
 	for _, batch := range chunkStrings(affectedEmails, sqlInChunk) {
-		if err := tx.Model(&model.ClientRecord{}).
+		result := tx.Model(&model.ClientRecord{}).
 			Where("email IN ?", batch).
-			UpdateColumn("group_name", group).Error; err != nil {
+			Where("group_name IS NULL OR group_name <> ?", group).
+			UpdateColumn("group_name", group)
+		if result.Error != nil {
 			tx.Rollback()
-			return 0, err
+			return 0, result.Error
 		}
+		affected += result.RowsAffected
 	}
 
 	var inboundIDs []int
@@ -331,7 +337,7 @@ func (s *ClientService) AddToGroup(emails []string, group string) (int, error) {
 	if err := tx.Commit().Error; err != nil {
 		return 0, err
 	}
-	return len(records), nil
+	return int(affected), nil
 }
 
 func (s *ClientService) replaceGroupValue(oldName, newName string) (int, error) {