Skip to content

Commit

Permalink
Merge pull request #54 from octoposprime/feature/smnr/5/user-name-val…
Browse files Browse the repository at this point in the history
…idation

user name validation func implemented
  • Loading branch information
Smnrgcl authored May 2, 2024
2 parents 90a9a5a + 2733018 commit 23c046a
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 17 deletions.
15 changes: 9 additions & 6 deletions internal/domain/model/object/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ var ERRORS []error = []error{
ErrorUserUsernameIsTooShort,
ErrorUserUsernameIsTooLong,
ErrorUserUsernameIsNotValid,
ErrorUserUsernameContainsSpecialChar,
ErrorUserEmailIsEmpty,
ErrorUserEmailIsNotValid,
ErrorUserEmailIsExists,
Expand All @@ -46,12 +47,13 @@ const (
)

const (
ErrEmpty string = "empty"
ErrTooShort string = "tooshort"
ErrTooLong string = "toolong"
ErrNotValid string = "notvalid"
ErrInactive string = "inactive"
ErrAlreadyExists string = "alreadyexists"
ErrEmpty string = "empty"
ErrTooShort string = "tooshort"
ErrTooLong string = "toolong"
ErrNotValid string = "notvalid"
ErrContainsSpecialChar string = "containsSpecialChar"
ErrInactive string = "inactive"
ErrAlreadyExists string = "alreadyexists"
)

var (
Expand All @@ -68,6 +70,7 @@ var (
ErrorUserUsernameIsTooShort error = errors.New(smodel.ErrBase + smodel.ErrSep + ErrUser + smodel.ErrSep + ErrUserName + smodel.ErrSep + ErrTooShort)
ErrorUserUsernameIsTooLong error = errors.New(smodel.ErrBase + smodel.ErrSep + ErrUser + smodel.ErrSep + ErrUserName + smodel.ErrSep + ErrTooLong)
ErrorUserUsernameIsNotValid error = errors.New(smodel.ErrBase + smodel.ErrSep + ErrUser + smodel.ErrSep + ErrUserName + smodel.ErrSep + ErrNotValid)
ErrorUserUsernameContainsSpecialChar error = errors.New(smodel.ErrBase + smodel.ErrSep + ErrUser + smodel.ErrSep + ErrUserName + smodel.ErrSep + ErrContainsSpecialChar)
ErrorUserEmailIsEmpty error = errors.New(smodel.ErrBase + smodel.ErrSep + ErrUser + smodel.ErrSep + ErrEmail + smodel.ErrSep + ErrEmpty)
ErrorUserEmailIsNotValid error = errors.New(smodel.ErrBase + smodel.ErrSep + ErrUser + smodel.ErrSep + ErrEmail + smodel.ErrSep + ErrNotValid)
ErrorUserEmailIsExists error = errors.New(smodel.ErrBase + smodel.ErrSep + ErrUser + smodel.ErrSep + ErrEmail + smodel.ErrSep + ErrAlreadyExists)
Expand Down
36 changes: 27 additions & 9 deletions internal/domain/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,43 @@ package domain

import (
"strings"
"unicode"

me "github.com/octoposprime/op-be-user/internal/domain/model/entity"
mo "github.com/octoposprime/op-be-user/internal/domain/model/object"
)

// This is the service layer of the domain layer.
// Service struct for user-related services
type Service struct {
}

// NewService creates a new *Service.
// NewService creates a new instance of Service
func NewService() *Service {
return &Service{}
}

// ValidateUser validates the user.
// ValidateUser validates the user based on certain criteria
func (s *Service) ValidateUser(user *me.User) error {
if err := user.Validate(); err != nil {
return err
}
return nil
}

// ValidatePassword validates the user password.
// ValidatePassword checks the validity of a user's password
func (s *Service) ValidatePassword(userPassword *me.UserPassword) error {
if err := userPassword.Validate(); err != nil {
return err
}
return nil
}

// ValidateToken validates the token.
// ValidateToken checks the validity of a token
func (s *Service) ValidateToken(token *mo.Token) error {
return token.Validate()
}

// CheckUserNameRules checks the rules for usernames
func (s *Service) CheckUserNameRules(user *me.User) error {
if user.UserName == "" {
return mo.ErrorUserUsernameIsEmpty
Expand All @@ -50,17 +52,31 @@ func (s *Service) CheckUserNameRules(user *me.User) error {
if strings.Contains(user.UserName, " ") {
return mo.ErrorUserUsernameIsNotValid
}
if !isValidUsername(user.UserName) {
return mo.ErrorUserUsernameContainsSpecialChar
}
return nil
}

func isValidUsername(username string) bool {
var hasLetterOrDigit bool
for _, ch := range username {
if unicode.IsLetter(ch) || unicode.IsDigit(ch) {
hasLetterOrDigit = true
}
if !unicode.IsLetter(ch) && !unicode.IsDigit(ch) && ch != '_' && ch != '.' {
return false
}
}
return hasLetterOrDigit // Make sure there is at least one alphanumeric character
}

// CheckEmailRules validates the email structure
func (s *Service) CheckEmailRules(user *me.User) error {
if user.Email == "" {
return mo.ErrorUserEmailIsEmpty
}
if !strings.Contains(user.Email, ".") {
return mo.ErrorUserEmailIsNotValid
}
if !strings.Contains(user.Email, "@") {
if !strings.Contains(user.Email, "@") || !strings.Contains(user.Email, ".") {
return mo.ErrorUserEmailIsNotValid
}
if strings.Contains(user.Email, " ") {
Expand All @@ -69,6 +85,7 @@ func (s *Service) CheckEmailRules(user *me.User) error {
return nil
}

// CheckPasswordRules checks the rules for passwords
func (s *Service) CheckPasswordRules(userPassword *me.UserPassword) error {
if userPassword.Password == "" {
return mo.ErrorUserPasswordIsEmpty
Expand All @@ -85,6 +102,7 @@ func (s *Service) CheckPasswordRules(userPassword *me.UserPassword) error {
return nil
}

// CheckIsAuthenticable checks if a user is authenticable based on their status
func (s *Service) CheckIsAuthenticable(user *me.User) error {
if user.UserStatus == mo.UserStatusINACTIVE {
return mo.ErrorUserIsInactive
Expand Down
106 changes: 104 additions & 2 deletions internal/domain/service/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,123 @@ package domain
import (
"testing"

"github.com/google/uuid"
me "github.com/octoposprime/op-be-user/internal/domain/model/entity"
mo "github.com/octoposprime/op-be-user/internal/domain/model/object"
)

func TestService_CheckUserNameRules(t *testing.T) {

type args struct {
user *me.User
}
tests := []struct {
name string
s *Service
args args
wantErr bool
}{
// TODO: Add test cases.
{
name: "Valid Username",
args: args{user: &me.User{
Id: uuid.UUID{},
User: mo.User{
UserName: "Qwe123_ee",
},
}},
wantErr: false,
},
{
name: "Username With Invalid Characters",
args: args{user: &me.User{
Id: uuid.UUID{},
User: mo.User{
UserName: "asd!^+.++dfghdr",
},
}},
wantErr: true,
},
{
name: "Username With Space",
args: args{user: &me.User{
Id: uuid.UUID{},
User: mo.User{
UserName: "user name",
},
}},
wantErr: true,
},
{
name: "Too Short Username",
args: args{user: &me.User{
Id: uuid.UUID{},
User: mo.User{
UserName: "short",
},
}},
wantErr: true,
},
{
name: "Too Long Username",
args: args{user: &me.User{
Id: uuid.UUID{},
User: mo.User{
UserName: "toolongusernameisdefinitelytoolong",
},
}},
wantErr: true,
},
{
name: "Valid Numeric Username",
args: args{user: &me.User{
Id: uuid.UUID{},
User: mo.User{
UserName: "12345678",
},
}},
wantErr: false,
},
{
name: "Valid Username With Period",
args: args{user: &me.User{
Id: uuid.UUID{},
User: mo.User{
UserName: "John.Doe",
},
}},
wantErr: false,
},
{
name: "Valid Username With Underscores",
args: args{user: &me.User{
Id: uuid.UUID{},
User: mo.User{
UserName: "valid_user123",
},
}},
wantErr: false,
},
{
name: "All Underscores",
args: args{user: &me.User{
Id: uuid.UUID{},
User: mo.User{
UserName: "________",
},
}},
wantErr: true,
},
{
name: "All Periods",
args: args{user: &me.User{
Id: uuid.UUID{},
User: mo.User{
UserName: "......",
},
}},
wantErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &Service{}
Expand Down

0 comments on commit 23c046a

Please sign in to comment.