Skip to content

Commit

Permalink
refactoring token service (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
arkanjoms committed Jul 21, 2021
1 parent c027e88 commit e989d9c
Show file tree
Hide file tree
Showing 11 changed files with 79 additions and 69 deletions.
6 changes: 3 additions & 3 deletions api/handler/checkTokenController.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package handler

import (
"encoding/json"
"golauth/usecase"
"golauth/usecase/token"
"net/http"
)

Expand All @@ -12,10 +12,10 @@ type CheckTokenController interface {
}

type checkTokenController struct {
svc usecase.TokenService
svc token.UseCase
}

func NewCheckTokenController(s usecase.TokenService) CheckTokenController {
func NewCheckTokenController(s token.UseCase) CheckTokenController {
return checkTokenController{svc: s}
}

Expand Down
24 changes: 12 additions & 12 deletions api/handler/checkTokenController_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"golauth/usecase"
"golauth/usecase/mock"
"golauth/usecase/token"
"golauth/usecase/token/mock"
"net/http"
"net/http/httptest"
"testing"
Expand All @@ -17,7 +17,7 @@ type CheckTokenControllerSuite struct {
suite.Suite
*require.Assertions
ctrl *gomock.Controller
tkSvc *mock.MockTokenService
tkSvc *mock.MockUseCase

ct CheckTokenController
}
Expand All @@ -29,7 +29,7 @@ func TestCheckTokenControllerSuite(t *testing.T) {
func (s *CheckTokenControllerSuite) SetupTest() {
s.Assertions = require.New(s.T())
s.ctrl = gomock.NewController(s.T())
s.tkSvc = mock.NewMockTokenService(s.ctrl)
s.tkSvc = mock.NewMockUseCase(s.ctrl)

s.ct = NewCheckTokenController(s.tkSvc)
}
Expand All @@ -41,19 +41,19 @@ func (s *CheckTokenControllerSuite) TearDownTest() {
func (s CheckTokenControllerSuite) TestCheckTokenErrExtractToken() {
w := httptest.NewRecorder()
r, _ := http.NewRequest("GET", "/check_token", nil)
s.tkSvc.EXPECT().ExtractToken(r).Return("", usecase.ErrBearerTokenExtract).Times(1)
s.tkSvc.EXPECT().ExtractToken(r).Return("", token.ErrBearerTokenExtract).Times(1)

s.ct.CheckToken(w, r)
s.Equal(http.StatusBadRequest, w.Code)
s.ErrorAs(errors.New(w.Body.String()), &usecase.ErrBearerTokenExtract)
s.ErrorAs(errors.New(w.Body.String()), &token.ErrBearerTokenExtract)
}

func (s CheckTokenControllerSuite) TestCheckTokenInvalidToken() {
token := "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZmlyc3ROYW1lIjoiQWRtaW4iLCJsYXN0TmFtZSI6IkFkbWluIiwiYXV0aG9yaXRpZXMiOlsiQURNSU4iLCJVU0VSIl0sImV4cCI6MTYyNTExMDI4MH0.aXZnvA7IGvVbXcv3xYWv2ApCzb4mSfCElDS2-8I0Eoey2yZjTXun7ToKZEp3ANUSNsAp0Cc2T-NwsvXw-28ZzJG6OW1BmZ8in6DGk5c82zWEuokt_oqF496jZC4doeomop39dO-ETgpD1j63M6jzwz0joecbvCg_rixYdtN52Ix6ekIFMae6mvElD68wLTIlJLp6ld58on_jyHV3o5K13SUhP8SHkFJzUfgVaJxLGFRAa8qeOPJakTDsIqigbOUQVw3RdNGVpCGwCj86G9NWhcz0SdMsOMLsnLAhqUSOf6sqyagt3-mvquD_ehv4KDdx8g1wLzsz62bwJUzl85PdJQ"
tk := "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZmlyc3ROYW1lIjoiQWRtaW4iLCJsYXN0TmFtZSI6IkFkbWluIiwiYXV0aG9yaXRpZXMiOlsiQURNSU4iLCJVU0VSIl0sImV4cCI6MTYyNTExMDI4MH0.aXZnvA7IGvVbXcv3xYWv2ApCzb4mSfCElDS2-8I0Eoey2yZjTXun7ToKZEp3ANUSNsAp0Cc2T-NwsvXw-28ZzJG6OW1BmZ8in6DGk5c82zWEuokt_oqF496jZC4doeomop39dO-ETgpD1j63M6jzwz0joecbvCg_rixYdtN52Ix6ekIFMae6mvElD68wLTIlJLp6ld58on_jyHV3o5K13SUhP8SHkFJzUfgVaJxLGFRAa8qeOPJakTDsIqigbOUQVw3RdNGVpCGwCj86G9NWhcz0SdMsOMLsnLAhqUSOf6sqyagt3-mvquD_ehv4KDdx8g1wLzsz62bwJUzl85PdJQ"
w := httptest.NewRecorder()
r, _ := http.NewRequest("GET", "/check_token", nil)
s.tkSvc.EXPECT().ExtractToken(r).Return(token, nil).Times(1)
s.tkSvc.EXPECT().ValidateToken(token).Return(fmt.Errorf("parsed token invalid")).Times(1)
s.tkSvc.EXPECT().ExtractToken(r).Return(tk, nil).Times(1)
s.tkSvc.EXPECT().ValidateToken(tk).Return(fmt.Errorf("parsed token invalid")).Times(1)

s.ct.CheckToken(w, r)
s.Equal(http.StatusUnauthorized, w.Code)
Expand All @@ -62,11 +62,11 @@ func (s CheckTokenControllerSuite) TestCheckTokenInvalidToken() {
}

func (s CheckTokenControllerSuite) TestCheckTokenOk() {
token := "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZmlyc3ROYW1lIjoiQWRtaW4iLCJsYXN0TmFtZSI6IkFkbWluIiwiYXV0aG9yaXRpZXMiOlsiQURNSU4iLCJVU0VSIl0sImV4cCI6MTYyNTExMDI4MH0.aXZnvA7IGvVbXcv3xYWv2ApCzb4mSfCElDS2-8I0Eoey2yZjTXun7ToKZEp3ANUSNsAp0Cc2T-NwsvXw-28ZzJG6OW1BmZ8in6DGk5c82zWEuokt_oqF496jZC4doeomop39dO-ETgpD1j63M6jzwz0joecbvCg_rixYdtN52Ix6ekIFMae6mvElD68wLTIlJLp6ld58on_jyHV3o5K13SUhP8SHkFJzUfgVaJxLGFRAa8qeOPJakTDsIqigbOUQVw3RdNGVpCGwCj86G9NWhcz0SdMsOMLsnLAhqUSOf6sqyagt3-mvquD_ehv4KDdx8g1wLzsz62bwJUzl85PdJQ"
tk := "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZmlyc3ROYW1lIjoiQWRtaW4iLCJsYXN0TmFtZSI6IkFkbWluIiwiYXV0aG9yaXRpZXMiOlsiQURNSU4iLCJVU0VSIl0sImV4cCI6MTYyNTExMDI4MH0.aXZnvA7IGvVbXcv3xYWv2ApCzb4mSfCElDS2-8I0Eoey2yZjTXun7ToKZEp3ANUSNsAp0Cc2T-NwsvXw-28ZzJG6OW1BmZ8in6DGk5c82zWEuokt_oqF496jZC4doeomop39dO-ETgpD1j63M6jzwz0joecbvCg_rixYdtN52Ix6ekIFMae6mvElD68wLTIlJLp6ld58on_jyHV3o5K13SUhP8SHkFJzUfgVaJxLGFRAa8qeOPJakTDsIqigbOUQVw3RdNGVpCGwCj86G9NWhcz0SdMsOMLsnLAhqUSOf6sqyagt3-mvquD_ehv4KDdx8g1wLzsz62bwJUzl85PdJQ"
w := httptest.NewRecorder()
r, _ := http.NewRequest("GET", "/check_token", nil)
s.tkSvc.EXPECT().ExtractToken(r).Return(token, nil).Times(1)
s.tkSvc.EXPECT().ValidateToken(token).Return(nil).Times(1)
s.tkSvc.EXPECT().ExtractToken(r).Return(tk, nil).Times(1)
s.tkSvc.EXPECT().ValidateToken(tk).Return(nil).Times(1)

s.ct.CheckToken(w, r)
s.Equal(http.StatusOK, w.Code)
Expand Down
5 changes: 3 additions & 2 deletions api/handler/tokenController.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"golauth/infrastructure/repository"
"golauth/model"
"golauth/usecase"
"golauth/usecase/token"
"net/http"
)

Expand All @@ -19,14 +20,14 @@ type TokenController interface {
type tokenController struct {
userRepository repository.UserRepository
userAuthorityRepository repository.UserAuthorityRepository
tokenService usecase.TokenService
tokenService token.UseCase
userService usecase.UserService
}

func NewTokenController(
userRepository repository.UserRepository,
userAuthorityRepository repository.UserAuthorityRepository,
tokenService usecase.TokenService,
tokenService token.UseCase,
userService usecase.UserService) TokenController {
return tokenController{
userRepository: userRepository,
Expand Down
5 changes: 3 additions & 2 deletions api/handler/tokenController_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
repoMock "golauth/infrastructure/repository/mock"
"golauth/model"
svcMock "golauth/usecase/mock"
tkMock "golauth/usecase/token/mock"
"net/http"
"net/http/httptest"
"strings"
Expand All @@ -23,7 +24,7 @@ type TokenControllerSuite struct {

uRepo *repoMock.MockUserRepository
uaRepo *repoMock.MockUserAuthorityRepository
tkSvc *svcMock.MockTokenService
tkSvc *tkMock.MockUseCase
uSvc *svcMock.MockUserService

ctrl TokenController
Expand All @@ -39,7 +40,7 @@ func (s *TokenControllerSuite) SetupTest() {

s.uRepo = repoMock.NewMockUserRepository(s.mockCtrl)
s.uaRepo = repoMock.NewMockUserAuthorityRepository(s.mockCtrl)
s.tkSvc = svcMock.NewMockTokenService(s.mockCtrl)
s.tkSvc = tkMock.NewMockUseCase(s.mockCtrl)
s.uSvc = svcMock.NewMockUserService(s.mockCtrl)

s.ctrl = NewTokenController(s.uRepo, s.uaRepo, s.tkSvc, s.uSvc)
Expand Down
6 changes: 3 additions & 3 deletions api/middleware/security.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package middleware

import (
"golauth/usecase"
"golauth/usecase/token"
"net/http"
)

type SecurityMiddleware struct {
service usecase.TokenService
service token.UseCase
publicURI map[string]bool
}

func NewSecurityMiddleware(service usecase.TokenService, pathPrefix string) *SecurityMiddleware {
func NewSecurityMiddleware(service token.UseCase, pathPrefix string) *SecurityMiddleware {
return &SecurityMiddleware{
service: service,
publicURI: map[string]bool{
Expand Down
5 changes: 3 additions & 2 deletions api/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"golauth/api/middleware"
"golauth/infrastructure/repository"
"golauth/usecase"
"golauth/usecase/token"
"net/http"

"github.com/gorilla/mux"
Expand All @@ -23,15 +24,15 @@ type router struct {
checkTokenController handler.CheckTokenController
userController handler.UserController
roleController handler.RoleController
tokenService usecase.TokenService
tokenService token.UseCase
}

func NewRouter(db *sql.DB) Router {
uRepo := repository.NewUserRepository(db)
rRepo := repository.NewRoleRepository(db)
urRepo := repository.NewUserRoleRepository(db)
uaRepo := repository.NewUserAuthorityRepository(db)
tokenService := usecase.NewTokenService()
tokenService := token.NewService()
userService := usecase.NewUserService(uRepo, rRepo, urRepo, uaRepo, tokenService)

roleSvc := usecase.NewRoleService(rRepo)
Expand Down
13 changes: 13 additions & 0 deletions usecase/token/interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//go:generate mockgen -source interface.go -destination mock/interface_mock.go -package mock
package token

import (
"golauth/entity"
"net/http"
)

type UseCase interface {
ValidateToken(token string) error
ExtractToken(r *http.Request) (string, error)
GenerateJwtToken(user entity.User, authorities []string) (string, error)
}
43 changes: 18 additions & 25 deletions usecase/tokenService.go → usecase/token/service.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:generate mockgen -source tokenService.go -destination mock/tokenService_mock.go -package mock
package usecase
package token

import (
"crypto/rand"
Expand All @@ -23,55 +22,49 @@ var (
tokenExpirationTime = 30
)

type TokenService interface {
ValidateToken(token string) error
ExtractToken(r *http.Request) (string, error)
GenerateJwtToken(user entity.User, authorities []string) (string, error)
}

type tokenService struct {
type Service struct {
signer jwt.Signer
verifier jwt.Verifier
}

func NewTokenService() TokenService {
ts := tokenService{}
ts.prepare()
return ts
func NewService() UseCase {
s := Service{}
s.prepare()
return s
}

func (ts *tokenService) prepare() {
key := ts.generatePrivateKey()
ts.signer = ts.generateSigner(key)
ts.verifier = ts.generateVerifier(key)
func (s *Service) prepare() {
key := s.generatePrivateKey()
s.signer = s.generateSigner(key)
s.verifier = s.generateVerifier(key)
}

func (ts tokenService) generateSigner(key *rsa.PrivateKey) jwt.Signer {
func (s Service) generateSigner(key *rsa.PrivateKey) jwt.Signer {
signer, err := jwt.NewSignerRS(keyAlgorithm, key)
if err != nil {
panic(errSignerGenerate)
}
return signer
}

func (ts tokenService) generateVerifier(key *rsa.PrivateKey) jwt.Verifier {
func (s Service) generateVerifier(key *rsa.PrivateKey) jwt.Verifier {
verifier, err := jwt.NewVerifierRS(keyAlgorithm, &key.PublicKey)
if err != nil {
panic(errVerifierGenerate)
}
return verifier
}

func (ts *tokenService) generatePrivateKey() *rsa.PrivateKey {
func (s *Service) generatePrivateKey() *rsa.PrivateKey {
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
panic(fmt.Errorf("could not generate private key: %w", err))
}
return privateKey
}

func (ts tokenService) ValidateToken(strToken string) error {
token, err := jwt.ParseAndVerifyString(strToken, ts.verifier)
func (s Service) ValidateToken(strToken string) error {
token, err := jwt.ParseAndVerifyString(strToken, s.verifier)
if err != nil {
return fmt.Errorf("could not parse and verify strToken: %w", err)
}
Expand All @@ -88,15 +81,15 @@ func (ts tokenService) ValidateToken(strToken string) error {
return nil
}

func (ts tokenService) ExtractToken(r *http.Request) (string, error) {
func (s Service) ExtractToken(r *http.Request) (string, error) {
authorization := r.Header.Get("Authorization")
if len(authorization) > len("Bearer ") {
return authorization[7:], nil
}
return "", ErrBearerTokenExtract
}

func (ts tokenService) GenerateJwtToken(user entity.User, authorities []string) (string, error) {
func (s Service) GenerateJwtToken(user entity.User, authorities []string) (string, error) {
expirationTime := time.Now().Add(time.Duration(tokenExpirationTime) * time.Minute)
claims := &model.Claims{
Username: user.Username,
Expand All @@ -107,7 +100,7 @@ func (ts tokenService) GenerateJwtToken(user entity.User, authorities []string)
ExpiresAt: jwt.NewNumericDate(expirationTime),
},
}
builder := jwt.NewBuilder(ts.signer)
builder := jwt.NewBuilder(s.signer)
token, err := builder.Build(claims)
if err != nil {
return "", fmt.Errorf("could not build token with claims: %w", err)
Expand Down
Loading

0 comments on commit e989d9c

Please sign in to comment.