From 31bc1ace97a8e776b73af3953c41a3c0b8bda07c Mon Sep 17 00:00:00 2001
From: David McKay <david@rawkode.com>
Date: Mon, 8 Aug 2016 10:54:36 +0100
Subject: [PATCH] Added a new validate class, AlphanumericExt, that allows a
 few extra characters ontop of regular Alphanumeric validation. Closes #17
 (#25)

---
 pkg/cmd/delete.go                         |  2 +-
 pkg/cmd/download.go                       |  2 +-
 pkg/cmd/save.go                           |  2 +-
 pkg/util/validate/pattern/pattern.go      | 13 +++++++++----
 pkg/util/validate/pattern/pattern_test.go | 22 ++++++++++++++++++++++
 pkg/util/validate/string.go               |  6 ++++++
 6 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/pkg/cmd/delete.go b/pkg/cmd/delete.go
index 2ea82d1..48c8d55 100644
--- a/pkg/cmd/delete.go
+++ b/pkg/cmd/delete.go
@@ -18,7 +18,7 @@ var Delete = &cli.Command{
 	Use:   "delete <template-tag>",
 	Short: "Delete a project template from the template registry",
 	Run: func(c *cli.Command, args []string) {
-		MustValidateVarArgs(args, validate.Argument{"template-path", validate.Alphanumeric})
+		MustValidateVarArgs(args, validate.Argument{"template-path", validate.AlphanumericExt})
 
 		MustValidateTemplateDir()
 
diff --git a/pkg/cmd/download.go b/pkg/cmd/download.go
index aaa7382..a04893f 100644
--- a/pkg/cmd/download.go
+++ b/pkg/cmd/download.go
@@ -103,7 +103,7 @@ var Download = &cli.Command{
 
 		MustValidateArgs(args, []validate.Argument{
 			{"template-repo", validate.UnixPath},
-			{"template-tag", validate.Alphanumeric},
+			{"template-tag", validate.AlphanumericExt},
 		})
 
 		MustValidateTemplateDir()
diff --git a/pkg/cmd/save.go b/pkg/cmd/save.go
index f2d7635..973bcfe 100644
--- a/pkg/cmd/save.go
+++ b/pkg/cmd/save.go
@@ -21,7 +21,7 @@ var Save = &cli.Command{
 	Run: func(c *cli.Command, args []string) {
 		MustValidateArgs(args, []validate.Argument{
 			{"template-path", validate.UnixPath},
-			{"template-tag", validate.Alphanumeric},
+			{"template-tag", validate.AlphanumericExt},
 		})
 
 		MustValidateTemplateDir()
diff --git a/pkg/util/validate/pattern/pattern.go b/pkg/util/validate/pattern/pattern.go
index 5604e8d..7efacf1 100644
--- a/pkg/util/validate/pattern/pattern.go
+++ b/pkg/util/validate/pattern/pattern.go
@@ -8,10 +8,11 @@ const (
 	email    = "^(((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$"
 	unixPath = `^((\/)|(?:\/*[a-zA-Z0-9\.\:]+(?:_[a-zA-Z0-9\:\.]+)*(?:\-[\:a-zA-Z0-9\.]+)*)+\/?)$`
 
-	alpha        = "^[a-zA-Z]+$"
-	alphanumeric = "^[a-zA-Z0-9]+$"
-	integer      = "^[-+]?(0|[1-9][0-9]*)$"
-	numeric      = "^[-+]?[0-9]+$"
+	alpha           = "^[a-zA-Z]+$"
+	alphanumeric    = "^[a-zA-Z0-9]+$"
+	integer         = "^[-+]?(0|[1-9][0-9]*)$"
+	numeric         = "^[-+]?[0-9]+$"
+	alphanumericext = "^[a-zA-Z0-9-_]+$"
 )
 
 var (
@@ -21,6 +22,10 @@ var (
 	// Alphanumeric regular expression for alphanumeric strings.
 	Alphanumeric = regexp.MustCompile(alphanumeric)
 
+	// AlphanumericExt regular expression for alphanumeric strings plus
+	// certain allowed characters.
+	AlphanumericExt = regexp.MustCompile(alphanumericext)
+
 	// Email regular expression for e-mail strings.
 	Email = regexp.MustCompile(email)
 
diff --git a/pkg/util/validate/pattern/pattern_test.go b/pkg/util/validate/pattern/pattern_test.go
index c6750b3..3839b94 100644
--- a/pkg/util/validate/pattern/pattern_test.go
+++ b/pkg/util/validate/pattern/pattern_test.go
@@ -48,6 +48,28 @@ func TestAlphanumericPattern(t *testing.T) {
 	}
 }
 
+func TestAlphanumericExtPattern(t *testing.T) {
+	tests := []struct {
+		String string
+		Valid  bool
+	}{
+		{" ", false},
+		{"/", false},
+		{"root", true},
+		{"tmp-dir", true},
+		{"tmp-dir_now", true},
+		{"TMPDIR", true},
+		{"L33T", true},
+		{"L@@T", false},
+	}
+
+	for _, test := range tests {
+		if ok := pattern.AlphanumericExt.MatchString(test.String); ok != test.Valid {
+			t.Errorf("pattern.AlphanumericExt.MatchString(%q) expected to be %v", test.String, test.Valid)
+		}
+	}
+}
+
 func TestIntegerPattern(t *testing.T) {
 	tests := []struct {
 		String string
diff --git a/pkg/util/validate/string.go b/pkg/util/validate/string.go
index 547e24e..f1dd0f1 100644
--- a/pkg/util/validate/string.go
+++ b/pkg/util/validate/string.go
@@ -37,3 +37,9 @@ func UnixPath(path string) bool {
 func Alphanumeric(s string) bool {
 	return pattern.Alphanumeric.MatchString(s)
 }
+
+// AlphanumericExt validates whether a string is an alphanumeric string, but a
+// small set of extra characters allowed
+func AlphanumericExt(s string) bool {
+	return pattern.AlphanumericExt.MatchString(s)
+}
-- 
GitLab