-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
prepare project to refactoring use cases (#25)
refactoring use case layer
- Loading branch information
Showing
73 changed files
with
1,933 additions
and
1,831 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package util | ||
|
||
import ( | ||
"net/http" | ||
) | ||
|
||
func ExtractToken(r *http.Request) (string, error) { | ||
authorization := r.Header.Get("Authorization") | ||
if len(authorization) > len("Bearer ") { | ||
return authorization[7:], nil | ||
} | ||
return "", ErrBearerTokenExtract | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package util | ||
|
||
import ( | ||
"fmt" | ||
"github.com/golang/mock/gomock" | ||
"github.com/stretchr/testify/require" | ||
"github.com/stretchr/testify/suite" | ||
"net/http" | ||
"strings" | ||
"testing" | ||
) | ||
|
||
type ExtractTokenSuite struct { | ||
suite.Suite | ||
*require.Assertions | ||
mockCtrl *gomock.Controller | ||
} | ||
|
||
func TestExtractToken(t *testing.T) { | ||
suite.Run(t, new(ExtractTokenSuite)) | ||
} | ||
|
||
func (s *ExtractTokenSuite) SetupTest() { | ||
s.Assertions = require.New(s.T()) | ||
s.mockCtrl = gomock.NewController(s.T()) | ||
} | ||
|
||
func (s *ExtractTokenSuite) TearDownTest() { | ||
s.mockCtrl.Finish() | ||
} | ||
func (s ExtractTokenSuite) TestExtractTokenOk() { | ||
tk := "aeyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZmlyc3ROYW1lIjoiQWRtaW4iLCJsYXN0TmFtZSI6IkFkbWluIiwiYXV0aG9yaXRpZXMiOlsiQURNSU4iLCJVU0VSIl0sImV4cCI6MTYyNTExMDI4MH0.aXZnvA7IGvVbXcv3xYWv2ApCzb4mSfCElDS2-8I0Eoey2yZjTXun7ToKZEp3ANUSNsAp0Cc2T-NwsvXw-28ZzJG6OW1BmZ8in6DGk5c82zWEuokt_oqF496jZC4doeomop39dO-ETgpD1j63M6jzwz0joecbvCg_rixYdtN52Ix6ekIFMae6mvElD68wLTIlJLp6ld58on_jyHV3o5K13SUhP8SHkFJzUfgVaJxLGFRAa8qeOPJakTDsIqigbOUQVw3RdNGVpCGwCj86G9NWhcz0SdMsOMLsnLAhqUSOf6sqyagt3-mvquD_ehv4KDdx8g1wLzsz62bwJUzl85PdJQ" | ||
reader := strings.NewReader("") | ||
req, err := http.NewRequest(http.MethodPost, "/check_token", reader) | ||
s.NoError(err) | ||
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", tk)) | ||
extracted, err := ExtractToken(req) | ||
s.NoError(err) | ||
s.NotEmpty(extracted) | ||
s.Equal(tk, extracted) | ||
} | ||
|
||
func (s ExtractTokenSuite) TestExtractTokenNotOk() { | ||
reader := strings.NewReader("") | ||
req, err := http.NewRequest(http.MethodPost, "/check_token", reader) | ||
if err != nil { | ||
s.T().Fatal("error when creating request: %w", err) | ||
} | ||
extracted, err := ExtractToken(req) | ||
s.Error(err) | ||
s.Empty(extracted) | ||
s.ErrorAs(err, &ErrBearerTokenExtract) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
//go:generate mockgen -source GenerateJwtToken.go -destination mock/GenerateJwtToken_mock.go -package mock | ||
package util | ||
|
||
import ( | ||
"crypto/rand" | ||
"crypto/rsa" | ||
"errors" | ||
"fmt" | ||
"github.com/cristalhq/jwt/v3" | ||
"github.com/golauth/golauth/domain/entity" | ||
"github.com/golauth/golauth/infra/api/controller/model" | ||
"time" | ||
) | ||
|
||
var ( | ||
ErrBearerTokenExtract = errors.New("bearer token extract error") | ||
errSignerGenerate = errors.New("could not generate signer from private key") | ||
errVerifierGenerate = errors.New("could not generate verifier from public key") | ||
keyAlgorithm = jwt.RS512 | ||
TokenExpirationTime = 60 | ||
) | ||
|
||
type GenerateJwtToken interface { | ||
Execute(user *entity.User, authorities []string) (string, error) | ||
} | ||
|
||
func NewGenerateJwtToken(key *rsa.PrivateKey) GenerateJwtToken { | ||
return generateJwtToken{signer: GenerateSigner(key)} | ||
} | ||
|
||
type generateJwtToken struct { | ||
signer jwt.Signer | ||
} | ||
|
||
func (uc generateJwtToken) Execute(user *entity.User, authorities []string) (string, error) { | ||
expirationTime := time.Now().Add(time.Duration(TokenExpirationTime) * time.Minute) | ||
claims := &model.Claims{ | ||
Username: user.Username, | ||
FirstName: user.FirstName, | ||
LastName: user.LastName, | ||
Authorities: authorities, | ||
StandardClaims: jwt.StandardClaims{ | ||
ExpiresAt: jwt.NewNumericDate(expirationTime), | ||
}, | ||
} | ||
builder := jwt.NewBuilder(uc.signer) | ||
tk, err := builder.Build(claims) | ||
if err != nil { | ||
return "", fmt.Errorf("could not build token with claims: %w", err) | ||
} | ||
|
||
return tk.String(), nil | ||
} | ||
|
||
func GenerateSigner(key *rsa.PrivateKey) jwt.Signer { | ||
signer, err := jwt.NewSignerRS(keyAlgorithm, key) | ||
if err != nil { | ||
panic(errSignerGenerate) | ||
} | ||
return signer | ||
} | ||
|
||
func 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 GenerateVerifier(key *rsa.PrivateKey) jwt.Verifier { | ||
verifier, err := jwt.NewVerifierRS(keyAlgorithm, &key.PublicKey) | ||
if err != nil { | ||
panic(errVerifierGenerate) | ||
} | ||
return verifier | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package entity | ||
|
||
type Token struct { | ||
AccessToken string | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
//go:generate mockgen -source RepositoryFactory.go -destination mock/RepositoryFactory_mock.go -package mock | ||
package factory | ||
|
||
import ( | ||
"github.com/golauth/golauth/domain/repository" | ||
) | ||
|
||
type RepositoryFactory interface { | ||
NewRoleRepository() repository.RoleRepository | ||
NewUserAuthorityRepository() repository.UserAuthorityRepository | ||
NewUserRepository() repository.UserRepository | ||
NewUserRoleRepository() repository.UserRoleRepository | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,11 @@ | ||
//go:generate mockgen -source UserAuthorityRepository.go -destination mock/UserAuthorityRepository_mock.go -package mock | ||
package repository | ||
|
||
import "github.com/google/uuid" | ||
import ( | ||
"context" | ||
"github.com/google/uuid" | ||
) | ||
|
||
type UserAuthorityRepository interface { | ||
FindAuthoritiesByUserID(userId uuid.UUID) ([]string, error) | ||
FindAuthoritiesByUserID(ctx context.Context, userId uuid.UUID) ([]string, error) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,11 @@ | ||
//go:generate mockgen -source UserRoleRepository.go -destination mock/UserRoleRepository_mock.go -package mock | ||
package repository | ||
|
||
import "github.com/google/uuid" | ||
import ( | ||
"context" | ||
"github.com/google/uuid" | ||
) | ||
|
||
type UserRoleRepository interface { | ||
AddUserRole(userId uuid.UUID, roleId uuid.UUID) error | ||
AddUserRole(ctx context.Context, userId uuid.UUID, roleId uuid.UUID) error | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
//go:generate mockgen -source AddRole.go -destination mock/AddRole_mock.go -package mock | ||
package role | ||
|
||
import ( | ||
"context" | ||
"github.com/golauth/golauth/domain/entity" | ||
"github.com/golauth/golauth/domain/factory" | ||
"github.com/golauth/golauth/domain/repository" | ||
) | ||
|
||
type AddRole interface { | ||
Execute(ctx context.Context, input *entity.Role) (*entity.Role, error) | ||
} | ||
|
||
type addRole struct { | ||
repo repository.RoleRepository | ||
} | ||
|
||
func NewAddRole(repoFactory factory.RepositoryFactory) *addRole { | ||
return &addRole{repo: repoFactory.NewRoleRepository()} | ||
} | ||
|
||
func (uc addRole) Execute(ctx context.Context, input *entity.Role) (*entity.Role, error) { | ||
role, err := uc.repo.Create(ctx, input) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return role, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package role | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/golang/mock/gomock" | ||
"github.com/golauth/golauth/domain/entity" | ||
factoryMock "github.com/golauth/golauth/domain/factory/mock" | ||
"github.com/golauth/golauth/domain/repository/mock" | ||
"github.com/google/uuid" | ||
"github.com/stretchr/testify/require" | ||
"github.com/stretchr/testify/suite" | ||
"testing" | ||
"time" | ||
) | ||
|
||
type AddRoleSuite struct { | ||
suite.Suite | ||
*require.Assertions | ||
mockCtrl *gomock.Controller | ||
rf *factoryMock.MockRepositoryFactory | ||
repo *mock.MockRoleRepository | ||
addRole *addRole | ||
} | ||
|
||
func TestAddRole(t *testing.T) { | ||
suite.Run(t, new(AddRoleSuite)) | ||
} | ||
|
||
func (s *AddRoleSuite) SetupTest() { | ||
s.Assertions = require.New(s.T()) | ||
s.mockCtrl = gomock.NewController(s.T()) | ||
s.rf = factoryMock.NewMockRepositoryFactory(s.mockCtrl) | ||
s.repo = mock.NewMockRoleRepository(s.mockCtrl) | ||
s.rf.EXPECT().NewRoleRepository().Return(s.repo) | ||
s.addRole = NewAddRole(s.rf) | ||
} | ||
|
||
func (s *AddRoleSuite) TearDownTest() { | ||
s.mockCtrl.Finish() | ||
} | ||
|
||
func (s AddRoleSuite) TestCreateOk() { | ||
input := entity.Role{ | ||
Name: "NEW_ROLE", | ||
Description: "New Role", | ||
Enabled: true, | ||
} | ||
savedEntity := entity.Role{ | ||
ID: uuid.New(), | ||
Name: "NEW_ROLE", | ||
Description: "New Role", | ||
Enabled: true, | ||
CreationDate: time.Now(), | ||
} | ||
s.repo.EXPECT().Create(gomock.Any(), gomock.Any()).Return(&savedEntity, nil).Times(1) | ||
resp, err := s.addRole.Execute(context.Background(), &input) | ||
s.NoError(err) | ||
s.NotZero(resp) | ||
s.Equal(savedEntity.ID, resp.ID) | ||
s.Equal(savedEntity.Name, resp.Name) | ||
s.Equal(savedEntity.Description, resp.Description) | ||
s.Equal(savedEntity.Enabled, resp.Enabled) | ||
s.Equal(savedEntity.CreationDate, resp.CreationDate) | ||
} | ||
|
||
func (s AddRoleSuite) TestCreateNotOk() { | ||
errMessage := "could not create role" | ||
input := &entity.Role{ | ||
Name: "NEW_ROLE", | ||
Description: "New Role", | ||
} | ||
s.repo.EXPECT().Create(gomock.Any(), gomock.Any()).Return(nil, fmt.Errorf(errMessage)).Times(1) | ||
resp, err := s.addRole.Execute(context.Background(), input) | ||
s.Error(err) | ||
s.Zero(resp) | ||
s.EqualError(err, errMessage) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
//go:generate mockgen -source ChangeRoleStatus.go -destination mock/ChangeRoleStatus_mock.go -package mock | ||
package role | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/golauth/golauth/domain/repository" | ||
"github.com/google/uuid" | ||
) | ||
|
||
type ChangeRoleStatus interface { | ||
Execute(ctx context.Context, id uuid.UUID, enabled bool) error | ||
} | ||
|
||
type changeRoleStatus struct { | ||
repo repository.RoleRepository | ||
} | ||
|
||
func NewChangeRoleStatus(repo repository.RoleRepository) ChangeRoleStatus { | ||
return changeRoleStatus{repo: repo} | ||
} | ||
|
||
func (uc changeRoleStatus) Execute(ctx context.Context, id uuid.UUID, enabled bool) error { | ||
exists, err := uc.repo.ExistsById(ctx, id) | ||
if err != nil { | ||
return err | ||
} | ||
if !exists { | ||
return fmt.Errorf("role with id %s does not exists", id) | ||
} | ||
return uc.repo.ChangeStatus(ctx, id, enabled) | ||
} |
Oops, something went wrong.