This commit is contained in:
2026-01-27 03:13:15 -08:00
parent 5def1cf6d8
commit 48c92ea374
36 changed files with 1189 additions and 123 deletions
+36 -8
View File
@@ -18,6 +18,7 @@ import (
"github.com/perfect-panel/server/internal/model/auth"
"github.com/perfect-panel/server/internal/model/coupon"
"github.com/perfect-panel/server/internal/model/document"
iapapple "github.com/perfect-panel/server/internal/model/iap/apple"
"github.com/perfect-panel/server/internal/model/log"
logmessage "github.com/perfect-panel/server/internal/model/logmessage"
"github.com/perfect-panel/server/internal/model/order"
@@ -27,7 +28,6 @@ import (
"github.com/perfect-panel/server/internal/model/ticket"
"github.com/perfect-panel/server/internal/model/traffic"
"github.com/perfect-panel/server/internal/model/user"
iapapple "github.com/perfect-panel/server/internal/model/iap/apple"
"github.com/perfect-panel/server/pkg/limit"
"github.com/perfect-panel/server/pkg/nodeMultiplier"
"github.com/perfect-panel/server/pkg/orm"
@@ -56,13 +56,13 @@ type ServiceContext struct {
ClientModel client.Model
TicketModel ticket.Model
//ServerModel server.Model
SystemModel system.Model
CouponModel coupon.Model
PaymentModel payment.Model
DocumentModel document.Model
SubscribeModel subscribe.Model
TrafficLogModel traffic.Model
AnnouncementModel announcement.Model
SystemModel system.Model
CouponModel coupon.Model
PaymentModel payment.Model
DocumentModel document.Model
SubscribeModel subscribe.Model
TrafficLogModel traffic.Model
AnnouncementModel announcement.Model
IAPAppleTransactionModel iapapple.Model
Restart func() error
@@ -126,6 +126,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
}
func (srv *ServiceContext) SessionLimit() int64 {
// check custom data
cd := srv.Config.Site.CustomData
if cd != "" {
var obj map[string]interface{}
@@ -134,10 +135,12 @@ func (srv *ServiceContext) SessionLimit() int64 {
switch val := v.(type) {
case float64:
if val > 0 {
fmt.Printf("[SessionLimit] Using CustomData deviceLimit: %d\n", int64(val))
return int64(val)
}
case string:
if n, err := strconv.ParseInt(strings.TrimSpace(val), 10, 64); err == nil && n > 0 {
fmt.Printf("[SessionLimit] Using CustomData deviceLimit: %d\n", n)
return n
}
}
@@ -146,16 +149,19 @@ func (srv *ServiceContext) SessionLimit() int64 {
switch val := v.(type) {
case float64:
if val > 0 {
fmt.Printf("[SessionLimit] Using CustomData DeviceLimit: %d\n", int64(val))
return int64(val)
}
case string:
if n, err := strconv.ParseInt(strings.TrimSpace(val), 10, 64); err == nil && n > 0 {
fmt.Printf("[SessionLimit] Using CustomData DeviceLimit: %d\n", n)
return n
}
}
}
}
}
fmt.Printf("[SessionLimit] Using Config MaxSessionsPerUser: %d\n", srv.Config.JwtAuth.MaxSessionsPerUser)
return srv.Config.JwtAuth.MaxSessionsPerUser
}
@@ -173,6 +179,22 @@ func (srv *ServiceContext) EnforceUserSessionLimit(ctx context.Context, userId i
return err
}
if count > max {
// [SessionDebug] Log all current sessions before eviction
// Fetch all sessions (oldest to newest)
sessions, _ := srv.Redis.ZRange(ctx, sessionsKey, 0, -1).Result()
fmt.Printf("[SessionMonitor] ⚠️ Session Limit Exceeded (Count: %d, Max: %d). User %d has the following active sessions:\n", count, max, userId)
for i, sid := range sessions {
detailKey := fmt.Sprintf("%s:detail:%s", config.SessionIdKey, sid)
val, err := srv.Redis.Get(ctx, detailKey).Result()
if err == nil {
fmt.Printf(" [%d] SessionID: %s | Detail: %s\n", i+1, sid, val)
} else {
fmt.Printf(" [%d] SessionID: %s | (No Detail - Likely old session)\n", i+1, sid)
}
}
// Log before eviction
popped, err := srv.Redis.ZPopMin(ctx, sessionsKey, count-max).Result()
if err != nil {
return err
@@ -180,6 +202,12 @@ func (srv *ServiceContext) EnforceUserSessionLimit(ctx context.Context, userId i
for _, z := range popped {
sid := fmt.Sprintf("%v", z.Member)
_ = srv.Redis.Del(ctx, fmt.Sprintf("%v:%v", config.SessionIdKey, sid)).Err()
// Also delete detail
_ = srv.Redis.Del(ctx, fmt.Sprintf("%s:detail:%s", config.SessionIdKey, sid)).Err()
// 记录被踢出的 Session 信息
fmt.Printf("[SessionMonitor] ❌ KICKED OUT Session: user_id=%d session_id=%s reason=exceed_limit\n",
userId, sid)
}
}
_ = srv.Redis.Expire(ctx, sessionsKey, time.Duration(srv.Config.JwtAuth.AccessExpire)*time.Second).Err()