Feature/fix external subscription client expiry (#6333)

* fix(sub): honor client expiry for external links

* fix(ui): show client expiry on external links

* fix(sub): address external expiry review
This commit is contained in:
duqigit
2026-09-04 04:32:05 +08:00
committed by GitHub
parent 13e87a18c8
commit 2ddcf53020
16 changed files with 332 additions and 61 deletions
+26 -6
View File
@@ -298,7 +298,7 @@ func TestGetClientExternalLinksBySubId(t *testing.T) {
// A client with two link rows: ordering by sort_index and email/enable
// attribution from the owning client (the loop copies rec.Email/rec.Enable).
rec := &model.ClientRecord{Email: "owner@x", SubID: "sub-ok", UUID: "u2", Enable: true}
rec := &model.ClientRecord{Email: "owner@x", SubID: "sub-ok", UUID: "u2", Enable: true, ExpiryTime: time.Now().Add(time.Hour).UnixMilli()}
if err := db.Create(rec).Error; err != nil {
t.Fatalf("seed client: %v", err)
}
@@ -331,10 +331,12 @@ func TestGetClientExternalLinksBySubId(t *testing.T) {
if out[0].Email != "owner@x" || out[0].Enable != true {
t.Fatalf("attribution wrong: email=%q enable=%v", out[0].Email, out[0].Enable)
}
if !out[0].Active {
t.Fatal("active owner marked inactive")
}
// A DISABLED client must produce entries with Enable=false, proving the
// value is read from the client row (Enable has a gorm default:true, so
// flip it with a raw UPDATE that bypasses the default).
// A disabled owner stays visible as metadata but cannot expose its link.
// Enable has a gorm default:true, so update it after insertion.
dis := &model.ClientRecord{Email: "off@x", SubID: "sub-off", UUID: "u3", Enable: true}
if err := db.Create(dis).Error; err != nil {
t.Fatalf("seed disabled client: %v", err)
@@ -352,8 +354,26 @@ func TestGetClientExternalLinksBySubId(t *testing.T) {
if len(offOut) != 1 {
t.Fatalf("disabled client entries = %d, want 1", len(offOut))
}
if offOut[0].Email != "off@x" || offOut[0].Enable != false {
t.Fatalf("disabled attribution wrong: email=%q enable=%v", offOut[0].Email, offOut[0].Enable)
if offOut[0].Enable || offOut[0].Active {
t.Fatalf("disabled owner state = enable:%v active:%v", offOut[0].Enable, offOut[0].Active)
}
expired := &model.ClientRecord{Email: "expired@x", SubID: "sub-expired", UUID: "u4", Enable: true, ExpiryTime: time.Now().Add(-time.Hour).UnixMilli()}
if err := db.Create(expired).Error; err != nil {
t.Fatalf("seed expired client: %v", err)
}
if err := db.Create(&model.ClientExternalLink{ClientId: expired.Id, Kind: model.ExternalLinkKindLink, Value: "trojan://d", SortIndex: 1}).Error; err != nil {
t.Fatalf("seed expired client link: %v", err)
}
expiredOut, err := s.getClientExternalLinksBySubId("sub-expired")
if err != nil {
t.Fatalf("expired subId err = %v", err)
}
if len(expiredOut) != 1 {
t.Fatalf("expired client entries = %d, want 1", len(expiredOut))
}
if !expiredOut[0].Enable || expiredOut[0].Active {
t.Fatalf("expired owner state = enable:%v active:%v", expiredOut[0].Enable, expiredOut[0].Active)
}
}