Repository: lestrrat-go/jwx
Pull request #503 (2021-11-25 22:59:08)

[jwk] Add a Set() method to jwk.Set

codecov-commenter: # [Codecov](https://codecov.io/gh/lestrrat-go/jwx/pull/503?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lestrrat-go) Report
> Merging [#503](https://codecov.io/gh/lestrrat-go/jwx/pull/503?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lestrrat-go) (1a1bad7) into [main](https://codecov.io/gh/lestrrat-go/jwx/commit/1a1ea73babfe57e6ae3a86bca256d2a46ab7efb2?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lestrrat-go) (1a1ea73) will **decrease** coverage by `0.02%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/lestrrat-go/jwx/pull/503/graphs/tree.svg?width=650&height=150&src=pr&token=kU2RSDosPt&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lestrrat-go)](https://codecov.io/gh/lestrrat-go/jwx/pull/503?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lestrrat-go)

```diff
@@            Coverage Diff             @@
##             main     #503      +/-   ##
==========================================
- Coverage   72.61%   72.58%   -0.03%     
==========================================
  Files          80       77       -3     
  Lines        9270     9268       -2     
==========================================
- Hits         6731     6727       -4     
- Misses       1731     1733       +2     
  Partials      808      808              
```


| [Impacted Files](https://codecov.io/gh/lestrrat-go/jwx/pull/503?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lestrrat-go) | Coverage Δ | |
|---|---|---|
| [jwk/set.go](https://codecov.io/gh/lestrrat-go/jwx/pull/503/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lestrrat-go#diff-andrL3NldC5nbw==) | `83.22% <100.00%> (+1.20%)` | :arrow_up: |
| [internal/ecutil/ecutil.go](https://codecov.io/gh/lestrrat-go/jwx/pull/503/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lestrrat-go#diff-aW50ZXJuYWwvZWN1dGlsL2VjdXRpbC5nbw==) | `76.92% <0.00%> (-5.13%)` | :arrow_down: |
| [jwa/secp2561k.go](https://codecov.io/gh/lestrrat-go/jwx/pull/503/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lestrrat-go#diff-andhL3NlY3AyNTYxay5nbw==) | | |
| [internal/json/stdlib.go](https://codecov.io/gh/lestrrat-go/jwx/pull/503/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lestrrat-go#diff-aW50ZXJuYWwvanNvbi9zdGRsaWIuZ28=) | | |
| [jwk/es256k.go](https://codecov.io/gh/lestrrat-go/jwx/pull/503/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lestrrat-go#diff-andrL2VzMjU2ay5nbw==) | | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/lestrrat-go/jwx/pull/503?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lestrrat-go).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lestrrat-go)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/lestrrat-go/jwx/pull/503?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lestrrat-go). Last update [1a1ea73...1a1bad7](https://codecov.io/gh/lestrrat-go/jwx/pull/503?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lestrrat-go). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lestrrat-go).


Patch:
diff --git a/jwk/interface.go b/jwk/interface.go
index b8504c69..9a0fc90d 100644
--- a/jwk/interface.go
+++ b/jwk/interface.go
@@ -57,10 +57,13 @@ const (
 type Set interface {
 	// Add adds the specified key. If the key already exists in the set, it is
 	// not added.
+	// This method will be renamed to `AddKey(Key)` in a future major release.
 	Add(Key) bool
 
 	// Clear resets the list of keys associated with this set, emptying the
 	// internal list of `jwk.Key`s
+	// This method will be changed in the future to clear all contents in the
+	// `jwk.Set` instead of just the keys.
 	Clear()
 
 	// Get returns the key at index `idx`. If the index is out of range,
@@ -69,11 +72,23 @@ type Set interface {
 	Get(int) (Key, bool)
 
 	// Field returns the value of a private field in the key set.
+	//
 	// For the purposes of a key set, any field other than the "keys" field is
-	// considered to be a private field.
+	// considered to be a private field. In other words, you cannot use this
+	// method to directly access the list of keys in the set
+	//
 	// This method will be renamed to `Get(string)` in a future major release.
 	Field(string) (interface{}, bool)
 
+	// Set sets the value of a single field.
+	//
+	// This method, which takes an `interface{}`, exists because
+	// these objects can contain extra _arbitrary_ fields that users can
+	// specify, and there is no way of knowing what type they could be.
+	Set(string, interface{}) error
+
+	// Remove removes the field associated with the specified key.
+	// There is no way to remove the `kty` (key type). You will ALWAYS be left with one field in a jwk.Key.
 	// Index returns the index where the given key exists, -1 otherwise
 	Index(Key) int
 
diff --git a/jwk/set.go b/jwk/set.go
index 7a5918b9..127fa421 100644
--- a/jwk/set.go
+++ b/jwk/set.go
@@ -12,6 +12,8 @@ import (
 	"github.com/pkg/errors"
 )
 
+const keysKey = `keys` // appease linter
+
 // NewSet creates and empty `jwk.Set` object
 func NewSet() Set {
 	return &set{
@@ -19,6 +21,23 @@ func NewSet() Set {
 	}
 }
 
+func (s *set) Set(n string, v interface{}) error {
+	s.mu.RLock()
+	defer s.mu.RUnlock()
+
+	if n == keysKey {
+		vl, ok := v.([]Key)
+		if !ok {
+			return errors.Errorf(`value for field "keys" must be []jwk.Key`)
+		}
+		s.keys = vl
+		return nil
+	}
+
+	s.privateParams[n] = v
+	return nil
+}
+
 func (s *set) Field(n string) (interface{}, bool) {
 	s.mu.RLock()
 	defer s.mu.RUnlock()
@@ -126,7 +145,7 @@ func (s *set) MarshalJSON() ([]byte, error) {
 	defer pool.ReleaseBytesBuffer(buf)
 	enc := json.NewEncoder(buf)
 
-	fields := []string{`keys`}
+	fields := []string{keysKey}
 	for k := range s.privateParams {
 		fields = append(fields, k)
 	}
@@ -138,7 +157,7 @@ func (s *set) MarshalJSON() ([]byte, error) {
 			buf.WriteByte(',')
 		}
 		fmt.Fprintf(buf, `%q:`, field)
-		if field != `keys` {
+		if field != keysKey {
 			if err := enc.Encode(s.privateParams[field]); err != nil {
 				return nil, errors.Wrapf(err, `failed to marshal field %q`, field)
 			}


Test patch:
diff --git a/jwk/jwk_test.go b/jwk/jwk_test.go
index 1ff5f849..eccb07cf 100644
--- a/jwk/jwk_test.go
+++ b/jwk/jwk_test.go
@@ -1769,4 +1769,37 @@ func TestSetWithPrivateParams(t *testing.T) {
 			check(t, js)
 		})
 	})
+	t.Run("Set private parameters", func(t *testing.T) {
+		set := jwk.NewSet()
+		if !assert.NoError(t, set.Set(`renewal_kid`, `foo`), `set.Set should succeed`) {
+			return
+		}
+
+		v, ok := set.Field(`renewal_kid`)
+		if !assert.True(t, ok, `set.Get("renewal_kid") should succeed`) {
+			return
+		}
+
+		if !assert.Equal(t, `foo`, v, `set.Get("renewal_kid") should return "foo"`) {
+			return
+		}
+
+		if !assert.Error(t, set.Set(`keys`, []string{"foo"}), `set.Set should fail`) {
+			return
+		}
+
+		k, err := jwk.New([]byte("foobar"))
+		if !assert.NoError(t, err, `jwk.New should succeed`) {
+			return
+		}
+		keys := []jwk.Key{k}
+
+		if !assert.NoError(t, set.Set(`keys`, keys), `set.Set should succeed`) {
+			return
+		}
+
+		if !assert.Equal(t, set.Len(), 1, `set should have 1 key`) {
+			return
+		}
+	})
 }