Skip to content

Commit

Permalink
Add total users to search all users method
Browse files Browse the repository at this point in the history
  • Loading branch information
dorsha committed Apr 30, 2024
1 parent 40a4f0e commit 0905e69
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 18 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -807,7 +807,7 @@ userRes, err := descopeClient.Management.User().LoadByUserID(context.Background(

// Search all users, optionally according to tenant and/or role filter
// Results can be paginated using the limit and page parameters
usersResp, err := descopeClient.Management.User().SearchAll(context.Background(), &descope.UserSearchOptions{TenantIDs: []string{"my-tenant-id"}})
usersResp, total, err := descopeClient.Management.User().SearchAll(context.Background(), &descope.UserSearchOptions{TenantIDs: []string{"my-tenant-id"}})
if err == nil {
for _, user := range usersResp {
// Do something
Expand Down
15 changes: 8 additions & 7 deletions descope/internal/mgmt/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,26 +214,26 @@ func (u *user) load(ctx context.Context, loginID, userID string) (*descope.UserR
return unmarshalUserResponse(res)
}

func (u *user) SearchAll(ctx context.Context, options *descope.UserSearchOptions) ([]*descope.UserResponse, error) {
func (u *user) SearchAll(ctx context.Context, options *descope.UserSearchOptions) ([]*descope.UserResponse, int, error) {
// Init empty options if non given
if options == nil {
options = &descope.UserSearchOptions{}
}

// Make sure limit is non-negative
if options.Limit < 0 {
return nil, utils.NewInvalidArgumentError("limit")
return nil, 0, utils.NewInvalidArgumentError("limit")
}

// Make sure page is non-negative
if options.Page < 0 {
return nil, utils.NewInvalidArgumentError("page")
return nil, 0, utils.NewInvalidArgumentError("page")
}

req := makeSearchAllRequest(options)
res, err := u.client.DoPostRequest(ctx, api.Routes.ManagementUserSearchAll(), req, nil, u.conf.ManagementKey)
if err != nil {
return nil, err
return nil, 0, err
}
return unmarshalUserSearchAllResponse(res)
}
Expand Down Expand Up @@ -833,15 +833,16 @@ func unmarshalUserBatchResponse(res *api.HTTPResponse) (*descope.UsersBatchRespo
return ures, err
}

func unmarshalUserSearchAllResponse(res *api.HTTPResponse) ([]*descope.UserResponse, error) {
func unmarshalUserSearchAllResponse(res *api.HTTPResponse) ([]*descope.UserResponse, int, error) {
ures := struct {
Users []*descope.UserResponse
Total int
}{}
err := utils.Unmarshal([]byte(res.BodyStr), &ures)
if err != nil {
return nil, err
return nil, 0, err
}
return ures.Users, nil
return ures.Users, ures.Total, nil
}

func unmarshalProviderTokenResponse(res *api.HTTPResponse) (*descope.ProviderTokenResponse, error) {
Expand Down
13 changes: 9 additions & 4 deletions descope/internal/mgmt/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,7 @@ func TestSearchAllUsersSuccess(t *testing.T) {
"users": []map[string]any{{
"email": "[email protected]",
}},
"total": 85,
}
tenantIDs := []string{"t1"}
roleNames := []string{"role1"}
Expand All @@ -550,7 +551,7 @@ func TestSearchAllUsersSuccess(t *testing.T) {
require.EqualValues(t, "blue", req["text"])
require.EqualValues(t, []interface{}([]interface{}{map[string]interface{}{"Desc": true, "Field": "nono"}, map[string]interface{}{"Desc": false, "Field": "lolo"}}), req["sort"])
}, response))
res, err := m.User().SearchAll(context.Background(), &descope.UserSearchOptions{
res, total, err := m.User().SearchAll(context.Background(), &descope.UserSearchOptions{
Statuses: []descope.UserStatus{descope.UserStatusDisabled},
TenantIDs: tenantIDs,
Roles: roleNames,
Expand All @@ -568,26 +569,30 @@ func TestSearchAllUsersSuccess(t *testing.T) {
require.NotNil(t, res)
require.Len(t, res, 1)
require.Equal(t, "[email protected]", res[0].Email)
require.Equal(t, 85, total)
}

func TestSearchAllUsersError(t *testing.T) {
m := newTestMgmt(nil, helpers.DoBadRequest(nil))
res, err := m.User().SearchAll(context.Background(), nil)
res, total, err := m.User().SearchAll(context.Background(), nil)
require.Error(t, err)
require.Nil(t, res)
require.Zero(t, total)
}

func TestSearchAllUsersBadRequest(t *testing.T) {
m := newTestMgmt(nil, helpers.DoBadRequest(nil))
res, err := m.User().SearchAll(context.Background(), &descope.UserSearchOptions{Limit: -1})
res, total, err := m.User().SearchAll(context.Background(), &descope.UserSearchOptions{Limit: -1})
require.ErrorIs(t, err, descope.ErrInvalidArguments)
require.Contains(t, err.Error(), "limit")
require.Nil(t, res)
require.Zero(t, total)

res, err = m.User().SearchAll(context.Background(), &descope.UserSearchOptions{Page: -1})
res, total, err = m.User().SearchAll(context.Background(), &descope.UserSearchOptions{Page: -1})
require.ErrorIs(t, err, descope.ErrInvalidArguments)
require.Contains(t, err.Error(), "page")
require.Nil(t, res)
require.Zero(t, total)
}

func TestUserActivateSuccess(t *testing.T) {
Expand Down
3 changes: 2 additions & 1 deletion descope/sdk/mgmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,8 @@ type User interface {
// The options optional parameter allows to fine-tune the search filters
// and results. Using nil will result in a filter-less query with a set amount of
// results.
SearchAll(ctx context.Context, options *descope.UserSearchOptions) ([]*descope.UserResponse, error)
// Returns slice of users and total number of users for the query
SearchAll(ctx context.Context, options *descope.UserSearchOptions) ([]*descope.UserResponse, int, error)

// Activate an existing user.
Activate(ctx context.Context, loginID string) (*descope.UserResponse, error)
Expand Down
11 changes: 6 additions & 5 deletions descope/tests/mocks/mgmt/managementmock.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,9 +269,10 @@ type MockUser struct {
LoadResponse *descope.UserResponse
LoadError error

SearchAllAssert func(options *descope.UserSearchOptions)
SearchAllResponse []*descope.UserResponse
SearchAllError error
SearchAllAssert func(options *descope.UserSearchOptions)
SearchAllResponse []*descope.UserResponse
SearchAllTotalResponse int
SearchAllError error

ActivateAssert func(loginID string)
ActivateResponse *descope.UserResponse
Expand Down Expand Up @@ -489,11 +490,11 @@ func (m *MockUser) LogoutUserByUserID(_ context.Context, userID string) error {
return m.LogoutError
}

func (m *MockUser) SearchAll(_ context.Context, options *descope.UserSearchOptions) ([]*descope.UserResponse, error) {
func (m *MockUser) SearchAll(_ context.Context, options *descope.UserSearchOptions) ([]*descope.UserResponse, int, error) {
if m.SearchAllAssert != nil {
m.SearchAllAssert(options)
}
return m.SearchAllResponse, m.SearchAllError
return m.SearchAllResponse, m.SearchAllTotalResponse, m.SearchAllError
}

func (m *MockUser) Activate(_ context.Context, loginID string) (*descope.UserResponse, error) {
Expand Down

0 comments on commit 0905e69

Please sign in to comment.