Skip to content

Commit

Permalink
add include_credential query param to /admin/identities list call
Browse files Browse the repository at this point in the history
  • Loading branch information
borisroman committed Feb 19, 2024
1 parent 72bdeda commit 3bd41c5
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 3 deletions.
32 changes: 30 additions & 2 deletions identity/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,15 @@ type listIdentitiesParameters struct {
// in: query
CredentialsIdentifierSimilar string `json:"preview_credentials_identifier_similar"`

// Include Credentials in Response
//
// Include any credential, for example `password` or `oidc`, in the response. When set to `oidc`, This will return
// the initial OAuth 2.0 Access Token, OAuth 2.0 Refresh Token and the OpenID Connect ID Token if available.
//
// required: false
// in: query
DeclassifyCredentials []string `json:"include_credential"`

crdbx.ConsistencyRequestParameters
}

Expand All @@ -183,6 +192,18 @@ type listIdentitiesParameters struct {
// 200: listIdentities
// default: errorGeneric
func (h *Handler) list(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
includeCredentials := r.URL.Query()["include_credential"]
var declassify []CredentialsType
for _, v := range includeCredentials {
tc, ok := ParseCredentialsType(v)
if ok {
declassify = append(declassify, tc)
} else {
h.r.Writer().WriteError(w, r, errors.WithStack(herodot.ErrBadRequest.WithReasonf("Invalid value `%s` for parameter `include_credential`.", declassify)))
return

Check warning on line 203 in identity/handler.go

View check run for this annotation

Codecov / codecov/patch

identity/handler.go#L202-L203

Added lines #L202 - L203 were not covered by tests
}
}

var (
err error
params = ListIdentityParameters{
Expand All @@ -191,13 +212,14 @@ func (h *Handler) list(w http.ResponseWriter, r *http.Request, _ httprouter.Para
CredentialsIdentifier: r.URL.Query().Get("credentials_identifier"),
CredentialsIdentifierSimilar: r.URL.Query().Get("preview_credentials_identifier_similar"),
ConsistencyLevel: crdbx.ConsistencyLevelFromRequest(r),
DeclassifyCredentials: declassify,
}
)
if params.CredentialsIdentifier != "" && params.CredentialsIdentifierSimilar != "" {
h.r.Writer().WriteError(w, r, herodot.ErrBadRequest.WithReason("Cannot pass both credentials_identifier and preview_credentials_identifier_similar."))
return
}
if params.CredentialsIdentifier != "" || params.CredentialsIdentifierSimilar != "" {
if params.CredentialsIdentifier != "" || params.CredentialsIdentifierSimilar != "" || len(params.DeclassifyCredentials) > 0 {
params.Expand = ExpandEverything
}
params.KeySetPagination, params.PagePagination, err = x.ParseKeysetOrPagePagination(r)
Expand Down Expand Up @@ -231,7 +253,13 @@ func (h *Handler) list(w http.ResponseWriter, r *http.Request, _ httprouter.Para
// Identities using the marshaler for including metadata_admin
isam := make([]WithCredentialsMetadataAndAdminMetadataInJSON, len(is))
for i, identity := range is {
isam[i] = WithCredentialsMetadataAndAdminMetadataInJSON(identity)
emit, err := identity.WithDeclassifiedCredentials(r.Context(), h.r, params.DeclassifyCredentials)
if err != nil {
h.r.Writer().WriteError(w, r, err)
return

Check warning on line 259 in identity/handler.go

View check run for this annotation

Codecov / codecov/patch

identity/handler.go#L258-L259

Added lines #L258 - L259 were not covered by tests
}

isam[i] = WithCredentialsMetadataAndAdminMetadataInJSON(*emit)
}

h.r.Writer().Write(w, r, isam)
Expand Down
14 changes: 13 additions & 1 deletion identity/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1302,7 +1302,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)
Expand All @@ -1313,6 +1313,18 @@ func TestHandler(t *testing.T) {
}
})

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_credential=totp", 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 list all identities with eventual consistency", func(t *testing.T) {
for name, ts := range map[string]*httptest.Server{"public": publicTS, "admin": adminTS} {
t.Run("endpoint="+name, func(t *testing.T) {
Expand Down
1 change: 1 addition & 0 deletions identity/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type (
IdsFilter []string
CredentialsIdentifier string
CredentialsIdentifierSimilar string
DeclassifyCredentials []CredentialsType
KeySetPagination []keysetpagination.Option
// DEPRECATED
PagePagination *x.Page
Expand Down
16 changes: 16 additions & 0 deletions internal/client-go/api_identity.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions internal/httpclient/api_identity.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions spec/api.json
Original file line number Diff line number Diff line change
Expand Up @@ -3628,6 +3628,17 @@
"schema": {
"type": "string"
}
},
{
"description": "Include Credentials in Response\n\nInclude any credential, for example `password` or `oidc`, in the response. When set to `oidc`, This will return\nthe initial OAuth 2.0 Access Token, OAuth 2.0 Refresh Token and the OpenID Connect ID Token if available.",
"in": "query",
"name": "include_credential",
"schema": {
"items": {
"type": "string"
},
"type": "array"
}
}
],
"responses": {
Expand Down
9 changes: 9 additions & 0 deletions spec/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,15 @@
"description": "This is an EXPERIMENTAL parameter that WILL CHANGE. Do NOT rely on consistent, deterministic behavior.\nTHIS PARAMETER WILL BE REMOVED IN AN UPCOMING RELEASE WITHOUT ANY MIGRATION PATH.\n\nCredentialsIdentifierSimilar is the (partial) identifier (username, email) of the credentials to look up using similarity search.\nOnly one of CredentialsIdentifier and CredentialsIdentifierSimilar can be used.",
"name": "preview_credentials_identifier_similar",
"in": "query"
},
{
"type": "array",
"items": {
"type": "string"
},
"description": "Include Credentials in Response\n\nInclude any credential, for example `password` or `oidc`, in the response. When set to `oidc`, This will return\nthe initial OAuth 2.0 Access Token, OAuth 2.0 Refresh Token and the OpenID Connect ID Token if available.",
"name": "include_credential",
"in": "query"
}
],
"responses": {
Expand Down

0 comments on commit 3bd41c5

Please sign in to comment.