From 508183a1b360db9044dd966dae5e6dda6f7cd47d Mon Sep 17 00:00:00 2001 From: Chris Hoffman Date: Mon, 17 Jul 2017 11:39:58 -0700 Subject: [PATCH] Add field type TypeNameString (#3028) --- logical/framework/field_data.go | 18 ++++++- logical/framework/field_data_test.go | 79 ++++++++++++++++++++++++++++ logical/framework/field_type.go | 7 +++ 3 files changed, 103 insertions(+), 1 deletion(-) diff --git a/logical/framework/field_data.go b/logical/framework/field_data.go index 97838028c6..3226521f7d 100644 --- a/logical/framework/field_data.go +++ b/logical/framework/field_data.go @@ -2,7 +2,9 @@ package framework import ( "encoding/json" + "errors" "fmt" + "regexp" "github.com/hashicorp/vault/helper/parseutil" "github.com/hashicorp/vault/helper/strutil" @@ -108,7 +110,7 @@ func (d *FieldData) GetOkErr(k string) (interface{}, bool, error) { switch schema.Type { case TypeBool, TypeInt, TypeMap, TypeDurationSecond, TypeString, - TypeSlice, TypeStringSlice, TypeCommaStringSlice: + TypeNameString, TypeSlice, TypeStringSlice, TypeCommaStringSlice: return d.getPrimitive(k, schema) default: return nil, false, @@ -145,6 +147,20 @@ func (d *FieldData) getPrimitive( } return result, true, nil + case TypeNameString: + var result string + if err := mapstructure.WeakDecode(raw, &result); err != nil { + return nil, true, err + } + matched, err := regexp.MatchString("^\\w(([\\w-.]+)?\\w)?$", result) + if err != nil { + return nil, true, err + } + if !matched { + return nil, true, errors.New("field does not match the formatting rules") + } + return result, true, nil + case TypeMap: var result map[string]interface{} if err := mapstructure.WeakDecode(raw, &result); err != nil { diff --git a/logical/framework/field_data_test.go b/logical/framework/field_data_test.go index 6bb83fd8ac..c25fcde8ce 100644 --- a/logical/framework/field_data_test.go +++ b/logical/framework/field_data_test.go @@ -256,6 +256,28 @@ func TestFieldDataGet(t *testing.T) { "foo", []string{}, }, + + "name string type, valid string": { + map[string]*FieldSchema{ + "foo": &FieldSchema{Type: TypeNameString}, + }, + map[string]interface{}{ + "foo": "bar", + }, + "foo", + "bar", + }, + + "name string type, valid value with special characters": { + map[string]*FieldSchema{ + "foo": &FieldSchema{Type: TypeNameString}, + }, + map[string]interface{}{ + "foo": "bar.baz-bay123", + }, + "foo", + "bar.baz-bay123", + }, } for name, tc := range cases { @@ -272,3 +294,60 @@ func TestFieldDataGet(t *testing.T) { } } } + +func TestFieldDataGet_Error(t *testing.T) { + cases := map[string]struct { + Schema map[string]*FieldSchema + Raw map[string]interface{} + Key string + }{ + "name string type, invalid value with invalid characters": { + map[string]*FieldSchema{ + "foo": &FieldSchema{Type: TypeNameString}, + }, + map[string]interface{}{ + "foo": "bar baz", + }, + "foo", + }, + "name string type, invalid value with special characters at beginning": { + map[string]*FieldSchema{ + "foo": &FieldSchema{Type: TypeNameString}, + }, + map[string]interface{}{ + "foo": ".barbaz", + }, + "foo", + }, + "name string type, invalid value with special characters at end": { + map[string]*FieldSchema{ + "foo": &FieldSchema{Type: TypeNameString}, + }, + map[string]interface{}{ + "foo": "barbaz-", + }, + "foo", + }, + "name string type, empty string": { + map[string]*FieldSchema{ + "foo": &FieldSchema{Type: TypeNameString}, + }, + map[string]interface{}{ + "foo": "", + }, + "foo", + }, + } + + for _, tc := range cases { + data := &FieldData{ + Raw: tc.Raw, + Schema: tc.Schema, + } + + _, _, err := data.GetOkErr(tc.Key) + if err == nil { + t.Fatalf("error expected, none received") + } + } +} diff --git a/logical/framework/field_type.go b/logical/framework/field_type.go index 034d0fe596..304d45ff0e 100644 --- a/logical/framework/field_type.go +++ b/logical/framework/field_type.go @@ -23,12 +23,19 @@ const ( // slice of strings and also supports parsing a comma-separated list in // a string field TypeCommaStringSlice + + // TypeNameString represents a name that is URI safe and follows specific + // rules. These rules include start and end with an alphanumeric + // character and characters in the middle can be alphanumeric or . or -. + TypeNameString ) func (t FieldType) String() string { switch t { case TypeString: return "string" + case TypeNameString: + return "name string" case TypeInt: return "int" case TypeBool: