Skip to content

Commit 0f61916

Browse files
fix(serviceaccount reset-credentials): validate serviceaccount ID in prompt (#720)
1 parent 98099ab commit 0f61916

File tree

4 files changed

+86
-2
lines changed

4 files changed

+86
-2
lines changed

pkg/cmd/serviceaccount/resetcredentials/reset_credentials.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
flagutil "github.com/redhat-developer/app-services-cli/pkg/cmdutil/flags"
1616
"github.com/redhat-developer/app-services-cli/pkg/iostreams"
1717
"github.com/redhat-developer/app-services-cli/pkg/serviceaccount/credentials"
18+
"github.com/redhat-developer/app-services-cli/pkg/serviceaccount/validation"
1819

1920
"github.com/redhat-developer/app-services-cli/internal/config"
2021
"github.com/redhat-developer/app-services-cli/pkg/cmd/factory"
@@ -70,6 +71,11 @@ func NewResetCredentialsCommand(f *factory.Factory) *cobra.Command {
7071
return flag.InvalidValueError("file-format", opts.fileFormat, flagutil.CredentialsOutputFormats...)
7172
}
7273

74+
validID := validation.ValidateUUID(opts.localizer)(opts.id)
75+
if validID != nil {
76+
return validID
77+
}
78+
7379
return runResetCredentials(opts)
7480
},
7581
}
@@ -217,7 +223,7 @@ func runInteractivePrompt(opts *Options) (err error) {
217223
Help: opts.localizer.MustLocalize("serviceAccount.resetCredentials.input.id.help"),
218224
}
219225

220-
err = survey.AskOne(promptID, &opts.id, survey.WithValidator(survey.Required))
226+
err = survey.AskOne(promptID, &opts.id, survey.WithValidator(survey.Required), survey.WithValidator(validation.ValidateUUID(opts.localizer)))
221227
if err != nil {
222228
return err
223229
}

pkg/localize/locales/en/cmd/serviceaccount.en.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,7 @@ one = 'invalid service account name "{{.Name}}"; only lowercase letters (a-z), n
8686
one = 'invalid service account description: only alphanumeric characters and "-", ".", "," are accepted.'
8787

8888
[serviceAccount.common.validation.description.error.lengthError]
89-
one = 'service account description cannot exceed {{.MaxLen}} characters'
89+
one = 'service account description cannot exceed {{.MaxLen}} characters'
90+
91+
[serviceAccount.common.validation.id.error.invalidID]
92+
one = '"{{.ID}}" is not a valid UUID'

pkg/serviceaccount/validation/validation.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ import (
66
"regexp"
77

88
"github.com/redhat-developer/app-services-cli/pkg/common/commonerr"
9+
"github.com/redhat-developer/app-services-cli/pkg/localize"
910
)
1011

1112
const (
1213
// name validation rules
1314
legalNameChars = "^[a-z]([-a-z0-9]*[a-z0-9])?$"
1415
maxNameLength = 50
1516
minNameLength = 1
17+
legalUUID = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
1618
// description validation rules
1719
legalDescriptionChars = "^[a-zA-Z0-9.,\\-\\s]*$"
1820
maxDescriptionLength = 255
@@ -63,3 +65,22 @@ func ValidateDescription(val interface{}) error {
6365

6466
return errors.New(`invalid service account description; only alphanumeric characters and "-", ".", "," are accepted`)
6567
}
68+
69+
// ValidateUUID validates if ID is a valid UUID
70+
func ValidateUUID(localizer localize.Localizer) func(v interface{}) error {
71+
return func(val interface{}) error {
72+
id, ok := val.(string)
73+
if !ok {
74+
return commonerr.NewCastError(val, "string")
75+
}
76+
77+
matched, _ := regexp.Match(legalUUID, []byte(id))
78+
79+
if matched {
80+
return nil
81+
}
82+
83+
return errors.New(localizer.MustLocalize("serviceAccount.common.validation.id.error.invalidID", localize.NewEntry("ID", id)))
84+
}
85+
86+
}

pkg/serviceaccount/validation/validation_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package validation
22

33
import (
44
"testing"
5+
6+
"github.com/redhat-developer/app-services-cli/pkg/localize/goi18n"
57
)
68

79
func TestValidateName(t *testing.T) {
@@ -69,6 +71,58 @@ func TestValidateName(t *testing.T) {
6971
}
7072
}
7173

74+
func TestValidateUUID(t *testing.T) {
75+
type args struct {
76+
val interface{}
77+
}
78+
tests := []struct {
79+
name string
80+
args args
81+
wantErr bool
82+
}{
83+
{
84+
name: "fails when length is 5",
85+
args: args{"kafka"},
86+
wantErr: true,
87+
},
88+
{
89+
name: "fails for empty string",
90+
args: args{""},
91+
wantErr: true,
92+
},
93+
{
94+
name: "fails for special chars",
95+
args: args{"9e4d1b1f-19d*-47c2-a334-e420c5e5bbce"},
96+
wantErr: true,
97+
},
98+
{
99+
name: "passes for valid UUID",
100+
args: args{"9e4d1b1f-19dd-47c2-a334-e420c5e5bbce"},
101+
wantErr: false,
102+
},
103+
{
104+
name: "passes for numeric UUID",
105+
args: args{"11111111-2222-3333-4444-555555555555"},
106+
wantErr: false,
107+
},
108+
{
109+
name: "fails for ID containing capital letters",
110+
args: args{"9e4d1b1f-19dd-47c2-A334-e420c5e5bbce"},
111+
wantErr: true,
112+
},
113+
}
114+
115+
localizer, _ := goi18n.New(nil)
116+
// nolint:scopelint
117+
for _, tt := range tests {
118+
t.Run(tt.name, func(t *testing.T) {
119+
if err := ValidateUUID(localizer)(tt.args.val); (err != nil) != tt.wantErr {
120+
t.Errorf("ValidateUUID() error = %v, wantErr %v", err, tt.wantErr)
121+
}
122+
})
123+
}
124+
}
125+
72126
func TestValidateDescription(t *testing.T) {
73127
type args struct {
74128
val interface{}

0 commit comments

Comments
 (0)