Skip to content

Commit

Permalink
Added onUnknownProfileRespondWithUuid param to the /profile endpoint
Browse files Browse the repository at this point in the history
Introducing profiles endpoint was a mistake, but we had to deal with that mistake until I'll remove it. The Accounts service needs textures with a signature. But it is possible that a user has a fresh account and Chrly has not yet received the profile information. In this case we have no way to get textures for the player. Adding the onUnknownProfileRespondWithUuid parameter solves this problem. This is a bad solution and nobody should use it except Ely.by infrastructure. In v5 version the texture signature on Chrly will be removed.
  • Loading branch information
erickskrauch committed Jun 11, 2024
1 parent ad31fdb commit 27c7b79
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 14 deletions.
27 changes: 21 additions & 6 deletions http/skinsystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,15 @@ func (ctx *Skinsystem) profileHandler(response http.ResponseWriter, request *htt
}

if profile == nil {
response.WriteHeader(http.StatusNoContent)
return
forceResponseWithUuid := request.URL.Query().Get("onUnknownProfileRespondWithUuid")
if forceResponseWithUuid == "" {
response.WriteHeader(http.StatusNoContent)
return
}

profile = createEmptyProfile()
profile.Id = formatUuid(forceResponseWithUuid)
profile.Username = parseUsername(mux.Vars(request)["username"])
}

texturesPropContent := &mojang.TexturesProp{
Expand Down Expand Up @@ -274,12 +281,10 @@ func (ctx *Skinsystem) getProfile(request *http.Request, proxy bool) (*profile,
return nil, err
}

profile := &profile{
Textures: &mojang.TexturesResponse{}, // Field must be initialized to avoid "null" after json encoding
}
profile := createEmptyProfile()

if skin != nil {
profile.Id = strings.Replace(skin.Uuid, "-", "", -1)
profile.Id = formatUuid(skin.Uuid)
profile.Username = skin.Username
}

Expand Down Expand Up @@ -354,6 +359,16 @@ func (ctx *Skinsystem) getProfile(request *http.Request, proxy bool) (*profile,
return profile, nil
}

func createEmptyProfile() *profile {
return &profile{
Textures: &mojang.TexturesResponse{}, // Field must be initialized to avoid "null" after json encoding
}
}

func formatUuid(uuid string) string {
return strings.Replace(uuid, "-", "", -1)
}

func parseUsername(username string) string {
return strings.TrimSuffix(username, ".png")
}
54 changes: 46 additions & 8 deletions http/skinsystem_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -742,11 +743,12 @@ func (suite *skinsystemTestSuite) TestSignedTextures() {
***************************/

type profileTestCase struct {
Name string
Signed bool
BeforeTest func(suite *skinsystemTestSuite)
PanicErr string
AfterTest func(suite *skinsystemTestSuite, response *http.Response)
Name string
Signed bool
ForceResponse string
BeforeTest func(suite *skinsystemTestSuite)
PanicErr string
AfterTest func(suite *skinsystemTestSuite, response *http.Response)
}

var profileTestsCases = []*profileTestCase{
Expand Down Expand Up @@ -1028,6 +1030,36 @@ var profileTestsCases = []*profileTestCase{
suite.Equal("", string(body))
},
},
{
Name: "Username not exists and Mojang profile unavailable, but there is a forceResponse param",
ForceResponse: "a12e41a4-e8e5-4503-987e-0adacf72ab93",
Signed: true,
BeforeTest: func(suite *skinsystemTestSuite) {
suite.SkinsRepository.On("FindSkinByUsername", "mock_username").Return(nil, nil)
suite.MojangTexturesProvider.On("GetForUsername", "mock_username").Once().Return(nil, nil)
suite.TexturesSigner.On("SignTextures", mock.Anything).Return("chrly signature", nil)
},
AfterTest: func(suite *skinsystemTestSuite, response *http.Response) {
suite.Equal(200, response.StatusCode)
suite.Equal("application/json", response.Header.Get("Content-Type"))
body, _ := ioutil.ReadAll(response.Body)
suite.JSONEq(`{
"id": "a12e41a4e8e54503987e0adacf72ab93",
"name": "mock_username",
"properties": [
{
"name": "textures",
"signature": "chrly signature",
"value": "eyJ0aW1lc3RhbXAiOjE2MTQyMTQyMjMwMDAsInByb2ZpbGVJZCI6ImExMmU0MWE0ZThlNTQ1MDM5ODdlMGFkYWNmNzJhYjkzIiwicHJvZmlsZU5hbWUiOiJtb2NrX3VzZXJuYW1lIiwidGV4dHVyZXMiOnt9fQ=="
},
{
"name": "texturesParamName",
"value": "texturesParamValue"
}
]
}`, string(body))
},
},
{
Name: "Username not exists and Mojang textures proxy returned an error",
BeforeTest: func(suite *skinsystemTestSuite) {
Expand Down Expand Up @@ -1060,12 +1092,18 @@ func (suite *skinsystemTestSuite) TestProfile() {
suite.RunSubTest(testCase.Name, func() {
testCase.BeforeTest(suite)

url := "http://chrly/profile/mock_username"
u, _ := url.Parse("http://chrly/profile/mock_username")
q := make(url.Values)
if testCase.Signed {
url += "?unsigned=false"
q.Set("unsigned", "false")
}

if testCase.ForceResponse != "" {
q.Set("onUnknownProfileRespondWithUuid", testCase.ForceResponse)
}

req := httptest.NewRequest("GET", url, nil)
u.RawQuery = q.Encode()
req := httptest.NewRequest("GET", u.String(), nil)
w := httptest.NewRecorder()

if testCase.PanicErr != "" {
Expand Down

0 comments on commit 27c7b79

Please sign in to comment.