fix: keep workbench user ids compatible

This commit is contained in:
richjohnrambo
2026-09-16 18:02:19 +08:00
parent 5789b85663
commit 903a77f2c5
4 changed files with 163 additions and 30 deletions
+100
View File
@@ -0,0 +1,100 @@
package httpapi
import (
"encoding/base64"
"encoding/binary"
"encoding/json"
"fmt"
"strconv"
"strings"
)
type userID int64
func (id *userID) UnmarshalJSON(raw []byte) error {
value, err := parseUserIDJSON(raw)
if err != nil {
return err
}
*id = userID(value)
return nil
}
type optionalUserID struct {
value int64
set bool
}
func (id *optionalUserID) UnmarshalJSON(raw []byte) error {
if strings.TrimSpace(string(raw)) == "null" {
id.set = true
id.value = 0
return nil
}
value, err := parseUserIDJSON(raw)
if err != nil {
return err
}
id.set = true
id.value = value
return nil
}
func (id optionalUserID) ptr() *int64 {
if !id.set {
return nil
}
return &id.value
}
func parseUserIDJSON(raw []byte) (int64, error) {
var text string
if err := json.Unmarshal(raw, &text); err == nil {
return parseUserID(text)
}
var number int64
if err := json.Unmarshal(raw, &number); err == nil {
return number, nil
}
return 0, fmt.Errorf("invalid user id")
}
func parseUserID(value string) (int64, error) {
value = strings.TrimSpace(value)
if value == "" {
return 0, fmt.Errorf("empty user id")
}
if strings.HasPrefix(value, "usr") {
decoded, err := base64.URLEncoding.WithPadding(base64.NoPadding).DecodeString(strings.TrimPrefix(value, "usr"))
if err != nil || len(decoded) < 8 {
return 0, fmt.Errorf("invalid user id")
}
return int64(binary.LittleEndian.Uint64(decoded[:8])), nil
}
return strconv.ParseInt(value, 10, 64)
}
func formatUserID(id int64) string {
if id == 0 {
return ""
}
src := make([]byte, 8)
dst := make([]byte, base64.URLEncoding.WithPadding(base64.NoPadding).EncodedLen(8))
binary.LittleEndian.PutUint64(src, uint64(id))
base64.URLEncoding.WithPadding(base64.NoPadding).Encode(dst, src)
return "usr" + string(dst)
}
func parseUserIDList(values []userID) []int64 {
items := make([]int64, 0, len(values))
seen := make(map[int64]bool, len(values))
for _, value := range values {
id := int64(value)
if id == 0 || seen[id] {
continue
}
seen[id] = true
items = append(items, id)
}
return items
}