Skip to content

Commit

Permalink
Start work on the user count endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
kanpov committed Jun 15, 2024
1 parent 5ff66a5 commit e9e7b8f
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 2 deletions.
2 changes: 2 additions & 0 deletions src/Keycloak.AuthServices.Sdk/Admin/ApiUrls.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ internal static class ApiUrls

internal const string GetUser = $"{GetRealm}/users/{{id}}";

internal const string GetUserCount = $"{GetRealm}/users/count";

internal const string CreateUser = $"{GetRealm}/users";

internal const string UpdateUser = $"{GetRealm}/users/{{id}}";
Expand Down
35 changes: 35 additions & 0 deletions src/Keycloak.AuthServices.Sdk/Admin/IKeycloakUserClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,41 @@ async Task<IEnumerable<UserRepresentation>> GetUsersAsync(
?? Enumerable.Empty<UserRepresentation>();
}

/// <summary>
/// Get the integer amount of users on the realm that match the provided <see cref="GetUserCountRequestParameters"/>.
///
/// Note that the response is not JSON, but simply the integer value as a string.
/// </summary>
/// <param name="realm">Realm name (not ID).</param>
/// <param name="parameters">Optional query parameters.</param>
/// <param name="cancellationToken"></param>
/// <returns>An integer amount of users</returns>
Task<HttpResponseMessage> GetUserCountWithResponseAsync(
string realm,
GetUserCountRequestParameters? parameters = default,
CancellationToken cancellationToken = default
);

/// <summary>
/// Get the integer amount of users on the realm that match the provided <see cref="GetUserCountRequestParameters"/>.
/// </summary>
/// <param name="realm">Realm name (not ID).</param>
/// <param name="parameters">Optional query parameters.</param>
/// <param name="cancellationToken"></param>
/// <returns>An integer amount of users</returns>
async Task<int> GetUserCountAsync(
string realm,
GetUserCountRequestParameters? parameters = default,
CancellationToken cancellationToken = default
)
{
var response = await this.GetUserCountWithResponseAsync(realm, parameters, cancellationToken);
var stringContent = await response.Content.ReadAsStringAsync(cancellationToken);
#pragma warning disable CA1305 // Specify IFormatProvider
return Convert.ToInt32(stringContent);
#pragma warning restore CA1305 // Specify IFormatProvider
}

