From d9a52802e5142628d1fd543401f7af9a2b456638 Mon Sep 17 00:00:00 2001 From: Alberto Ricart Date: Thu, 18 Apr 2024 11:55:17 -0500 Subject: [PATCH] [CHANGE] api to list scopes by role, return an array of scopes [CHANGE] api to list roles returns an unique list of names [FEAT] added Description to scopes --- account_signingkeys.go | 17 +++++++++++------ go.mod | 6 +++--- go.sum | 12 ++++++------ scope.go | 9 +++++++++ stream_imports.go | 1 + tests/accounts_test.go | 41 ++++++++++++++++++++++++----------------- tests/operator_test.go | 2 +- types.go | 8 +++++++- 8 files changed, 62 insertions(+), 34 deletions(-) diff --git a/account_signingkeys.go b/account_signingkeys.go index b685842..1ba0c2d 100644 --- a/account_signingkeys.go +++ b/account_signingkeys.go @@ -31,17 +31,21 @@ func (as *accountSigningKeys) Add() (string, error) { } func (as *accountSigningKeys) ListRoles() []string { - var roles []string + m := make(map[string]string) for _, k := range as.data.Claim.SigningKeys.Keys() { scope, ok := as.data.Claim.SigningKeys.GetScope(k) if ok && scope != nil { us, uok := scope.(*jwt.UserScope) if uok { - roles = append(roles, us.Role) + m[us.Role] = us.Role } } } - return roles + var v []string + for k := range m { + v = append(v, k) + } + return v } func (as *accountSigningKeys) Contains(sk string) (bool, bool) { @@ -75,16 +79,17 @@ func (as *accountSigningKeys) GetScope(key string) (ScopeLimits, error) { return nil, ErrNotFound } -func (as *accountSigningKeys) GetScopeByRole(role string) (ScopeLimits, error) { +func (as *accountSigningKeys) GetScopeByRole(role string) ([]ScopeLimits, error) { + var buf []ScopeLimits for _, v := range as.data.Claim.SigningKeys { if v != nil { scope, ok := v.(*jwt.UserScope) if ok && scope.Role == role { - return toScopeLimits(as.data, scope), nil + buf = append(buf, toScopeLimits(as.data, scope)) } } } - return nil, ErrNotFound + return buf, nil } func (as *accountSigningKeys) Delete(key string) (bool, error) { diff --git a/go.mod b/go.mod index 27d54e3..b2c9a8b 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/nats-io/jsm.go v0.1.1-0.20240314150821-1c7f0e424978 - github.com/nats-io/jwt/v2 v2.5.5 + github.com/nats-io/jwt/v2 v2.5.6 github.com/nats-io/nats-server/v2 v2.11.0-dev.0.20240313175812-f1cd3ed141b0 github.com/nats-io/nats.go v1.33.1 github.com/nats-io/nkeys v0.4.7 @@ -20,9 +20,9 @@ require ( github.com/minio/highwayhash v1.0.2 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/crypto v0.21.0 // indirect + golang.org/x/crypto v0.22.0 // indirect golang.org/x/net v0.22.0 // indirect - golang.org/x/sys v0.18.0 // indirect + golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 4a0ed06..a6b7e2e 100644 --- a/go.sum +++ b/go.sum @@ -13,8 +13,8 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/nats-io/jsm.go v0.1.1-0.20240314150821-1c7f0e424978 h1:VodpGrRg6AwgWMwcgLE9O9Z/ztICwyj8RKAIP0itNRA= github.com/nats-io/jsm.go v0.1.1-0.20240314150821-1c7f0e424978/go.mod h1:Sa4oF+OP1GyNAfbZSPVlIGrEiE0FzEcYN2gqGsTE1ls= -github.com/nats-io/jwt/v2 v2.5.5 h1:ROfXb50elFq5c9+1ztaUbdlrArNFl2+fQWP6B8HGEq4= -github.com/nats-io/jwt/v2 v2.5.5/go.mod h1:ZdWS1nZa6WMZfFwwgpEaqBV8EPGVgOTDHN/wTbz0Y5A= +github.com/nats-io/jwt/v2 v2.5.6 h1:Cp618+z4q042sWqHiSoIHFT08OZtAskui0hTmRfmGGQ= +github.com/nats-io/jwt/v2 v2.5.6/go.mod h1:ZdWS1nZa6WMZfFwwgpEaqBV8EPGVgOTDHN/wTbz0Y5A= github.com/nats-io/nats-server/v2 v2.11.0-dev.0.20240313175812-f1cd3ed141b0 h1:h+JREIhWsW3tradSo2WEsZE+GzFhPYguNtc7CeCXXgw= github.com/nats-io/nats-server/v2 v2.11.0-dev.0.20240313175812-f1cd3ed141b0/go.mod h1:H1n6zXtYLFCgXcf/SF8QNTSIFuS8tyZQMN9NguUHdEs= github.com/nats-io/nats.go v1.33.1 h1:8TxLZZ/seeEfR97qV0/Bl939tpDnt2Z2fK3HkPypj70= @@ -32,13 +32,13 @@ github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZV github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= diff --git a/scope.go b/scope.go index 4f19f85..51d7ec9 100644 --- a/scope.go +++ b/scope.go @@ -353,6 +353,15 @@ func (s *ScopeImpl) SetRole(name string) error { return s.update() } +func (s *ScopeImpl) Description() string { + return s.scope.Description +} + +func (s *ScopeImpl) SetDescription(description string) error { + s.scope.Description = description + return s.update() +} + func (s *ScopeImpl) update() error { s.accountData.Claim.SigningKeys[s.scope.Key] = s.scope return s.accountData.update() diff --git a/stream_imports.go b/stream_imports.go index 16d1abc..c6b7c32 100644 --- a/stream_imports.go +++ b/stream_imports.go @@ -2,6 +2,7 @@ package authb import ( "errors" + "github.com/nats-io/jwt/v2" ) diff --git a/tests/accounts_test.go b/tests/accounts_test.go index 4c1ee42..2c62f5b 100644 --- a/tests/accounts_test.go +++ b/tests/accounts_test.go @@ -193,9 +193,10 @@ func (t *ProviderSuite) Test_ScopedPermissionsMaxSubs() { a, err = o.Accounts().Get("A") t.NoError(err) - s, err = a.ScopedSigningKeys().GetScopeByRole("admin") + scopes, err := a.ScopedSigningKeys().GetScopeByRole("admin") t.NoError(err) - t.Equal(int64(10), s.MaxSubscriptions()) + t.Len(scopes, 1) + t.Equal(int64(10), scopes[0].MaxSubscriptions()) } func (t *ProviderSuite) Test_ScopedPermissionsMaxPayload() { @@ -214,9 +215,9 @@ func (t *ProviderSuite) Test_ScopedPermissionsMaxPayload() { a, err = o.Accounts().Get("A") t.NoError(err) - s, err = a.ScopedSigningKeys().GetScopeByRole("admin") + scopes, err := a.ScopedSigningKeys().GetScopeByRole("admin") t.NoError(err) - t.Equal(int64(101), s.MaxPayload()) + t.Equal(int64(101), scopes[0].MaxPayload()) } func (t *ProviderSuite) Test_ScopedPermissionsMaxData() { @@ -236,9 +237,9 @@ func (t *ProviderSuite) Test_ScopedPermissionsMaxData() { t.NoError(err) t.NotNil(a) - s, err = a.ScopedSigningKeys().GetScopeByRole("admin") + scopes, err := a.ScopedSigningKeys().GetScopeByRole("admin") t.NoError(err) - t.Equal(int64(4123), s.MaxData()) + t.Equal(int64(4123), scopes[0].MaxData()) } func (t *ProviderSuite) Test_ScopedPermissionsBearerToken() { @@ -257,9 +258,9 @@ func (t *ProviderSuite) Test_ScopedPermissionsBearerToken() { a, err = o.Accounts().Get("A") t.NoError(err) - s, err = a.ScopedSigningKeys().GetScopeByRole("admin") + scopes, err := a.ScopedSigningKeys().GetScopeByRole("admin") t.NoError(err) - t.True(s.BearerToken()) + t.True(scopes[0].BearerToken()) } func (t *ProviderSuite) Test_ScopedPermissionsConnectionTypes() { @@ -279,9 +280,10 @@ func (t *ProviderSuite) Test_ScopedPermissionsConnectionTypes() { a, err = o.Accounts().Get("A") t.NoError(err) - s, err = a.ScopedSigningKeys().GetScopeByRole("admin") + scopes, err := a.ScopedSigningKeys().GetScopeByRole("admin") t.NoError(err) - types = s.ConnectionTypes() + t.Len(scopes, 1) + types = scopes[0].ConnectionTypes() t.Contains(types.Types(), "websocket") } @@ -302,9 +304,10 @@ func (t *ProviderSuite) Test_ScopedPermissionsConnectionSources() { a, err = o.Accounts().Get("A") t.NoError(err) - s, err = a.ScopedSigningKeys().GetScopeByRole("admin") + scopes, err := a.ScopedSigningKeys().GetScopeByRole("admin") t.NoError(err) - sources = s.ConnectionSources() + t.Len(scopes, 1) + sources = scopes[0].ConnectionSources() t.Contains(sources.Sources(), "192.0.2.0/24") } @@ -325,9 +328,10 @@ func (t *ProviderSuite) Test_ScopedPermissionsConnectionTimes() { a, err = o.Accounts().Get("A") t.NoError(err) - s, err = a.ScopedSigningKeys().GetScopeByRole("admin") + scopes, err := a.ScopedSigningKeys().GetScopeByRole("admin") t.NoError(err) - times = s.ConnectionTimes() + t.Len(scopes, 1) + times = scopes[0].ConnectionTimes() t.Len(times.List(), 1) t.Equal(times.List()[0].Start, "08:00:00") t.Equal(times.List()[0].End, "12:00:00") @@ -348,9 +352,10 @@ func (t *ProviderSuite) Test_ScopedPermissionsLocale() { a, err = o.Accounts().Get("A") t.NoError(err) - s, err = a.ScopedSigningKeys().GetScopeByRole("admin") + scopes, err := a.ScopedSigningKeys().GetScopeByRole("admin") t.NoError(err) - t.Equal("en_US", s.Locale()) + t.Len(scopes, 1) + t.Equal("en_US", scopes[0].Locale()) } func (t *ProviderSuite) Test_ScopedPermissionsSubject() { @@ -374,8 +379,10 @@ func (t *ProviderSuite) Test_ScopedPermissionsSubject() { t.NoError(auth.Reload()) - admin, err = a.ScopedSigningKeys().GetScopeByRole("admin") + scopes, err := a.ScopedSigningKeys().GetScopeByRole("admin") t.NoError(err) + t.Len(scopes, 1) + admin = scopes[0] t.Contains(admin.PubPermissions().Allow(), "foo") t.Contains(admin.PubPermissions().Allow(), "bar") diff --git a/tests/operator_test.go b/tests/operator_test.go index e59072e..de357c8 100644 --- a/tests/operator_test.go +++ b/tests/operator_test.go @@ -3,12 +3,12 @@ package tests import ( "encoding/json" "errors" + "os" "github.com/nats-io/jwt/v2" "github.com/nats-io/nkeys" authb "github.com/synadia-io/jwt-auth-builder.go" "github.com/synadia-io/jwt-auth-builder.go/providers/nsc" - "os" ) func (t *ProviderSuite) Test_OperatorBasics() { diff --git a/types.go b/types.go index cebf152..3d1f2d3 100644 --- a/types.go +++ b/types.go @@ -687,6 +687,10 @@ type ScopeLimits interface { // SetRole sets the role associated with the scope. The role is simply a name // that you can use to identify the scope. It is not used by the server. SetRole(name string) error + // Description returns an user-assigned description associated with the scope. + Description() string + // SetDescription sets an user-assigned description associated with the scope. + SetDescription(description string) error } // ConnectionTypes is an interface for managing connection types that the connection @@ -839,10 +843,12 @@ type ScopedKeys interface { GetScope(string) (ScopeLimits, error) // GetScopeByRole returns the first scope that matches the specified role. // Note that the search must be an exact match of the scope role, and - GetScopeByRole(string) (ScopeLimits, error) + GetScopeByRole(string) ([]ScopeLimits, error) // List returns a list of signing keys List() []string // ListRoles returns the names of roles associated with the account + // Note that role names can be duplicated, and this name of roles + // will not contain duplicates so long as roles have the same capitalization, etc. ListRoles() []string // Contains returns found as true if the signing key was found, and isScoped as true // if the signing key is scoped.