From 3012ac8b4fa22e09d3e78d22c993456130186db9 Mon Sep 17 00:00:00 2001 From: KunalOfficial <35455566+developerkunal@users.noreply.github.com> Date: Wed, 8 Jan 2025 13:29:03 +0530 Subject: [PATCH] Add Support for User sessions Endpoints in `UserManager` (#482) --- management/management.gen.go | 190 ++++++++++++++ management/management.gen_test.go | 242 ++++++++++++++++++ management/management_request.go | 9 + management/management_test.go | 17 ++ management/user.go | 67 +++++ management/user_test.go | 17 ++ .../TestUserManager_DeleteUserSessions.yaml | 109 ++++++++ .../TestUserManager_ListUserSessions.yaml | 109 ++++++++ 8 files changed, 760 insertions(+) create mode 100644 test/data/recordings/TestUserManager_DeleteUserSessions.yaml create mode 100644 test/data/recordings/TestUserManager_ListUserSessions.yaml diff --git a/management/management.gen.go b/management/management.gen.go index 3f7d2f59..34c76b1e 100644 --- a/management/management.gen.go +++ b/management/management.gen.go @@ -11774,6 +11774,196 @@ func (u *UserRecoveryCode) String() string { return Stringify(u) } +// GetAuthenticatedAt returns the AuthenticatedAt field if it's non-nil, zero value otherwise. +func (u *UserSession) GetAuthenticatedAt() string { + if u == nil || u.AuthenticatedAt == nil { + return "" + } + return *u.AuthenticatedAt +} + +// GetAuthentication returns the Authentication field. +func (u *UserSession) GetAuthentication() *UserSessionAuthentication { + if u == nil { + return nil + } + return u.Authentication +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (u *UserSession) GetCreatedAt() string { + if u == nil || u.CreatedAt == nil { + return "" + } + return *u.CreatedAt +} + +// GetDevice returns the Device field. +func (u *UserSession) GetDevice() *UserSessionDevice { + if u == nil { + return nil + } + return u.Device +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (u *UserSession) GetExpiresAt() string { + if u == nil || u.ExpiresAt == nil { + return "" + } + return *u.ExpiresAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (u *UserSession) GetID() string { + if u == nil || u.ID == nil { + return "" + } + return *u.ID +} + +// GetIdleExpiresAt returns the IdleExpiresAt field if it's non-nil, zero value otherwise. +func (u *UserSession) GetIdleExpiresAt() string { + if u == nil || u.IdleExpiresAt == nil { + return "" + } + return *u.IdleExpiresAt +} + +// GetLastInteractedAt returns the LastInteractedAt field if it's non-nil, zero value otherwise. +func (u *UserSession) GetLastInteractedAt() string { + if u == nil || u.LastInteractedAt == nil { + return "" + } + return *u.LastInteractedAt +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (u *UserSession) GetUpdatedAt() string { + if u == nil || u.UpdatedAt == nil { + return "" + } + return *u.UpdatedAt +} + +// GetUserID returns the UserID field if it's non-nil, zero value otherwise. +func (u *UserSession) GetUserID() string { + if u == nil || u.UserID == nil { + return "" + } + return *u.UserID +} + +// String returns a string representation of UserSession. +func (u *UserSession) String() string { + return Stringify(u) +} + +// String returns a string representation of UserSessionAuthentication. +func (u *UserSessionAuthentication) String() string { + return Stringify(u) +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (u *UserSessionAuthenticationMethod) GetName() string { + if u == nil || u.Name == nil { + return "" + } + return *u.Name +} + +// GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise. +func (u *UserSessionAuthenticationMethod) GetTimestamp() string { + if u == nil || u.Timestamp == nil { + return "" + } + return *u.Timestamp +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (u *UserSessionAuthenticationMethod) GetType() string { + if u == nil || u.Type == nil { + return "" + } + return *u.Type +} + +// String returns a string representation of UserSessionAuthenticationMethod. +func (u *UserSessionAuthenticationMethod) String() string { + return Stringify(u) +} + +// GetClientID returns the ClientID field if it's non-nil, zero value otherwise. +func (u *UserSessionClient) GetClientID() string { + if u == nil || u.ClientID == nil { + return "" + } + return *u.ClientID +} + +// String returns a string representation of UserSessionClient. +func (u *UserSessionClient) String() string { + return Stringify(u) +} + +// GetInitialASN returns the InitialASN field if it's non-nil, zero value otherwise. +func (u *UserSessionDevice) GetInitialASN() string { + if u == nil || u.InitialASN == nil { + return "" + } + return *u.InitialASN +} + +// GetInitialIP returns the InitialIP field if it's non-nil, zero value otherwise. +func (u *UserSessionDevice) GetInitialIP() string { + if u == nil || u.InitialIP == nil { + return "" + } + return *u.InitialIP +} + +// GetInitialUserAgent returns the InitialUserAgent field if it's non-nil, zero value otherwise. +func (u *UserSessionDevice) GetInitialUserAgent() string { + if u == nil || u.InitialUserAgent == nil { + return "" + } + return *u.InitialUserAgent +} + +// GetLastASN returns the LastASN field if it's non-nil, zero value otherwise. +func (u *UserSessionDevice) GetLastASN() string { + if u == nil || u.LastASN == nil { + return "" + } + return *u.LastASN +} + +// GetLastIP returns the LastIP field if it's non-nil, zero value otherwise. +func (u *UserSessionDevice) GetLastIP() string { + if u == nil || u.LastIP == nil { + return "" + } + return *u.LastIP +} + +// GetLastUserAgent returns the LastUserAgent field if it's non-nil, zero value otherwise. +func (u *UserSessionDevice) GetLastUserAgent() string { + if u == nil || u.LastUserAgent == nil { + return "" + } + return *u.LastUserAgent +} + +// String returns a string representation of UserSessionDevice. +func (u *UserSessionDevice) String() string { + return Stringify(u) +} + +// String returns a string representation of UserSessionList. +func (u *UserSessionList) String() string { + return Stringify(u) +} + // GetMasterkey returns the Masterkey field if it's non-nil, zero value otherwise. func (w *WAMSClientAddon) GetMasterkey() string { if w == nil || w.Masterkey == nil { diff --git a/management/management.gen_test.go b/management/management.gen_test.go index 486d8bfb..f5cc5c61 100644 --- a/management/management.gen_test.go +++ b/management/management.gen_test.go @@ -14799,6 +14799,248 @@ func TestUserRecoveryCode_String(t *testing.T) { } } +func TestUserSession_GetAuthenticatedAt(tt *testing.T) { + var zeroValue string + u := &UserSession{AuthenticatedAt: &zeroValue} + u.GetAuthenticatedAt() + u = &UserSession{} + u.GetAuthenticatedAt() + u = nil + u.GetAuthenticatedAt() +} + +func TestUserSession_GetAuthentication(tt *testing.T) { + u := &UserSession{} + u.GetAuthentication() + u = nil + u.GetAuthentication() +} + +func TestUserSession_GetCreatedAt(tt *testing.T) { + var zeroValue string + u := &UserSession{CreatedAt: &zeroValue} + u.GetCreatedAt() + u = &UserSession{} + u.GetCreatedAt() + u = nil + u.GetCreatedAt() +} + +func TestUserSession_GetDevice(tt *testing.T) { + u := &UserSession{} + u.GetDevice() + u = nil + u.GetDevice() +} + +func TestUserSession_GetExpiresAt(tt *testing.T) { + var zeroValue string + u := &UserSession{ExpiresAt: &zeroValue} + u.GetExpiresAt() + u = &UserSession{} + u.GetExpiresAt() + u = nil + u.GetExpiresAt() +} + +func TestUserSession_GetID(tt *testing.T) { + var zeroValue string + u := &UserSession{ID: &zeroValue} + u.GetID() + u = &UserSession{} + u.GetID() + u = nil + u.GetID() +} + +func TestUserSession_GetIdleExpiresAt(tt *testing.T) { + var zeroValue string + u := &UserSession{IdleExpiresAt: &zeroValue} + u.GetIdleExpiresAt() + u = &UserSession{} + u.GetIdleExpiresAt() + u = nil + u.GetIdleExpiresAt() +} + +func TestUserSession_GetLastInteractedAt(tt *testing.T) { + var zeroValue string + u := &UserSession{LastInteractedAt: &zeroValue} + u.GetLastInteractedAt() + u = &UserSession{} + u.GetLastInteractedAt() + u = nil + u.GetLastInteractedAt() +} + +func TestUserSession_GetUpdatedAt(tt *testing.T) { + var zeroValue string + u := &UserSession{UpdatedAt: &zeroValue} + u.GetUpdatedAt() + u = &UserSession{} + u.GetUpdatedAt() + u = nil + u.GetUpdatedAt() +} + +func TestUserSession_GetUserID(tt *testing.T) { + var zeroValue string + u := &UserSession{UserID: &zeroValue} + u.GetUserID() + u = &UserSession{} + u.GetUserID() + u = nil + u.GetUserID() +} + +func TestUserSession_String(t *testing.T) { + var rawJSON json.RawMessage + v := &UserSession{} + if err := json.Unmarshal([]byte(v.String()), &rawJSON); err != nil { + t.Errorf("failed to produce a valid json") + } +} + +func TestUserSessionAuthentication_String(t *testing.T) { + var rawJSON json.RawMessage + v := &UserSessionAuthentication{} + if err := json.Unmarshal([]byte(v.String()), &rawJSON); err != nil { + t.Errorf("failed to produce a valid json") + } +} + +func TestUserSessionAuthenticationMethod_GetName(tt *testing.T) { + var zeroValue string + u := &UserSessionAuthenticationMethod{Name: &zeroValue} + u.GetName() + u = &UserSessionAuthenticationMethod{} + u.GetName() + u = nil + u.GetName() +} + +func TestUserSessionAuthenticationMethod_GetTimestamp(tt *testing.T) { + var zeroValue string + u := &UserSessionAuthenticationMethod{Timestamp: &zeroValue} + u.GetTimestamp() + u = &UserSessionAuthenticationMethod{} + u.GetTimestamp() + u = nil + u.GetTimestamp() +} + +func TestUserSessionAuthenticationMethod_GetType(tt *testing.T) { + var zeroValue string + u := &UserSessionAuthenticationMethod{Type: &zeroValue} + u.GetType() + u = &UserSessionAuthenticationMethod{} + u.GetType() + u = nil + u.GetType() +} + +func TestUserSessionAuthenticationMethod_String(t *testing.T) { + var rawJSON json.RawMessage + v := &UserSessionAuthenticationMethod{} + if err := json.Unmarshal([]byte(v.String()), &rawJSON); err != nil { + t.Errorf("failed to produce a valid json") + } +} + +func TestUserSessionClient_GetClientID(tt *testing.T) { + var zeroValue string + u := &UserSessionClient{ClientID: &zeroValue} + u.GetClientID() + u = &UserSessionClient{} + u.GetClientID() + u = nil + u.GetClientID() +} + +func TestUserSessionClient_String(t *testing.T) { + var rawJSON json.RawMessage + v := &UserSessionClient{} + if err := json.Unmarshal([]byte(v.String()), &rawJSON); err != nil { + t.Errorf("failed to produce a valid json") + } +} + +func TestUserSessionDevice_GetInitialASN(tt *testing.T) { + var zeroValue string + u := &UserSessionDevice{InitialASN: &zeroValue} + u.GetInitialASN() + u = &UserSessionDevice{} + u.GetInitialASN() + u = nil + u.GetInitialASN() +} + +func TestUserSessionDevice_GetInitialIP(tt *testing.T) { + var zeroValue string + u := &UserSessionDevice{InitialIP: &zeroValue} + u.GetInitialIP() + u = &UserSessionDevice{} + u.GetInitialIP() + u = nil + u.GetInitialIP() +} + +func TestUserSessionDevice_GetInitialUserAgent(tt *testing.T) { + var zeroValue string + u := &UserSessionDevice{InitialUserAgent: &zeroValue} + u.GetInitialUserAgent() + u = &UserSessionDevice{} + u.GetInitialUserAgent() + u = nil + u.GetInitialUserAgent() +} + +func TestUserSessionDevice_GetLastASN(tt *testing.T) { + var zeroValue string + u := &UserSessionDevice{LastASN: &zeroValue} + u.GetLastASN() + u = &UserSessionDevice{} + u.GetLastASN() + u = nil + u.GetLastASN() +} + +func TestUserSessionDevice_GetLastIP(tt *testing.T) { + var zeroValue string + u := &UserSessionDevice{LastIP: &zeroValue} + u.GetLastIP() + u = &UserSessionDevice{} + u.GetLastIP() + u = nil + u.GetLastIP() +} + +func TestUserSessionDevice_GetLastUserAgent(tt *testing.T) { + var zeroValue string + u := &UserSessionDevice{LastUserAgent: &zeroValue} + u.GetLastUserAgent() + u = &UserSessionDevice{} + u.GetLastUserAgent() + u = nil + u.GetLastUserAgent() +} + +func TestUserSessionDevice_String(t *testing.T) { + var rawJSON json.RawMessage + v := &UserSessionDevice{} + if err := json.Unmarshal([]byte(v.String()), &rawJSON); err != nil { + t.Errorf("failed to produce a valid json") + } +} + +func TestUserSessionList_String(t *testing.T) { + var rawJSON json.RawMessage + v := &UserSessionList{} + if err := json.Unmarshal([]byte(v.String()), &rawJSON); err != nil { + t.Errorf("failed to produce a valid json") + } +} + func TestWAMSClientAddon_GetMasterkey(tt *testing.T) { var zeroValue string w := &WAMSClientAddon{Masterkey: &zeroValue} diff --git a/management/management_request.go b/management/management_request.go index 911bd023..23278465 100644 --- a/management/management_request.go +++ b/management/management_request.go @@ -174,6 +174,15 @@ func applyListDefaults(options []RequestOption) RequestOption { }) } +func applyListCheckpointDefaults(options []RequestOption) RequestOption { + return newRequestOption(func(r *http.Request) { + Take(50).apply(r) + for _, option := range options { + option.apply(r) + } + }) +} + // IncludeFields configures a request to include the desired fields. func IncludeFields(fields ...string) RequestOption { return newRequestOption(func(r *http.Request) { diff --git a/management/management_test.go b/management/management_test.go index 22cede6b..4d8a4b4f 100644 --- a/management/management_test.go +++ b/management/management_test.go @@ -167,6 +167,23 @@ func TestOptionDefaults(t *testing.T) { assert.Equal(t, "false", includeTotals) } +func TestOptionCheckpointDefaults(t *testing.T) { + r, _ := http.NewRequest("GET", "/", nil) + + applyListCheckpointDefaults([]RequestOption{ + Take(20), // This should be persisted (default is 50). + From("abc"), // This should be persisted (default is nil). + }).apply(r) + + v := r.URL.Query() + + take := v.Get("take") + assert.Equal(t, "20", take) + + from := v.Get("from") + assert.Equal(t, "abc", from) +} + func TestOptionSort(t *testing.T) { r, _ := http.NewRequest("GET", "/", nil) diff --git a/management/user.go b/management/user.go index 7fd50a38..09cad581 100644 --- a/management/user.go +++ b/management/user.go @@ -413,6 +413,54 @@ type RefreshTokenResourceServer struct { Scopes *string `json:"scopes,omitempty"` } +// UserSessionList represents a list of user sessions. +type UserSessionList struct { + List + Sessions []*UserSession `json:"sessions,omitempty"` +} + +// UserSession represents a user session. +type UserSession struct { + ID *string `json:"id,omitempty"` + UserID *string `json:"user_id,omitempty"` + CreatedAt *string `json:"created_at,omitempty"` + UpdatedAt *string `json:"updated_at,omitempty"` + AuthenticatedAt *string `json:"authenticated_at,omitempty"` + IdleExpiresAt *string `json:"idle_expires_at,omitempty"` + ExpiresAt *string `json:"expires_at,omitempty"` + LastInteractedAt *string `json:"last_interacted_at,omitempty"` + Device *UserSessionDevice `json:"device,omitempty"` + Clients []*UserSessionClient `json:"clients,omitempty"` + Authentication *UserSessionAuthentication `json:"authentication,omitempty"` +} + +// UserSessionDevice represents the device metadata for a user session. +type UserSessionDevice struct { + InitialUserAgent *string `json:"initial_user_agent,omitempty"` + InitialIP *string `json:"initial_ip,omitempty"` + InitialASN *string `json:"initial_asn,omitempty"` + LastUserAgent *string `json:"last_user_agent,omitempty"` + LastIP *string `json:"last_ip,omitempty"` + LastASN *string `json:"last_asn,omitempty"` +} + +// UserSessionClient represents the client details for a user session. +type UserSessionClient struct { + ClientID *string `json:"client_id,omitempty"` +} + +// UserSessionAuthentication represents the authentication signals obtained during the login flow. +type UserSessionAuthentication struct { + Methods []*UserSessionAuthenticationMethod `json:"methods,omitempty"` +} + +// UserSessionAuthenticationMethod represents the authentication signal details. +type UserSessionAuthenticationMethod struct { + Name *string `json:"name,omitempty"` + Timestamp *string `json:"timestamp,omitempty"` + Type *string `json:"type,omitempty"` +} + // UserManager manages Auth0 User resources. type UserManager manager @@ -768,3 +816,22 @@ func (m *UserManager) DeleteRefreshTokens(ctx context.Context, userID string, op err = m.management.Request(ctx, "DELETE", m.management.URI("users", userID, "refresh-tokens"), nil, opts...) return } + +// ListUserSessions retrieves details for a user's sessions. +// +// It allows pagination using the provided options. For more information on pagination, refer to: +// https://pkg.go.dev/github.com/auth0/go-auth0/management#hdr-Page_Based_Pagination +// +// See: https://auth0.com/docs/api/management/v2/users/get-sessions-for-user +func (m *UserManager) ListUserSessions(ctx context.Context, userID string, opts ...RequestOption) (r *UserSessionList, err error) { + err = m.management.Request(ctx, "GET", m.management.URI("users", userID, "sessions"), &r, applyListCheckpointDefaults(opts)) + return +} + +// DeleteUserSessions deletes all sessions for a user. +// +// See: https://auth0.com/docs/api/management/v2/users/delete-sessions-for-user +func (m *UserManager) DeleteUserSessions(ctx context.Context, userID string, opts ...RequestOption) (err error) { + err = m.management.Request(ctx, "DELETE", m.management.URI("users", userID, "sessions"), nil, opts...) + return +} diff --git a/management/user_test.go b/management/user_test.go index 4de17c48..9f69c669 100644 --- a/management/user_test.go +++ b/management/user_test.go @@ -299,6 +299,23 @@ func TestUserManager_Unlink(t *testing.T) { assert.Equal(t, mainUser.GetID(), "auth0|"+unlinkedIdentities[0].GetUserID()) } +func TestUserManager_ListUserSessions(t *testing.T) { + configureHTTPTestRecordings(t) + + user := givenAUser(t) + sessions, err := api.User.ListUserSessions(context.Background(), user.GetID()) + assert.NoError(t, err) + assert.Len(t, sessions.Sessions, 0) +} + +func TestUserManager_DeleteUserSessions(t *testing.T) { + configureHTTPTestRecordings(t) + + user := givenAUser(t) + err := api.User.DeleteUserSessions(context.Background(), user.GetID()) + assert.NoError(t, err) +} + func TestUser_MarshalJSON(t *testing.T) { for user, expected := range map[*User]string{ {}: `{}`, diff --git a/test/data/recordings/TestUserManager_DeleteUserSessions.yaml b/test/data/recordings/TestUserManager_DeleteUserSessions.yaml new file mode 100644 index 00000000..ad941831 --- /dev/null +++ b/test/data/recordings/TestUserManager_DeleteUserSessions.yaml @@ -0,0 +1,109 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 479 + transfer_encoding: [] + trailer: {} + host: go-auth0-dev.eu.auth0.com + remote_addr: "" + request_uri: "" + body: | + {"connection":"Username-Password-Authentication","email":"chuck59@example.com","given_name":"Chuck","family_name":"Sanchez","username":"test-user262","nickname":"Chucky","password":"Passwords hide their chuck","user_metadata":{"favourite_attack":"roundhouse_kick"},"verify_email":false,"app_metadata":{"facts":["count_to_infinity_twice","kill_two_stones_with_one_bird","can_hear_sign_language"]},"picture":"https://example-picture-url.jpg","blocked":false,"email_verified":true} + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - Go-Auth0/1.13.1 + url: https://go-auth0-dev.eu.auth0.com/api/v2/users + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 659 + uncompressed: false + body: '{"blocked":false,"created_at":"2025-01-08T06:16:30.932Z","email":"chuck59@example.com","email_verified":true,"family_name":"Sanchez","given_name":"Chuck","identities":[{"connection":"Username-Password-Authentication","user_id":"677e183e3bda1f389d6ba9e6","provider":"auth0","isSocial":false}],"name":"chuck59@example.com","nickname":"Chucky","picture":"https://example-picture-url.jpg","updated_at":"2025-01-08T06:16:30.932Z","user_id":"auth0|677e183e3bda1f389d6ba9e6","user_metadata":{"favourite_attack":"roundhouse_kick"},"username":"test-user262","app_metadata":{"facts":["count_to_infinity_twice","kill_two_stones_with_one_bird","can_hear_sign_language"]}}' + headers: + Content-Type: + - application/json; charset=utf-8 + status: 201 Created + code: 201 + duration: 1.045178959s + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: go-auth0-dev.eu.auth0.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - Go-Auth0/1.13.1 + url: https://go-auth0-dev.eu.auth0.com/api/v2/users/auth0%7C677e183e3bda1f389d6ba9e6/sessions + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 2 + uncompressed: false + body: '{}' + headers: + Content-Type: + - application/json; charset=utf-8 + status: 202 Accepted + code: 202 + duration: 425.850167ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: go-auth0-dev.eu.auth0.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - Go-Auth0/1.13.1 + url: https://go-auth0-dev.eu.auth0.com/api/v2/users/auth0%7C677e183e3bda1f389d6ba9e6 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Content-Type: + - application/json; charset=utf-8 + status: 204 No Content + code: 204 + duration: 400.5045ms diff --git a/test/data/recordings/TestUserManager_ListUserSessions.yaml b/test/data/recordings/TestUserManager_ListUserSessions.yaml new file mode 100644 index 00000000..66fb04da --- /dev/null +++ b/test/data/recordings/TestUserManager_ListUserSessions.yaml @@ -0,0 +1,109 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 480 + transfer_encoding: [] + trailer: {} + host: go-auth0-dev.eu.auth0.com + remote_addr: "" + request_uri: "" + body: | + {"connection":"Username-Password-Authentication","email":"chuck843@example.com","given_name":"Chuck","family_name":"Sanchez","username":"test-user608","nickname":"Chucky","password":"Passwords hide their chuck","user_metadata":{"favourite_attack":"roundhouse_kick"},"verify_email":false,"app_metadata":{"facts":["count_to_infinity_twice","kill_two_stones_with_one_bird","can_hear_sign_language"]},"picture":"https://example-picture-url.jpg","blocked":false,"email_verified":true} + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - Go-Auth0/1.13.1 + url: https://go-auth0-dev.eu.auth0.com/api/v2/users + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 661 + uncompressed: false + body: '{"blocked":false,"created_at":"2025-01-08T06:16:17.101Z","email":"chuck843@example.com","email_verified":true,"family_name":"Sanchez","given_name":"Chuck","identities":[{"connection":"Username-Password-Authentication","user_id":"677e183104cb56de4c43408a","provider":"auth0","isSocial":false}],"name":"chuck843@example.com","nickname":"Chucky","picture":"https://example-picture-url.jpg","updated_at":"2025-01-08T06:16:17.101Z","user_id":"auth0|677e183104cb56de4c43408a","user_metadata":{"favourite_attack":"roundhouse_kick"},"username":"test-user608","app_metadata":{"facts":["count_to_infinity_twice","kill_two_stones_with_one_bird","can_hear_sign_language"]}}' + headers: + Content-Type: + - application/json; charset=utf-8 + status: 201 Created + code: 201 + duration: 1.02425075s + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: go-auth0-dev.eu.auth0.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - Go-Auth0/1.13.1 + url: https://go-auth0-dev.eu.auth0.com/api/v2/users/auth0%7C677e183104cb56de4c43408a/sessions?take=50 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 15 + uncompressed: false + body: '{"sessions":[]}' + headers: + Content-Type: + - application/json; charset=utf-8 + status: 200 OK + code: 200 + duration: 432.664166ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: go-auth0-dev.eu.auth0.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - Go-Auth0/1.13.1 + url: https://go-auth0-dev.eu.auth0.com/api/v2/users/auth0%7C677e183104cb56de4c43408a + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Content-Type: + - application/json; charset=utf-8 + status: 204 No Content + code: 204 + duration: 373.715541ms