feat: add WeakStringList type to support lists in aud claim
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
This commit is contained in:
parent
78b9c98c5c
commit
97fa1183bf
2 changed files with 140 additions and 0 deletions
55
registry/auth/token/types.go
Normal file
55
registry/auth/token/types.go
Normal file
|
@ -0,0 +1,55 @@
|
|||
package token
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// WeakStringList is a slice of strings that can be deserialized from either a single string value or a list of strings.
|
||||
type WeakStringList []string
|
||||
|
||||
func (s *WeakStringList) UnmarshalJSON(data []byte) (err error) {
|
||||
var value interface{}
|
||||
|
||||
if err = json.Unmarshal(data, &value); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
*s = []string{v}
|
||||
|
||||
case []string:
|
||||
*s = v
|
||||
|
||||
case []interface{}:
|
||||
var ss []string
|
||||
|
||||
for _, vv := range v {
|
||||
vs, ok := vv.(string)
|
||||
if !ok {
|
||||
return &json.UnsupportedTypeError{
|
||||
Type: reflect.TypeOf(vv),
|
||||
}
|
||||
}
|
||||
|
||||
ss = append(ss, vs)
|
||||
}
|
||||
|
||||
*s = ss
|
||||
|
||||
case nil:
|
||||
return nil
|
||||
|
||||
default:
|
||||
return &json.UnsupportedTypeError{
|
||||
Type: reflect.TypeOf(v),
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s WeakStringList) MarshalJSON() (b []byte, err error) {
|
||||
return json.Marshal([]string(s))
|
||||
}
|
85
registry/auth/token/types_test.go
Normal file
85
registry/auth/token/types_test.go
Normal file
|
@ -0,0 +1,85 @@
|
|||
package token
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestWeakStringList_Unmarshal(t *testing.T) {
|
||||
t.Run("OK", func(t *testing.T) {
|
||||
testCases := []struct {
|
||||
value string
|
||||
expected WeakStringList
|
||||
}{
|
||||
{
|
||||
value: `"audience"`,
|
||||
expected: WeakStringList{"audience"},
|
||||
},
|
||||
{
|
||||
value: `["audience1", "audience2"]`,
|
||||
expected: WeakStringList{"audience1", "audience2"},
|
||||
},
|
||||
{
|
||||
value: `null`,
|
||||
expected: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
testCase := testCase
|
||||
|
||||
t.Run("", func(t *testing.T) {
|
||||
var actual WeakStringList
|
||||
|
||||
err := json.Unmarshal([]byte(testCase.value), &actual)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assertStringListEqual(t, testCase.expected, actual)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Error", func(t *testing.T) {
|
||||
var actual WeakStringList
|
||||
|
||||
err := json.Unmarshal([]byte("1234"), &actual)
|
||||
if err == nil {
|
||||
t.Fatal("expected unmarshal to fail")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestWeakStringList_Marshal(t *testing.T) {
|
||||
value := WeakStringList{"audience"}
|
||||
|
||||
expected := `["audience"]`
|
||||
|
||||
actual, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if expected != string(actual) {
|
||||
t.Errorf("expected marshaled list to be %v, got %v", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func assertStringListEqual(t *testing.T, expected []string, actual []string) {
|
||||
t.Helper()
|
||||
|
||||
if len(expected) != len(actual) {
|
||||
t.Errorf("length mismatch: expected %d long slice, got %d", len(expected), len(actual))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
for i, v := range expected {
|
||||
if v != actual[i] {
|
||||
t.Errorf("expected %d. item to be %q, got %q", i, v, actual[i])
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue