From 063e677869d6c732022e27aac994a53a88e03ac1 Mon Sep 17 00:00:00 2001 From: James Tombleson Date: Tue, 26 Mar 2024 17:52:15 -0700 Subject: [PATCH] trying to remove the user repo and use a service --- .vscode/settings.json | 9 ++ api/services/userService.go | 105 ++++++++++++++++++ .../{users_test.go => userService_test.go} | 0 api/services/users.go | 43 ------- 4 files changed, 114 insertions(+), 43 deletions(-) create mode 100644 api/services/userService.go rename api/services/{users_test.go => userService_test.go} (100%) delete mode 100644 api/services/users.go diff --git a/.vscode/settings.json b/.vscode/settings.json index ae2f0c1..a160986 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,9 +1,18 @@ { "cSpell.words": [ + "echojwt", "glebarez", "gocook", "huandu", "labstack", "sqlbuilder" + ], + "sqltools.connections": [ + { + "previewLimit": 50, + "driver": "SQLite", + "database": "${workspaceFolder:go-cook}/gocook.db", + "name": "gocook" + } ] } \ No newline at end of file diff --git a/api/services/userService.go b/api/services/userService.go new file mode 100644 index 0000000..2a7e83f --- /dev/null +++ b/api/services/userService.go @@ -0,0 +1,105 @@ +package services + +import ( + "database/sql" + "errors" + "go-cook/api/models" + "go-cook/api/repositories" + "strings" + + "golang.org/x/crypto/bcrypt" +) + +const ( + ErrPasswordNotLongEnough = "password needs to be 8 character or longer" + ErrPasswordMissingSpecialCharacter = "password needs to contain one of the following: !, @, #" + ErrInvalidPassword = "invalid password" +) + +// This will handle operations that are user related, but one layer higher then the repository +type UserService struct { + repo repositories.IUserTable +} + +func NewUserService(conn *sql.DB) UserService { + return UserService{ + repo: repositories.NewUserRepository(conn), + } +} + +func (us UserService) DoesUserExist(username string) error { + _, err := us.repo.GetByName(username) + if err != nil { + return err + } + return nil +} + +func (us UserService) DoesPasswordMatchHash(username, password string) error { + passwordBytes := []byte(password) + hash, err := bcrypt.GenerateFromPassword(passwordBytes, bcrypt.DefaultCost) + if err != nil { + return err + } + + model, err := us.GetUser(username) + if err != nil { + return err + } + + if model.Hash != string(hash) { + return errors.New(ErrInvalidPassword) + } + + return nil +} + +func (us UserService) GetUser(username string) (models.UserModel, error) { + return us.repo.GetByName(username) +} + +func (us UserService) CreateNewUser(name, password string) (models.UserModel, error) { + err := us.CheckPasswordForRequirements(password) + if err != nil { + return models.UserModel{}, err + } + + us.repo.Create(name, password) + return models.UserModel{}, nil +} + +func (us UserService) CheckPasswordForRequirements(password string) error { + err := us.checkPasswordLength(password) + if err != nil { + return err + } + + err = us.checkPasswordForSpecialCharacters(password) + if err != nil { + return err + } + + return nil +} + +func (us UserService) checkPasswordLength(password string) error { + if len(password) <= 8 { + return errors.New(ErrPasswordNotLongEnough) + } + return nil +} + +func (us UserService) checkPasswordForSpecialCharacters(password string) error { + var chars []string + chars = append(chars, "!") + chars = append(chars, "@") + chars = append(chars, "#") + + for _, char := range chars { + if strings.Contains(password, char) { + return nil + } + } + + return errors.New(ErrPasswordMissingSpecialCharacter) +} diff --git a/api/services/users_test.go b/api/services/userService_test.go similarity index 100% rename from api/services/users_test.go rename to api/services/userService_test.go diff --git a/api/services/users.go b/api/services/users.go deleted file mode 100644 index bb2d355..0000000 --- a/api/services/users.go +++ /dev/null @@ -1,43 +0,0 @@ -package services - -import ( - "database/sql" - "errors" - "go-cook/api/models" - "go-cook/api/repositories" -) - -const ( - ErrPasswordNotLongEnough = "password needs to be 8 character or longer" -) - -// This will handle operations that are user related, but one layer higher then the repository -type UserService struct { - repo repositories.UserRepository -} - -func NewUserService(conn *sql.DB) UserService { - return UserService{ - repo: repositories.NewUserRepository(conn), - } -} - -func (us UserService) DoesUserExist(username string) error { - _, err := us.repo.GetByName(username) - if err != nil { - return err - } - return nil -} - -func (us UserService) CreateNewUser(name, password string) (models.UserModel, error) { - us.repo.NewUser(name, password) - return models.UserModel{}, nil -} - -func (us UserService) CheckPasswordForRequirements(password string) error { - if len(password) <= 8 { - return errors.New(ErrPasswordNotLongEnough) - } - return nil -}