From c6ef8a8706a51b4e6a17c365bbf685f00d292910 Mon Sep 17 00:00:00 2001 From: xmdhs Date: Sun, 10 Sep 2023 20:46:11 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E7=94=A8=E6=88=B7=E5=B1=9E?= =?UTF-8?q?=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- handle/yggdrasil/user.go | 18 ++++++++++++++++++ model/yggdrasil/model.go | 29 +++++++++++------------------ server/route/route.go | 3 ++- service/user.go | 14 +------------- service/yggdrasil/user.go | 29 ++++++++++++++++++++--------- utils/uuid.go | 16 ++++++++++++++++ 6 files changed, 68 insertions(+), 41 deletions(-) create mode 100644 utils/uuid.go diff --git a/handle/yggdrasil/user.go b/handle/yggdrasil/user.go index 3f96b79..63a61d7 100644 --- a/handle/yggdrasil/user.go +++ b/handle/yggdrasil/user.go @@ -6,6 +6,7 @@ import ( "net/http" "github.com/julienschmidt/httprouter" + "github.com/samber/lo" "github.com/xmdhs/authlib-skin/model/yggdrasil" sutils "github.com/xmdhs/authlib-skin/service/utils" yggdrasilS "github.com/xmdhs/authlib-skin/service/yggdrasil" @@ -154,3 +155,20 @@ func (y *Yggdrasil) GetProfile() httprouter.Handle { w.Write(b) } } + +func (y *Yggdrasil) BatchProfile() httprouter.Handle { + return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { + ctx := r.Context() + a, has := getAnyModel[[]string](ctx, w, r.Body, y.validate, y.logger) + if !has { + return + } + ul, err := y.yggdrasilService.BatchProfile(ctx, a) + if err != nil { + y.logger.WarnContext(ctx, err.Error()) + handleYgError(ctx, w, yggdrasil.Error{ErrorMessage: err.Error()}, 500) + return + } + w.Write(lo.Must1(json.Marshal(ul))) + } +} diff --git a/model/yggdrasil/model.go b/model/yggdrasil/model.go index 1a8b333..98d2677 100644 --- a/model/yggdrasil/model.go +++ b/model/yggdrasil/model.go @@ -22,23 +22,16 @@ type Error struct { ErrorMessage string `json:"errorMessage,omitempty"` } +type TokenUserID struct { + ID string `json:"id"` +} + type Token struct { - AccessToken string `json:"accessToken"` - AvailableProfiles []TokenProfile `json:"availableProfiles,omitempty"` - ClientToken string `json:"clientToken"` - SelectedProfile TokenProfile `json:"selectedProfile"` - User TokenUser `json:"user,omitempty"` -} - -type TokenProfile struct { - // 就是 uuid - ID string `json:"id"` - Name string `json:"name"` -} - -type TokenUser struct { - ID string `json:"id"` - Properties []any `json:"properties"` + AccessToken string `json:"accessToken"` + AvailableProfiles []UserInfo `json:"availableProfiles,omitempty"` + ClientToken string `json:"clientToken"` + SelectedProfile UserInfo `json:"selectedProfile"` + User TokenUserID `json:"user,omitempty"` } type ValidateToken struct { @@ -49,8 +42,8 @@ type ValidateToken struct { type RefreshToken struct { ValidateToken - RequestUser bool `json:"requestUser"` - SelectedProfile TokenProfile `json:"selectedProfile"` + RequestUser bool `json:"requestUser"` + SelectedProfile UserInfo `json:"selectedProfile"` } type UserInfo struct { diff --git a/server/route/route.go b/server/route/route.go index c11cb67..86333df 100644 --- a/server/route/route.go +++ b/server/route/route.go @@ -32,7 +32,8 @@ func newYggdrasil(r *httprouter.Router, handelY yggdrasil.Yggdrasil) error { r.PUT("/api/yggdrasil/api/user/profile/:uuid/:textureType", handelY.PutTexture()) r.DELETE("/api/yggdrasil/api/user/profile/:uuid/:textureType", warpHJSON(handelY.DelTexture())) - r.GET("/api/yggdrasil/sessionserver/session/minecraft/profile/:uuid", handelY.GetProfile()) + r.GET("/api/yggdrasil/sessionserver/session/minecraft/profile/:uuid", warpHJSON(handelY.GetProfile())) + r.POST("/api/profiles/minecraft", warpHJSON(handelY.BatchProfile())) r.GET("/api/yggdrasil", func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { w.Write([]byte(`{ diff --git a/service/user.go b/service/user.go index fa282de..5331024 100644 --- a/service/user.go +++ b/service/user.go @@ -2,8 +2,6 @@ package service import ( "context" - "crypto/md5" - "encoding/hex" "errors" "fmt" "strings" @@ -26,7 +24,7 @@ var ( func (w *WebService) Reg(ctx context.Context, u model.User, ip string) error { var userUuid string if w.config.OfflineUUID { - userUuid = uuidGen(u.Name) + userUuid = utils.UUIDGen(u.Name) } else { userUuid = strings.ReplaceAll(uuid.New().String(), "-", "") } @@ -82,13 +80,3 @@ func (w *WebService) Reg(ctx context.Context, u model.User, ip string) error { } return nil } - -func uuidGen(t string) string { - data := []byte("OfflinePlayer:" + t) - h := md5.New() - h.Write(data) - uuid := h.Sum(nil) - uuid[6] = (uuid[6] & 0x0f) | uint8((3&0xf)<<4) - uuid[8] = (uuid[8] & 0x3f) | 0x80 - return hex.EncodeToString(uuid) -} diff --git a/service/yggdrasil/user.go b/service/yggdrasil/user.go index f726d07..3738eaf 100644 --- a/service/yggdrasil/user.go +++ b/service/yggdrasil/user.go @@ -85,18 +85,17 @@ func (y *Yggdrasil) Authenticate(cxt context.Context, auth yggdrasil.Authenticat return yggdrasil.Token{}, fmt.Errorf("Authenticate: %w", err) } - p := yggdrasil.TokenProfile{ + p := yggdrasil.UserInfo{ ID: u.Edges.Profile.UUID, Name: u.Edges.Profile.Name, } return yggdrasil.Token{ AccessToken: jwts, - AvailableProfiles: []yggdrasil.TokenProfile{p}, + AvailableProfiles: []yggdrasil.UserInfo{p}, ClientToken: clientToken, SelectedProfile: p, - User: yggdrasil.TokenUser{ - ID: u.Edges.Profile.UUID, - Properties: []any{}, + User: yggdrasil.TokenUserID{ + ID: utils.UUIDGen(strconv.Itoa(u.ID)), }, }, nil } @@ -159,13 +158,12 @@ func (y *Yggdrasil) Refresh(ctx context.Context, token yggdrasil.RefreshToken) ( return yggdrasil.Token{ AccessToken: jwts, ClientToken: t.CID, - SelectedProfile: yggdrasil.TokenProfile{ + SelectedProfile: yggdrasil.UserInfo{ ID: up.UUID, Name: up.Name, }, - User: yggdrasil.TokenUser{ - ID: t.Subject, - Properties: []any{}, + User: yggdrasil.TokenUserID{ + ID: utils.UUIDGen(strconv.Itoa(t.UID)), }, }, nil } @@ -238,3 +236,16 @@ func (y *Yggdrasil) GetProfile(ctx context.Context, uuid string, unsigned bool, return uinfo, nil } + +func (y *Yggdrasil) BatchProfile(ctx context.Context, names []string) ([]yggdrasil.UserInfo, error) { + pl, err := y.client.UserProfile.Query().Where(userprofile.NameIn(names...)).All(ctx) + if err != nil { + return nil, fmt.Errorf("GetProfile: %w", err) + } + return lo.Map[*ent.UserProfile, yggdrasil.UserInfo](pl, func(item *ent.UserProfile, index int) yggdrasil.UserInfo { + return yggdrasil.UserInfo{ + ID: item.UUID, + Name: item.Name, + } + }), nil +} diff --git a/utils/uuid.go b/utils/uuid.go new file mode 100644 index 0000000..3f1a19a --- /dev/null +++ b/utils/uuid.go @@ -0,0 +1,16 @@ +package utils + +import ( + "crypto/md5" + "encoding/hex" +) + +func UUIDGen(t string) string { + data := []byte("OfflinePlayer:" + t) + h := md5.New() + h.Write(data) + uuid := h.Sum(nil) + uuid[6] = (uuid[6] & 0x0f) | uint8((3&0xf)<<4) + uuid[8] = (uuid[8] & 0x3f) | 0x80 + return hex.EncodeToString(uuid) +}