/// <summary>
/// Get representation of a user.
/// </summary>
Expand Down
39 changes: 37 additions & 2 deletions src/Keycloak.AuthServices.Sdk/Admin/KeycloakClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
/// <summary>
/// Represents a client for interacting with the Keycloak Admin API.
/// </summary>
public partial class KeycloakClient : IKeycloakClient
public class KeycloakClient : IKeycloakClient
{
private readonly HttpClient httpClient;

Expand Down Expand Up @@ -94,7 +94,42 @@ public async Task<HttpResponseMessage> GetUsersWithResponseAsync(

var responseMessage = await this.httpClient.GetAsync(path + query, cancellationToken);

return responseMessage!;
return responseMessage;
}

/// <inheritdoc/>
public async Task<HttpResponseMessage> GetUserCountWithResponseAsync(
string realm,
GetUserCountRequestParameters? parameters = default,
CancellationToken cancellationToken = default
)
{
var path = ApiUrls.GetUserCount.WithRealm(realm);

var query = string.Empty;

if (parameters is not null)
{
var queryParameters = new List<KeyValuePair<string, string?>>()
{
new("email", parameters.Email),
new("emailVerified", parameters.EmailVerified?.ToString()),
new("enabled", parameters.Enabled?.ToString()),
new("firstName", parameters.FirstName),
new("lastName", parameters.LastName),
new("q", parameters.Query),
new("search", parameters.Search),
new("username", parameters.Username)
};

query = new QueryBuilder(queryParameters.Where(q => q.Value is not null)!)
.ToQueryString()
.ToString();
}

var responseMessage = await this.httpClient.GetAsync(path + query, cancellationToken);

return responseMessage;
}

/// <inheritdoc/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
namespace Keycloak.AuthServices.Sdk.Admin.Requests.Users;

/// <summary>
/// Optional request parameters for the <see cref="IKeycloakClient.GetUserCountAsync"/> endpoint.

Check warning on line 4 in src/Keycloak.AuthServices.Sdk/Admin/Requests/Users/GetUserCountRequestParameters.cs

View workflow job for this annotation

GitHub Actions / Build-ubuntu-latest

XML comment has cref attribute 'GetUserCountAsync' that could not be resolved

Check warning on line 4 in src/Keycloak.AuthServices.Sdk/Admin/Requests/Users/GetUserCountRequestParameters.cs

View workflow job for this annotation

GitHub Actions / Build-ubuntu-latest

XML comment has cref attribute 'GetUserCountAsync' that could not be resolved

Check warning on line 4 in src/Keycloak.AuthServices.Sdk/Admin/Requests/Users/GetUserCountRequestParameters.cs

View workflow job for this annotation

GitHub Actions / Build-ubuntu-latest

XML comment has cref attribute 'GetUserCountAsync' that could not be resolved

Check warning on line 4 in src/Keycloak.AuthServices.Sdk/Admin/Requests/Users/GetUserCountRequestParameters.cs

View workflow job for this annotation

GitHub Actions / Build-ubuntu-latest

XML comment has cref attribute 'GetUserCountAsync' that could not be resolved

Check warning on line 4 in src/Keycloak.AuthServices.Sdk/Admin/Requests/Users/GetUserCountRequestParameters.cs

View workflow job for this annotation

GitHub Actions / Build-ubuntu-latest

XML comment has cref attribute 'GetUserCountAsync' that could not be resolved

Check warning on line 4 in src/Keycloak.AuthServices.Sdk/Admin/Requests/Users/GetUserCountRequestParameters.cs

View workflow job for this annotation

GitHub Actions / Build-windows-latest

XML comment has cref attribute 'GetUserCountAsync' that could not be resolved

Check warning on line 4 in src/Keycloak.AuthServices.Sdk/Admin/Requests/Users/GetUserCountRequestParameters.cs

View workflow job for this annotation

GitHub Actions / Build-windows-latest

XML comment has cref attribute 'GetUserCountAsync' that could not be resolved

Check warning on line 4 in src/Keycloak.AuthServices.Sdk/Admin/Requests/Users/GetUserCountRequestParameters.cs

View workflow job for this annotation

GitHub Actions / Build-windows-latest

XML comment has cref attribute 'GetUserCountAsync' that could not be resolved

Check warning on line 4 in src/Keycloak.AuthServices.Sdk/Admin/Requests/Users/GetUserCountRequestParameters.cs

View workflow job for this annotation

GitHub Actions / Build-windows-latest

XML comment has cref attribute 'GetUserCountAsync' that could not be resolved

Check warning on line 4 in src/Keycloak.AuthServices.Sdk/Admin/Requests/Users/GetUserCountRequestParameters.cs

View workflow job for this annotation

GitHub Actions / Build-windows-latest

XML comment has cref attribute 'GetUserCountAsync' that could not be resolved
/// If these are not specified, the total amount of users in the provided realm will be returned, otherwise, the amount
/// of users in the realm that match the criteria defined in these parameters will be returned.
/// </summary>
public class GetUserCountRequestParameters
{
/// <summary>
/// An optional filter for a user's email.
/// </summary>
public string? Email { get; init; }

/// <summary>
/// Whether a user's email has to be verified to be included.
/// </summary>
public bool? EmailVerified { get; init; }

/// <summary>
/// Whether a user has to be enabled to be included.
/// </summary>
public bool? Enabled { get; init; }

/// <summary>
/// An optional filter for a user's first name.
/// </summary>
public string? FirstName { get; init; }

/// <summary>
/// An optional filter for a user's last name.
/// </summary>
public string? LastName { get; init; }

/// <summary>
/// An optional query to search for custom attributes, in the format "<c>key1:value2 key2:value2</c>".
/// </summary>
public string? Query { get; init; }

/// <summary>
/// An optional search string for all the fields of a user.
/// Default search behavior is prefix-based (e.g., foo or foo*). Use foo for infix search and "foo" for exact search.
/// </summary>
public string? Search { get; init; }

/// <summary>
/// An optional filter for a user's username.
/// </summary>
public string? Username { get; init; }
}

0 comments on commit e9e7b8f

Please sign in to comment.