Skip to content

Commit b253a1e

Browse files
authored
User prompt input validation (#226)
* user prompt input validation * adds support for regex validation from modules
1 parent 6f16cef commit b253a1e

File tree

5 files changed

+54
-14
lines changed

5 files changed

+54
-14
lines changed

internal/apply/apply.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,9 @@ func applyAll(dir string, projectConfig projectconfig.ZeroProjectConfig, applyEn
101101
// promptEnvironments Prompts the user for the environments to apply against and returns a slice of strings representing the environments
102102
func promptEnvironments() []string {
103103
items := map[string][]string{
104-
"Staging ": {"staging"},
105-
"Production": {"production"},
106-
"Both Staging and Production": {"staging", "production"},
104+
"Staging ": {"stage"},
105+
"Production": {"prod"},
106+
"Both Staging and Production": {"stage", "prod"},
107107
}
108108

109109
var labels []string

internal/config/moduleconfig/module_config.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,20 @@ type ModuleConfig struct {
1717
}
1818

1919
type Parameter struct {
20-
Field string
21-
Label string `yaml:"label,omitempty"`
22-
Options []string `yaml:"options,omitempty"`
23-
Execute string `yaml:"execute,omitempty"`
24-
Value string `yaml:"value,omitempty"`
25-
Default string `yaml:"default,omitempty"`
26-
Info string `yaml:"info,omitempty"`
20+
Field string
21+
Label string `yaml:"label,omitempty"`
22+
Options []string `yaml:"options,omitempty"`
23+
Execute string `yaml:"execute,omitempty"`
24+
Value string `yaml:"value,omitempty"`
25+
Default string `yaml:"default,omitempty"`
26+
Info string `yaml:"info,omitempty"`
27+
FieldValidation Validate `yaml:"fieldValidation,omitempty"`
28+
}
29+
30+
type Validate struct {
31+
Type string `yaml:"type,omitempty"`
32+
Value string `yaml:"value,omitempty"`
33+
ErrorMessage string `yaml:"errorMessage,omitempty"`
2734
}
2835

2936
type TemplateConfig struct {

internal/constants/constants.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,10 @@ const (
88
ZeroHomeDirectory = ".zero"
99
IgnoredPaths = "(?i)zero.module.yml|.git/"
1010
TemplateExtn = ".tmpl"
11+
12+
// prompt constants
13+
14+
MaxPnameLength = 16
15+
RegexValidation = "regex"
16+
FunctionValidation = "function"
1117
)

internal/init/init.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ func getProjectNamePrompt() PromptHandler {
125125
Default: "",
126126
},
127127
Condition: NoCondition,
128-
Validate: NoValidation,
128+
Validate: ValidateProjectName,
129129
}
130130
}
131131

internal/init/prompts.go

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"github.com/commitdev/zero/internal/config/globalconfig"
1313
"github.com/commitdev/zero/internal/config/moduleconfig"
14+
"github.com/commitdev/zero/internal/constants"
1415
"github.com/commitdev/zero/internal/util"
1516
"github.com/commitdev/zero/pkg/credentials"
1617
"github.com/commitdev/zero/pkg/util/exit"
@@ -88,7 +89,20 @@ func ValidateSAK(input string) error {
8889
return nil
8990
}
9091

91-
// TODO: validation / allow prompt retry ...etc
92+
// ValidateProjectName validates Project Name field user input.
93+
func ValidateProjectName(input string) error {
94+
// the first 62 char out of base64 and -
95+
var pName = regexp.MustCompile(`^[A-Za-z0-9-]{1,16}$`)
96+
if !pName.MatchString(input) {
97+
// error if char len is greater than 16
98+
if len(input) > constants.MaxPnameLength {
99+
return errors.New("Invalid, Project Name: (cannot exceed a max length of 16)")
100+
}
101+
return errors.New("Invalid, Project Name: (can only contain alphanumeric chars & '-')")
102+
}
103+
return nil
104+
}
105+
92106
func (p PromptHandler) GetParam(projectParams map[string]string) string {
93107
var err error
94108
var result string
@@ -170,18 +184,31 @@ func sanitizeParameterValue(str string) string {
170184

171185
// PromptParams renders series of prompt UI based on the config
172186
func PromptModuleParams(moduleConfig moduleconfig.ModuleConfig, parameters map[string]string, projectCredentials globalconfig.ProjectCredential) (map[string]string, error) {
173-
174187
credentialEnvs := projectCredentials.SelectedVendorsCredentialsAsEnv(moduleConfig.RequiredCredentials)
175188
for _, promptConfig := range moduleConfig.Parameters {
176189
// deduplicate fields already prompted and received
177190
if _, isAlreadySet := parameters[promptConfig.Field]; isAlreadySet {
178191
continue
179192
}
180193

194+
var validateFunc func(input string) error = nil
195+
196+
// type:regex field validation for zero-module.yaml
197+
if promptConfig.FieldValidation.Type == constants.RegexValidation {
198+
validateFunc = func(input string) error {
199+
var regexRule = regexp.MustCompile(promptConfig.FieldValidation.Value)
200+
if !regexRule.MatchString(input) {
201+
return errors.New(promptConfig.FieldValidation.ErrorMessage)
202+
}
203+
return nil
204+
}
205+
}
206+
// TODO: type:fuction field validation for zero-module.yaml
207+
181208
promptHandler := PromptHandler{
182209
Parameter: promptConfig,
183210
Condition: NoCondition,
184-
Validate: NoValidation,
211+
Validate: validateFunc,
185212
}
186213
// merging the context of param and credentals
187214
// this treats credentialEnvs as throwaway, parameters is shared between modules

0 commit comments

Comments
 (0)