Skip to content

Commit

Permalink
Merge pull request #4 from josephspurrier/usercase-branch
Browse files Browse the repository at this point in the history
Usecase branch
  • Loading branch information
josephspurrier committed Mar 9, 2017
2 parents 84b0bfc + de851a2 commit e442af6
Show file tree
Hide file tree
Showing 30 changed files with 1,270 additions and 132 deletions.
8 changes: 4 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ language: go
go:
#- 1.0
#- 1.1
- 1.2
- 1.3
- 1.4
- 1.5
#- 1.2
#- 1.3
#- 1.4
#- 1.5
- 1.6
- 1.7
- 1.8
Expand Down
2 changes: 1 addition & 1 deletion controller/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (

// LoginHandler represents the services required for this controller.
type LoginHandler struct {
UserService domain.UserService
UserService domain.UserCase
ViewService view.Service
}

Expand Down
19 changes: 12 additions & 7 deletions controller/login_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import (
"testing"

"github.com/josephspurrier/gocleanarchitecture/controller"
"github.com/josephspurrier/gocleanarchitecture/database"
"github.com/josephspurrier/gocleanarchitecture/domain"
"github.com/josephspurrier/gocleanarchitecture/lib/passhash"
"github.com/josephspurrier/gocleanarchitecture/lib/view"
"github.com/josephspurrier/gocleanarchitecture/repository"
"github.com/josephspurrier/gocleanarchitecture/usecase"
)

// TestLoginIndex ensures the index function returns a 200 code.
Expand Down Expand Up @@ -41,8 +43,9 @@ func TestLoginStoreMissingRequiredFields(t *testing.T) {

// Call the handler.
h := new(controller.LoginHandler)
db := new(database.MockService)
h.UserService = database.NewUserService(db)
h.UserService = usecase.NewUserCase(
repository.NewUserRepo(new(repository.MockService)),
new(passhash.Item))
h.ViewService = view.New("../view", "tmpl")
h.Index(w, r)

Expand All @@ -67,8 +70,9 @@ func TestLoginStoreAuthenticateOK(t *testing.T) {

// Call the handler.
h := new(controller.LoginHandler)
db := new(database.MockService)
h.UserService = database.NewUserService(db)
h.UserService = usecase.NewUserCase(
repository.NewUserRepo(new(repository.MockService)),
new(passhash.Item))
h.ViewService = view.New("../view", "tmpl")

// Create a new user.
Expand Down Expand Up @@ -100,8 +104,9 @@ func TestLoginStoreAuthenticateFail(t *testing.T) {

// Call the handler.
h := new(controller.LoginHandler)
db := new(database.MockService)
h.UserService = database.NewUserService(db)
h.UserService = usecase.NewUserCase(
repository.NewUserRepo(new(repository.MockService)),
new(passhash.Item))
h.ViewService = view.New("../view", "tmpl")

// Create a new user.
Expand Down
2 changes: 1 addition & 1 deletion controller/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (

// RegisterHandler represents the services required for this controller.
type RegisterHandler struct {
UserService domain.UserService
UserService domain.UserCase
ViewService view.Service
}

Expand Down
19 changes: 12 additions & 7 deletions controller/register_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import (
"testing"

"github.com/josephspurrier/gocleanarchitecture/controller"
"github.com/josephspurrier/gocleanarchitecture/database"
"github.com/josephspurrier/gocleanarchitecture/lib/passhash"
"github.com/josephspurrier/gocleanarchitecture/lib/view"
"github.com/josephspurrier/gocleanarchitecture/repository"
"github.com/josephspurrier/gocleanarchitecture/usecase"
)

// TestRegisterIndex ensures the index function returns a 200 code.
Expand Down Expand Up @@ -48,8 +50,9 @@ func TestRegisterStoreCreateOK(t *testing.T) {

// Call the handler.
h := new(controller.RegisterHandler)
db := new(database.MockService)
h.UserService = database.NewUserService(db)
h.UserService = usecase.NewUserCase(
repository.NewUserRepo(new(repository.MockService)),
new(passhash.Item))
h.ViewService = view.New("../view", "tmpl")
h.Index(w, r)

Expand All @@ -73,8 +76,9 @@ func TestRegisterStoreCreateNoFieldFail(t *testing.T) {

// Call the handler.
h := new(controller.RegisterHandler)
db := new(database.MockService)
h.UserService = database.NewUserService(db)
h.UserService = usecase.NewUserCase(
repository.NewUserRepo(new(repository.MockService)),
new(passhash.Item))
h.ViewService = view.New("../view", "tmpl")
h.Index(w, r)

Expand Down Expand Up @@ -102,8 +106,9 @@ func TestRegisterStoreCreateOneMissingFieldFail(t *testing.T) {

// Call the handler.
h := new(controller.RegisterHandler)
db := new(database.MockService)
h.UserService = database.NewUserService(db)
h.UserService = usecase.NewUserCase(
repository.NewUserRepo(new(repository.MockService)),
new(passhash.Item))
h.ViewService = view.New("../view", "tmpl")
h.Index(w, r)

Expand Down
83 changes: 0 additions & 83 deletions database/user_service.go

This file was deleted.

19 changes: 19 additions & 0 deletions domain/passhash.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package domain

import (
"errors"
)

var (
// ErrPasswordHash is when a password hash operation fails.
ErrPasswordHash = errors.New("Password hash failed.")
)

// Passhash represents a password hashing system.
type Passhash struct{}

// PasshashCase represents a service for managing hashed passwords.
type PasshashCase interface {
Hash(password string) (string, error)
Match(hash, password string) bool
}
14 changes: 10 additions & 4 deletions domain/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,15 @@ type User struct {
Password string `json:"password"`
}

// UserService represents a service for managing users.
type UserService interface {
// UserCase represents a service for managing users.
type UserCase interface {
User(email string) (*User, error)
CreateUser(user *User) error
Authenticate(user *User) error
CreateUser(item *User) error
Authenticate(item *User) error
}

// UserRepo represents a service for storage of users.
type UserRepo interface {
FindByEmail(email string) (*User, error)
Store(item *User) error
}
12 changes: 8 additions & 4 deletions lib/boot/service.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package boot

import (
"github.com/josephspurrier/gocleanarchitecture/database"
"github.com/josephspurrier/gocleanarchitecture/domain"
"github.com/josephspurrier/gocleanarchitecture/lib/passhash"
"github.com/josephspurrier/gocleanarchitecture/lib/view"
"github.com/josephspurrier/gocleanarchitecture/repository"
"github.com/josephspurrier/gocleanarchitecture/usecase"
)

// Service represents all the services that the application uses.
type Service struct {
UserService domain.UserService
UserService domain.UserCase
ViewService view.Service
}

Expand All @@ -18,10 +20,12 @@ func RegisterServices() *Service {
s := new(Service)

// Initialize the clients.
db := database.NewClient("db.json")
db := repository.NewClient("db.json")

// Store all the services for the application.
s.UserService = database.NewUserService(db)
s.UserService = usecase.NewUserCase(
repository.NewUserRepo(db),
new(passhash.Item))
s.ViewService = view.New("../../view", "tmpl")

return s
Expand Down
14 changes: 14 additions & 0 deletions lib/passhash/implement.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package passhash

// Item represents a password hashing system.
type Item struct{}

// Hash returns a hashed string and an error.
func (s *Item) Hash(password string) (string, error) {
return HashString(password)
}

// Match returns true if the hash matches the password.
func (s *Item) Match(hash, password string) bool {
return MatchString(hash, password)
}
46 changes: 46 additions & 0 deletions lib/passhash/passhash.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Package passhash provides password hashing functionality using bcrypt.
package passhash

import (
"golang.org/x/crypto/bcrypt"
)

// HashString returns a hashed string and an error.
func HashString(password string) (string, error) {
key, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
return "", err
}

return string(key), nil
}

// HashBytes returns a hashed byte array and an error.
func HashBytes(password []byte) ([]byte, error) {
key, err := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)
if err != nil {
return nil, err
}

return key, nil
}

// MatchString returns true if the hash matches the password.
func MatchString(hash, password string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
if err == nil {
return true
}

return false
}

// MatchBytes returns true if the hash matches the password.
func MatchBytes(hash, password []byte) bool {
err := bcrypt.CompareHashAndPassword(hash, []byte(password))
if err == nil {
return true
}

return false
}
Loading

0 comments on commit e442af6

Please sign in to comment.