|
|
@@ -0,0 +1,44 @@
|
|
|
+package service
|
|
|
+
|
|
|
+import (
|
|
|
+ "encoding/json"
|
|
|
+ "testing"
|
|
|
+
|
|
|
+ "github.com/mhsanaei/3x-ui/v3/internal/database"
|
|
|
+ "github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
|
|
+)
|
|
|
+
|
|
|
+// Exports from v2.x store tgId as a string ("" when unset); the stored copies
|
|
|
+// are healed by a startup migration, but an imported export never passes it.
|
|
|
+func TestAddInboundAcceptsLegacyStringClientFields(t *testing.T) {
|
|
|
+ setupConflictDB(t)
|
|
|
+ settings := `{"clients":[` +
|
|
|
+ `{"id":"11111111-1111-1111-1111-111111111111","email":"legacy-a","tgId":"","subId":"s-a","enable":true,"limitIp":0,"totalGB":0,"expiryTime":0,"reset":0},` +
|
|
|
+ `{"id":"22222222-2222-2222-2222-222222222222","email":"legacy-b","tgId":"123456","subId":"s-b","enable":true,"limitIp":0,"totalGB":0,"expiryTime":0,"reset":0}` +
|
|
|
+ `],"decryption":"none","fallbacks":[]}`
|
|
|
+ in := makeImportInbound("in-9201-tcp", 9201, settings, nil)
|
|
|
+
|
|
|
+ saved, _, err := (&InboundService{}).AddInbound(in)
|
|
|
+ if err != nil {
|
|
|
+ t.Fatalf("AddInbound: %v", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ var rec model.ClientRecord
|
|
|
+ if err := database.GetDB().Where("email = ?", "legacy-b").First(&rec).Error; err != nil {
|
|
|
+ t.Fatalf("read client: %v", err)
|
|
|
+ }
|
|
|
+ if rec.TgID != 123456 {
|
|
|
+ t.Fatalf("client tgId = %d, want 123456 parsed from the string", rec.TgID)
|
|
|
+ }
|
|
|
+ var stored struct {
|
|
|
+ Clients []map[string]any `json:"clients"`
|
|
|
+ }
|
|
|
+ if err := json.Unmarshal([]byte(saved.Settings), &stored); err != nil {
|
|
|
+ t.Fatalf("stored settings: %v", err)
|
|
|
+ }
|
|
|
+ for _, c := range stored.Clients {
|
|
|
+ if _, isString := c["tgId"].(string); isString {
|
|
|
+ t.Fatalf("stored settings keep a string tgId for %v: %v", c["email"], c["tgId"])
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|