Add stats reporter events listener, restore all events for http layer, rework authentication middleware and authenticator interface

This commit is contained in:
ErickSkrauch
2020-02-16 13:23:47 +03:00
parent db728451f8
commit 40c53ea0d9
12 changed files with 602 additions and 185 deletions

View File

@@ -4,7 +4,10 @@ import (
"encoding/json"
"net"
"net/http"
"strings"
"time"
"github.com/gorilla/mux"
)
type Emitter interface {
@@ -28,6 +31,53 @@ func Serve(address string, handler http.Handler) error {
return server.Serve(listener)
}
type loggingResponseWriter struct {
http.ResponseWriter
statusCode int
}
func (lrw *loggingResponseWriter) WriteHeader(code int) {
lrw.statusCode = code
lrw.ResponseWriter.WriteHeader(code)
}
func CreateRequestEventsMiddleware(emitter Emitter, prefix string) mux.MiddlewareFunc {
beforeTopic := strings.Join([]string{prefix, "before_request"}, ":")
afterTopic := strings.Join([]string{prefix, "after_request"}, ":")
return func(handler http.Handler) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
emitter.Emit(beforeTopic, req)
lrw := &loggingResponseWriter{
ResponseWriter: resp,
statusCode: http.StatusOK,
}
handler.ServeHTTP(lrw, req)
emitter.Emit(afterTopic, req, lrw.statusCode)
})
}
}
type Authenticator interface {
Authenticate(req *http.Request) error
}
func CreateAuthenticationMiddleware(checker Authenticator) mux.MiddlewareFunc {
return func(handler http.Handler) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
err := checker.Authenticate(req)
if err != nil {
apiForbidden(resp, err.Error())
return
}
handler.ServeHTTP(resp, req)
})
}
}
func NotFound(response http.ResponseWriter, _ *http.Request) {
data, _ := json.Marshal(map[string]string{
"status": "404",

View File

@@ -1,7 +1,9 @@
package http
import (
"errors"
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"
@@ -14,10 +16,84 @@ type emitterMock struct {
}
func (e *emitterMock) Emit(name string, args ...interface{}) {
e.Called((append([]interface{}{name}, args...))...)
e.Called(append([]interface{}{name}, args...)...)
}
func TestConfig_NotFound(t *testing.T) {
func TestCreateRequestEventsMiddleware(t *testing.T) {
req := httptest.NewRequest("GET", "http://example.com", nil)
resp := httptest.NewRecorder()
emitter := &emitterMock{}
emitter.On("Emit", "test_prefix:before_request", req)
emitter.On("Emit", "test_prefix:after_request", req, 400)
isHandlerCalled := false
middlewareFunc := CreateRequestEventsMiddleware(emitter, "test_prefix")
middlewareFunc.Middleware(http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
resp.WriteHeader(400)
isHandlerCalled = true
})).ServeHTTP(resp, req)
if !isHandlerCalled {
t.Fatal("Handler isn't called from the middleware")
}
emitter.AssertExpectations(t)
}
type authCheckerMock struct {
mock.Mock
}
func (m *authCheckerMock) Authenticate(req *http.Request) error {
args := m.Called(req)
return args.Error(0)
}
func TestCreateAuthenticationMiddleware(t *testing.T) {
t.Run("pass", func(t *testing.T) {
req := httptest.NewRequest("GET", "http://example.com", nil)
resp := httptest.NewRecorder()
auth := &authCheckerMock{}
auth.On("Authenticate", req).Once().Return(nil)
isHandlerCalled := false
middlewareFunc := CreateAuthenticationMiddleware(auth)
middlewareFunc.Middleware(http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
isHandlerCalled = true
})).ServeHTTP(resp, req)
testify.True(t, isHandlerCalled, "Handler isn't called from the middleware")
auth.AssertExpectations(t)
})
t.Run("fail", func(t *testing.T) {
req := httptest.NewRequest("GET", "http://example.com", nil)
resp := httptest.NewRecorder()
auth := &authCheckerMock{}
auth.On("Authenticate", req).Once().Return(errors.New("error reason"))
isHandlerCalled := false
middlewareFunc := CreateAuthenticationMiddleware(auth)
middlewareFunc.Middleware(http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
isHandlerCalled = true
})).ServeHTTP(resp, req)
testify.False(t, isHandlerCalled, "Handler shouldn't be called")
testify.Equal(t, 403, resp.Code)
body, _ := ioutil.ReadAll(resp.Body)
testify.JSONEq(t, `{
"error": "error reason"
}`, string(body))
auth.AssertExpectations(t)
})
}
func TestNotFound(t *testing.T) {
assert := testify.New(t)
req := httptest.NewRequest("GET", "http://example.com", nil)

78
http/jwt.go Normal file
View File

@@ -0,0 +1,78 @@
package http
import (
"errors"
"net/http"
"strings"
"time"
"github.com/SermoDigital/jose/crypto"
"github.com/SermoDigital/jose/jws"
)
var hashAlg = crypto.SigningMethodHS256
const scopesClaim = "scopes"
type Scope string
var (
SkinScope = Scope("skin")
)
type JwtAuth struct {
Emitter
Key []byte
}
func (t *JwtAuth) NewToken(scopes ...Scope) ([]byte, error) {
if len(t.Key) == 0 {
return nil, errors.New("signing key not available")
}
claims := jws.Claims{}
claims.Set(scopesClaim, scopes)
claims.SetIssuedAt(time.Now())
encoder := jws.NewJWT(claims, hashAlg)
token, err := encoder.Serialize(t.Key)
if err != nil {
return nil, err
}
return token, nil
}
func (t *JwtAuth) Authenticate(req *http.Request) error {
if len(t.Key) == 0 {
return t.emitErr(errors.New("Signing key not set"))
}
bearerToken := req.Header.Get("Authorization")
if bearerToken == "" {
return t.emitErr(errors.New("Authentication header not presented"))
}
if !strings.EqualFold(bearerToken[0:7], "BEARER ") {
return t.emitErr(errors.New("Cannot recognize JWT token in passed value"))
}
tokenStr := bearerToken[7:]
token, err := jws.ParseJWT([]byte(tokenStr))
if err != nil {
return t.emitErr(errors.New("Cannot parse passed JWT token"))
}
err = token.Validate(t.Key, hashAlg)
if err != nil {
return t.emitErr(errors.New("JWT token have invalid signature. It may be corrupted or expired"))
}
t.Emit("authentication:success")
return nil
}
func (t *JwtAuth) emitErr(err error) error {
t.Emit("authentication:error", err)
return err
}

127
http/jwt_test.go Normal file
View File

@@ -0,0 +1,127 @@
package http
import (
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
const jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxNTE2NjU4MTkzIiwic2NvcGVzIjoic2tpbiJ9.agbBS0qdyYMBaVfTZJAZcTTRgW1Y0kZty4H3N2JHBO8"
func TestJwtAuth_NewToken(t *testing.T) {
t.Run("success", func(t *testing.T) {
jwt := &JwtAuth{Key: []byte("secret")}
token, err := jwt.NewToken(SkinScope)
assert.Nil(t, err)
assert.NotNil(t, token)
})
t.Run("key not provided", func(t *testing.T) {
jwt := &JwtAuth{}
token, err := jwt.NewToken(SkinScope)
assert.Error(t, err, "signing key not available")
assert.Nil(t, token)
})
}
func TestJwtAuth_Authenticate(t *testing.T) {
t.Run("success", func(t *testing.T) {
emitter := &emitterMock{}
emitter.On("Emit", "authentication:success")
req := httptest.NewRequest("POST", "http://localhost", nil)
req.Header.Add("Authorization", "Bearer " + jwt)
jwt := &JwtAuth{Key: []byte("secret"), Emitter: emitter}
err := jwt.Authenticate(req)
assert.Nil(t, err)
emitter.AssertExpectations(t)
})
t.Run("request without auth header", func(t *testing.T) {
emitter := &emitterMock{}
emitter.On("Emit", "authentication:error", mock.MatchedBy(func(err error) bool {
assert.Error(t, err, "Authentication header not presented")
return true
}))
req := httptest.NewRequest("POST", "http://localhost", nil)
jwt := &JwtAuth{Key: []byte("secret"), Emitter: emitter}
err := jwt.Authenticate(req)
assert.Error(t, err, "Authentication header not presented")
emitter.AssertExpectations(t)
})
t.Run("no bearer token prefix", func(t *testing.T) {
emitter := &emitterMock{}
emitter.On("Emit", "authentication:error", mock.MatchedBy(func(err error) bool {
assert.Error(t, err, "Cannot recognize JWT token in passed value")
return true
}))
req := httptest.NewRequest("POST", "http://localhost", nil)
req.Header.Add("Authorization", "this is not jwt")
jwt := &JwtAuth{Key: []byte("secret"), Emitter: emitter}
err := jwt.Authenticate(req)
assert.Error(t, err, "Cannot recognize JWT token in passed value")
emitter.AssertExpectations(t)
})
t.Run("bearer token but not jwt", func(t *testing.T) {
emitter := &emitterMock{}
emitter.On("Emit", "authentication:error", mock.MatchedBy(func(err error) bool {
assert.Error(t, err, "Cannot parse passed JWT token")
return true
}))
req := httptest.NewRequest("POST", "http://localhost", nil)
req.Header.Add("Authorization", "Bearer thisIs.Not.Jwt")
jwt := &JwtAuth{Key: []byte("secret"), Emitter: emitter}
err := jwt.Authenticate(req)
assert.Error(t, err, "Cannot parse passed JWT token")
emitter.AssertExpectations(t)
})
t.Run("when secret is not set", func(t *testing.T) {
emitter := &emitterMock{}
emitter.On("Emit", "authentication:error", mock.MatchedBy(func(err error) bool {
assert.Error(t, err, "Signing key not set")
return true
}))
req := httptest.NewRequest("POST", "http://localhost", nil)
req.Header.Add("Authorization", "Bearer " + jwt)
jwt := &JwtAuth{Emitter: emitter}
err := jwt.Authenticate(req)
assert.Error(t, err, "Signing key not set")
emitter.AssertExpectations(t)
})
t.Run("invalid signature", func(t *testing.T) {
emitter := &emitterMock{}
emitter.On("Emit", "authentication:error", mock.MatchedBy(func(err error) bool {
assert.Error(t, err, "JWT token have invalid signature. It may be corrupted or expired")
return true
}))
req := httptest.NewRequest("POST", "http://localhost", nil)
req.Header.Add("Authorization", "Bearer " + jwt)
jwt := &JwtAuth{Key: []byte("this is another secret"), Emitter: emitter}
err := jwt.Authenticate(req)
assert.Error(t, err, "JWT token have invalid signature. It may be corrupted or expired")
emitter.AssertExpectations(t)
})
}

View File

@@ -14,10 +14,10 @@ import (
"github.com/thedevsaddam/govalidator"
"github.com/elyby/chrly/api/mojang"
"github.com/elyby/chrly/auth"
"github.com/elyby/chrly/model"
)
//noinspection GoSnakeCaseUsage
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)
@@ -78,10 +78,6 @@ type MojangTexturesProvider interface {
GetForUsername(username string) (*mojang.SignedTexturesResponse, error)
}
type AuthChecker interface {
Check(req *http.Request) error
}
type Skinsystem struct {
Emitter
TexturesExtraParamName string
@@ -89,25 +85,26 @@ type Skinsystem struct {
SkinsRepo SkinsRepository
CapesRepo CapesRepository
MojangTexturesProvider MojangTexturesProvider
Auth AuthChecker
Authenticator Authenticator
}
func (ctx *Skinsystem) CreateHandler() *mux.Router {
router := mux.NewRouter().StrictSlash(true)
router.Use(CreateRequestEventsMiddleware(ctx.Emitter, "skinsystem"))
router.HandleFunc("/skins/{username}", ctx.Skin).Methods("GET")
router.HandleFunc("/cloaks/{username}", ctx.Cape).Methods("GET").Name("cloaks")
router.HandleFunc("/textures/{username}", ctx.Textures).Methods("GET")
router.HandleFunc("/textures/signed/{username}", ctx.SignedTextures).Methods("GET")
router.HandleFunc("/skins/{username}", ctx.Skin).Methods(http.MethodGet)
router.HandleFunc("/cloaks/{username}", ctx.Cape).Methods(http.MethodGet).Name("cloaks")
router.HandleFunc("/textures/{username}", ctx.Textures).Methods(http.MethodGet)
router.HandleFunc("/textures/signed/{username}", ctx.SignedTextures).Methods(http.MethodGet)
// Legacy
router.HandleFunc("/skins", ctx.SkinGET).Methods("GET")
router.HandleFunc("/cloaks", ctx.CapeGET).Methods("GET")
router.HandleFunc("/skins", ctx.SkinGET).Methods(http.MethodGet)
router.HandleFunc("/cloaks", ctx.CapeGET).Methods(http.MethodGet)
// API
apiRouter := router.PathPrefix("/api").Subrouter()
apiRouter.Use(ctx.AuthenticationMiddleware)
apiRouter.HandleFunc("/skins", ctx.PostSkin).Methods("POST")
apiRouter.HandleFunc("/skins/id:{id:[0-9]+}", ctx.DeleteSkinByUserId).Methods("DELETE")
apiRouter.HandleFunc("/skins/{username}", ctx.DeleteSkinByUsername).Methods("DELETE")
apiRouter.Use(CreateAuthenticationMiddleware(ctx.Authenticator))
apiRouter.HandleFunc("/skins", ctx.PostSkin).Methods(http.MethodPost)
apiRouter.HandleFunc("/skins/id:{id:[0-9]+}", ctx.DeleteSkinByUserId).Methods(http.MethodDelete)
apiRouter.HandleFunc("/skins/{username}", ctx.DeleteSkinByUsername).Methods(http.MethodDelete)
// 404
router.NotFoundHandler = http.HandlerFunc(NotFound)
@@ -226,7 +223,7 @@ func (ctx *Skinsystem) Textures(response http.ResponseWriter, request *http.Requ
texturesProp := mojangTextures.DecodeTextures()
if texturesProp == nil {
ctx.Emit("skinsystem.error", errors.New("unable to find textures property"))
ctx.Emit("skinsystem:error", errors.New("unable to find textures property"))
apiServerError(response)
return
}
@@ -330,28 +327,6 @@ func (ctx *Skinsystem) DeleteSkinByUsername(resp http.ResponseWriter, req *http.
ctx.deleteSkin(skin, err, resp)
}
func (ctx *Skinsystem) AuthenticationMiddleware(handler http.Handler) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
// TODO: decide on how I would cover this with logging
// ctx.Logger.IncCounter("authentication.challenge", 1)
err := ctx.Auth.Check(req)
if err != nil {
if _, ok := err.(*auth.Unauthorized); ok {
// ctx.Logger.IncCounter("authentication.failed", 1)
apiForbidden(resp, err.Error())
} else {
// ctx.Logger.Error("Unknown error on validating api request: :err", wd.ErrParam(err))
apiServerError(resp)
}
return
}
// ctx.Logger.IncCounter("authentication.success", 1)
handler.ServeHTTP(resp, req)
})
}
func (ctx *Skinsystem) deleteSkin(skin *model.Skin, err error, resp http.ResponseWriter) {
if err != nil {
if _, ok := err.(*SkinNotFoundError); ok {

View File

@@ -20,7 +20,6 @@ import (
"github.com/stretchr/testify/suite"
"github.com/elyby/chrly/api/mojang"
"github.com/elyby/chrly/auth"
"github.com/elyby/chrly/model"
)
@@ -95,15 +94,6 @@ func (m *mojangTexturesProviderMock) GetForUsername(username string) (*mojang.Si
return result, args.Error(1)
}
type authCheckerMock struct {
mock.Mock
}
func (m *authCheckerMock) Check(req *http.Request) error {
args := m.Called(req)
return args.Error(0)
}
type skinsystemTestSuite struct {
suite.Suite
@@ -131,7 +121,7 @@ func (suite *skinsystemTestSuite) SetupTest() {
SkinsRepo: suite.SkinsRepository,
CapesRepo: suite.CapesRepository,
MojangTexturesProvider: suite.MojangTexturesProvider,
Auth: suite.Auth,
Authenticator: suite.Auth,
Emitter: suite.Emitter,
}
}
@@ -215,6 +205,8 @@ var skinsTestsCases = []*skinsystemTestCase{
func (suite *skinsystemTestSuite) TestSkin() {
for _, testCase := range skinsTestsCases {
suite.RunSubTest(testCase.Name, func() {
suite.Emitter.On("Emit", "skinsystem:before_request", mock.Anything)
suite.Emitter.On("Emit", "skinsystem:after_request", mock.Anything, mock.Anything)
testCase.BeforeTest(suite)
req := httptest.NewRequest("GET", "http://chrly/skins/mock_username", nil)
@@ -227,6 +219,8 @@ func (suite *skinsystemTestSuite) TestSkin() {
}
suite.RunSubTest("Pass username with png extension", func() {
suite.Emitter.On("Emit", "skinsystem:before_request", mock.Anything)
suite.Emitter.On("Emit", "skinsystem:after_request", mock.Anything, mock.Anything)
suite.SkinsRepository.On("FindByUsername", "mock_username").Return(createSkinModel("mock_username", false), nil)
req := httptest.NewRequest("GET", "http://chrly/skins/mock_username.png", nil)
@@ -243,6 +237,8 @@ func (suite *skinsystemTestSuite) TestSkin() {
func (suite *skinsystemTestSuite) TestSkinGET() {
for _, testCase := range skinsTestsCases {
suite.RunSubTest(testCase.Name, func() {
suite.Emitter.On("Emit", "skinsystem:before_request", mock.Anything)
suite.Emitter.On("Emit", "skinsystem:after_request", mock.Anything, mock.Anything)
testCase.BeforeTest(suite)
req := httptest.NewRequest("GET", "http://chrly/skins?name=mock_username", nil)
@@ -255,6 +251,9 @@ func (suite *skinsystemTestSuite) TestSkinGET() {
}
suite.RunSubTest("Do not pass name param", func() {
suite.Emitter.On("Emit", "skinsystem:before_request", mock.Anything)
suite.Emitter.On("Emit", "skinsystem:after_request", mock.Anything, mock.Anything)
req := httptest.NewRequest("GET", "http://chrly/skins", nil)
w := httptest.NewRecorder()
@@ -318,6 +317,8 @@ var capesTestsCases = []*skinsystemTestCase{
func (suite *skinsystemTestSuite) TestCape() {
for _, testCase := range capesTestsCases {
suite.RunSubTest(testCase.Name, func() {
suite.Emitter.On("Emit", "skinsystem:before_request", mock.Anything)
suite.Emitter.On("Emit", "skinsystem:after_request", mock.Anything, mock.Anything)
testCase.BeforeTest(suite)
req := httptest.NewRequest("GET", "http://chrly/cloaks/mock_username", nil)
@@ -330,6 +331,8 @@ func (suite *skinsystemTestSuite) TestCape() {
}
suite.RunSubTest("Pass username with png extension", func() {
suite.Emitter.On("Emit", "skinsystem:before_request", mock.Anything)
suite.Emitter.On("Emit", "skinsystem:after_request", mock.Anything, mock.Anything)
suite.CapesRepository.On("FindByUsername", "mock_username").Return(createCapeModel(), nil)
req := httptest.NewRequest("GET", "http://chrly/cloaks/mock_username.png", nil)
@@ -348,6 +351,8 @@ func (suite *skinsystemTestSuite) TestCape() {
func (suite *skinsystemTestSuite) TestCapeGET() {
for _, testCase := range capesTestsCases {
suite.RunSubTest(testCase.Name, func() {
suite.Emitter.On("Emit", "skinsystem:before_request", mock.Anything)
suite.Emitter.On("Emit", "skinsystem:after_request", mock.Anything, mock.Anything)
testCase.BeforeTest(suite)
req := httptest.NewRequest("GET", "http://chrly/cloaks?name=mock_username", nil)
@@ -360,6 +365,9 @@ func (suite *skinsystemTestSuite) TestCapeGET() {
}
suite.RunSubTest("Do not pass name param", func() {
suite.Emitter.On("Emit", "skinsystem:before_request", mock.Anything)
suite.Emitter.On("Emit", "skinsystem:after_request", mock.Anything, mock.Anything)
req := httptest.NewRequest("GET", "http://chrly/cloaks", nil)
w := httptest.NewRecorder()
@@ -486,6 +494,8 @@ var texturesTestsCases = []*skinsystemTestCase{
func (suite *skinsystemTestSuite) TestTextures() {
for _, testCase := range texturesTestsCases {
suite.RunSubTest(testCase.Name, func() {
suite.Emitter.On("Emit", "skinsystem:before_request", mock.Anything)
suite.Emitter.On("Emit", "skinsystem:after_request", mock.Anything, mock.Anything)
testCase.BeforeTest(suite)
req := httptest.NewRequest("GET", "http://chrly/textures/mock_username", nil)
@@ -609,6 +619,8 @@ var signedTexturesTestsCases = []*signedTexturesTestCase{
func (suite *skinsystemTestSuite) TestSignedTextures() {
for _, testCase := range signedTexturesTestsCases {
suite.RunSubTest(testCase.Name, func() {
suite.Emitter.On("Emit", "skinsystem:before_request", mock.Anything)
suite.Emitter.On("Emit", "skinsystem:after_request", mock.Anything, mock.Anything)
testCase.BeforeTest(suite)
var target string
@@ -817,7 +829,9 @@ var postSkinTestsCases = []*postSkinTestCase{
func (suite *skinsystemTestSuite) TestPostSkin() {
for _, testCase := range postSkinTestsCases {
suite.RunSubTest(testCase.Name, func() {
suite.Auth.On("Check", mock.Anything).Return(nil)
suite.Emitter.On("Emit", "skinsystem:before_request", mock.Anything)
suite.Emitter.On("Emit", "skinsystem:after_request", mock.Anything, mock.Anything)
suite.Auth.On("Authenticate", mock.Anything).Return(nil)
testCase.BeforeTest(suite)
req := httptest.NewRequest("POST", "http://chrly/api/skins", testCase.Form)
@@ -831,7 +845,9 @@ func (suite *skinsystemTestSuite) TestPostSkin() {
}
suite.RunSubTest("Get errors about required fields", func() {
suite.Auth.On("Check", mock.Anything).Return(nil)
suite.Emitter.On("Emit", "skinsystem:before_request", mock.Anything)
suite.Emitter.On("Emit", "skinsystem:after_request", mock.Anything, mock.Anything)
suite.Auth.On("Authenticate", mock.Anything).Return(nil)
req := httptest.NewRequest("POST", "http://chrly/api/skins", bytes.NewBufferString(url.Values{
"mojangTextures": {"someBase64EncodedString"},
@@ -878,11 +894,13 @@ func (suite *skinsystemTestSuite) TestPostSkin() {
})
suite.RunSubTest("Send request without authorization", func() {
suite.Emitter.On("Emit", "skinsystem:before_request", mock.Anything)
suite.Emitter.On("Emit", "skinsystem:after_request", mock.Anything, mock.Anything)
req := httptest.NewRequest("POST", "http://chrly/api/skins", nil)
req.Header.Add("Authorization", "Bearer invalid.jwt.token")
w := httptest.NewRecorder()
suite.Auth.On("Check", mock.Anything).Return(&auth.Unauthorized{Reason: "Cannot parse passed JWT token"})
suite.Auth.On("Authenticate", mock.Anything).Return(errors.New("Cannot parse passed JWT token"))
suite.App.CreateHandler().ServeHTTP(w, req)
@@ -896,7 +914,9 @@ func (suite *skinsystemTestSuite) TestPostSkin() {
})
suite.RunSubTest("Upload textures with skin as file", func() {
suite.Auth.On("Check", mock.Anything).Return(nil)
suite.Emitter.On("Emit", "skinsystem:before_request", mock.Anything)
suite.Emitter.On("Emit", "skinsystem:after_request", mock.Anything, mock.Anything)
suite.Auth.On("Authenticate", mock.Anything).Return(nil)
inputBody := &bytes.Buffer{}
writer := multipart.NewWriter(inputBody)
@@ -940,7 +960,9 @@ func (suite *skinsystemTestSuite) TestPostSkin() {
func (suite *skinsystemTestSuite) TestDeleteByUserId() {
suite.RunSubTest("Delete skin by its identity id", func() {
suite.Auth.On("Check", mock.Anything).Return(nil)
suite.Emitter.On("Emit", "skinsystem:before_request", mock.Anything)
suite.Emitter.On("Emit", "skinsystem:after_request", mock.Anything, mock.Anything)
suite.Auth.On("Authenticate", mock.Anything).Return(nil)
suite.SkinsRepository.On("FindByUserId", 1).Return(createSkinModel("mock_username", false), nil)
suite.SkinsRepository.On("RemoveByUserId", 1).Once().Return(nil)
@@ -957,7 +979,9 @@ func (suite *skinsystemTestSuite) TestDeleteByUserId() {
})
suite.RunSubTest("Try to remove not exists identity id", func() {
suite.Auth.On("Check", mock.Anything).Return(nil)
suite.Emitter.On("Emit", "skinsystem:before_request", mock.Anything)
suite.Emitter.On("Emit", "skinsystem:after_request", mock.Anything, mock.Anything)
suite.Auth.On("Authenticate", mock.Anything).Return(nil)
suite.SkinsRepository.On("FindByUserId", 1).Return(nil, &SkinNotFoundError{Who: "unknown"})
req := httptest.NewRequest("DELETE", "http://chrly/api/skins/id:1", nil)
@@ -981,7 +1005,9 @@ func (suite *skinsystemTestSuite) TestDeleteByUserId() {
func (suite *skinsystemTestSuite) TestDeleteByUsername() {
suite.RunSubTest("Delete skin by its identity username", func() {
suite.Auth.On("Check", mock.Anything).Return(nil)
suite.Emitter.On("Emit", "skinsystem:before_request", mock.Anything)
suite.Emitter.On("Emit", "skinsystem:after_request", mock.Anything, mock.Anything)
suite.Auth.On("Authenticate", mock.Anything).Return(nil)
suite.SkinsRepository.On("FindByUsername", "mock_username").Return(createSkinModel("mock_username", false), nil)
suite.SkinsRepository.On("RemoveByUserId", 1).Once().Return(nil)
@@ -998,7 +1024,9 @@ func (suite *skinsystemTestSuite) TestDeleteByUsername() {
})
suite.RunSubTest("Try to remove not exists identity username", func() {
suite.Auth.On("Check", mock.Anything).Return(nil)
suite.Emitter.On("Emit", "skinsystem:before_request", mock.Anything)
suite.Emitter.On("Emit", "skinsystem:after_request", mock.Anything, mock.Anything)
suite.Auth.On("Authenticate", mock.Anything).Return(nil)
suite.SkinsRepository.On("FindByUsername", "mock_username").Return(nil, &SkinNotFoundError{Who: "mock_username"})
req := httptest.NewRequest("DELETE", "http://chrly/api/skins/mock_username", nil)