From 1e1f74ee0e5ffccf1aff7d80cdce5d4befb328a8 Mon Sep 17 00:00:00 2001 From: Boris Schrijver Date: Fri, 23 Jun 2023 11:30:30 +0200 Subject: [PATCH] add include_credentials query param to /admin/identities list call --- identity/handler.go | 15 ++++++++++++++- identity/handler_test.go | 26 +++++++++++++++++++++++++- internal/client-go/api_identity.go | 8 ++++++++ internal/httpclient/api_identity.go | 8 ++++++++ spec/api.json | 9 +++++++++ spec/swagger.json | 7 +++++++ 6 files changed, 71 insertions(+), 2 deletions(-) diff --git a/identity/handler.go b/identity/handler.go index 8de630ca85ef..6db82d9c6e8f 100644 --- a/identity/handler.go +++ b/identity/handler.go @@ -8,6 +8,7 @@ import ( "encoding/json" "io" "net/http" + "strconv" "time" "github.com/ory/x/pagination/migrationpagination" @@ -137,6 +138,13 @@ type listIdentitiesParameters struct { // required: false // in: query CredentialsIdentifier string `json:"credentials_identifier"` + + // IncludeCredentials when set to true includes all of the identity's credentials. + // + // default: false + // required: false + // in: query + IncludeCredentials bool `json:"include_credentials"` } // swagger:route GET /admin/identities identity listIdentities @@ -159,8 +167,13 @@ type listIdentitiesParameters struct { func (h *Handler) list(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { page, itemsPerPage := x.ParsePagination(r) + includeCredentials := false + if param, err := strconv.ParseBool(r.URL.Query().Get("include_credentials")); err == nil { + includeCredentials = param + } + params := ListIdentityParameters{Expand: ExpandDefault, Page: page, PerPage: itemsPerPage, CredentialsIdentifier: r.URL.Query().Get("credentials_identifier")} - if params.CredentialsIdentifier != "" { + if includeCredentials || params.CredentialsIdentifier != "" { params.Expand = ExpandEverything } diff --git a/identity/handler_test.go b/identity/handler_test.go index 8a7e5a48ab91..cf5decf94bc5 100644 --- a/identity/handler_test.go +++ b/identity/handler_test.go @@ -1213,7 +1213,7 @@ func TestHandler(t *testing.T) { }) t.Run("case=should list all identities", func(t *testing.T) { - for name, ts := range map[string]*httptest.Server{"public": publicTS, "admin": adminTS} { + for name, ts := range map[string]*httptest.Server{"admin": adminTS} { t.Run("endpoint="+name, func(t *testing.T) { res := get(t, ts, "/identities", http.StatusOK) assert.False(t, res.Get("0.credentials").Exists(), "credentials config should be omitted: %s", res.Raw) @@ -1224,6 +1224,30 @@ func TestHandler(t *testing.T) { } }) + t.Run("case=should list all identities without credentials", func(t *testing.T) { + for name, ts := range map[string]*httptest.Server{"admin": adminTS} { + t.Run("endpoint="+name, func(t *testing.T) { + res := get(t, ts, "/identities?include_credentials=false", http.StatusOK) + assert.False(t, res.Get("0.credentials").Exists(), "credentials config should be omitted: %s", res.Raw) + assert.True(t, res.Get("0.metadata_public").Exists(), "metadata_public config should be included: %s", res.Raw) + assert.True(t, res.Get("0.metadata_admin").Exists(), "metadata_admin config should be included: %s", res.Raw) + assert.EqualValues(t, "baz", res.Get(`#(traits.bar=="baz").traits.bar`).String(), "%s", res.Raw) + }) + } + }) + + t.Run("case=should list all identities with credentials", func(t *testing.T) { + for name, ts := range map[string]*httptest.Server{"admin": adminTS} { + t.Run("endpoint="+name, func(t *testing.T) { + res := get(t, ts, "/identities?include_credentials=true", http.StatusOK) + assert.True(t, res.Get("0.credentials").Exists(), "credentials config should be included: %s", res.Raw) + assert.True(t, res.Get("0.metadata_public").Exists(), "metadata_public config should be included: %s", res.Raw) + assert.True(t, res.Get("0.metadata_admin").Exists(), "metadata_admin config should be included: %s", res.Raw) + assert.EqualValues(t, "baz", res.Get(`#(traits.bar=="baz").traits.bar`).String(), "%s", res.Raw) + }) + } + }) + t.Run("case=should not be able to update an identity that does not exist yet", func(t *testing.T) { for name, ts := range map[string]*httptest.Server{"public": publicTS, "admin": adminTS} { t.Run("endpoint="+name, func(t *testing.T) { diff --git a/internal/client-go/api_identity.go b/internal/client-go/api_identity.go index 52a30f8e99b6..2252ce838147 100644 --- a/internal/client-go/api_identity.go +++ b/internal/client-go/api_identity.go @@ -2050,6 +2050,7 @@ type IdentityApiApiListIdentitiesRequest struct { perPage *int64 page *int64 credentialsIdentifier *string + includeCredentials *bool } func (r IdentityApiApiListIdentitiesRequest) PerPage(perPage int64) IdentityApiApiListIdentitiesRequest { @@ -2064,6 +2065,10 @@ func (r IdentityApiApiListIdentitiesRequest) CredentialsIdentifier(credentialsId r.credentialsIdentifier = &credentialsIdentifier return r } +func (r IdentityApiApiListIdentitiesRequest) IncludeCredentials(includeCredentials bool) IdentityApiApiListIdentitiesRequest { + r.includeCredentials = &includeCredentials + return r +} func (r IdentityApiApiListIdentitiesRequest) Execute() ([]Identity, *http.Response, error) { return r.ApiService.ListIdentitiesExecute(r) @@ -2116,6 +2121,9 @@ func (a *IdentityApiService) ListIdentitiesExecute(r IdentityApiApiListIdentitie if r.credentialsIdentifier != nil { localVarQueryParams.Add("credentials_identifier", parameterToString(*r.credentialsIdentifier, "")) } + if r.includeCredentials != nil { + localVarQueryParams.Add("include_credentials", parameterToString(*r.includeCredentials, "")) + } // to determine the Content-Type header localVarHTTPContentTypes := []string{} diff --git a/internal/httpclient/api_identity.go b/internal/httpclient/api_identity.go index 52a30f8e99b6..2252ce838147 100644 --- a/internal/httpclient/api_identity.go +++ b/internal/httpclient/api_identity.go @@ -2050,6 +2050,7 @@ type IdentityApiApiListIdentitiesRequest struct { perPage *int64 page *int64 credentialsIdentifier *string + includeCredentials *bool } func (r IdentityApiApiListIdentitiesRequest) PerPage(perPage int64) IdentityApiApiListIdentitiesRequest { @@ -2064,6 +2065,10 @@ func (r IdentityApiApiListIdentitiesRequest) CredentialsIdentifier(credentialsId r.credentialsIdentifier = &credentialsIdentifier return r } +func (r IdentityApiApiListIdentitiesRequest) IncludeCredentials(includeCredentials bool) IdentityApiApiListIdentitiesRequest { + r.includeCredentials = &includeCredentials + return r +} func (r IdentityApiApiListIdentitiesRequest) Execute() ([]Identity, *http.Response, error) { return r.ApiService.ListIdentitiesExecute(r) @@ -2116,6 +2121,9 @@ func (a *IdentityApiService) ListIdentitiesExecute(r IdentityApiApiListIdentitie if r.credentialsIdentifier != nil { localVarQueryParams.Add("credentials_identifier", parameterToString(*r.credentialsIdentifier, "")) } + if r.includeCredentials != nil { + localVarQueryParams.Add("include_credentials", parameterToString(*r.includeCredentials, "")) + } // to determine the Content-Type header localVarHTTPContentTypes := []string{} diff --git a/spec/api.json b/spec/api.json index 90334abaa976..1bb4506df61b 100755 --- a/spec/api.json +++ b/spec/api.json @@ -3296,6 +3296,15 @@ "schema": { "type": "string" } + }, + { + "description": "IncludeCredentials when set to true includes all of the identity's credentials.", + "in": "query", + "name": "include_credentials", + "schema": { + "default": false, + "type": "boolean" + } } ], "responses": { diff --git a/spec/swagger.json b/spec/swagger.json index c8467e49c068..622c5341f704 100755 --- a/spec/swagger.json +++ b/spec/swagger.json @@ -209,6 +209,13 @@ "description": "CredentialsIdentifier is the identifier (username, email) of the credentials to look up.", "name": "credentials_identifier", "in": "query" + }, + { + "type": "boolean", + "default": false, + "description": "IncludeCredentials when set to true includes all of the identity's credentials.", + "name": "include_credentials", + "in": "query" } ], "responses": {