Merge branch 'master' into v5

This commit is contained in:
ErickSkrauch
2023-12-29 07:51:28 +01:00
8 changed files with 76 additions and 93 deletions

View File

@@ -19,14 +19,6 @@ const UUID_ANY = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$
var regexUuidAny = regexp.MustCompile(UUID_ANY)
func init() {
govalidator.AddCustomRule("skinUploadingNotAvailable", func(field string, rule string, message string, value interface{}) error {
if message == "" {
message = "Skin uploading is temporary unavailable"
}
return errors.New(message)
})
// Add ability to validate any possible uuid form
govalidator.AddCustomRule("uuid_any", func(field string, rule string, message string, value interface{}) error {
str := value.(string)
@@ -163,50 +155,41 @@ func (ctx *Api) findIdentityOrCleanup(identityId int, username string) (*model.S
}
func validatePostSkinRequest(request *http.Request) map[string][]string {
const maxMultipartMemory int64 = 32 << 20
const oneOfSkinOrUrlMessage = "One of url or skin should be provided, but not both"
_ = request.ParseMultipartForm(maxMultipartMemory)
_ = request.ParseForm()
validationRules := govalidator.MapData{
"identityId": {"required", "numeric", "min:1"},
"username": {"required"},
"uuid": {"required", "uuid_any"},
"skinId": {"required", "numeric", "min:1"},
"url": {"url"},
"file:skin": {"ext:png", "size:24576", "mime:image/png"},
"is1_8": {"bool"},
"isSlim": {"bool"},
"identityId": {"required", "numeric", "min:1"},
"username": {"required"},
"uuid": {"required", "uuid_any"},
"skinId": {"required", "numeric"},
"url": {},
"is1_8": {"bool"},
"isSlim": {"bool"},
"mojangTextures": {},
"mojangSignature": {},
}
shouldAppendSkinRequiredError := false
url := request.Form.Get("url")
_, _, skinErr := request.FormFile("skin")
if (url != "" && skinErr == nil) || (url == "" && skinErr != nil) {
shouldAppendSkinRequiredError = true
} else if skinErr == nil {
validationRules["file:skin"] = append(validationRules["file:skin"], "skinUploadingNotAvailable")
} else if url != "" {
if url == "" {
validationRules["skinId"] = append(validationRules["skinId"], "numeric_between:0,0")
} else {
validationRules["url"] = append(validationRules["url"], "url")
validationRules["skinId"] = append(validationRules["skinId"], "numeric_between:1,")
validationRules["is1_8"] = append(validationRules["is1_8"], "required")
validationRules["isSlim"] = append(validationRules["isSlim"], "required")
}
mojangTextures := request.Form.Get("mojangTextures")
if mojangTextures != "" {
validationRules["mojangSignature"] = []string{"required"}
validationRules["mojangSignature"] = append(validationRules["mojangSignature"], "required")
}
validator := govalidator.New(govalidator.Options{
Request: request,
Rules: validationRules,
RequiredDefault: false,
FormSize: maxMultipartMemory,
})
validationResults := validator.Validate()
if shouldAppendSkinRequiredError {
validationResults["url"] = append(validationResults["url"], oneOfSkinOrUrlMessage)
validationResults["skin"] = append(validationResults["skin"], oneOfSkinOrUrlMessage)
}
if len(validationResults) != 0 {
return validationResults

View File

@@ -6,7 +6,6 @@ import (
"errors"
"io"
"io/ioutil"
"mime/multipart"
"net/http"
"net/http/httptest"
"net/url"
@@ -136,6 +135,41 @@ var postSkinTestsCases = []*postSkinTestCase{
suite.Empty(body)
},
},
{
Name: "Update exists identity by changing textures data to empty",
Form: bytes.NewBufferString(url.Values{
"identityId": {"1"},
"username": {"mock_username"},
"uuid": {"0f657aa8-bfbe-415d-b700-5750090d3af3"},
"skinId": {"0"},
"is1_8": {"0"},
"isSlim": {"0"},
"url": {""},
"mojangTextures": {""},
"mojangSignature": {""},
}.Encode()),
BeforeTest: func(suite *apiTestSuite) {
suite.SkinsRepository.On("FindSkinByUserId", 1).Return(createSkinModel("mock_username", false), nil)
suite.SkinsRepository.On("SaveSkin", mock.MatchedBy(func(model *model.Skin) bool {
suite.Equal(1, model.UserId)
suite.Equal("mock_username", model.Username)
suite.Equal("0f657aa8-bfbe-415d-b700-5750090d3af3", model.Uuid)
suite.Equal(0, model.SkinId)
suite.False(model.Is1_8)
suite.False(model.IsSlim)
suite.Equal("", model.Url)
suite.Equal("", model.MojangTextures)
suite.Equal("", model.MojangSignature)
return true
})).Times(1).Return(nil)
},
AfterTest: func(suite *apiTestSuite, response *http.Response) {
suite.Equal(201, response.StatusCode)
body, _ := io.ReadAll(response.Body)
suite.Equal("", string(body))
},
},
{
Name: "Update exists identity by changing its identityId",
Form: bytes.NewBufferString(url.Values{
@@ -271,7 +305,7 @@ func (suite *apiTestSuite) TestPostSkin() {
"skinId": [
"The skinId field is required",
"The skinId field must be numeric",
"The skinId field must be minimum 1 char"
"The skinId field must be numeric value between 0 and 0"
],
"username": [
"The username field is required"
@@ -280,54 +314,12 @@ func (suite *apiTestSuite) TestPostSkin() {
"The uuid field is required",
"The uuid field must contain valid UUID"
],
"url": [
"One of url or skin should be provided, but not both"
],
"skin": [
"One of url or skin should be provided, but not both"
],
"mojangSignature": [
"The mojangSignature field is required"
]
}
}`, string(body))
})
suite.RunSubTest("Upload textures with skin as file", func() {
inputBody := &bytes.Buffer{}
writer := multipart.NewWriter(inputBody)
part, _ := writer.CreateFormFile("skin", "char.png")
_, _ = part.Write(loadSkinFile())
_ = writer.WriteField("identityId", "1")
_ = writer.WriteField("username", "mock_user")
_ = writer.WriteField("uuid", "0f657aa8-bfbe-415d-b700-5750090d3af3")
_ = writer.WriteField("skinId", "5")
err := writer.Close()
if err != nil {
panic(err)
}
req := httptest.NewRequest("POST", "http://chrly/skins", inputBody)
req.Header.Add("Content-Type", writer.FormDataContentType())
w := httptest.NewRecorder()
suite.App.Handler().ServeHTTP(w, req)
resp := w.Result()
defer resp.Body.Close()
suite.Equal(400, resp.StatusCode)
responseBody, _ := ioutil.ReadAll(resp.Body)
suite.JSONEq(`{
"errors": {
"skin": [
"Skin uploading is temporary unavailable"
]
}
}`, string(responseBody))
})
}
/**************************************

View File

@@ -6,7 +6,6 @@ import (
"encoding/base64"
"encoding/json"
"encoding/pem"
"github.com/elyby/chrly/utils"
"io"
"net/http"
"strings"
@@ -16,6 +15,7 @@ import (
"github.com/elyby/chrly/api/mojang"
"github.com/elyby/chrly/model"
"github.com/elyby/chrly/utils"
)
var timeNow = time.Now
@@ -275,12 +275,7 @@ func (ctx *Skinsystem) getProfile(request *http.Request, proxy bool) (*profile,
}
profile := &profile{
Id: "",
Username: "",
Textures: &mojang.TexturesResponse{}, // Field must be initialized to avoid "null" after json encoding
CapeFile: nil,
MojangTextures: "",
MojangSignature: "",
Textures: &mojang.TexturesResponse{}, // Field must be initialized to avoid "null" after json encoding
}
if skin != nil {
@@ -288,7 +283,7 @@ func (ctx *Skinsystem) getProfile(request *http.Request, proxy bool) (*profile,
profile.Username = skin.Username
}
if skin != nil && skin.SkinId != 0 {
if skin != nil && skin.Url != "" {
profile.Textures.Skin = &mojang.SkinTexturesResponse{
Url: skin.Url,
}
@@ -350,6 +345,8 @@ func (ctx *Skinsystem) getProfile(request *http.Request, proxy bool) (*profile,
profile.Id = mojangProfile.Id
profile.Username = mojangProfile.Name
}
} else if profile.Id != "" {
return profile, nil
} else {
return nil, nil
}