diff --git a/main.go b/main.go index ea37104..8ecc3aa 100644 --- a/main.go +++ b/main.go @@ -31,13 +31,13 @@ func main() { } jwtUtil := src.NewJwtUtil(key) - bcryptUtil := src.NewBcrypt() + passwordUtil := src.NewPasswordUtil() db := src.NewDB(sqlDb) userService := src.NewUserService(src.UserServiceDeps{ - Jwt: jwtUtil, - Bcrypt: bcryptUtil, - Db: db, - Cache: src.NewCacheInmem[string, src.UserDTO](60 * 60), + Jwt: jwtUtil, + Password: passwordUtil, + Db: db, + Cache: src.NewCacheInmem[string, src.UserDTO](60 * 60), }) r := gin.New() diff --git a/src/bcrypt.go b/src/bcrypt.go deleted file mode 100644 index 232d78b..0000000 --- a/src/bcrypt.go +++ /dev/null @@ -1,23 +0,0 @@ -package src - -import "golang.org/x/crypto/bcrypt" - -type BCryptUtil interface { - HashPassword(password string) (string, error) - IsPasswordsEqual(password, hash string) bool -} - -func NewBcrypt() BCryptUtil { - return &bcryptImpl{} -} - -type bcryptImpl struct{} - -func (b *bcryptImpl) HashPassword(password string) (string, error) { - bytes, _ := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) - return string(bytes), nil -} - -func (b *bcryptImpl) IsPasswordsEqual(password, hash string) bool { - return nil == bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) -} diff --git a/src/password_util.go b/src/password_util.go new file mode 100644 index 0000000..76ccf7f --- /dev/null +++ b/src/password_util.go @@ -0,0 +1,35 @@ +package src + +import ( + "fmt" + + "golang.org/x/crypto/bcrypt" +) + +type PasswordUtil interface { + Hash(password string) (string, error) + Compare(password, hash string) bool + Validate(password string) error +} + +func NewPasswordUtil() PasswordUtil { + return &passwordUtil{} +} + +type passwordUtil struct{} + +func (b *passwordUtil) Hash(password string) (string, error) { + bytes, _ := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) + return string(bytes), nil +} + +func (b *passwordUtil) Compare(password, hash string) bool { + return nil == bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) +} + +func (b *passwordUtil) Validate(password string) error { + if len(password) < 8 { + return fmt.Errorf("password must contain 8 or more characters") + } + return nil +} diff --git a/src/service.go b/src/service.go index f0f45da..51ce773 100644 --- a/src/service.go +++ b/src/service.go @@ -10,6 +10,7 @@ var ( ErrUserExists = fmt.Errorf("user with this login already exists") ErrUserWrongPassword = fmt.Errorf("wrong password") ErrUserWrongToken = fmt.Errorf("bad user token") + ErrUserBadPassword = fmt.Errorf("password must contain at least 8 characters") // ErrUserInternal = fmt.Errorf("unexpected error. contact tech support") ) @@ -24,10 +25,10 @@ func NewUserService(deps UserServiceDeps) UserService { } type UserServiceDeps struct { - Db DB - Jwt JwtUtil - Bcrypt BCryptUtil - Cache Cache[string, UserDTO] + Db DB + Jwt JwtUtil + Password PasswordUtil + Cache Cache[string, UserDTO] } type userService struct { @@ -49,7 +50,11 @@ func (u *userService) CreateUser(ctx context.Context, params UserCreateParams) ( return nil, ErrUserExists } - secret, err := u.deps.Bcrypt.HashPassword(params.Password) + if err := u.deps.Password.Validate(params.Password); err != nil { + return nil, ErrUserBadPassword + } + + secret, err := u.deps.Password.Hash(params.Password) if err != nil { return nil, err } @@ -79,7 +84,7 @@ func (u *userService) AuthenticateUser(ctx context.Context, login, password stri return "", ErrUserNotExists } - if !u.deps.Bcrypt.IsPasswordsEqual(password, user.Secret) { + if !u.deps.Password.Compare(password, user.Secret) { return "", ErrUserWrongPassword } diff --git a/src/user_create_handler.go b/src/user_create_handler.go index 5fcbe4f..305cf39 100644 --- a/src/user_create_handler.go +++ b/src/user_create_handler.go @@ -31,7 +31,7 @@ func NewUserCreateHandler(userService UserService) gin.HandlerFunc { Password: params.Password, Name: params.Name, }) - if err == ErrUserExists { + if err == ErrUserExists || err == ErrUserBadPassword { ctx.Data(400, "plain/text", []byte(err.Error())) return }