fix(auth): encode snowflake user ids as strings in session and /user-info

Registered users get snowflake ids above JS MAX_SAFE_INTEGER.
/user-info emitted them as JSON numbers and login stored uint64 in
the session. Both now use decimal strings. Tests cover admin vs
non-admin cookie access to /user/self, /user-info, and /upload/my.
This commit is contained in:
ryan
2026-09-02 19:56:10 +08:00
parent c27da41b64
commit df6aa9ff4d
7 changed files with 339 additions and 25 deletions
+1 -1
View File
@@ -146,7 +146,7 @@ type CallbackRequest struct {
// BasicUserInfo 用户基本信息结构体
type BasicUserInfo struct {
ID uint64 `json:"id"`
ID uint64 `json:"id,string"`
Username string `json:"username"`
Nickname string `json:"nickname"`
Email string `json:"email"`
@@ -0,0 +1,44 @@
// Copyright 2026 Arctel.net
// SPDX-License-Identifier: Apache-2.0
package auth
import (
"encoding/json"
"strconv"
"testing"
)
func TestParseUserIDSnowflakeStringPreservesValue(t *testing.T) {
id := uint64(99835970421002240)
got := ParseUserID(strconv.FormatUint(id, 10))
if got != id {
t.Errorf("ParseUserID(%q) = %d, want %d", strconv.FormatUint(id, 10), got, id)
}
}
func TestParseUserIDJSONNumberAboveMaxSafeInteger(t *testing.T) {
// 2^53+1 cannot be represented as a distinct IEEE-754 float64.
id := uint64(9007199254740993)
got := ParseUserID(float64(id))
if got == id {
t.Fatalf("ParseUserID(float64(%d)) = %d, want a rounded value", id, got)
}
}
func TestBasicUserInfoJSONEncodesIDAsString(t *testing.T) {
info := BasicUserInfo{ID: 99835970421002240, Username: "plain_user"}
raw, err := json.Marshal(info)
if err != nil {
t.Fatalf("json.Marshal(BasicUserInfo) error = %v", err)
}
var probe struct {
ID json.RawMessage `json:"id"`
}
if err := json.Unmarshal(raw, &probe); err != nil {
t.Fatalf("json.Unmarshal probe error = %v", err)
}
if len(probe.ID) == 0 || probe.ID[0] != '"' {
t.Errorf("BasicUserInfo id JSON = %s, want a JSON string", probe.ID)
}
}
+1 -1
View File
@@ -128,7 +128,7 @@ func SetLoginSession(ctx context.Context, c *gin.Context, user *contracts.UserDT
session.Clear()
rotateSessionID(session)
session.Set(UserIDKey, user.ID)
session.Set(UserIDKey, strconv.FormatUint(user.ID, 10))
session.Set(UserNameKey, user.Username)
if len(extras) > 0 {
for key, value := range extras[0] {