皮肤删除接口

This commit is contained in:
xmdhs 2023-09-08 23:03:13 +08:00
parent f966b1bfdc
commit bdd93bd7d2
No known key found for this signature in database
GPG Key ID: E809D6D43DEFCC95
3 changed files with 91 additions and 18 deletions

View File

@ -7,6 +7,7 @@ import (
"fmt"
"image/png"
"io"
"log/slog"
"net/http"
"strings"
@ -46,14 +47,14 @@ func (y *Yggdrasil) validTextureType(ctx context.Context, w http.ResponseWriter,
func (y *Yggdrasil) PutTexture() httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
ctx := r.Context()
uuid := p.ByName("uuid")
textureType := p.ByName("textureType")
if uuid == "" || textureType == "" {
y.logger.DebugContext(ctx, "路径中缺少参数 uuid / textureType")
handleYgError(ctx, w, yggdrasil.Error{ErrorMessage: "路径中缺少参数 uuid / textureType"}, 400)
uuid, textureType, ok := getUUIDbyParams(ctx, p, y.logger, w)
if !ok {
return
}
token := y.getTokenbyAuthorization(ctx, w, r)
if token == "" {
return
}
model := r.FormValue("model")
@ -114,3 +115,40 @@ func (y *Yggdrasil) PutTexture() httprouter.Handle {
w.WriteHeader(204)
}
}
func getUUIDbyParams(ctx context.Context, p httprouter.Params, l *slog.Logger, w http.ResponseWriter) (string, string, bool) {
uuid := p.ByName("uuid")
textureType := p.ByName("textureType")
if uuid == "" || textureType == "" {
l.DebugContext(ctx, "路径中缺少参数 uuid / textureType")
handleYgError(ctx, w, yggdrasil.Error{ErrorMessage: "路径中缺少参数 uuid / textureType"}, 400)
return "", "", false
}
return uuid, textureType, true
}
func (y *Yggdrasil) DelTexture() httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
ctx := r.Context()
uuid, textureType, ok := getUUIDbyParams(ctx, p, y.logger, w)
if !ok {
return
}
token := y.getTokenbyAuthorization(ctx, w, r)
if token == "" {
return
}
err := y.yggdrasilService.DelTexture(ctx, uuid, token, textureType)
if err != nil {
if errors.Is(err, utils.ErrTokenInvalid) {
y.logger.DebugContext(ctx, err.Error())
w.WriteHeader(401)
return
}
y.logger.WarnContext(ctx, err.Error())
handleYgError(ctx, w, yggdrasil.Error{ErrorMessage: err.Error()}, 500)
return
}
w.WriteHeader(204)
}
}

View File

@ -29,6 +29,7 @@ func newYggdrasil(r *httprouter.Router, handelY yggdrasil.Yggdrasil) error {
r.POST("/api/yggdrasil/authserver/invalidate", handelY.Invalidate())
r.POST("/api/yggdrasil/authserver/refresh", handelY.Refresh())
r.PUT("/api/yggdrasil/api/user/profile/:uuid/:textureType", handelY.PutTexture())
r.DELETE("/api/yggdrasil/api/user/profile/:uuid/:textureType", handelY.DelTexture())
r.GET("/api/yggdrasil", func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
w.Write([]byte(`{
"meta": {

View File

@ -24,21 +24,11 @@ var (
ErrUUIDNotEq = errors.New("uuid 不相同")
)
func (y *Yggdrasil) PutTexture(ctx context.Context, token string, texturebyte []byte, model string, uuid string, textureType string) error {
t, err := utilsService.Auth(ctx, yggdrasil.ValidateToken{AccessToken: token}, y.client, &y.prikey.PublicKey, true)
if err != nil {
return fmt.Errorf("PutTexture: %w", err)
}
if uuid != t.Subject {
return fmt.Errorf("PutTexture: %w", ErrUUIDNotEq)
}
up, err := y.client.UserProfile.Query().Where(userprofile.HasUserWith(user.ID(t.UID))).First(ctx)
err = utils.WithTx(ctx, y.client, func(tx *ent.Tx) error {
func (y *Yggdrasil) delTexture(ctx context.Context, userProfileID int, textureType string) error {
err := utils.WithTx(ctx, y.client, func(tx *ent.Tx) error {
// 查找此用户该类型下是否已经存在皮肤
tl, err := tx.UserTexture.Query().Where(usertexture.And(
usertexture.UserProfileID(up.ID),
usertexture.UserProfileID(userProfileID),
usertexture.Type(textureType),
)).ForUpdate().All(ctx)
if err != nil {
@ -75,11 +65,55 @@ func (y *Yggdrasil) PutTexture(ctx context.Context, token string, texturebyte []
return item.UserProfileID
})
// 中间表删除记录
// UserProfile 上没有于此相关的字段,所以无需操作
_, err = tx.UserTexture.Delete().Where(usertexture.UserProfileIDIn(ids...)).Exec(ctx)
return err
// 小概率皮肤上传后,高并发时被此处清理。问题不大重新上传一遍就行。
// 条件为使用一个独一无二的皮肤的用户,更换皮肤时,另一个用户同时更换自己的皮肤到这个独一无二的皮肤上。
})
if err != nil {
return fmt.Errorf("delTexture: %w", err)
}
return nil
}
func (y *Yggdrasil) DelTexture(ctx context.Context, uuid string, token string, textureType string) error {
t, err := utilsService.Auth(ctx, yggdrasil.ValidateToken{AccessToken: token}, y.client, &y.prikey.PublicKey, true)
if err != nil {
return fmt.Errorf("DelTexture: %w", err)
}
if uuid != t.Subject {
return fmt.Errorf("PutTexture: %w", errors.Join(ErrUUIDNotEq, utilsService.ErrTokenInvalid))
}
up, err := y.client.UserProfile.Query().Where(userprofile.HasUserWith(user.ID(t.UID))).First(ctx)
if err != nil {
return fmt.Errorf("DelTexture: %w", err)
}
err = y.delTexture(ctx, up.ID, textureType)
if err != nil {
return fmt.Errorf("DelTexture: %w", err)
}
return nil
}
func (y *Yggdrasil) PutTexture(ctx context.Context, token string, texturebyte []byte, model string, uuid string, textureType string) error {
t, err := utilsService.Auth(ctx, yggdrasil.ValidateToken{AccessToken: token}, y.client, &y.prikey.PublicKey, true)
if err != nil {
return fmt.Errorf("PutTexture: %w", err)
}
if uuid != t.Subject {
return fmt.Errorf("PutTexture: %w", errors.Join(ErrUUIDNotEq, utilsService.ErrTokenInvalid))
}
up, err := y.client.UserProfile.Query().Where(userprofile.HasUserWith(user.ID(t.UID))).First(ctx)
if err != nil {
return fmt.Errorf("PutTexture: %w", err)
}
err = y.delTexture(ctx, up.ID, textureType)
if err != nil {
return fmt.Errorf("PutTexture: %w", err)
}
hashstr, err := createTextureFile(y.config.TexturePath, texturebyte)
if err != nil {