diff --git a/pkg/utils/helper.go b/pkg/utils/helper.go index 612f814f..31f06c9b 100644 --- a/pkg/utils/helper.go +++ b/pkg/utils/helper.go @@ -1,7 +1,10 @@ package utils import ( + "errors" "fmt" + "regexp" + "strconv" "strings" "time" ) @@ -40,3 +43,82 @@ func FormatSize(size int64) string { mbSize := float64(size) / (1024 * 1024) return fmt.Sprintf("%.2fMiB", mbSize) } + +func ValidateUserName(username string) bool { + pattern := `^[a-zA-Z0-9]{1,255}$` + re := regexp.MustCompile(pattern) + return re.MatchString(username) +} + +func ValidateEmail(email string) bool { + pattern := `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$` + re := regexp.MustCompile(pattern) + return re.MatchString(email) +} + +func ValidateFL(name string) bool { + pattern := `^[A-Za-z]{1,20}\s[A-Za-z]{1,20}$` + re := regexp.MustCompile(pattern) + return re.MatchString(name) +} + +// check if the password format is vaild +func ValidatePassword(password string) error { + if len(password) < 8 || len(password) > 256 { + return errors.New("worong! the password length must be at least 8 characters and at most 256 characters") + } + // checking the password has a minimum of one lower case letter + if done, _ := regexp.MatchString("([a-z])+", password); !done { + return errors.New("worong! the password doesn't have a lowercase letter") + } + + // checking the password has a minimmum of one upper case letter + if done, _ := regexp.MatchString("([A-Z])+", password); !done { + return errors.New("worong! the password doesn't have an upppercase letter") + } + + // checking if the password has a minimum of one digit + if done, _ := regexp.Match("([0-9])+", []byte(password)); !done { + return errors.New("worong! the password doesn't have a digit number") + } + + return nil +} + +// check if the tag name is valid +func ValidateTagName(tagName string) bool { + pattern := `^[\w][\w.-]{0,127}$` + + re := regexp.MustCompile(pattern) + + return re.MatchString(tagName) +} + +// check if the project name is valid +func ValidateProjectName(projectName string) bool { + pattern := `^[a-z0-9][a-z0-9._-]{0,254}$` + + re := regexp.MustCompile(pattern) + + return re.MatchString(projectName) +} + +func ValidateStorageLimit(sl string) error { + storageLimit, err := strconv.Atoi(sl) + if err != nil { + return errors.New("the storage limit only takes integer values") + } + + if storageLimit < -1 || (storageLimit > -1 && storageLimit < 0) || storageLimit > 1024 { + return errors.New("the maximum value for the storage cannot exceed 1024 terabytes and -1 for no limit") + } + return nil +} + +func ValidateRegistryName(rn string) bool { + pattern := `^[\w][\w.-]{0,63}$` + + re := regexp.MustCompile(pattern) + + return re.MatchString(rn) +} diff --git a/pkg/views/artifact/tags/create/view.go b/pkg/views/artifact/tags/create/view.go index dd7449e4..011024df 100644 --- a/pkg/views/artifact/tags/create/view.go +++ b/pkg/views/artifact/tags/create/view.go @@ -2,8 +2,10 @@ package create import ( "errors" + "strings" "github.com/charmbracelet/huh" + "github.com/goharbor/harbor-cli/pkg/utils" log "github.com/sirupsen/logrus" ) @@ -16,8 +18,11 @@ func CreateTagView(tagName *string) { Title("Tag Name"). Value(tagName). Validate(func(str string) error { - if str == "" { - return errors.New("project name cannot be empty") + if strings.TrimSpace(str) == "" { + return errors.New("tag name cannot be empty or only spaces") + } + if isVaild := utils.ValidateTagName(str); !isVaild { + return errors.New("please enter the correct tag name format") } return nil }), diff --git a/pkg/views/login/create.go b/pkg/views/login/create.go index 36e30ad6..b0b9a4e9 100644 --- a/pkg/views/login/create.go +++ b/pkg/views/login/create.go @@ -2,8 +2,11 @@ package login import ( "errors" + "net/url" + "strings" "github.com/charmbracelet/huh" + "github.com/goharbor/harbor-cli/pkg/utils" log "github.com/sirupsen/logrus" ) @@ -22,8 +25,12 @@ func CreateView(loginView *LoginView) { Title("Server"). Value(&loginView.Server). Validate(func(str string) error { - if str == "" { - return errors.New("server cannot be empty") + if strings.TrimSpace(str) == "" { + return errors.New("server cannot be empty or only spaces") + } + formattedUrl := utils.FormatUrl(str) + if _, err := url.ParseRequestURI(formattedUrl); err != nil { + return errors.New("please enter the correct server format") } return nil }), @@ -31,8 +38,11 @@ func CreateView(loginView *LoginView) { Title("User Name"). Value(&loginView.Username). Validate(func(str string) error { - if str == "" { - return errors.New("username cannot be empty") + if strings.TrimSpace(str) == "" { + return errors.New("username cannot be empty or only spaces") + } + if isValid := utils.ValidateUserName(str); !isValid { + return errors.New("please enter correct username format") } return nil }), @@ -41,14 +51,23 @@ func CreateView(loginView *LoginView) { EchoMode(huh.EchoModePassword). Value(&loginView.Password). Validate(func(str string) error { - if str == "" { - return errors.New("password cannot be empty") + if strings.TrimSpace(str) == "" { + return errors.New("password cannot be empty or only spaces") + } + if err := utils.ValidatePassword(str); err != nil { + return err } return nil }), huh.NewInput(). Title("Name of Credential"). - Value(&loginView.Name), + Value(&loginView.Name). + Validate(func(str string) error { + if str == "" { + return errors.New("credential name cannot be empty") + } + return nil + }), ), ).WithTheme(theme).Run() diff --git a/pkg/views/project/create/view.go b/pkg/views/project/create/view.go index 484c0a05..89ea0c79 100644 --- a/pkg/views/project/create/view.go +++ b/pkg/views/project/create/view.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "strings" "github.com/charmbracelet/huh" "github.com/goharbor/go-client/pkg/sdk/v2.0/client/registry" @@ -55,8 +56,11 @@ func CreateProjectView(createView *CreateView) { Title("Project Name"). Value(&createView.ProjectName). Validate(func(str string) error { - if str == "" { - return errors.New("project name cannot be empty") + if strings.TrimSpace(str) == "" { + return errors.New("project name cannot be empty or only spaces") + } + if isValid := utils.ValidateProjectName(str); !isValid { + return errors.New("please enter correct project name format") } return nil }), @@ -70,6 +74,12 @@ func CreateProjectView(createView *CreateView) { Value(&createView.StorageLimit). Validate(func(str string) error { // Assuming StorageLimit is an int64 + if strings.TrimSpace(str) == "" { + return errors.New("storage limit cannot be empty or only spaces") + } + if err := utils.ValidateStorageLimit(str); err != nil { + return err + } return nil }), diff --git a/pkg/views/registry/create/view.go b/pkg/views/registry/create/view.go index 3bb6aed4..ff090ec5 100644 --- a/pkg/views/registry/create/view.go +++ b/pkg/views/registry/create/view.go @@ -2,10 +2,13 @@ package create import ( "errors" + "net/url" "strconv" + "strings" "github.com/charmbracelet/huh" "github.com/goharbor/harbor-cli/pkg/api" + "github.com/goharbor/harbor-cli/pkg/utils" log "github.com/sirupsen/logrus" ) @@ -58,8 +61,11 @@ func CreateRegistryView(createView *api.CreateRegView) { Title("Name"). Value(&createView.Name). Validate(func(str string) error { - if str == "" { - return errors.New("name cannot be empty") + if strings.TrimSpace(str) == "" { + return errors.New("name cannot be empty or only spaces") + } + if isVaild := utils.ValidateRegistryName(str); !isVaild { + return errors.New("please enter the correct name format") } return nil }), @@ -70,8 +76,12 @@ func CreateRegistryView(createView *api.CreateRegView) { Title("URL"). Value(&createView.URL). Validate(func(str string) error { - if str == "" { - return errors.New("url cannot be empty") + if strings.TrimSpace(str) == "" { + return errors.New("url cannot be empty or only spaces") + } + formattedUrl := utils.FormatUrl(str) + if _, err := url.ParseRequestURI(formattedUrl); err != nil { + return errors.New("please enter the correct url format") } return nil }), diff --git a/pkg/views/user/create/view.go b/pkg/views/user/create/view.go index bf671c06..e52b3498 100644 --- a/pkg/views/user/create/view.go +++ b/pkg/views/user/create/view.go @@ -2,8 +2,10 @@ package create import ( "errors" + "strings" "github.com/charmbracelet/huh" + "github.com/goharbor/harbor-cli/pkg/utils" log "github.com/sirupsen/logrus" ) @@ -23,17 +25,23 @@ func CreateUserView(createView *CreateView) { Title("User Name"). Value(&createView.Username). Validate(func(str string) error { - if str == "" { + if strings.TrimSpace(str) == "" { return errors.New("user name cannot be empty") } + if isVaild := utils.ValidateUserName(str); !isVaild { + return errors.New("username cannot contain special characters") + } return nil }), huh.NewInput(). Title("Email"). Value(&createView.Email). Validate(func(str string) error { - if str == "" { - return errors.New("email cannot be empty") + if strings.TrimSpace(str) == "" { + return errors.New("email cannot be empty or only spaces") + } + if isVaild := utils.ValidateEmail(str); !isVaild { + return errors.New("please enter correct email format") } return nil }), @@ -42,9 +50,12 @@ func CreateUserView(createView *CreateView) { Title("First and Last Name"). Value(&createView.Realname). Validate(func(str string) error { - if str == "" { + if strings.TrimSpace(str) == "" { return errors.New("real name cannot be empty") } + if isValid := utils.ValidateFL(str); !isValid { + return errors.New("please enter correct first and last name format, like `Bob Dylan`") + } return nil }), huh.NewInput(). @@ -52,8 +63,11 @@ func CreateUserView(createView *CreateView) { EchoMode(huh.EchoModePassword). Value(&createView.Password). Validate(func(str string) error { - if str == "" { - return errors.New("password cannot be empty") + if strings.TrimSpace(str) == "" { + return errors.New("password cannot be empty or only spaces") + } + if err := utils.ValidatePassword(str); err != nil { + return err } return nil }),