SCIMReferenceCode icon indicating copy to clipboard operation
SCIMReferenceCode copied to clipboard

Pagination not working on GET /Users or /Groups

Open OutstandingBillNeal opened this issue 3 years ago • 1 comments

I think there's a design flaw around pagination. The provider implementation in WebHostSample seems to be responsible for pagination (although it does not currently .Skip(), it just .Take()s), but ProviderBase (in SystemForCrossDomainIdentityManagement) is responsible for setting TotalResults. ProviderBase cannot know the correct value for TotalResults if the result it receives from the implementation is already paginated.

The specification says (https://datatracker.ietf.org/doc/html/rfc7644#page-25) that "totalResults [should specify] the total number of results matching the client query". In the example provided by IETF, GET /Users?startIndex=1&count=10 yields

{
  "totalResults":100,
  "itemsPerPage":10,
  "startIndex":1,
  "schemas":["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
  "Resources":[{
    ...
  }]
}

As well as correcting TotalResults, an ideal implementation would also be mindful of efficiency concerns. That might enable the provider to return TotalResults along with the results, so that the implementation can decide whether to use the same query or a different one to ascertain its value.

For example, it might be more efficient to do this

// UserProvider
var results = _db.UserProfiles
    .Where(u => u.ClientId == "xyz")
    .Skip(startIndex)
    .Take(count)
    .Select(some DTO);
var totalResults = _db.UserProfiles
    .Count(u => u.ClientId == "xyz");

than this

// UserProvider
var allResources = _db.UserProfiles
    .Where(u => u.ClientId == "xyz")
    .Select(some DTO);

// ProviderBase
var results = allResources
    .Skip(startIndex)
    .Take(count);
var totalResults = allResources.Count();

OutstandingBillNeal avatar Mar 28 '22 22:03 OutstandingBillNeal

I think the idea of ProviderBase is to be very low effort implementation where end user does not need to implement everything to get the basic functionality. For most cases, database could handle the pagination as a whole.

For WebHostSample, override could be done which implements PaginateQueryAsync function and deals with the issue as you stated.

Sefriol avatar May 21 '24 11:05 Sefriol