Skip to content

Commit 722f904

Browse files
authored
Implemented the OIDCProviderConfigs() API (#285)
1 parent 68e385d commit 722f904

File tree

2 files changed

+164
-3
lines changed

2 files changed

+164
-3
lines changed

auth/provider_config.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,65 @@ func (config *OIDCProviderConfigToUpdate) buildRequest() (nestedMap, error) {
245245
return config.params, nil
246246
}
247247

248+
// OIDCProviderConfigIterator is an iterator over OIDC provider configurations.
249+
type OIDCProviderConfigIterator struct {
250+
client *providerConfigClient
251+
ctx context.Context
252+
nextFunc func() error
253+
pageInfo *iterator.PageInfo
254+
configs []*OIDCProviderConfig
255+
}
256+
257+
// PageInfo supports pagination.
258+
func (it *OIDCProviderConfigIterator) PageInfo() *iterator.PageInfo {
259+
return it.pageInfo
260+
}
261+
262+
// Next returns the next OIDCProviderConfig. The error value of [iterator.Done] is
263+
// returned if there are no more results. Once Next returns [iterator.Done], all
264+
// subsequent calls will return [iterator.Done].
265+
func (it *OIDCProviderConfigIterator) Next() (*OIDCProviderConfig, error) {
266+
if err := it.nextFunc(); err != nil {
267+
return nil, err
268+
}
269+
270+
config := it.configs[0]
271+
it.configs = it.configs[1:]
272+
return config, nil
273+
}
274+
275+
func (it *OIDCProviderConfigIterator) fetch(pageSize int, pageToken string) (string, error) {
276+
params := map[string]string{
277+
"pageSize": strconv.Itoa(pageSize),
278+
}
279+
if pageToken != "" {
280+
params["pageToken"] = pageToken
281+
}
282+
283+
req := &internal.Request{
284+
Method: http.MethodGet,
285+
URL: "/oauthIdpConfigs",
286+
Opts: []internal.HTTPOption{
287+
internal.WithQueryParams(params),
288+
},
289+
}
290+
291+
var result struct {
292+
Configs []oidcProviderConfigDAO `json:"oauthIdpConfigs"`
293+
NextPageToken string `json:"nextPageToken"`
294+
}
295+
if _, err := it.client.makeRequest(it.ctx, req, &result); err != nil {
296+
return "", err
297+
}
298+
299+
for _, config := range result.Configs {
300+
it.configs = append(it.configs, config.toOIDCProviderConfig())
301+
}
302+
303+
it.pageInfo.Token = result.NextPageToken
304+
return result.NextPageToken, nil
305+
}
306+
248307
// SAMLProviderConfig is the SAML auth provider configuration.
249308
// See http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0.html.
250309
type SAMLProviderConfig struct {
@@ -652,6 +711,24 @@ func (c *providerConfigClient) DeleteOIDCProviderConfig(ctx context.Context, id
652711
return err
653712
}
654713

714+
// OIDCProviderConfigs returns an iterator over OIDC provider configurations.
715+
//
716+
// If nextPageToken is empty, the iterator will start at the beginning. Otherwise,
717+
// iterator starts after the token.
718+
func (c *providerConfigClient) OIDCProviderConfigs(ctx context.Context, nextPageToken string) *OIDCProviderConfigIterator {
719+
it := &OIDCProviderConfigIterator{
720+
ctx: ctx,
721+
client: c,
722+
}
723+
it.pageInfo, it.nextFunc = iterator.NewPageInfo(
724+
it.fetch,
725+
func() int { return len(it.configs) },
726+
func() interface{} { b := it.configs; it.configs = nil; return b })
727+
it.pageInfo.MaxSize = maxConfigs
728+
it.pageInfo.Token = nextPageToken
729+
return it
730+
}
731+
655732
// SAMLProviderConfig returns the SAMLProviderConfig with the given ID.
656733
func (c *providerConfigClient) SAMLProviderConfig(ctx context.Context, id string) (*SAMLProviderConfig, error) {
657734
if err := validateSAMLConfigID(id); err != nil {

auth/provider_config_test.go

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,84 @@ func TestDeleteOIDCProviderConfigError(t *testing.T) {
508508
}
509509
}
510510

511+
func TestOIDCProviderConfigs(t *testing.T) {
512+
template := `{
513+
"oauthIdpConfigs": [
514+
%s,
515+
%s,
516+
%s
517+
],
518+
"nextPageToken": ""
519+
}`
520+
response := fmt.Sprintf(template, oidcConfigResponse, oidcConfigResponse, oidcConfigResponse)
521+
s := echoServer([]byte(response), t)
522+
defer s.Close()
523+
524+
want := []*OIDCProviderConfig{
525+
oidcProviderConfig,
526+
oidcProviderConfig,
527+
oidcProviderConfig,
528+
}
529+
wantPath := "/projects/mock-project-id/oauthIdpConfigs"
530+
531+
testIterator := func(iter *OIDCProviderConfigIterator, token string, req string) {
532+
count := 0
533+
for i := 0; i < len(want); i++ {
534+
config, err := iter.Next()
535+
if err == iterator.Done {
536+
break
537+
}
538+
if err != nil {
539+
t.Fatal(err)
540+
}
541+
if !reflect.DeepEqual(config, want[i]) {
542+
t.Errorf("OIDCProviderConfigs(%q) = %#v; want = %#v", token, config, want[i])
543+
}
544+
count++
545+
}
546+
if count != len(want) {
547+
t.Errorf("OIDCProviderConfigs(%q) = %d; want = %d", token, count, len(want))
548+
}
549+
if _, err := iter.Next(); err != iterator.Done {
550+
t.Errorf("OIDCProviderConfigs(%q) = %v; want = %v", token, err, iterator.Done)
551+
}
552+
553+
url := s.Req[len(s.Req)-1].URL
554+
if url.Path != wantPath {
555+
t.Errorf("OIDCProviderConfigs(%q) = %q; want = %q", token, url.Path, wantPath)
556+
}
557+
558+
// Check the query string of the last HTTP request made.
559+
gotReq := url.Query().Encode()
560+
if gotReq != req {
561+
t.Errorf("OIDCProviderConfigs(%q) = %q; want = %v", token, gotReq, req)
562+
}
563+
}
564+
565+
client := s.Client.pcc
566+
testIterator(
567+
client.OIDCProviderConfigs(context.Background(), ""),
568+
"",
569+
"pageSize=100")
570+
testIterator(
571+
client.OIDCProviderConfigs(context.Background(), "pageToken"),
572+
"pageToken",
573+
"pageSize=100&pageToken=pageToken")
574+
}
575+
576+
func TestOIDCProviderConfigsError(t *testing.T) {
577+
s := echoServer([]byte("{}"), t)
578+
defer s.Close()
579+
s.Status = http.StatusInternalServerError
580+
581+
client := s.Client.pcc
582+
it := client.OIDCProviderConfigs(context.Background(), "")
583+
config, err := it.Next()
584+
if config != nil || err == nil || !IsUnknown(err) {
585+
t.Errorf("OIDCProviderConfigs() = (%v, %v); want = (nil, %q)", config, err, "unknown-error")
586+
}
587+
}
588+
511589
func TestSAMLProviderConfig(t *testing.T) {
512590
s := echoServer([]byte(samlConfigResponse), t)
513591
defer s.Close()
@@ -1074,6 +1152,7 @@ func TestSAMLProviderConfigs(t *testing.T) {
10741152
samlProviderConfig,
10751153
samlProviderConfig,
10761154
}
1155+
wantPath := "/projects/mock-project-id/inboundSamlConfigs"
10771156

10781157
testIterator := func(iter *SAMLProviderConfigIterator, token string, req string) {
10791158
count := 0
@@ -1094,13 +1173,18 @@ func TestSAMLProviderConfigs(t *testing.T) {
10941173
t.Errorf("SAMLProviderConfigs(%q) = %d; want = %d", token, count, len(want))
10951174
}
10961175
if _, err := iter.Next(); err != iterator.Done {
1097-
t.Errorf("SAMLProviderConfigs(%q) = %v, want = %v", token, err, iterator.Done)
1176+
t.Errorf("SAMLProviderConfigs(%q) = %v; want = %v", token, err, iterator.Done)
1177+
}
1178+
1179+
url := s.Req[len(s.Req)-1].URL
1180+
if url.Path != wantPath {
1181+
t.Errorf("SAMLProviderConfigs(%q) = %q; want = %q", token, url.Path, wantPath)
10981182
}
10991183

11001184
// Check the query string of the last HTTP request made.
1101-
gotReq := s.Req[len(s.Req)-1].URL.Query().Encode()
1185+
gotReq := url.Query().Encode()
11021186
if gotReq != req {
1103-
t.Errorf("SAMLProviderConfigs(%q) = %q, want = %v", token, gotReq, req)
1187+
t.Errorf("SAMLProviderConfigs(%q) = %q; want = %v", token, gotReq, req)
11041188
}
11051189
}
11061190

0 commit comments

Comments
 (0)