From 3fb43b91bf908803a3d324372c3455f41a51513b Mon Sep 17 00:00:00 2001 From: shaw Date: Thu, 8 Jan 2026 17:45:31 +0800 Subject: [PATCH] =?UTF-8?q?fix(security):=20=E5=BC=BA=E5=8C=96=20usage=20?= =?UTF-8?q?=E7=AB=AF=E7=82=B9=E4=BF=A1=E6=81=AF=E6=9A=B4=E9=9C=B2=E6=8E=A7?= =?UTF-8?q?=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../internal/handler/admin/usage_handler.go | 2 +- backend/internal/handler/dto/mappers.go | 33 +++++++++++++++++-- backend/internal/handler/dto/types.go | 9 ++++- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/backend/internal/handler/admin/usage_handler.go b/backend/internal/handler/admin/usage_handler.go index ad336b3e..c7b983f1 100644 --- a/backend/internal/handler/admin/usage_handler.go +++ b/backend/internal/handler/admin/usage_handler.go @@ -144,7 +144,7 @@ func (h *UsageHandler) List(c *gin.Context) { out := make([]dto.UsageLog, 0, len(records)) for i := range records { - out = append(out, *dto.UsageLogFromService(&records[i])) + out = append(out, *dto.UsageLogFromServiceAdmin(&records[i])) } response.Paginated(c, out, result.Total, page, pageSize) } diff --git a/backend/internal/handler/dto/mappers.go b/backend/internal/handler/dto/mappers.go index 764a4132..bf15e9dc 100644 --- a/backend/internal/handler/dto/mappers.go +++ b/backend/internal/handler/dto/mappers.go @@ -234,7 +234,21 @@ func RedeemCodeFromService(rc *service.RedeemCode) *RedeemCode { } } -func UsageLogFromService(l *service.UsageLog) *UsageLog { +// AccountSummaryFromService returns a minimal AccountSummary for usage log display. +// Only includes ID and Name - no sensitive fields like Credentials, Proxy, etc. +func AccountSummaryFromService(a *service.Account) *AccountSummary { + if a == nil { + return nil + } + return &AccountSummary{ + ID: a.ID, + Name: a.Name, + } +} + +// usageLogFromServiceBase is a helper that converts service UsageLog to DTO. +// The account parameter allows caller to control what Account info is included. +func usageLogFromServiceBase(l *service.UsageLog, account *AccountSummary) *UsageLog { if l == nil { return nil } @@ -269,12 +283,27 @@ func UsageLogFromService(l *service.UsageLog) *UsageLog { CreatedAt: l.CreatedAt, User: UserFromServiceShallow(l.User), APIKey: APIKeyFromService(l.APIKey), - Account: AccountFromService(l.Account), + Account: account, Group: GroupFromServiceShallow(l.Group), Subscription: UserSubscriptionFromService(l.Subscription), } } +// UsageLogFromService converts a service UsageLog to DTO for regular users. +// It excludes Account details - users should not see account information. +func UsageLogFromService(l *service.UsageLog) *UsageLog { + return usageLogFromServiceBase(l, nil) +} + +// UsageLogFromServiceAdmin converts a service UsageLog to DTO for admin users. +// It includes minimal Account info (ID, Name only). +func UsageLogFromServiceAdmin(l *service.UsageLog) *UsageLog { + if l == nil { + return nil + } + return usageLogFromServiceBase(l, AccountSummaryFromService(l.Account)) +} + func SettingFromService(s *service.Setting) *Setting { if s == nil { return nil diff --git a/backend/internal/handler/dto/types.go b/backend/internal/handler/dto/types.go index a11662fe..bb953fae 100644 --- a/backend/internal/handler/dto/types.go +++ b/backend/internal/handler/dto/types.go @@ -184,11 +184,18 @@ type UsageLog struct { User *User `json:"user,omitempty"` APIKey *APIKey `json:"api_key,omitempty"` - Account *Account `json:"account,omitempty"` + Account *AccountSummary `json:"account,omitempty"` // Use minimal AccountSummary to prevent data leakage Group *Group `json:"group,omitempty"` Subscription *UserSubscription `json:"subscription,omitempty"` } +// AccountSummary is a minimal account info for usage log display. +// It intentionally excludes sensitive fields like Credentials, Proxy, etc. +type AccountSummary struct { + ID int64 `json:"id"` + Name string `json:"name"` +} + type Setting struct { ID int64 `json:"id"` Key string `json:"key"`