mirror of
https://github.com/elyby/chrly.git
synced 2025-03-12 02:49:26 +05:30
Go, Go Context! Added context transfer literally everywhere
This commit is contained in:
parent
fdafbc4f0e
commit
f5bc474b4d
1
go.mod
1
go.mod
@ -14,6 +14,7 @@ require (
|
||||
github.com/jellydator/ttlcache/v3 v3.1.1
|
||||
github.com/mediocregopher/radix/v4 v4.1.4
|
||||
github.com/mono83/slf v0.0.0-20170919161409-79153e9636db
|
||||
github.com/SentimensRG/ctx v0.0.0-20180729130232-0bfd988c655d
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/spf13/viper v1.18.1
|
||||
github.com/valyala/fastjson v1.6.4
|
||||
|
@ -15,7 +15,6 @@ const userUuidToUsernameKey = "hash:uuid-to-username"
|
||||
|
||||
type Redis struct {
|
||||
client radix.Client
|
||||
context context.Context
|
||||
serializer db.ProfileSerializer
|
||||
}
|
||||
|
||||
@ -27,14 +26,13 @@ func New(ctx context.Context, profileSerializer db.ProfileSerializer, addr strin
|
||||
|
||||
return &Redis{
|
||||
client: client,
|
||||
context: ctx,
|
||||
serializer: profileSerializer,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *Redis) FindProfileByUsername(username string) (*db.Profile, error) {
|
||||
func (r *Redis) FindProfileByUsername(ctx context.Context, username string) (*db.Profile, error) {
|
||||
var profile *db.Profile
|
||||
err := r.client.Do(r.context, radix.WithConn("", func(ctx context.Context, conn radix.Conn) error {
|
||||
err := r.client.Do(ctx, radix.WithConn("", func(ctx context.Context, conn radix.Conn) error {
|
||||
var err error
|
||||
profile, err = r.findProfileByUsername(ctx, conn, username)
|
||||
|
||||
@ -58,38 +56,13 @@ func (r *Redis) findProfileByUsername(ctx context.Context, conn radix.Conn, user
|
||||
return r.serializer.Deserialize(encodedResult)
|
||||
}
|
||||
|
||||
func (r *Redis) FindProfileByUuid(uuid string) (*db.Profile, error) {
|
||||
var skin *db.Profile
|
||||
err := r.client.Do(r.context, radix.WithConn("", func(ctx context.Context, conn radix.Conn) error {
|
||||
var err error
|
||||
skin, err = r.findProfileByUuid(ctx, conn, uuid)
|
||||
|
||||
return err
|
||||
}))
|
||||
|
||||
return skin, err
|
||||
}
|
||||
|
||||
func (r *Redis) findProfileByUuid(ctx context.Context, conn radix.Conn, uuid string) (*db.Profile, error) {
|
||||
username, err := r.findUsernameHashKeyByUuid(ctx, conn, uuid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if username == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return r.findProfileByUsername(ctx, conn, username)
|
||||
}
|
||||
|
||||
func (r *Redis) findUsernameHashKeyByUuid(ctx context.Context, conn radix.Conn, uuid string) (string, error) {
|
||||
var username string
|
||||
return username, conn.Do(ctx, radix.FlatCmd(&username, "HGET", userUuidToUsernameKey, normalizeUuid(uuid)))
|
||||
}
|
||||
|
||||
func (r *Redis) SaveProfile(profile *db.Profile) error {
|
||||
return r.client.Do(r.context, radix.WithConn("", func(ctx context.Context, conn radix.Conn) error {
|
||||
func (r *Redis) SaveProfile(ctx context.Context, profile *db.Profile) error {
|
||||
return r.client.Do(ctx, radix.WithConn("", func(ctx context.Context, conn radix.Conn) error {
|
||||
return r.saveProfile(ctx, conn, profile)
|
||||
}))
|
||||
}
|
||||
@ -137,8 +110,8 @@ func (r *Redis) saveProfile(ctx context.Context, conn radix.Conn, profile *db.Pr
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Redis) RemoveProfileByUuid(uuid string) error {
|
||||
return r.client.Do(r.context, radix.WithConn("", func(ctx context.Context, conn radix.Conn) error {
|
||||
func (r *Redis) RemoveProfileByUuid(ctx context.Context, uuid string) error {
|
||||
return r.client.Do(ctx, radix.WithConn("", func(ctx context.Context, conn radix.Conn) error {
|
||||
return r.removeProfileByUuid(ctx, conn, uuid)
|
||||
}))
|
||||
}
|
||||
@ -169,10 +142,10 @@ func (r *Redis) removeProfileByUuid(ctx context.Context, conn radix.Conn, uuid s
|
||||
return conn.Do(ctx, radix.Cmd(nil, "EXEC"))
|
||||
}
|
||||
|
||||
func (r *Redis) GetUuidForMojangUsername(username string) (string, string, error) {
|
||||
func (r *Redis) GetUuidForMojangUsername(ctx context.Context, username string) (string, string, error) {
|
||||
var uuid string
|
||||
foundUsername := username
|
||||
err := r.client.Do(r.context, radix.WithConn("", func(ctx context.Context, conn radix.Conn) error {
|
||||
err := r.client.Do(ctx, radix.WithConn("", func(ctx context.Context, conn radix.Conn) error {
|
||||
var err error
|
||||
uuid, foundUsername, err = findMojangUuidByUsername(ctx, conn, username)
|
||||
|
||||
@ -199,8 +172,8 @@ func findMojangUuidByUsername(ctx context.Context, conn radix.Conn, username str
|
||||
return parts[1], parts[0], nil
|
||||
}
|
||||
|
||||
func (r *Redis) StoreMojangUuid(username string, uuid string) error {
|
||||
return r.client.Do(r.context, radix.WithConn("", func(ctx context.Context, conn radix.Conn) error {
|
||||
func (r *Redis) StoreMojangUuid(ctx context.Context, username string, uuid string) error {
|
||||
return r.client.Do(ctx, radix.WithConn("", func(ctx context.Context, conn radix.Conn) error {
|
||||
return storeMojangUuid(ctx, conn, username, uuid)
|
||||
}))
|
||||
}
|
||||
|
@ -115,19 +115,20 @@ func TestRedis(t *testing.T) {
|
||||
}
|
||||
|
||||
func (s *redisTestSuite) TestFindProfileByUsername() {
|
||||
ctx := context.Background()
|
||||
s.Run("exists record", func() {
|
||||
serializedData := []byte("mock.exists.profile")
|
||||
expectedProfile := &db.Profile{}
|
||||
s.cmd("HSET", usernameToProfileKey, "mock", serializedData)
|
||||
s.Serializer.On("Deserialize", serializedData).Return(expectedProfile, nil)
|
||||
|
||||
profile, err := s.Redis.FindProfileByUsername("Mock")
|
||||
profile, err := s.Redis.FindProfileByUsername(ctx, "Mock")
|
||||
s.Require().NoError(err)
|
||||
s.Require().Same(expectedProfile, profile)
|
||||
})
|
||||
|
||||
s.Run("not exists record", func() {
|
||||
profile, err := s.Redis.FindProfileByUsername("Mock")
|
||||
profile, err := s.Redis.FindProfileByUsername(ctx, "Mock")
|
||||
s.Require().NoError(err)
|
||||
s.Require().Nil(profile)
|
||||
})
|
||||
@ -137,40 +138,15 @@ func (s *redisTestSuite) TestFindProfileByUsername() {
|
||||
s.cmd("HSET", usernameToProfileKey, "mock", "some-invalid-mock-data")
|
||||
s.Serializer.On("Deserialize", mock.Anything).Return(nil, expectedError)
|
||||
|
||||
profile, err := s.Redis.FindProfileByUsername("Mock")
|
||||
profile, err := s.Redis.FindProfileByUsername(ctx, "Mock")
|
||||
s.Require().Nil(profile)
|
||||
s.Require().ErrorIs(err, expectedError)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *redisTestSuite) TestFindProfileByUuid() {
|
||||
s.Run("exists record", func() {
|
||||
serializedData := []byte("mock.exists.profile")
|
||||
expectedProfile := &db.Profile{Username: "Mock"}
|
||||
s.cmd("HSET", usernameToProfileKey, "mock", serializedData)
|
||||
s.cmd("HSET", userUuidToUsernameKey, "f57f36d54f504728948a42d5d80b18f3", "mock")
|
||||
s.Serializer.On("Deserialize", serializedData).Return(expectedProfile, nil)
|
||||
|
||||
profile, err := s.Redis.FindProfileByUuid("f57f36d5-4f50-4728-948a-42d5d80b18f3")
|
||||
s.Require().NoError(err)
|
||||
s.Require().Same(expectedProfile, profile)
|
||||
})
|
||||
|
||||
s.Run("not exists record", func() {
|
||||
profile, err := s.Redis.FindProfileByUuid("f57f36d5-4f50-4728-948a-42d5d80b18f3")
|
||||
s.Require().NoError(err)
|
||||
s.Require().Nil(profile)
|
||||
})
|
||||
|
||||
s.Run("exists uuid record, but related profile not exists", func() {
|
||||
s.cmd("HSET", userUuidToUsernameKey, "f57f36d54f504728948a42d5d80b18f3", "mock")
|
||||
profile, err := s.Redis.FindProfileByUuid("f57f36d5-4f50-4728-948a-42d5d80b18f3")
|
||||
s.Require().NoError(err)
|
||||
s.Require().Nil(profile)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *redisTestSuite) TestSaveProfile() {
|
||||
ctx := context.Background()
|
||||
|
||||
s.Run("save new entity", func() {
|
||||
profile := &db.Profile{
|
||||
Uuid: "f57f36d5-4f50-4728-948a-42d5d80b18f3",
|
||||
@ -182,7 +158,7 @@ func (s *redisTestSuite) TestSaveProfile() {
|
||||
s.cmd("HSET", usernameToProfileKey, "mock", serializedProfile)
|
||||
s.cmd("HSET", userUuidToUsernameKey, "f57f36d54f504728948a42d5d80b18f3", "mock")
|
||||
|
||||
err := s.Redis.SaveProfile(profile)
|
||||
err := s.Redis.SaveProfile(ctx, profile)
|
||||
s.Require().NoError(err)
|
||||
|
||||
uuidResp := s.cmd("HGET", userUuidToUsernameKey, "f57f36d54f504728948a42d5d80b18f3")
|
||||
@ -203,7 +179,7 @@ func (s *redisTestSuite) TestSaveProfile() {
|
||||
s.cmd("HSET", usernameToProfileKey, "mock", "serialized-old-profile")
|
||||
s.cmd("HSET", userUuidToUsernameKey, "f57f36d54f504728948a42d5d80b18f3", "mock")
|
||||
|
||||
err := s.Redis.SaveProfile(newProfile)
|
||||
err := s.Redis.SaveProfile(ctx, newProfile)
|
||||
s.Require().NoError(err)
|
||||
|
||||
uuidResp := s.cmd("HGET", userUuidToUsernameKey, "f57f36d54f504728948a42d5d80b18f3")
|
||||
@ -218,11 +194,13 @@ func (s *redisTestSuite) TestSaveProfile() {
|
||||
}
|
||||
|
||||
func (s *redisTestSuite) TestRemoveProfileByUuid() {
|
||||
ctx := context.Background()
|
||||
|
||||
s.Run("exists record", func() {
|
||||
s.cmd("HSET", usernameToProfileKey, "mock", "serialized-profile")
|
||||
s.cmd("HSET", userUuidToUsernameKey, "f57f36d54f504728948a42d5d80b18f3", "mock")
|
||||
|
||||
err := s.Redis.RemoveProfileByUuid("f57f36d5-4f50-4728-948a-42d5d80b18f3")
|
||||
err := s.Redis.RemoveProfileByUuid(ctx, "f57f36d5-4f50-4728-948a-42d5d80b18f3")
|
||||
s.Require().NoError(err)
|
||||
|
||||
uuidResp := s.cmd("HGET", userUuidToUsernameKey, "f57f36d54f504728948a42d5d80b18f3")
|
||||
@ -235,7 +213,7 @@ func (s *redisTestSuite) TestRemoveProfileByUuid() {
|
||||
s.Run("uuid exists, username is missing", func() {
|
||||
s.cmd("HSET", userUuidToUsernameKey, "f57f36d54f504728948a42d5d80b18f3", "mock")
|
||||
|
||||
err := s.Redis.RemoveProfileByUuid("f57f36d5-4f50-4728-948a-42d5d80b18f3")
|
||||
err := s.Redis.RemoveProfileByUuid(ctx, "f57f36d5-4f50-4728-948a-42d5d80b18f3")
|
||||
s.Require().NoError(err)
|
||||
|
||||
uuidResp := s.cmd("HGET", userUuidToUsernameKey, "f57f36d54f504728948a42d5d80b18f3")
|
||||
@ -243,16 +221,18 @@ func (s *redisTestSuite) TestRemoveProfileByUuid() {
|
||||
})
|
||||
|
||||
s.Run("uuid not exists", func() {
|
||||
err := s.Redis.RemoveProfileByUuid("f57f36d5-4f50-4728-948a-42d5d80b18f3")
|
||||
err := s.Redis.RemoveProfileByUuid(ctx, "f57f36d5-4f50-4728-948a-42d5d80b18f3")
|
||||
s.Require().NoError(err)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *redisTestSuite) TestGetUuidForMojangUsername() {
|
||||
ctx := context.Background()
|
||||
|
||||
s.Run("exists record", func() {
|
||||
s.cmd("SET", "mojang:uuid:mock", "MoCk:d3ca513eb3e14946b58047f2bd3530fd")
|
||||
|
||||
uuid, username, err := s.Redis.GetUuidForMojangUsername("Mock")
|
||||
uuid, username, err := s.Redis.GetUuidForMojangUsername(ctx, "Mock")
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal("MoCk", username)
|
||||
s.Require().Equal("d3ca513eb3e14946b58047f2bd3530fd", uuid)
|
||||
@ -261,14 +241,14 @@ func (s *redisTestSuite) TestGetUuidForMojangUsername() {
|
||||
s.Run("exists record with empty uuid value", func() {
|
||||
s.cmd("SET", "mojang:uuid:mock", "MoCk:")
|
||||
|
||||
uuid, username, err := s.Redis.GetUuidForMojangUsername("Mock")
|
||||
uuid, username, err := s.Redis.GetUuidForMojangUsername(ctx, "Mock")
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal("MoCk", username)
|
||||
s.Require().Empty(uuid)
|
||||
})
|
||||
|
||||
s.Run("not exists record", func() {
|
||||
uuid, username, err := s.Redis.GetUuidForMojangUsername("Mock")
|
||||
uuid, username, err := s.Redis.GetUuidForMojangUsername(ctx, "Mock")
|
||||
s.Require().NoError(err)
|
||||
s.Require().Empty(username)
|
||||
s.Require().Empty(uuid)
|
||||
@ -276,8 +256,10 @@ func (s *redisTestSuite) TestGetUuidForMojangUsername() {
|
||||
}
|
||||
|
||||
func (s *redisTestSuite) TestStoreUuid() {
|
||||
ctx := context.Background()
|
||||
|
||||
s.Run("store uuid", func() {
|
||||
err := s.Redis.StoreMojangUuid("MoCk", "d3ca513eb3e14946b58047f2bd3530fd")
|
||||
err := s.Redis.StoreMojangUuid(ctx, "MoCk", "d3ca513eb3e14946b58047f2bd3530fd")
|
||||
s.Require().NoError(err)
|
||||
|
||||
resp := s.cmd("GET", "mojang:uuid:mock")
|
||||
@ -285,7 +267,7 @@ func (s *redisTestSuite) TestStoreUuid() {
|
||||
})
|
||||
|
||||
s.Run("store empty uuid", func() {
|
||||
err := s.Redis.StoreMojangUuid("MoCk", "")
|
||||
err := s.Redis.StoreMojangUuid(ctx, "MoCk", "")
|
||||
s.Require().NoError(err)
|
||||
|
||||
resp := s.cmd("GET", "mojang:uuid:mock")
|
||||
|
@ -1,6 +1,7 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
@ -12,8 +13,8 @@ import (
|
||||
)
|
||||
|
||||
type ProfilesManager interface {
|
||||
PersistProfile(profile *db.Profile) error
|
||||
RemoveProfileByUuid(uuid string) error
|
||||
PersistProfile(ctx context.Context, profile *db.Profile) error
|
||||
RemoveProfileByUuid(ctx context.Context, uuid string) error
|
||||
}
|
||||
|
||||
type Api struct {
|
||||
@ -47,7 +48,7 @@ func (ctx *Api) postProfileHandler(resp http.ResponseWriter, req *http.Request)
|
||||
MojangSignature: req.Form.Get("mojangSignature"),
|
||||
}
|
||||
|
||||
err = ctx.PersistProfile(profile)
|
||||
err = ctx.PersistProfile(req.Context(), profile)
|
||||
if err != nil {
|
||||
var v *profiles.ValidationError
|
||||
if errors.As(err, &v) {
|
||||
@ -64,7 +65,7 @@ func (ctx *Api) postProfileHandler(resp http.ResponseWriter, req *http.Request)
|
||||
|
||||
func (ctx *Api) deleteProfileByUuidHandler(resp http.ResponseWriter, req *http.Request) {
|
||||
uuid := mux.Vars(req)["uuid"]
|
||||
err := ctx.ProfilesManager.RemoveProfileByUuid(uuid)
|
||||
err := ctx.ProfilesManager.RemoveProfileByUuid(req.Context(), uuid)
|
||||
if err != nil {
|
||||
apiServerError(resp, fmt.Errorf("unable to delete profile from db: %w", err))
|
||||
return
|
||||
|
@ -2,6 +2,7 @@ package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
@ -21,12 +22,12 @@ type ProfilesManagerMock struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (m *ProfilesManagerMock) PersistProfile(profile *db.Profile) error {
|
||||
return m.Called(profile).Error(0)
|
||||
func (m *ProfilesManagerMock) PersistProfile(ctx context.Context, profile *db.Profile) error {
|
||||
return m.Called(ctx, profile).Error(0)
|
||||
}
|
||||
|
||||
func (m *ProfilesManagerMock) RemoveProfileByUuid(uuid string) error {
|
||||
return m.Called(uuid).Error(0)
|
||||
func (m *ProfilesManagerMock) RemoveProfileByUuid(ctx context.Context, uuid string) error {
|
||||
return m.Called(ctx, uuid).Error(0)
|
||||
}
|
||||
|
||||
type ApiTestSuite struct {
|
||||
@ -50,7 +51,7 @@ func (t *ApiTestSuite) TearDownSubTest() {
|
||||
|
||||
func (t *ApiTestSuite) TestPostProfile() {
|
||||
t.Run("successfully post profile", func() {
|
||||
t.ProfilesManager.On("PersistProfile", &db.Profile{
|
||||
t.ProfilesManager.On("PersistProfile", mock.Anything, &db.Profile{
|
||||
Uuid: "0f657aa8-bfbe-415d-b700-5750090d3af3",
|
||||
Username: "mock_username",
|
||||
SkinUrl: "https://example.com/skin.png",
|
||||
@ -100,7 +101,7 @@ func (t *ApiTestSuite) TestPostProfile() {
|
||||
})
|
||||
|
||||
t.Run("receive validation errors", func() {
|
||||
t.ProfilesManager.On("PersistProfile", mock.Anything).Once().Return(&profiles.ValidationError{
|
||||
t.ProfilesManager.On("PersistProfile", mock.Anything, mock.Anything).Once().Return(&profiles.ValidationError{
|
||||
Errors: map[string][]string{
|
||||
"mock": {"error1", "error2"},
|
||||
},
|
||||
@ -126,7 +127,7 @@ func (t *ApiTestSuite) TestPostProfile() {
|
||||
})
|
||||
|
||||
t.Run("receive other error", func() {
|
||||
t.ProfilesManager.On("PersistProfile", mock.Anything).Once().Return(errors.New("mock error"))
|
||||
t.ProfilesManager.On("PersistProfile", mock.Anything, mock.Anything).Once().Return(errors.New("mock error"))
|
||||
|
||||
req := httptest.NewRequest("POST", "http://chrly/profiles", strings.NewReader(""))
|
||||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
@ -141,7 +142,7 @@ func (t *ApiTestSuite) TestPostProfile() {
|
||||
|
||||
func (t *ApiTestSuite) TestDeleteProfileByUuid() {
|
||||
t.Run("successfully delete", func() {
|
||||
t.ProfilesManager.On("RemoveProfileByUuid", "0f657aa8-bfbe-415d-b700-5750090d3af3").Once().Return(nil)
|
||||
t.ProfilesManager.On("RemoveProfileByUuid", mock.Anything, "0f657aa8-bfbe-415d-b700-5750090d3af3").Once().Return(nil)
|
||||
|
||||
req := httptest.NewRequest("DELETE", "http://chrly/profiles/0f657aa8-bfbe-415d-b700-5750090d3af3", nil)
|
||||
w := httptest.NewRecorder()
|
||||
@ -155,7 +156,7 @@ func (t *ApiTestSuite) TestDeleteProfileByUuid() {
|
||||
})
|
||||
|
||||
t.Run("error from manager", func() {
|
||||
t.ProfilesManager.On("RemoveProfileByUuid", mock.Anything).Return(errors.New("mock error"))
|
||||
t.ProfilesManager.On("RemoveProfileByUuid", mock.Anything, mock.Anything).Return(errors.New("mock error"))
|
||||
|
||||
req := httptest.NewRequest("DELETE", "http://chrly/profiles/0f657aa8-bfbe-415d-b700-5750090d3af3", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
@ -25,9 +25,10 @@ type ProfilesProvider interface {
|
||||
FindProfileByUsername(ctx context.Context, username string, allowProxy bool) (*db.Profile, error)
|
||||
}
|
||||
|
||||
// TexturesSigner uses context because in the future we may separate this logic into a separate microservice
|
||||
type TexturesSigner interface {
|
||||
SignTextures(textures string) (string, error)
|
||||
GetPublicKey() (*rsa.PublicKey, error)
|
||||
SignTextures(ctx context.Context, textures string) (string, error)
|
||||
GetPublicKey(ctx context.Context) (*rsa.PublicKey, error)
|
||||
}
|
||||
|
||||
type Skinsystem struct {
|
||||
@ -202,7 +203,7 @@ func (ctx *Skinsystem) profileHandler(response http.ResponseWriter, request *htt
|
||||
}
|
||||
|
||||
if request.URL.Query().Has("unsigned") && !getToBool(request.URL.Query().Get("unsigned")) {
|
||||
signature, err := ctx.TexturesSigner.SignTextures(texturesProp.Value)
|
||||
signature, err := ctx.TexturesSigner.SignTextures(request.Context(), texturesProp.Value)
|
||||
if err != nil {
|
||||
apiServerError(response, fmt.Errorf("unable to sign textures: %w", err))
|
||||
return
|
||||
@ -229,7 +230,7 @@ func (ctx *Skinsystem) profileHandler(response http.ResponseWriter, request *htt
|
||||
}
|
||||
|
||||
func (ctx *Skinsystem) signatureVerificationKeyHandler(response http.ResponseWriter, request *http.Request) {
|
||||
publicKey, err := ctx.TexturesSigner.GetPublicKey()
|
||||
publicKey, err := ctx.TexturesSigner.GetPublicKey(request.Context())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -38,13 +38,13 @@ type TexturesSignerMock struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (m *TexturesSignerMock) SignTextures(textures string) (string, error) {
|
||||
args := m.Called(textures)
|
||||
func (m *TexturesSignerMock) SignTextures(ctx context.Context, textures string) (string, error) {
|
||||
args := m.Called(ctx, textures)
|
||||
return args.String(0), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *TexturesSignerMock) GetPublicKey() (*rsa.PublicKey, error) {
|
||||
args := m.Called()
|
||||
func (m *TexturesSignerMock) GetPublicKey(ctx context.Context) (*rsa.PublicKey, error) {
|
||||
args := m.Called(ctx)
|
||||
var publicKey *rsa.PublicKey
|
||||
if casted, ok := args.Get(0).(*rsa.PublicKey); ok {
|
||||
publicKey = casted
|
||||
@ -470,7 +470,7 @@ func (t *SkinsystemTestSuite) TestProfile() {
|
||||
SkinUrl: "https://example.com/skin.png",
|
||||
SkinModel: "slim",
|
||||
}, nil)
|
||||
t.TexturesSigner.On("SignTextures", "eyJ0aW1lc3RhbXAiOjE2MTQyMTQyMjMwMDAsInByb2ZpbGVJZCI6Im1vY2stdXVpZCIsInByb2ZpbGVOYW1lIjoibW9ja191c2VybmFtZSIsInRleHR1cmVzIjp7IlNLSU4iOnsidXJsIjoiaHR0cHM6Ly9leGFtcGxlLmNvbS9za2luLnBuZyIsIm1ldGFkYXRhIjp7Im1vZGVsIjoic2xpbSJ9fX19").Return("mock signature", nil)
|
||||
t.TexturesSigner.On("SignTextures", mock.Anything, "eyJ0aW1lc3RhbXAiOjE2MTQyMTQyMjMwMDAsInByb2ZpbGVJZCI6Im1vY2stdXVpZCIsInByb2ZpbGVOYW1lIjoibW9ja191c2VybmFtZSIsInRleHR1cmVzIjp7IlNLSU4iOnsidXJsIjoiaHR0cHM6Ly9leGFtcGxlLmNvbS9za2luLnBuZyIsIm1ldGFkYXRhIjp7Im1vZGVsIjoic2xpbSJ9fX19").Return("mock signature", nil)
|
||||
|
||||
t.App.Handler().ServeHTTP(w, req)
|
||||
|
||||
@ -526,7 +526,7 @@ func (t *SkinsystemTestSuite) TestProfile() {
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
t.ProfilesProvider.On("FindProfileByUsername", mock.Anything, "mock_username", true).Return(&db.Profile{}, nil)
|
||||
t.TexturesSigner.On("SignTextures", mock.Anything).Return("", errors.New("mock error"))
|
||||
t.TexturesSigner.On("SignTextures", mock.Anything, mock.Anything).Return("", errors.New("mock error"))
|
||||
|
||||
t.App.Handler().ServeHTTP(w, req)
|
||||
|
||||
@ -551,7 +551,7 @@ var signingKeyTestsCases = []*signingKeyTestCase{
|
||||
pubPem, _ := pem.Decode([]byte("-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANbUpVCZkMKpfvYZ08W3lumdAaYxLBnm\nUDlzHBQH3DpYef5WCO32TDU6feIJ58A0lAywgtZ4wwi2dGHOz/1hAvcCAwEAAQ==\n-----END PUBLIC KEY-----"))
|
||||
publicKey, _ := x509.ParsePKIXPublicKey(pubPem.Bytes)
|
||||
|
||||
suite.TexturesSigner.On("GetPublicKey").Return(publicKey, nil)
|
||||
suite.TexturesSigner.On("GetPublicKey", mock.Anything).Return(publicKey, nil)
|
||||
},
|
||||
AfterTest: func(suite *SkinsystemTestSuite, response *http.Response) {
|
||||
suite.Equal(200, response.StatusCode)
|
||||
@ -568,7 +568,7 @@ var signingKeyTestsCases = []*signingKeyTestCase{
|
||||
pubPem, _ := pem.Decode([]byte("-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANbUpVCZkMKpfvYZ08W3lumdAaYxLBnm\nUDlzHBQH3DpYef5WCO32TDU6feIJ58A0lAywgtZ4wwi2dGHOz/1hAvcCAwEAAQ==\n-----END PUBLIC KEY-----"))
|
||||
publicKey, _ := x509.ParsePKIXPublicKey(pubPem.Bytes)
|
||||
|
||||
suite.TexturesSigner.On("GetPublicKey").Return(publicKey, nil)
|
||||
suite.TexturesSigner.On("GetPublicKey", mock.Anything).Return(publicKey, nil)
|
||||
},
|
||||
AfterTest: func(suite *SkinsystemTestSuite, response *http.Response) {
|
||||
suite.Equal(200, response.StatusCode)
|
||||
@ -582,7 +582,7 @@ var signingKeyTestsCases = []*signingKeyTestCase{
|
||||
Name: "Error while obtaining public key",
|
||||
KeyFormat: "DER",
|
||||
BeforeTest: func(suite *SkinsystemTestSuite) {
|
||||
suite.TexturesSigner.On("GetPublicKey").Return(nil, errors.New("textures signer error"))
|
||||
suite.TexturesSigner.On("GetPublicKey", mock.Anything).Return(nil, errors.New("textures signer error"))
|
||||
},
|
||||
PanicErr: "textures signer error",
|
||||
},
|
||||
|
@ -6,14 +6,18 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/SentimensRG/ctx/mergectx"
|
||||
|
||||
"ely.by/chrly/internal/utils"
|
||||
)
|
||||
|
||||
type UsernamesToUuidsEndpoint func(ctx context.Context, usernames []string) ([]*ProfileInfo, error)
|
||||
|
||||
type BatchUuidsProvider struct {
|
||||
UsernamesToUuidsEndpoint func(usernames []string) ([]*ProfileInfo, error)
|
||||
batch int
|
||||
delay time.Duration
|
||||
fireOnFull bool
|
||||
UsernamesToUuidsEndpoint
|
||||
batch int
|
||||
delay time.Duration
|
||||
fireOnFull bool
|
||||
|
||||
queue *utils.Queue[*job]
|
||||
fireChan chan any
|
||||
@ -22,7 +26,7 @@ type BatchUuidsProvider struct {
|
||||
}
|
||||
|
||||
func NewBatchUuidsProvider(
|
||||
endpoint func(usernames []string) ([]*ProfileInfo, error),
|
||||
endpoint UsernamesToUuidsEndpoint,
|
||||
batchSize int,
|
||||
awaitDelay time.Duration,
|
||||
fireOnFull bool,
|
||||
@ -115,12 +119,14 @@ func (p *BatchUuidsProvider) fireRequest() {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
usernames := make([]string, len(jobs))
|
||||
for i, job := range jobs {
|
||||
usernames[i] = job.Username
|
||||
ctx = mergectx.Join(ctx, job.Ctx)
|
||||
}
|
||||
|
||||
profiles, err := p.UsernamesToUuidsEndpoint(usernames)
|
||||
profiles, err := p.UsernamesToUuidsEndpoint(ctx, usernames)
|
||||
for _, job := range jobs {
|
||||
response := &jobResult{}
|
||||
if err == nil {
|
||||
|
@ -16,8 +16,8 @@ type mojangUsernamesToUuidsRequestMock struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (o *mojangUsernamesToUuidsRequestMock) UsernamesToUuids(usernames []string) ([]*ProfileInfo, error) {
|
||||
args := o.Called(usernames)
|
||||
func (o *mojangUsernamesToUuidsRequestMock) UsernamesToUuids(ctx context.Context, usernames []string) ([]*ProfileInfo, error) {
|
||||
args := o.Called(ctx, usernames)
|
||||
var result []*ProfileInfo
|
||||
if casted, ok := args.Get(0).([]*ProfileInfo); ok {
|
||||
result = casted
|
||||
@ -81,7 +81,7 @@ func (s *batchUuidsProviderTestSuite) TestGetUuidForFewUsernamesSuccessfully() {
|
||||
expectedResult1 := &ProfileInfo{Id: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", Name: "username1"}
|
||||
expectedResult2 := &ProfileInfo{Id: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", Name: "username2"}
|
||||
|
||||
s.MojangApi.On("UsernamesToUuids", expectedUsernames).Once().Return([]*ProfileInfo{
|
||||
s.MojangApi.On("UsernamesToUuids", mock.Anything, expectedUsernames).Once().Return([]*ProfileInfo{
|
||||
expectedResult1,
|
||||
expectedResult2,
|
||||
}, nil)
|
||||
@ -110,8 +110,8 @@ func (s *batchUuidsProviderTestSuite) TestGetUuidForFewUsernamesSuccessfully() {
|
||||
func (s *batchUuidsProviderTestSuite) TestGetUuidForManyUsernamesSplitByMultipleIterations() {
|
||||
var emptyResponse []string
|
||||
|
||||
s.MojangApi.On("UsernamesToUuids", []string{"username1", "username2", "username3"}).Once().Return(emptyResponse, nil)
|
||||
s.MojangApi.On("UsernamesToUuids", []string{"username4"}).Once().Return(emptyResponse, nil)
|
||||
s.MojangApi.On("UsernamesToUuids", mock.Anything, []string{"username1", "username2", "username3"}).Once().Return(emptyResponse, nil)
|
||||
s.MojangApi.On("UsernamesToUuids", mock.Anything, []string{"username4"}).Once().Return(emptyResponse, nil)
|
||||
|
||||
resultChan1 := s.GetUuidAsync("username1")
|
||||
resultChan2 := s.GetUuidAsync("username2")
|
||||
@ -133,7 +133,7 @@ func (s *batchUuidsProviderTestSuite) TestGetUuidForManyUsernamesSplitByMultiple
|
||||
func (s *batchUuidsProviderTestSuite) TestGetUuidForManyUsernamesWhenOneOfContextIsDeadlined() {
|
||||
var emptyResponse []string
|
||||
|
||||
s.MojangApi.On("UsernamesToUuids", []string{"username1", "username2", "username4"}).Once().Return(emptyResponse, nil)
|
||||
s.MojangApi.On("UsernamesToUuids", mock.Anything, []string{"username1", "username2", "username4"}).Once().Return(emptyResponse, nil)
|
||||
|
||||
ctx, cancelCtx := context.WithCancel(context.Background())
|
||||
|
||||
@ -167,8 +167,8 @@ func (s *batchUuidsProviderTestSuite) TestGetUuidForManyUsernamesFireOnFull() {
|
||||
|
||||
var emptyResponse []string
|
||||
|
||||
s.MojangApi.On("UsernamesToUuids", []string{"username1", "username2", "username3"}).Once().Return(emptyResponse, nil)
|
||||
s.MojangApi.On("UsernamesToUuids", []string{"username4"}).Once().Return(emptyResponse, nil)
|
||||
s.MojangApi.On("UsernamesToUuids", mock.Anything, []string{"username1", "username2", "username3"}).Once().Return(emptyResponse, nil)
|
||||
s.MojangApi.On("UsernamesToUuids", mock.Anything, []string{"username4"}).Once().Return(emptyResponse, nil)
|
||||
|
||||
resultChan1 := s.GetUuidAsync("username1")
|
||||
resultChan2 := s.GetUuidAsync("username2")
|
||||
@ -191,7 +191,7 @@ func (s *batchUuidsProviderTestSuite) TestGetUuidForFewUsernamesWithAnError() {
|
||||
expectedUsernames := []string{"username1", "username2"}
|
||||
expectedError := errors.New("mock error")
|
||||
|
||||
s.MojangApi.On("UsernamesToUuids", expectedUsernames).Once().Return(nil, expectedError)
|
||||
s.MojangApi.On("UsernamesToUuids", mock.Anything, expectedUsernames).Once().Return(nil, expectedError)
|
||||
|
||||
resultChan1 := s.GetUuidAsync("username1")
|
||||
resultChan2 := s.GetUuidAsync("username2")
|
||||
|
@ -2,6 +2,7 @@ package mojang
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@ -43,9 +44,9 @@ func NewMojangApi(
|
||||
|
||||
// Exchanges usernames array to array of uuids
|
||||
// See https://wiki.vg/Mojang_API#Playernames_-.3E_UUIDs
|
||||
func (c *MojangApi) UsernamesToUuids(usernames []string) ([]*ProfileInfo, error) {
|
||||
func (c *MojangApi) UsernamesToUuids(ctx context.Context, usernames []string) ([]*ProfileInfo, error) {
|
||||
requestBody, _ := json.Marshal(usernames)
|
||||
request, err := http.NewRequest("POST", c.batchUuidsUrl, bytes.NewBuffer(requestBody))
|
||||
request, err := http.NewRequestWithContext(ctx, "POST", c.batchUuidsUrl, bytes.NewBuffer(requestBody))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -75,14 +76,14 @@ func (c *MojangApi) UsernamesToUuids(usernames []string) ([]*ProfileInfo, error)
|
||||
|
||||
// Obtains textures information for provided uuid
|
||||
// See https://wiki.vg/Mojang_API#UUID_-.3E_Profile_.2B_Skin.2FCape
|
||||
func (c *MojangApi) UuidToTextures(uuid string, signed bool) (*ProfileResponse, error) {
|
||||
func (c *MojangApi) UuidToTextures(ctx context.Context, uuid string, signed bool) (*ProfileResponse, error) {
|
||||
normalizedUuid := strings.ReplaceAll(uuid, "-", "")
|
||||
url := c.profileUrl + normalizedUuid
|
||||
if signed {
|
||||
url += "?unsigned=false"
|
||||
}
|
||||
|
||||
request, err := http.NewRequest("GET", url, nil)
|
||||
request, err := http.NewRequestWithContext(ctx, "GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package mojang
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
@ -44,19 +45,18 @@ func (s *MojangApiSuite) TestUsernamesToUuidsSuccessfully() {
|
||||
},
|
||||
})
|
||||
|
||||
result, err := s.api.UsernamesToUuids([]string{"Thinkofdeath", "maksimkurb"})
|
||||
if s.Assert().NoError(err) {
|
||||
s.Assert().Len(result, 2)
|
||||
s.Assert().Equal("4566e69fc90748ee8d71d7ba5aa00d20", result[0].Id)
|
||||
s.Assert().Equal("Thinkofdeath", result[0].Name)
|
||||
s.Assert().False(result[0].IsLegacy)
|
||||
s.Assert().True(result[0].IsDemo)
|
||||
result, err := s.api.UsernamesToUuids(context.Background(), []string{"Thinkofdeath", "maksimkurb"})
|
||||
s.NoError(err)
|
||||
s.Len(result, 2)
|
||||
s.Equal("4566e69fc90748ee8d71d7ba5aa00d20", result[0].Id)
|
||||
s.Equal("Thinkofdeath", result[0].Name)
|
||||
s.False(result[0].IsLegacy)
|
||||
s.True(result[0].IsDemo)
|
||||
|
||||
s.Assert().Equal("0d252b7218b648bfb86c2ae476954d32", result[1].Id)
|
||||
s.Assert().Equal("maksimkurb", result[1].Name)
|
||||
s.Assert().False(result[1].IsLegacy)
|
||||
s.Assert().False(result[1].IsDemo)
|
||||
}
|
||||
s.Equal("0d252b7218b648bfb86c2ae476954d32", result[1].Id)
|
||||
s.Equal("maksimkurb", result[1].Name)
|
||||
s.False(result[1].IsLegacy)
|
||||
s.False(result[1].IsDemo)
|
||||
}
|
||||
|
||||
func (s *MojangApiSuite) TestUsernamesToUuidsBadRequest() {
|
||||
@ -68,10 +68,10 @@ func (s *MojangApiSuite) TestUsernamesToUuidsBadRequest() {
|
||||
"errorMessage": "profileName can not be null or empty.",
|
||||
})
|
||||
|
||||
result, err := s.api.UsernamesToUuids([]string{""})
|
||||
s.Assert().Nil(result)
|
||||
s.Assert().IsType(&BadRequestError{}, err)
|
||||
s.Assert().EqualError(err, "400 IllegalArgumentException: profileName can not be null or empty.")
|
||||
result, err := s.api.UsernamesToUuids(context.Background(), []string{""})
|
||||
s.Nil(result)
|
||||
s.IsType(&BadRequestError{}, err)
|
||||
s.EqualError(err, "400 IllegalArgumentException: profileName can not be null or empty.")
|
||||
}
|
||||
|
||||
func (s *MojangApiSuite) TestUsernamesToUuidsForbidden() {
|
||||
@ -80,10 +80,10 @@ func (s *MojangApiSuite) TestUsernamesToUuidsForbidden() {
|
||||
Reply(403).
|
||||
BodyString("just because")
|
||||
|
||||
result, err := s.api.UsernamesToUuids([]string{"Thinkofdeath", "maksimkurb"})
|
||||
s.Assert().Nil(result)
|
||||
s.Assert().IsType(&ForbiddenError{}, err)
|
||||
s.Assert().EqualError(err, "403: Forbidden")
|
||||
result, err := s.api.UsernamesToUuids(context.Background(), []string{"Thinkofdeath", "maksimkurb"})
|
||||
s.Nil(result)
|
||||
s.IsType(&ForbiddenError{}, err)
|
||||
s.EqualError(err, "403: Forbidden")
|
||||
}
|
||||
|
||||
func (s *MojangApiSuite) TestUsernamesToUuidsTooManyRequests() {
|
||||
@ -95,10 +95,10 @@ func (s *MojangApiSuite) TestUsernamesToUuidsTooManyRequests() {
|
||||
"errorMessage": "The client has sent too many requests within a certain amount of time",
|
||||
})
|
||||
|
||||
result, err := s.api.UsernamesToUuids([]string{"Thinkofdeath", "maksimkurb"})
|
||||
s.Assert().Nil(result)
|
||||
s.Assert().IsType(&TooManyRequestsError{}, err)
|
||||
s.Assert().EqualError(err, "429: Too Many Requests")
|
||||
result, err := s.api.UsernamesToUuids(context.Background(), []string{"Thinkofdeath", "maksimkurb"})
|
||||
s.Nil(result)
|
||||
s.IsType(&TooManyRequestsError{}, err)
|
||||
s.EqualError(err, "429: Too Many Requests")
|
||||
}
|
||||
|
||||
func (s *MojangApiSuite) TestUsernamesToUuidsServerError() {
|
||||
@ -107,11 +107,11 @@ func (s *MojangApiSuite) TestUsernamesToUuidsServerError() {
|
||||
Reply(500).
|
||||
BodyString("500 Internal Server Error")
|
||||
|
||||
result, err := s.api.UsernamesToUuids([]string{"Thinkofdeath", "maksimkurb"})
|
||||
s.Assert().Nil(result)
|
||||
s.Assert().IsType(&ServerError{}, err)
|
||||
s.Assert().EqualError(err, "500: Server error")
|
||||
s.Assert().Equal(500, err.(*ServerError).Status)
|
||||
result, err := s.api.UsernamesToUuids(context.Background(), []string{"Thinkofdeath", "maksimkurb"})
|
||||
s.Nil(result)
|
||||
s.IsType(&ServerError{}, err)
|
||||
s.EqualError(err, "500: Server error")
|
||||
s.Equal(500, err.(*ServerError).Status)
|
||||
}
|
||||
|
||||
func (s *MojangApiSuite) TestUuidToTexturesSuccessfulResponse() {
|
||||
@ -129,14 +129,14 @@ func (s *MojangApiSuite) TestUuidToTexturesSuccessfulResponse() {
|
||||
},
|
||||
})
|
||||
|
||||
result, err := s.api.UuidToTextures("4566e69fc90748ee8d71d7ba5aa00d20", false)
|
||||
s.Assert().NoError(err)
|
||||
s.Assert().Equal("4566e69fc90748ee8d71d7ba5aa00d20", result.Id)
|
||||
s.Assert().Equal("Thinkofdeath", result.Name)
|
||||
s.Assert().Equal(1, len(result.Props))
|
||||
s.Assert().Equal("textures", result.Props[0].Name)
|
||||
s.Assert().Equal(476, len(result.Props[0].Value))
|
||||
s.Assert().Equal("", result.Props[0].Signature)
|
||||
result, err := s.api.UuidToTextures(context.Background(), "4566e69fc90748ee8d71d7ba5aa00d20", false)
|
||||
s.NoError(err)
|
||||
s.Equal("4566e69fc90748ee8d71d7ba5aa00d20", result.Id)
|
||||
s.Equal("Thinkofdeath", result.Name)
|
||||
s.Equal(1, len(result.Props))
|
||||
s.Equal("textures", result.Props[0].Name)
|
||||
s.Equal(476, len(result.Props[0].Value))
|
||||
s.Equal("", result.Props[0].Signature)
|
||||
}
|
||||
|
||||
func (s *MojangApiSuite) TestUuidToTexturesEmptyResponse() {
|
||||
@ -145,9 +145,9 @@ func (s *MojangApiSuite) TestUuidToTexturesEmptyResponse() {
|
||||
Reply(204).
|
||||
BodyString("")
|
||||
|
||||
result, err := s.api.UuidToTextures("4566e69fc90748ee8d71d7ba5aa00d20", false)
|
||||
s.Assert().Nil(result)
|
||||
s.Assert().NoError(err)
|
||||
result, err := s.api.UuidToTextures(context.Background(), "4566e69fc90748ee8d71d7ba5aa00d20", false)
|
||||
s.NoError(err)
|
||||
s.Nil(result)
|
||||
}
|
||||
|
||||
func (s *MojangApiSuite) TestUuidToTexturesTooManyRequests() {
|
||||
@ -159,10 +159,10 @@ func (s *MojangApiSuite) TestUuidToTexturesTooManyRequests() {
|
||||
"errorMessage": "The client has sent too many requests within a certain amount of time",
|
||||
})
|
||||
|
||||
result, err := s.api.UuidToTextures("4566e69fc90748ee8d71d7ba5aa00d20", false)
|
||||
s.Assert().Nil(result)
|
||||
s.Assert().IsType(&TooManyRequestsError{}, err)
|
||||
s.Assert().EqualError(err, "429: Too Many Requests")
|
||||
result, err := s.api.UuidToTextures(context.Background(), "4566e69fc90748ee8d71d7ba5aa00d20", false)
|
||||
s.Nil(result)
|
||||
s.IsType(&TooManyRequestsError{}, err)
|
||||
s.EqualError(err, "429: Too Many Requests")
|
||||
}
|
||||
|
||||
func (s *MojangApiSuite) TestUuidToTexturesServerError() {
|
||||
@ -171,18 +171,18 @@ func (s *MojangApiSuite) TestUuidToTexturesServerError() {
|
||||
Reply(500).
|
||||
BodyString("500 Internal Server Error")
|
||||
|
||||
result, err := s.api.UuidToTextures("4566e69fc90748ee8d71d7ba5aa00d20", false)
|
||||
s.Assert().Nil(result)
|
||||
s.Assert().IsType(&ServerError{}, err)
|
||||
s.Assert().EqualError(err, "500: Server error")
|
||||
s.Assert().Equal(500, err.(*ServerError).Status)
|
||||
result, err := s.api.UuidToTextures(context.Background(), "4566e69fc90748ee8d71d7ba5aa00d20", false)
|
||||
s.Nil(result)
|
||||
s.IsType(&ServerError{}, err)
|
||||
s.EqualError(err, "500: Server error")
|
||||
s.Equal(500, err.(*ServerError).Status)
|
||||
}
|
||||
|
||||
func TestMojangApi(t *testing.T) {
|
||||
suite.Run(t, new(MojangApiSuite))
|
||||
}
|
||||
|
||||
func TestSignedTexturesResponse(t *testing.T) {
|
||||
func TestProfileResponse(t *testing.T) {
|
||||
t.Run("DecodeTextures", func(t *testing.T) {
|
||||
obj := &ProfileResponse{
|
||||
Id: "00000000000000000000000000000000",
|
||||
|
@ -9,11 +9,11 @@ import (
|
||||
)
|
||||
|
||||
type MojangApiTexturesProvider struct {
|
||||
MojangApiTexturesEndpoint func(uuid string, signed bool) (*ProfileResponse, error)
|
||||
MojangApiTexturesEndpoint func(ctx context.Context, uuid string, signed bool) (*ProfileResponse, error)
|
||||
}
|
||||
|
||||
func (p *MojangApiTexturesProvider) GetTextures(ctx context.Context, uuid string) (*ProfileResponse, error) {
|
||||
return p.MojangApiTexturesEndpoint(uuid, true)
|
||||
return p.MojangApiTexturesEndpoint(ctx, uuid, true)
|
||||
}
|
||||
|
||||
// Perfectly there should be an object with provider and cache implementation,
|
||||
|
@ -34,8 +34,8 @@ type MojangUuidToTexturesRequestMock struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (m *MojangUuidToTexturesRequestMock) UuidToTextures(uuid string, signed bool) (*ProfileResponse, error) {
|
||||
args := m.Called(uuid, signed)
|
||||
func (m *MojangUuidToTexturesRequestMock) UuidToTextures(ctx context.Context, uuid string, signed bool) (*ProfileResponse, error) {
|
||||
args := m.Called(ctx, uuid, signed)
|
||||
var result *ProfileResponse
|
||||
if casted, ok := args.Get(0).(*ProfileResponse); ok {
|
||||
result = casted
|
||||
@ -63,9 +63,11 @@ func (s *MojangApiTexturesProviderSuite) TearDownTest() {
|
||||
}
|
||||
|
||||
func (s *MojangApiTexturesProviderSuite) TestGetTextures() {
|
||||
s.MojangApi.On("UuidToTextures", "dead24f9a4fa4877b7b04c8c6c72bb46", true).Once().Return(signedTexturesResponse, nil)
|
||||
ctx := context.Background()
|
||||
|
||||
result, err := s.Provider.GetTextures(context.Background(), "dead24f9a4fa4877b7b04c8c6c72bb46")
|
||||
s.MojangApi.On("UuidToTextures", ctx, "dead24f9a4fa4877b7b04c8c6c72bb46", true).Once().Return(signedTexturesResponse, nil)
|
||||
|
||||
result, err := s.Provider.GetTextures(ctx, "dead24f9a4fa4877b7b04c8c6c72bb46")
|
||||
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(signedTexturesResponse, result)
|
||||
@ -73,7 +75,7 @@ func (s *MojangApiTexturesProviderSuite) TestGetTextures() {
|
||||
|
||||
func (s *MojangApiTexturesProviderSuite) TestGetTexturesWithError() {
|
||||
expectedError := errors.New("mock error")
|
||||
s.MojangApi.On("UuidToTextures", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", true).Once().Return(nil, expectedError)
|
||||
s.MojangApi.On("UuidToTextures", mock.Anything, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", true).Once().Return(nil, expectedError)
|
||||
|
||||
result, err := s.Provider.GetTextures(context.Background(), "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
|
||||
|
||||
|
@ -5,9 +5,9 @@ import "context"
|
||||
type MojangUuidsStorage interface {
|
||||
// The second argument must be returned as a incoming username in case,
|
||||
// when cached result indicates that there is no Mojang user with provided username
|
||||
GetUuidForMojangUsername(username string) (foundUuid string, foundUsername string, err error)
|
||||
GetUuidForMojangUsername(ctx context.Context, username string) (foundUuid string, foundUsername string, err error)
|
||||
// An empty uuid value can be passed if the corresponding account has not been found
|
||||
StoreMojangUuid(username string, uuid string) error
|
||||
StoreMojangUuid(ctx context.Context, username string, uuid string) error
|
||||
}
|
||||
|
||||
type UuidsProviderWithCache struct {
|
||||
@ -16,7 +16,7 @@ type UuidsProviderWithCache struct {
|
||||
}
|
||||
|
||||
func (p *UuidsProviderWithCache) GetUuid(ctx context.Context, username string) (*ProfileInfo, error) {
|
||||
uuid, foundUsername, err := p.Storage.GetUuidForMojangUsername(username)
|
||||
uuid, foundUsername, err := p.Storage.GetUuidForMojangUsername(ctx, username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -41,7 +41,7 @@ func (p *UuidsProviderWithCache) GetUuid(ctx context.Context, username string) (
|
||||
wellCasedUsername = profile.Name
|
||||
}
|
||||
|
||||
_ = p.Storage.StoreMojangUuid(wellCasedUsername, freshUuid)
|
||||
_ = p.Storage.StoreMojangUuid(ctx, wellCasedUsername, freshUuid)
|
||||
|
||||
return profile, nil
|
||||
}
|
||||
|
@ -29,13 +29,13 @@ type MojangUuidsStorageMock struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (m *MojangUuidsStorageMock) GetUuidForMojangUsername(username string) (string, string, error) {
|
||||
args := m.Called(username)
|
||||
func (m *MojangUuidsStorageMock) GetUuidForMojangUsername(ctx context.Context, username string) (string, string, error) {
|
||||
args := m.Called(ctx, username)
|
||||
return args.String(0), args.String(1), args.Error(2)
|
||||
}
|
||||
|
||||
func (m *MojangUuidsStorageMock) StoreMojangUuid(username string, uuid string) error {
|
||||
m.Called(username, uuid)
|
||||
func (m *MojangUuidsStorageMock) StoreMojangUuid(ctx context.Context, username string, uuid string) error {
|
||||
m.Called(ctx, username, uuid)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -64,8 +64,8 @@ func (s *UuidsProviderWithCacheSuite) TearDownTest() {
|
||||
func (s *UuidsProviderWithCacheSuite) TestUncachedSuccessfully() {
|
||||
ctx := context.Background()
|
||||
|
||||
s.Storage.On("GetUuidForMojangUsername", "username").Return("", "", nil)
|
||||
s.Storage.On("StoreMojangUuid", "UserName", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").Once().Return(nil)
|
||||
s.Storage.On("GetUuidForMojangUsername", ctx, "username").Return("", "", nil)
|
||||
s.Storage.On("StoreMojangUuid", ctx, "UserName", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").Once().Return(nil)
|
||||
|
||||
s.Original.On("GetUuid", ctx, "username").Once().Return(mockProfile, nil)
|
||||
|
||||
@ -76,8 +76,8 @@ func (s *UuidsProviderWithCacheSuite) TestUncachedSuccessfully() {
|
||||
}
|
||||
|
||||
func (s *UuidsProviderWithCacheSuite) TestUncachedNotExistsMojangUsername() {
|
||||
s.Storage.On("GetUuidForMojangUsername", "username").Return("", "", nil)
|
||||
s.Storage.On("StoreMojangUuid", "username", "").Once().Return(nil)
|
||||
s.Storage.On("GetUuidForMojangUsername", mock.Anything, "username").Return("", "", nil)
|
||||
s.Storage.On("StoreMojangUuid", mock.Anything, "username", "").Once().Return(nil)
|
||||
|
||||
s.Original.On("GetUuid", mock.Anything, "username").Once().Return(nil, nil)
|
||||
|
||||
@ -88,7 +88,7 @@ func (s *UuidsProviderWithCacheSuite) TestUncachedNotExistsMojangUsername() {
|
||||
}
|
||||
|
||||
func (s *UuidsProviderWithCacheSuite) TestKnownCachedUsername() {
|
||||
s.Storage.On("GetUuidForMojangUsername", "username").Return("mock-uuid", "UserName", nil)
|
||||
s.Storage.On("GetUuidForMojangUsername", mock.Anything, "username").Return("mock-uuid", "UserName", nil)
|
||||
|
||||
result, err := s.Provider.GetUuid(context.Background(), "username")
|
||||
|
||||
@ -99,7 +99,7 @@ func (s *UuidsProviderWithCacheSuite) TestKnownCachedUsername() {
|
||||
}
|
||||
|
||||
func (s *UuidsProviderWithCacheSuite) TestUnknownCachedUsername() {
|
||||
s.Storage.On("GetUuidForMojangUsername", "username").Return("", "UserName", nil)
|
||||
s.Storage.On("GetUuidForMojangUsername", mock.Anything, "username").Return("", "UserName", nil)
|
||||
|
||||
result, err := s.Provider.GetUuid(context.Background(), "username")
|
||||
|
||||
@ -109,7 +109,7 @@ func (s *UuidsProviderWithCacheSuite) TestUnknownCachedUsername() {
|
||||
|
||||
func (s *UuidsProviderWithCacheSuite) TestErrorDuringCacheQuery() {
|
||||
expectedError := errors.New("mock error")
|
||||
s.Storage.On("GetUuidForMojangUsername", "username").Return("", "", expectedError)
|
||||
s.Storage.On("GetUuidForMojangUsername", mock.Anything, "username").Return("", "", expectedError)
|
||||
|
||||
result, err := s.Provider.GetUuid(context.Background(), "username")
|
||||
|
||||
@ -119,7 +119,7 @@ func (s *UuidsProviderWithCacheSuite) TestErrorDuringCacheQuery() {
|
||||
|
||||
func (s *UuidsProviderWithCacheSuite) TestErrorFromOriginalProvider() {
|
||||
expectedError := errors.New("mock error")
|
||||
s.Storage.On("GetUuidForMojangUsername", "username").Return("", "", nil)
|
||||
s.Storage.On("GetUuidForMojangUsername", mock.Anything, "username").Return("", "", nil)
|
||||
|
||||
s.Original.On("GetUuid", mock.Anything, "username").Once().Return(nil, expectedError)
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package profiles
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
@ -11,9 +12,8 @@ import (
|
||||
)
|
||||
|
||||
type ProfilesRepository interface {
|
||||
FindProfileByUuid(uuid string) (*db.Profile, error)
|
||||
SaveProfile(profile *db.Profile) error
|
||||
RemoveProfileByUuid(uuid string) error
|
||||
SaveProfile(ctx context.Context, profile *db.Profile) error
|
||||
RemoveProfileByUuid(ctx context.Context, uuid string) error
|
||||
}
|
||||
|
||||
func NewManager(pr ProfilesRepository) *Manager {
|
||||
@ -28,7 +28,7 @@ type Manager struct {
|
||||
profileValidator *validator.Validate
|
||||
}
|
||||
|
||||
func (m *Manager) PersistProfile(profile *db.Profile) error {
|
||||
func (m *Manager) PersistProfile(ctx context.Context, profile *db.Profile) error {
|
||||
validationErrors := m.profileValidator.Struct(profile)
|
||||
if validationErrors != nil {
|
||||
return mapValidationErrorsToCommonError(validationErrors.(validator.ValidationErrors))
|
||||
@ -39,11 +39,11 @@ func (m *Manager) PersistProfile(profile *db.Profile) error {
|
||||
profile.SkinModel = ""
|
||||
}
|
||||
|
||||
return m.ProfilesRepository.SaveProfile(profile)
|
||||
return m.ProfilesRepository.SaveProfile(ctx, profile)
|
||||
}
|
||||
|
||||
func (m *Manager) RemoveProfileByUuid(uuid string) error {
|
||||
return m.ProfilesRepository.RemoveProfileByUuid(cleanupUuid(uuid))
|
||||
func (m *Manager) RemoveProfileByUuid(ctx context.Context, uuid string) error {
|
||||
return m.ProfilesRepository.RemoveProfileByUuid(ctx, cleanupUuid(uuid))
|
||||
}
|
||||
|
||||
type ValidationError struct {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package profiles
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/mock"
|
||||
@ -13,22 +14,12 @@ type ProfilesRepositoryMock struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (m *ProfilesRepositoryMock) FindProfileByUuid(uuid string) (*db.Profile, error) {
|
||||
args := m.Called(uuid)
|
||||
var result *db.Profile
|
||||
if casted, ok := args.Get(0).(*db.Profile); ok {
|
||||
result = casted
|
||||
}
|
||||
|
||||
return result, args.Error(1)
|
||||
func (m *ProfilesRepositoryMock) SaveProfile(ctx context.Context, profile *db.Profile) error {
|
||||
return m.Called(ctx, profile).Error(0)
|
||||
}
|
||||
|
||||
func (m *ProfilesRepositoryMock) SaveProfile(profile *db.Profile) error {
|
||||
return m.Called(profile).Error(0)
|
||||
}
|
||||
|
||||
func (m *ProfilesRepositoryMock) RemoveProfileByUuid(uuid string) error {
|
||||
return m.Called(uuid).Error(0)
|
||||
func (m *ProfilesRepositoryMock) RemoveProfileByUuid(ctx context.Context, uuid string) error {
|
||||
return m.Called(ctx, uuid).Error(0)
|
||||
}
|
||||
|
||||
type ManagerTestSuite struct {
|
||||
@ -50,6 +41,7 @@ func (t *ManagerTestSuite) TearDownSubTest() {
|
||||
|
||||
func (t *ManagerTestSuite) TestPersistProfile() {
|
||||
t.Run("valid profile (full)", func() {
|
||||
ctx := context.Background()
|
||||
profile := &db.Profile{
|
||||
Uuid: "ba866a9c-c839-4268-a30f-7b26ae604c51",
|
||||
Username: "mock-username",
|
||||
@ -59,9 +51,9 @@ func (t *ManagerTestSuite) TestPersistProfile() {
|
||||
MojangTextures: "eyJ0aW1lc3RhbXAiOjE0ODYzMzcyNTQ4NzIsInByb2ZpbGVJZCI6ImM0ZjFlNTZmNjFkMTQwYTc4YzMyOGQ5MTY2ZWVmOWU3IiwicHJvZmlsZU5hbWUiOiJXaHlZb3VSZWFkVGhpcyIsInRleHR1cmVzIjp7IlNLSU4iOnsidXJsIjoiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS83Mzk1NmE4ZTY0ZWU2ZDhlYzY1NmFkYmI0NDA0ZjhlYmZmMzQxMWIwY2I5MGIzMWNiNDc2ZWNiOTk2ZDNiOCJ9fX0=",
|
||||
MojangSignature: "QH+1rlQJYk8tW+8WlSJnzxZZUL5RIkeOO33dq84cgNoxwCkzL95Zy5pbPMFhoiMXXablqXeqyNRZDQa+OewgDBSZxm0BmkNmwdTLzCPHgnlNYhwbO4sirg3hKjCZ82ORZ2q7VP2NQIwNvc3befiCakhDlMWUuhjxe7p/HKNtmKA7a/JjzmzwW7BWMv8b88ZaQaMaAc7puFQcu2E54G2Zk2kyv3T1Bm7bV4m7ymbL8McOmQc6Ph7C95/EyqIK1a5gRBUHPEFIEj0I06YKTHsCRFU1U/hJpk98xXHzHuULJobpajqYXuVJ8QEVgF8k8dn9VkS8BMbXcjzfbb6JJ36v7YIV6Rlt75wwTk2wr3C3P0ij55y0iXth1HjwcEKsg54n83d9w8yQbkUCiTpMbOqxTEOOS7G2O0ZDBJDXAKQ4n5qCiCXKZ4febv4+dWVQtgfZHnpGJUD3KdduDKslMePnECOXMjGSAOQou//yze2EkL2rBpJtAAiOtvBlm/aWnDZpij5cQk+pWmeHWZIf0LSSlsYRUWRDk/VKBvUTEAO9fqOxWqmSgQRUY2Ea56u0ZsBb4vEa1UY6mlJj3+PNZaWu5aP2E9Unh0DIawV96eW8eFQgenlNXHMmXd4aOra4sz2eeOnY53JnJP+eVE4cB1hlq8RA2mnwTtcy3lahzZonOWc=",
|
||||
}
|
||||
t.ProfilesRepository.On("SaveProfile", profile).Once().Return(nil)
|
||||
t.ProfilesRepository.On("SaveProfile", ctx, profile).Once().Return(nil)
|
||||
|
||||
err := t.Manager.PersistProfile(profile)
|
||||
err := t.Manager.PersistProfile(ctx, profile)
|
||||
t.NoError(err)
|
||||
})
|
||||
|
||||
@ -70,9 +62,9 @@ func (t *ManagerTestSuite) TestPersistProfile() {
|
||||
Uuid: "ba866a9c-c839-4268-a30f-7b26ae604c51",
|
||||
Username: "mock-username",
|
||||
}
|
||||
t.ProfilesRepository.On("SaveProfile", profile).Once().Return(nil)
|
||||
t.ProfilesRepository.On("SaveProfile", mock.Anything, profile).Once().Return(nil)
|
||||
|
||||
err := t.Manager.PersistProfile(profile)
|
||||
err := t.Manager.PersistProfile(context.Background(), profile)
|
||||
t.NoError(err)
|
||||
})
|
||||
|
||||
@ -86,9 +78,9 @@ func (t *ManagerTestSuite) TestPersistProfile() {
|
||||
expectedProfile := *profile
|
||||
expectedProfile.Uuid = "ba866a9cc8394268a30f7b26ae604c51"
|
||||
expectedProfile.SkinModel = ""
|
||||
t.ProfilesRepository.On("SaveProfile", &expectedProfile).Once().Return(nil)
|
||||
t.ProfilesRepository.On("SaveProfile", mock.Anything, &expectedProfile).Once().Return(nil)
|
||||
|
||||
err := t.Manager.PersistProfile(profile)
|
||||
err := t.Manager.PersistProfile(context.Background(), profile)
|
||||
t.NoError(err)
|
||||
})
|
||||
|
||||
@ -99,7 +91,7 @@ func (t *ManagerTestSuite) TestPersistProfile() {
|
||||
MojangTextures: "eyJ0aW1lc3RhbXAiOjE0ODYzMzcyNTQ4NzIsInByb2ZpbGVJZCI6ImM0ZjFlNTZmNjFkMTQwYTc4YzMyOGQ5MTY2ZWVmOWU3IiwicHJvZmlsZU5hbWUiOiJXaHlZb3VSZWFkVGhpcyIsInRleHR1cmVzIjp7IlNLSU4iOnsidXJsIjoiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS83Mzk1NmE4ZTY0ZWU2ZDhlYzY1NmFkYmI0NDA0ZjhlYmZmMzQxMWIwY2I5MGIzMWNiNDc2ZWNiOTk2ZDNiOCJ9fX0=",
|
||||
}
|
||||
|
||||
err := t.Manager.PersistProfile(profile)
|
||||
err := t.Manager.PersistProfile(context.Background(), profile)
|
||||
t.Error(err)
|
||||
t.IsType(&ValidationError{}, err)
|
||||
castedErr := err.(*ValidationError)
|
||||
@ -114,7 +106,7 @@ func (t *ManagerTestSuite) TestPersistProfile() {
|
||||
Username: "invalid\"username",
|
||||
}
|
||||
|
||||
err := t.Manager.PersistProfile(profile)
|
||||
err := t.Manager.PersistProfile(context.Background(), profile)
|
||||
t.Error(err)
|
||||
t.IsType(&ValidationError{}, err)
|
||||
castedErr := err.(*ValidationError)
|
||||
@ -126,7 +118,7 @@ func (t *ManagerTestSuite) TestPersistProfile() {
|
||||
t.Run("empty profile", func() {
|
||||
profile := &db.Profile{}
|
||||
|
||||
err := t.Manager.PersistProfile(profile)
|
||||
err := t.Manager.PersistProfile(context.Background(), profile)
|
||||
t.Error(err)
|
||||
t.IsType(&ValidationError{}, err)
|
||||
// TODO: validate errors
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
type ProfilesFinder interface {
|
||||
FindProfileByUsername(username string) (*db.Profile, error)
|
||||
FindProfileByUsername(ctx context.Context, username string) (*db.Profile, error)
|
||||
}
|
||||
|
||||
type MojangProfilesProvider interface {
|
||||
@ -22,7 +22,7 @@ type Provider struct {
|
||||
}
|
||||
|
||||
func (p *Provider) FindProfileByUsername(ctx context.Context, username string, allowProxy bool) (*db.Profile, error) {
|
||||
profile, err := p.ProfilesFinder.FindProfileByUsername(username)
|
||||
profile, err := p.ProfilesFinder.FindProfileByUsername(ctx, username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -18,8 +18,8 @@ type ProfilesFinderMock struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (m *ProfilesFinderMock) FindProfileByUsername(username string) (*db.Profile, error) {
|
||||
args := m.Called(username)
|
||||
func (m *ProfilesFinderMock) FindProfileByUsername(ctx context.Context, username string) (*db.Profile, error) {
|
||||
args := m.Called(ctx, username)
|
||||
var result *db.Profile
|
||||
if casted, ok := args.Get(0).(*db.Profile); ok {
|
||||
result = casted
|
||||
@ -67,14 +67,15 @@ func (t *CombinedProfilesProviderSuite) TearDownSubTest() {
|
||||
|
||||
func (t *CombinedProfilesProviderSuite) TestFindByUsername() {
|
||||
t.Run("exists profile with a skin", func() {
|
||||
ctx := context.Background()
|
||||
profile := &db.Profile{
|
||||
Uuid: "mock-uuid",
|
||||
Username: "Mock",
|
||||
SkinUrl: "https://example.com/skin.png",
|
||||
}
|
||||
t.ProfilesFinder.On("FindProfileByUsername", "Mock").Return(profile, nil)
|
||||
t.ProfilesFinder.On("FindProfileByUsername", ctx, "Mock").Return(profile, nil)
|
||||
|
||||
foundProfile, err := t.Provider.FindProfileByUsername(context.Background(), "Mock", true)
|
||||
foundProfile, err := t.Provider.FindProfileByUsername(ctx, "Mock", true)
|
||||
t.NoError(err)
|
||||
t.Same(profile, foundProfile)
|
||||
})
|
||||
@ -85,7 +86,7 @@ func (t *CombinedProfilesProviderSuite) TestFindByUsername() {
|
||||
Username: "Mock",
|
||||
CapeUrl: "https://example.com/cape.png",
|
||||
}
|
||||
t.ProfilesFinder.On("FindProfileByUsername", "Mock").Return(profile, nil)
|
||||
t.ProfilesFinder.On("FindProfileByUsername", mock.Anything, "Mock").Return(profile, nil)
|
||||
|
||||
foundProfile, err := t.Provider.FindProfileByUsername(context.Background(), "Mock", true)
|
||||
t.NoError(err)
|
||||
@ -97,7 +98,7 @@ func (t *CombinedProfilesProviderSuite) TestFindByUsername() {
|
||||
Uuid: "mock-uuid",
|
||||
Username: "Mock",
|
||||
}
|
||||
t.ProfilesFinder.On("FindProfileByUsername", "Mock").Return(profile, nil)
|
||||
t.ProfilesFinder.On("FindProfileByUsername", mock.Anything, "Mock").Return(profile, nil)
|
||||
|
||||
foundProfile, err := t.Provider.FindProfileByUsername(context.Background(), "Mock", false)
|
||||
t.NoError(err)
|
||||
@ -105,7 +106,7 @@ func (t *CombinedProfilesProviderSuite) TestFindByUsername() {
|
||||
})
|
||||
|
||||
t.Run("not exists profile (no proxy)", func() {
|
||||
t.ProfilesFinder.On("FindProfileByUsername", "Mock").Return(nil, nil)
|
||||
t.ProfilesFinder.On("FindProfileByUsername", mock.Anything, "Mock").Return(nil, nil)
|
||||
|
||||
foundProfile, err := t.Provider.FindProfileByUsername(context.Background(), "Mock", false)
|
||||
t.NoError(err)
|
||||
@ -114,7 +115,7 @@ func (t *CombinedProfilesProviderSuite) TestFindByUsername() {
|
||||
|
||||
t.Run("handle error from profiles repository", func() {
|
||||
expectedError := errors.New("mock error")
|
||||
t.ProfilesFinder.On("FindProfileByUsername", "Mock").Return(nil, expectedError)
|
||||
t.ProfilesFinder.On("FindProfileByUsername", mock.Anything, "Mock").Return(nil, expectedError)
|
||||
|
||||
foundProfile, err := t.Provider.FindProfileByUsername(context.Background(), "Mock", false)
|
||||
t.Same(expectedError, err)
|
||||
@ -128,7 +129,7 @@ func (t *CombinedProfilesProviderSuite) TestFindByUsername() {
|
||||
}
|
||||
mojangProfile := createMojangProfile(true, true)
|
||||
ctx := context.Background()
|
||||
t.ProfilesFinder.On("FindProfileByUsername", "Mock").Return(profile, nil)
|
||||
t.ProfilesFinder.On("FindProfileByUsername", ctx, "Mock").Return(profile, nil)
|
||||
t.MojangProfilesProvider.On("GetForUsername", ctx, "Mock").Return(mojangProfile, nil)
|
||||
|
||||
foundProfile, err := t.Provider.FindProfileByUsername(ctx, "Mock", true)
|
||||
@ -146,7 +147,7 @@ func (t *CombinedProfilesProviderSuite) TestFindByUsername() {
|
||||
|
||||
t.Run("not exists profile (with proxy)", func() {
|
||||
mojangProfile := createMojangProfile(true, true)
|
||||
t.ProfilesFinder.On("FindProfileByUsername", "Mock").Return(nil, nil)
|
||||
t.ProfilesFinder.On("FindProfileByUsername", mock.Anything, "Mock").Return(nil, nil)
|
||||
t.MojangProfilesProvider.On("GetForUsername", mock.Anything, "Mock").Return(mojangProfile, nil)
|
||||
|
||||
foundProfile, err := t.Provider.FindProfileByUsername(context.Background(), "Mock", true)
|
||||
@ -167,7 +168,7 @@ func (t *CombinedProfilesProviderSuite) TestFindByUsername() {
|
||||
Uuid: "mock-uuid",
|
||||
Username: "Mock",
|
||||
}
|
||||
t.ProfilesFinder.On("FindProfileByUsername", "Mock").Return(profile, nil)
|
||||
t.ProfilesFinder.On("FindProfileByUsername", mock.Anything, "Mock").Return(profile, nil)
|
||||
t.MojangProfilesProvider.On("GetForUsername", mock.Anything, "Mock").Return(nil, errors.New("mock error"))
|
||||
|
||||
foundProfile, err := t.Provider.FindProfileByUsername(context.Background(), "Mock", true)
|
||||
@ -176,7 +177,7 @@ func (t *CombinedProfilesProviderSuite) TestFindByUsername() {
|
||||
})
|
||||
|
||||
t.Run("should not return an error when passed the invalid username", func() {
|
||||
t.ProfilesFinder.On("FindProfileByUsername", "Mock").Return(nil, nil)
|
||||
t.ProfilesFinder.On("FindProfileByUsername", mock.Anything, "Mock").Return(nil, nil)
|
||||
t.MojangProfilesProvider.On("GetForUsername", mock.Anything, "Mock").Return(nil, mojang.InvalidUsername)
|
||||
|
||||
foundProfile, err := t.Provider.FindProfileByUsername(context.Background(), "Mock", true)
|
||||
@ -186,7 +187,7 @@ func (t *CombinedProfilesProviderSuite) TestFindByUsername() {
|
||||
|
||||
t.Run("should return an error from mojang provider", func() {
|
||||
expectedError := errors.New("mock error")
|
||||
t.ProfilesFinder.On("FindProfileByUsername", "Mock").Return(nil, nil)
|
||||
t.ProfilesFinder.On("FindProfileByUsername", mock.Anything, "Mock").Return(nil, nil)
|
||||
t.MojangProfilesProvider.On("GetForUsername", mock.Anything, "Mock").Return(nil, expectedError)
|
||||
|
||||
foundProfile, err := t.Provider.FindProfileByUsername(context.Background(), "Mock", true)
|
||||
@ -204,7 +205,7 @@ func (t *CombinedProfilesProviderSuite) TestFindByUsername() {
|
||||
},
|
||||
},
|
||||
}
|
||||
t.ProfilesFinder.On("FindProfileByUsername", "Mock").Return(nil, nil)
|
||||
t.ProfilesFinder.On("FindProfileByUsername", mock.Anything, "Mock").Return(nil, nil)
|
||||
t.MojangProfilesProvider.On("GetForUsername", mock.Anything, "Mock").Return(mojangProfile, nil)
|
||||
|
||||
foundProfile, err := t.Provider.FindProfileByUsername(context.Background(), "Mock", true)
|
||||
@ -218,7 +219,7 @@ func (t *CombinedProfilesProviderSuite) TestFindByUsername() {
|
||||
Name: "mOcK",
|
||||
Props: []*mojang.Property{},
|
||||
}
|
||||
t.ProfilesFinder.On("FindProfileByUsername", "Mock").Return(nil, nil)
|
||||
t.ProfilesFinder.On("FindProfileByUsername", mock.Anything, "Mock").Return(nil, nil)
|
||||
t.MojangProfilesProvider.On("GetForUsername", mock.Anything, "Mock").Return(mojangProfile, nil)
|
||||
|
||||
foundProfile, err := t.Provider.FindProfileByUsername(context.Background(), "Mock", true)
|
||||
|
@ -1,6 +1,7 @@
|
||||
package security
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
@ -18,7 +19,7 @@ type Signer struct {
|
||||
Key *rsa.PrivateKey
|
||||
}
|
||||
|
||||
func (s *Signer) SignTextures(textures string) (string, error) {
|
||||
func (s *Signer) SignTextures(ctx context.Context, textures string) (string, error) {
|
||||
message := []byte(textures)
|
||||
messageHash := sha1.New()
|
||||
_, err := messageHash.Write(message)
|
||||
@ -35,6 +36,6 @@ func (s *Signer) SignTextures(textures string) (string, error) {
|
||||
return base64.StdEncoding.EncodeToString(signature), nil
|
||||
}
|
||||
|
||||
func (s *Signer) GetPublicKey() (*rsa.PublicKey, error) {
|
||||
func (s *Signer) GetPublicKey(ctx context.Context) (*rsa.PublicKey, error) {
|
||||
return &s.Key.PublicKey, nil
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package security
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
@ -24,7 +25,7 @@ func TestSigner_SignTextures(t *testing.T) {
|
||||
|
||||
signer := NewSigner(key)
|
||||
|
||||
signature, err := signer.SignTextures("eyJ0aW1lc3RhbXAiOjE2MTQzMDcxMzQsInByb2ZpbGVJZCI6ImZmYzhmZGM5NTgyNDUwOWU4YTU3Yzk5Yjk0MGZiOTk2IiwicHJvZmlsZU5hbWUiOiJFcmlja1NrcmF1Y2giLCJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly9lbHkuYnkvc3RvcmFnZS9za2lucy82OWM2NzQwZDI5OTNlNWQ2ZjZhN2ZjOTI0MjBlZmMyOS5wbmcifX0sImVseSI6dHJ1ZX0")
|
||||
signature, err := signer.SignTextures(context.Background(), "eyJ0aW1lc3RhbXAiOjE2MTQzMDcxMzQsInByb2ZpbGVJZCI6ImZmYzhmZGM5NTgyNDUwOWU4YTU3Yzk5Yjk0MGZiOTk2IiwicHJvZmlsZU5hbWUiOiJFcmlja1NrcmF1Y2giLCJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly9lbHkuYnkvc3RvcmFnZS9za2lucy82OWM2NzQwZDI5OTNlNWQ2ZjZhN2ZjOTI0MjBlZmMyOS5wbmcifX0sImVseSI6dHJ1ZX0")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "IyHCxTP5ITquEXTHcwCtLd08jWWy16JwlQeWg8naxhoAVQecHGRdzHRscuxtdq/446kmeox7h4EfRN2A2ZLL+A==", signature)
|
||||
}
|
||||
@ -37,7 +38,7 @@ func TestSigner_GetPublicKey(t *testing.T) {
|
||||
|
||||
signer := NewSigner(key)
|
||||
|
||||
publicKey, err := signer.GetPublicKey()
|
||||
publicKey, err := signer.GetPublicKey(context.Background())
|
||||
require.NoError(t, err)
|
||||
require.IsType(t, &rsa.PublicKey{}, publicKey)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user