diff --git a/implem/gin.server/ROUTER.go b/implem/gin.server/ROUTER.go index 74c9d28..27421f9 100644 --- a/implem/gin.server/ROUTER.go +++ b/implem/gin.server/ROUTER.go @@ -4,6 +4,10 @@ import ( "fmt" "net/http" + "strings" + + "errors" + "github.com/err0r500/go-realworld-clean/uc" "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/render" @@ -53,9 +57,10 @@ func (rH RouterHandler) usersRoutes(api *gin.RouterGroup) { users.POST("", rH.userPost) // Register a new user users.POST("/login", rH.userLoginPost) // Login for existing user - users.GET("", rH.jwtMiddleware(), rH.userGet) // Gets the currently logged-in user - users.PUT("", rH.jwtMiddleware(), rH.userPatch) // WARNING : it's a in fact a PATCH request in the API contract !!! - users.PATCH("", rH.jwtMiddleware(), rH.userPatch) // just in case it's fixed one day.... + user := api.Group("/user") + user.GET("", rH.jwtMiddleware(), rH.userGet) // Gets the currently logged-in user + user.PUT("", rH.jwtMiddleware(), rH.userPatch) // WARNING : it's a in fact a PATCH request in the API contract !!! + user.PATCH("", rH.jwtMiddleware(), rH.userPatch) // just in case it's fixed one day.... } func (rH RouterHandler) articlesRoutes(api *gin.RouterGroup) { @@ -87,7 +92,14 @@ const userNameKey = "userNameKey" func (rH RouterHandler) jwtMiddleware() gin.HandlerFunc { return func(c *gin.Context) { - userName, err := rH.authHandler.GetUserName(c.GetHeader("Authorization")) + jwt, err := getJWT(c.GetHeader("Authorization")) + if err != nil { + c.Status(http.StatusUnauthorized) + c.Abort() + return + } + + userName, err := rH.authHandler.GetUserName(jwt) if err != nil { c.Status(http.StatusUnauthorized) c.Abort() @@ -99,6 +111,14 @@ func (rH RouterHandler) jwtMiddleware() gin.HandlerFunc { } } +func getJWT(authHeader string) (string, error) { + splitted := strings.Split(authHeader, "Token ") + if len(splitted) != 2 { + return "", errors.New("malformed header") + } + return splitted[1], nil +} + func (rH RouterHandler) errorCatcher() gin.HandlerFunc { return func(c *gin.Context) { c.Next() diff --git a/implem/gin.server/articleComment_test.go b/implem/gin.server/articleComment_test.go index ed04c41..972915a 100644 --- a/implem/gin.server/articleComment_test.go +++ b/implem/gin.server/articleComment_test.go @@ -44,7 +44,7 @@ func TestArticleCommentGet(t *testing.T) { t.Run("happyCase", func(t *testing.T) { baloo.New(ts.URL). Get(articleCommentPath). - AddHeader("Authorization", authToken). + AddHeader("Authorization", testData.TokenPrefix+authToken). Expect(t). Status(200). JSONSchema(testData.CommentsMultipleResponse). @@ -86,7 +86,7 @@ func TestArticleCommentPost(t *testing.T) { t.Run("happyCase", func(t *testing.T) { baloo.New(ts.URL). Post(articleCommentPath). - AddHeader("Authorization", authToken). + AddHeader("Authorization", testData.TokenPrefix+authToken). BodyString(validReq). Expect(t). Status(201). @@ -107,7 +107,7 @@ func TestArticleCommentPost(t *testing.T) { t.Run("no body", func(t *testing.T) { baloo.New(ts.URL). Post(articleCommentPath). - AddHeader("Authorization", authToken). + AddHeader("Authorization", testData.TokenPrefix+authToken). Expect(t). Status(400). Done() @@ -141,7 +141,7 @@ func TestArticleCommentDelete(t *testing.T) { t.Run("happyCase", func(t *testing.T) { baloo.New(ts.URL). Delete(articleCommentPath+"/"+strconv.Itoa(testData.Article("jane").Comments[0].ID)). - AddHeader("Authorization", authToken). + AddHeader("Authorization", testData.TokenPrefix+authToken). Expect(t). Status(200). Done() diff --git a/implem/gin.server/articleFavorite_test.go b/implem/gin.server/articleFavorite_test.go index 91f0583..4d739ce 100644 --- a/implem/gin.server/articleFavorite_test.go +++ b/implem/gin.server/articleFavorite_test.go @@ -44,7 +44,7 @@ func TestArticleFavoritePost(t *testing.T) { t.Run("happyCase Add to favorites", func(t *testing.T) { baloo.New(ts.URL). Post(articleFavoritePath). - AddHeader("Authorization", authToken). + AddHeader("Authorization", testData.TokenPrefix+authToken). Expect(t). Status(200). Done() @@ -88,7 +88,7 @@ func TestArticleFavoriteDelete(t *testing.T) { t.Run("happyCase Remove from to favorites", func(t *testing.T) { baloo.New(ts.URL). Delete(articleFavoritePath). - AddHeader("Authorization", authToken). + AddHeader("Authorization", testData.TokenPrefix+authToken). Expect(t). Status(200). JSONSchema(testData.ArticleSingleRespDefinition). diff --git a/implem/gin.server/article_test.go b/implem/gin.server/article_test.go index 004b836..81af34b 100644 --- a/implem/gin.server/article_test.go +++ b/implem/gin.server/article_test.go @@ -53,7 +53,7 @@ func TestRouterHandler_articlePost(t *testing.T) { t.Run("happycase", func(t *testing.T) { baloo.New(ts.URL). Post(artPath). - AddHeader("Authorization", authToken). + AddHeader("Authorization", testData.TokenPrefix+authToken). BodyString(reqBody).Expect(t). Status(http.StatusCreated). JSONSchema(testData.ArticleSingleRespDefinition). @@ -69,7 +69,7 @@ func TestRouterHandler_articlePost(t *testing.T) { t.Run("no body", func(t *testing.T) { baloo.New(ts.URL). Post(artPath). - AddHeader("Authorization", authToken). + AddHeader("Authorization", testData.TokenPrefix+authToken). Expect(t). Status(http.StatusBadRequest). Done() @@ -111,7 +111,7 @@ func TestRouterHandler_articlePut(t *testing.T) { t.Run("happycase", func(t *testing.T) { baloo.New(ts.URL). Put(artPath+"/"+expectedArticle.Slug). - AddHeader("Authorization", authToken). + AddHeader("Authorization", testData.TokenPrefix+authToken). BodyString(reqBody). Expect(t). Status(http.StatusOK). @@ -131,7 +131,7 @@ func TestRouterHandler_articlePut(t *testing.T) { t.Run("no body", func(t *testing.T) { baloo.New(ts.URL). Put(artPath+"/"+expectedArticle.Slug). - AddHeader("Authorization", authToken). + AddHeader("Authorization", testData.TokenPrefix+authToken). Expect(t). Status(http.StatusBadRequest). Done() @@ -185,7 +185,7 @@ func TestRouterHandler_articleDelete(t *testing.T) { baloo.New(ts.URL). Delete(artPath+"/"+expectedArticle.Slug). - AddHeader("Authorization", authToken). + AddHeader("Authorization", testData.TokenPrefix+authToken). Expect(t). Status(http.StatusOK). Done() diff --git a/implem/gin.server/articles_test.go b/implem/gin.server/articles_test.go index 810d36a..93fec23 100644 --- a/implem/gin.server/articles_test.go +++ b/implem/gin.server/articles_test.go @@ -85,7 +85,7 @@ func TestArticlesFeed(t *testing.T) { baloo.New(ts.URL). Get(articlesFeedPath). - AddHeader("Authorization", authToken). + AddHeader("Authorization", testData.TokenPrefix+authToken). AddQuery("limit", strconv.Itoa(limit)). AddQuery("offset", strconv.Itoa(offset)). Expect(t). @@ -122,7 +122,7 @@ func TestArticlesFeed(t *testing.T) { baloo.New(ts.URL). Get(articlesFeedPath). - AddHeader("Authorization", authToken). + AddHeader("Authorization", testData.TokenPrefix+authToken). AddQuery("limit", strconv.Itoa(limit)). AddQuery("offset", strconv.Itoa(offset)). Expect(t). diff --git a/implem/gin.server/profileFollowDelete_test.go b/implem/gin.server/profileFollowDelete_test.go index e9a117e..4c679e2 100644 --- a/implem/gin.server/profileFollowDelete_test.go +++ b/implem/gin.server/profileFollowDelete_test.go @@ -39,7 +39,7 @@ func TestProfileFollowDelete_happyCase(t *testing.T) { baloo.New(ts.URL). Delete(profileFollowDeletePath). - AddHeader("Authorization", authToken). + AddHeader("Authorization", testData.TokenPrefix+authToken). Expect(t). Status(200). JSONSchema(testData.ProfileRespDefinition). diff --git a/implem/gin.server/profileFollowPost_test.go b/implem/gin.server/profileFollowPost_test.go index 7271c03..51d65d6 100644 --- a/implem/gin.server/profileFollowPost_test.go +++ b/implem/gin.server/profileFollowPost_test.go @@ -37,7 +37,7 @@ func TestProfileFollowPost_happyCase(t *testing.T) { baloo.New(ts.URL). Post(profileFollowPostPath). - AddHeader("Authorization", authToken). + AddHeader("Authorization", testData.TokenPrefix+authToken). Expect(t). Status(200). JSONSchema(testData.ProfileRespDefinition). diff --git a/implem/gin.server/profileGet.go b/implem/gin.server/profileGet.go index 793ab91..5c4a943 100644 --- a/implem/gin.server/profileGet.go +++ b/implem/gin.server/profileGet.go @@ -10,8 +10,11 @@ import ( func (rH RouterHandler) profileGet(c *gin.Context) { log := rH.log(rH.MethodAndPath(c)) requestingUserName := "" - if userName, err := rH.authHandler.GetUserName(c.GetHeader("Authorization")); err == nil { - requestingUserName = userName + + if jwt, err := getJWT(c.GetHeader("Authorization")); err == nil { + if userName, err := rH.authHandler.GetUserName(jwt); err == nil { + requestingUserName = userName + } } user, follows, err := rH.ucHandler.ProfileGet(requestingUserName, c.Param("username")) diff --git a/implem/gin.server/profileGet_test.go b/implem/gin.server/profileGet_test.go index baa9aa8..1b45404 100644 --- a/implem/gin.server/profileGet_test.go +++ b/implem/gin.server/profileGet_test.go @@ -63,7 +63,7 @@ func TestProfileGet_happyCaseAuthenticated(t *testing.T) { baloo.New(ts.URL). Get(profileGetPath). - AddHeader("Authorization", authToken). + AddHeader("Authorization", testData.TokenPrefix+authToken). Expect(t). Status(200). JSONSchema(testData.ProfileRespDefinition). diff --git a/implem/gin.server/userGet_test.go b/implem/gin.server/userGet_test.go index 410c7e6..352bd54 100644 --- a/implem/gin.server/userGet_test.go +++ b/implem/gin.server/userGet_test.go @@ -15,7 +15,7 @@ import ( "gopkg.in/h2non/baloo.v3" ) -var userGetPath = "/api/users" +var userGetPath = "/api/user" func TestUserGet_happyCase(t *testing.T) { mockCtrl := gomock.NewController(t) @@ -39,7 +39,7 @@ func TestUserGet_happyCase(t *testing.T) { baloo.New(ts.URL). Get(userGetPath). - AddHeader("Authorization", authToken). + AddHeader("Authorization", testData.TokenPrefix+authToken). Expect(t). Status(http.StatusOK). JSONSchema(testData.UserRespDefinition). diff --git a/implem/gin.server/userPatch_test.go b/implem/gin.server/userPatch_test.go index 1d22e3b..7fe0106 100644 --- a/implem/gin.server/userPatch_test.go +++ b/implem/gin.server/userPatch_test.go @@ -16,7 +16,7 @@ import ( "gopkg.in/h2non/baloo.v3" ) -var userPutPath = "/api/users" +var userPutPath = "/api/user" func TestUserPut_happyCase(t *testing.T) { mockCtrl := gomock.NewController(t) @@ -42,7 +42,7 @@ func TestUserPut_happyCase(t *testing.T) { assert.NoError(t, err) baloo.New(ts.URL). Put(userPutPath). - AddHeader("Authorization", token). + AddHeader("Authorization", testData.TokenPrefix+token). BodyString(`{ "user": { "bio": "` + testData.User("rick").Email + `", diff --git a/implem/logrus.logger/logrus.go b/implem/logrus.logger/logrus.go index 7f04e3a..aec524e 100644 --- a/implem/logrus.logger/logrus.go +++ b/implem/logrus.logger/logrus.go @@ -3,7 +3,6 @@ package logger import ( "log" - "github.com/err0r500/go-cleanarch-skeleton/domain" "github.com/err0r500/go-realworld-clean/uc" "github.com/sirupsen/logrus" ) @@ -57,37 +56,9 @@ func (l LogrusLogger) Log(args ...interface{}) { l.Logger.Info(args...) } +//fixme func (l LogrusLogger) newLog(err error, usecase interface{}) { - switch v := err.(type) { - case *domain.Message: - f := logrus.Fields{ - "type": v.MessageType.String(), - "mess": v.Title, - } - - f["env"] = l.env - - if v.Additional != "" { - f["additional"] = v.Additional - } - - ll := l.Logger.WithFields(f) - switch v.MessageLevel { - case domain.MessDebug: - ll.Debug(usecase) - case domain.MessInfo: - ll.Info(usecase) - case domain.MessWarn: - ll.Warn(usecase) - case domain.MessError: - ll.Error(usecase) - case domain.MessFatal: - ll.Fatal(usecase) - } - - default: - l.Logger.WithError(err).Error(usecase) - } + l.Logger.WithError(err).Error(usecase) } type SimpleLogger struct{} diff --git a/implem/memory.articleRW/readWriter.go b/implem/memory.articleRW/readWriter.go index 055baf4..e49d1fc 100644 --- a/implem/memory.articleRW/readWriter.go +++ b/implem/memory.articleRW/readWriter.go @@ -5,6 +5,10 @@ import ( "errors" + "time" + + "log" + "github.com/err0r500/go-realworld-clean/domain" "github.com/err0r500/go-realworld-clean/uc" ) @@ -20,9 +24,11 @@ func New() uc.ArticleRW { } func (rw rw) Create(article domain.Article) (*domain.Article, error) { if _, err := rw.GetBySlug(article.Slug); err == nil { + log.Println(err) return nil, uc.ErrAlreadyInUse } - + article.CreatedAt = time.Now() + article.UpdatedAt = time.Now() rw.store.Store(article.Slug, article) return rw.GetBySlug(article.Slug) diff --git a/testData/example.go b/testData/example.go index 9cb71be..6f22f4f 100644 --- a/testData/example.go +++ b/testData/example.go @@ -42,19 +42,7 @@ var jane = domain.User{ Password: "janePassword", } -//func Profile(name string) domain.Profile { -// switch name { -// case "janeFollowingRick": -// return janeFollowingRick -// default: -// return janeFollowingRick -// } -//} - -//var janeFollowingRick = domain.Profile{ -// User: rick, -// Following: true, -//} +const TokenPrefix = "Token " var janeArticle = domain.Article{ Slug: "articleSlug", diff --git a/uc/article.go b/uc/article.go index 0c83642..3e025d3 100644 --- a/uc/article.go +++ b/uc/article.go @@ -13,8 +13,8 @@ func (i interactor) ArticlePost(username string, article domain.Article) (*domai } slug := i.slugger.NewSlug(article.Title) - if _, err := i.getArticleAndCheckUser("", slug); err != errArticleNotFound { - return nil, errors.New("this title is already taken by another article") + if _, err := i.articleRW.GetBySlug(slug); err == nil { + return nil, ErrAlreadyInUse } article.Slug = slug diff --git a/uc/article_test.go b/uc/article_test.go index 383333b..1cd097c 100644 --- a/uc/article_test.go +++ b/uc/article_test.go @@ -3,6 +3,8 @@ package uc_test import ( "testing" + "errors" + "github.com/err0r500/go-realworld-clean/domain" mock "github.com/err0r500/go-realworld-clean/implem/mock.uc" "github.com/err0r500/go-realworld-clean/testData" @@ -23,7 +25,7 @@ func TestInteractor_ArticlePost(t *testing.T) { i := mock.NewMockedInteractor(mockCtrl) i.UserRW.EXPECT().GetByName(rick.Name).Return(&rick, nil).Times(1) i.Slugger.EXPECT().NewSlug(article.Title).Return(slug).Times(1) - i.ArticleRW.EXPECT().GetBySlug(slug).Return(nil, nil).Times(1) + i.ArticleRW.EXPECT().GetBySlug(slug).Return(nil, errors.New("not found")).Times(1) i.ArticleValidator.EXPECT().BeforeCreationCheck(gomock.Any()).Return(nil).Times(1) i.ArticleRW.EXPECT().Create(gomock.Any())