3
0
corteza/auth/service/user.go
2018-09-17 16:08:02 +02:00

101 lines
2.4 KiB
Go

package service
import (
"context"
"github.com/crusttech/crust/auth/repository"
"github.com/crusttech/crust/auth/types"
)
const (
ErrUserInvalidCredentials = serviceError("UserInvalidCredentials")
ErrUserLocked = serviceError("UserLocked")
)
type (
user struct {
repository repository.User
}
UserService interface {
With(ctx context.Context) UserService
FindByID(id uint64) (*types.User, error)
Find(filter *types.UserFilter) ([]*types.User, error)
Create(input *types.User) (*types.User, error)
Update(mod *types.User) (*types.User, error)
FindOrCreate(email string) (*types.User, error)
ValidateCredentials(username, password string) (*types.User, error)
}
)
func User() UserService {
return &user{
repository.NewUser(context.Background()),
}
}
func (svc *user) With(ctx context.Context) UserService {
return &user{
svc.repository.With(ctx),
}
}
func (svc *user) ValidateCredentials(username, password string) (*types.User, error) {
user, err := svc.repository.FindUserByUsername(username)
if err != nil {
return nil, err
}
if !user.ValidatePassword(password) {
return nil, ErrUserInvalidCredentials
}
if !svc.canLogin(user) {
return nil, ErrUserLocked
}
return user, nil
}
func (svc *user) FindByID(id uint64) (*types.User, error) {
return svc.repository.FindUserByID(id)
}
func (svc *user) Find(filter *types.UserFilter) ([]*types.User, error) {
return svc.repository.FindUsers(filter)
}
// Finds if user with a specific email exists and returns it otherwise it creates a fresh one
func (svc *user) FindOrCreate(email string) (user *types.User, err error) {
return user, svc.repository.DB().Transaction(func() error {
if user, err = svc.repository.FindUserByEmail(email); err != repository.ErrUserNotFound {
return err
} else if user, err = svc.repository.CreateUser(&types.User{Email: email}); err != nil {
return err
}
return nil
})
}
func (svc *user) Create(input *types.User) (user *types.User, err error) {
return user, svc.repository.DB().Transaction(func() error {
// Encrypt user password
if user, err = svc.repository.CreateUser(input); err != nil {
return err
}
return nil
})
}
func (svc *user) Update(mod *types.User) (*types.User, error) {
return svc.repository.UpdateUser(mod)
}
func (svc *user) canLogin(u *types.User) bool {
return u != nil && u.ID > 0 && u.SuspendedAt == nil && u.DeletedAt == nil
}