From 892d66ec1094cce1b81057381e5e6ca0535de5d8 Mon Sep 17 00:00:00 2001 From: Sharwin Bobde Date: Mon, 23 Oct 2023 12:10:42 +0200 Subject: [PATCH 1/6] accessing realm groups --- .../Constants/KeycloakClientApiConstants.cs | 6 ++++ .../Admin/IKeycloakClient.cs | 2 +- .../Admin/IKeycloakGroupClient.cs | 34 +++++++++++++++++++ .../Admin/Models/Group/Group.cs | 18 ++++++++++ .../Keycloak.AuthServices.Sdk.csproj | 4 +++ 5 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 src/Keycloak.AuthServices.Sdk/Admin/IKeycloakGroupClient.cs create mode 100644 src/Keycloak.AuthServices.Sdk/Admin/Models/Group/Group.cs diff --git a/src/Keycloak.AuthServices.Sdk/Admin/Constants/KeycloakClientApiConstants.cs b/src/Keycloak.AuthServices.Sdk/Admin/Constants/KeycloakClientApiConstants.cs index 360be6c8..d8080a37 100644 --- a/src/Keycloak.AuthServices.Sdk/Admin/Constants/KeycloakClientApiConstants.cs +++ b/src/Keycloak.AuthServices.Sdk/Admin/Constants/KeycloakClientApiConstants.cs @@ -40,5 +40,11 @@ internal static class KeycloakClientApiConstants internal const string ExecuteActionsEmail = $"{GetRealm}/users/{{id}}/execute-actions-email"; + + + internal const string GetGroups = $"{GetRealm}/groups"; + + internal const string GetGroup = $"{GetRealm}/groups/{{id}}"; + #endregion } diff --git a/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakClient.cs b/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakClient.cs index c0b9ee90..cfeeb70e 100644 --- a/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakClient.cs +++ b/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakClient.cs @@ -7,6 +7,6 @@ namespace Keycloak.AuthServices.Sdk.Admin; /// Aggregates multiple clients. and /// public interface IKeycloakClient - : IKeycloakRealmClient, IKeycloakProtectedResourceClient, IKeycloakUserClient + : IKeycloakRealmClient, IKeycloakProtectedResourceClient, IKeycloakUserClient, IKeycloakGroupClient { } diff --git a/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakGroupClient.cs b/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakGroupClient.cs new file mode 100644 index 00000000..6ba9eede --- /dev/null +++ b/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakGroupClient.cs @@ -0,0 +1,34 @@ +namespace Keycloak.AuthServices.Sdk.Admin; + +using System.Collections; +using System.Threading.Tasks; +using Constants; +using Models; +using Refit; +using Requests.Users; + +/// +/// Group management +/// +[Headers("Accept: application/json")] +public interface IKeycloakGroupClient +{ + + /// + /// Get a stream of groups on the realm. + /// + /// Realm name (not ID). + /// Optional query parameters. + /// A stream of groups, filtered according to query parameters. + [Get(KeycloakClientApiConstants.GetGroups)] + Task> GetGroups(string realm, [Query] GetUsersRequestParameters? parameters = default); + + /// + /// Get representation of a group. + /// + /// Realm name (not ID). + /// group ID. + /// The group representation. + [Get(KeycloakClientApiConstants.GetGroups)] + Task GetGroups(string realm, [AliasAs("id")] string groupId); +} diff --git a/src/Keycloak.AuthServices.Sdk/Admin/Models/Group/Group.cs b/src/Keycloak.AuthServices.Sdk/Admin/Models/Group/Group.cs new file mode 100644 index 00000000..6655765a --- /dev/null +++ b/src/Keycloak.AuthServices.Sdk/Admin/Models/Group/Group.cs @@ -0,0 +1,18 @@ +#pragma warning disable CS1591, CS8618 +namespace Keycloak.AuthServices.Sdk.Admin.Models; + +using System.Collections.Generic; + +/// +/// Group representation. +/// +public class Group +{ + public string? Id { get; init; } + public string? Name { get; init; } + public string? Path { get; init; } + public Dictionary? ClientRoles { get; init; } + public string[]? RealmRoles { get; init; } + public Group[]? SubGroups { get; init; } + public Dictionary? Attributes { get; init; } +} diff --git a/src/Keycloak.AuthServices.Sdk/Keycloak.AuthServices.Sdk.csproj b/src/Keycloak.AuthServices.Sdk/Keycloak.AuthServices.Sdk.csproj index 61f0c5e5..76fe3e28 100644 --- a/src/Keycloak.AuthServices.Sdk/Keycloak.AuthServices.Sdk.csproj +++ b/src/Keycloak.AuthServices.Sdk/Keycloak.AuthServices.Sdk.csproj @@ -32,4 +32,8 @@ + + + + From d429d8b3f20f54abbc6c21e724e88d4227816ad2 Mon Sep 17 00:00:00 2001 From: Sharwin Bobde Date: Mon, 23 Oct 2023 15:15:06 +0200 Subject: [PATCH 2/6] fix: unused KeycloakClientApiConstants.GetGroup --- src/Keycloak.AuthServices.Sdk/Admin/IKeycloakGroupClient.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakGroupClient.cs b/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakGroupClient.cs index 6ba9eede..441bd5a5 100644 --- a/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakGroupClient.cs +++ b/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakGroupClient.cs @@ -29,6 +29,6 @@ public interface IKeycloakGroupClient /// Realm name (not ID). /// group ID. /// The group representation. - [Get(KeycloakClientApiConstants.GetGroups)] - Task GetGroups(string realm, [AliasAs("id")] string groupId); + [Get(KeycloakClientApiConstants.GetGroup)] + Task GetGroup(string realm, [AliasAs("id")] string groupId); } From 764f3673c18a7015c8d6a02e72245346340f9065 Mon Sep 17 00:00:00 2001 From: Sharwin Bobde Date: Mon, 23 Oct 2023 15:15:41 +0200 Subject: [PATCH 3/6] feature: new endpoint to get a specific user's groups --- .../Admin/Constants/KeycloakClientApiConstants.cs | 1 + .../Admin/IKeycloakUserClient.cs | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/src/Keycloak.AuthServices.Sdk/Admin/Constants/KeycloakClientApiConstants.cs b/src/Keycloak.AuthServices.Sdk/Admin/Constants/KeycloakClientApiConstants.cs index d8080a37..7e4d7c52 100644 --- a/src/Keycloak.AuthServices.Sdk/Admin/Constants/KeycloakClientApiConstants.cs +++ b/src/Keycloak.AuthServices.Sdk/Admin/Constants/KeycloakClientApiConstants.cs @@ -39,6 +39,7 @@ internal static class KeycloakClientApiConstants internal const string SendVerifyEmail = $"{GetRealm}/users/{{id}}/send-verify-email"; internal const string ExecuteActionsEmail = $"{GetRealm}/users/{{id}}/execute-actions-email"; + internal const string GetUserGroups = $"{GetRealm}/users/{{id}}/groups"; diff --git a/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakUserClient.cs b/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakUserClient.cs index 61e36d9d..bfa6ea72 100644 --- a/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakUserClient.cs +++ b/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakUserClient.cs @@ -84,4 +84,14 @@ Task ExecuteActionsEmail(string realm, [AliasAs("id")] string userId, [Query] int? lifespan = default, [Query][AliasAs("redirect_uri")] string? redirectUri = default, [Body] List? actions = default); + + /// + /// Get a users's groups. + /// + /// Realm name (not ID). + /// User ID. + /// Optional query parameters. + /// A stream of users, filtered according to query parameters. + [Get(KeycloakClientApiConstants.GetUserGroups)] + Task> GetUserGroups(string realm, [AliasAs("id")] string userId, [Query] GetUsersRequestParameters? parameters = default); } From 0e642f3a63790d7151e85084e0e047c291cb244f Mon Sep 17 00:00:00 2001 From: Sharwin Bobde Date: Wed, 25 Oct 2023 11:43:37 +0200 Subject: [PATCH 4/6] Group Id is not nullable --- src/Keycloak.AuthServices.Sdk/Admin/Models/Group/Group.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Keycloak.AuthServices.Sdk/Admin/Models/Group/Group.cs b/src/Keycloak.AuthServices.Sdk/Admin/Models/Group/Group.cs index 6655765a..987de774 100644 --- a/src/Keycloak.AuthServices.Sdk/Admin/Models/Group/Group.cs +++ b/src/Keycloak.AuthServices.Sdk/Admin/Models/Group/Group.cs @@ -8,7 +8,7 @@ namespace Keycloak.AuthServices.Sdk.Admin.Models; /// public class Group { - public string? Id { get; init; } + public string Id { get; init; } = default!; public string? Name { get; init; } public string? Path { get; init; } public Dictionary? ClientRoles { get; init; } From be792dabc9df8074a75585976268367cd3f91f35 Mon Sep 17 00:00:00 2001 From: Sharwin Bobde Date: Wed, 25 Oct 2023 11:43:56 +0200 Subject: [PATCH 5/6] remove redundant info in comment --- src/Keycloak.AuthServices.Sdk/Admin/IKeycloakGroupClient.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakGroupClient.cs b/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakGroupClient.cs index 441bd5a5..0492f414 100644 --- a/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakGroupClient.cs +++ b/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakGroupClient.cs @@ -17,7 +17,7 @@ public interface IKeycloakGroupClient /// /// Get a stream of groups on the realm. /// - /// Realm name (not ID). + /// Realm name. /// Optional query parameters. /// A stream of groups, filtered according to query parameters. [Get(KeycloakClientApiConstants.GetGroups)] @@ -26,7 +26,7 @@ public interface IKeycloakGroupClient /// /// Get representation of a group. /// - /// Realm name (not ID). + /// Realm name. /// group ID. /// The group representation. [Get(KeycloakClientApiConstants.GetGroup)] From 0928151b6775d16c57f427bd129ce0dd662f9244 Mon Sep 17 00:00:00 2001 From: Sharwin Bobde Date: Wed, 25 Oct 2023 12:39:29 +0200 Subject: [PATCH 6/6] added GetGroupRequestParameters --- .../Admin/IKeycloakGroupClient.cs | 5 +- .../Admin/IKeycloakUserClient.cs | 3 +- .../Groups/GetGroupRequestParameters.cs | 71 +++++++++++++++++++ .../Keycloak.AuthServices.Sdk.csproj | 4 -- 4 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 src/Keycloak.AuthServices.Sdk/Admin/Requests/Groups/GetGroupRequestParameters.cs diff --git a/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakGroupClient.cs b/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakGroupClient.cs index 0492f414..acd65722 100644 --- a/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakGroupClient.cs +++ b/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakGroupClient.cs @@ -1,11 +1,10 @@ namespace Keycloak.AuthServices.Sdk.Admin; -using System.Collections; using System.Threading.Tasks; using Constants; using Models; using Refit; -using Requests.Users; +using Requests.Groups; /// /// Group management @@ -21,7 +20,7 @@ public interface IKeycloakGroupClient /// Optional query parameters. /// A stream of groups, filtered according to query parameters. [Get(KeycloakClientApiConstants.GetGroups)] - Task> GetGroups(string realm, [Query] GetUsersRequestParameters? parameters = default); + Task> GetGroups(string realm, [Query] GetGroupRequestParameters? parameters = default); /// /// Get representation of a group. diff --git a/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakUserClient.cs b/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakUserClient.cs index bfa6ea72..0d3e52a5 100644 --- a/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakUserClient.cs +++ b/src/Keycloak.AuthServices.Sdk/Admin/IKeycloakUserClient.cs @@ -3,6 +3,7 @@ using Constants; using Models; using Refit; +using Requests.Groups; using Requests.Users; /// @@ -93,5 +94,5 @@ Task ExecuteActionsEmail(string realm, [AliasAs("id")] string userId, /// Optional query parameters. /// A stream of users, filtered according to query parameters. [Get(KeycloakClientApiConstants.GetUserGroups)] - Task> GetUserGroups(string realm, [AliasAs("id")] string userId, [Query] GetUsersRequestParameters? parameters = default); + Task> GetUserGroups(string realm, [AliasAs("id")] string userId, [Query] GetGroupRequestParameters? parameters = default); } diff --git a/src/Keycloak.AuthServices.Sdk/Admin/Requests/Groups/GetGroupRequestParameters.cs b/src/Keycloak.AuthServices.Sdk/Admin/Requests/Groups/GetGroupRequestParameters.cs new file mode 100644 index 00000000..17637e92 --- /dev/null +++ b/src/Keycloak.AuthServices.Sdk/Admin/Requests/Groups/GetGroupRequestParameters.cs @@ -0,0 +1,71 @@ +namespace Keycloak.AuthServices.Sdk.Admin.Requests.Groups; + +using Keycloak.AuthServices.Sdk.Admin.Models; +using Refit; + +/// +/// Optional request parameters for the endpoint. +/// It can be called in three different ways. +/// +/// +/// +/// Don’t specify any criteria. A stream of all groups within that realm will be returned (limited by pagination). +/// +/// +/// +/// +/// If is specified, other criteria such as +/// will be ignored even though you may set them. The string will be matched against +/// the , , +/// and the of a . +/// +/// +/// +/// +/// If is unspecified but any of , , +/// or are specified, then those criteria are matched against +/// their respective fields on a entity. Combined with a logical AND. +/// +/// +/// +/// +public class GetGroupRequestParameters +{ + /// + /// Defines whether brief representations are returned. Default is false. + /// + [AliasAs("briefRepresentation")] + public bool? BriefRepresentation { get; init; } + + /// + /// Defines whether the params , , + /// and must match exactly + /// + [AliasAs("exact")] + public bool? Exact { get; init; } + + /// + /// Pagination offset. + /// + [AliasAs("first")] + public int? First { get; init; } + + /// + /// Maximum results size. Default is 100. + /// + [AliasAs("max")] + public int? Max { get; init; } + + /// + /// A query to search for custom attributes, in the format "key1:value2 key2:value2". + /// + [AliasAs("q")] + public string? Query { get; init; } + + /// + /// Search for a string contained in , , + /// or . + /// + [AliasAs("search")] + public string? Search { get; init; } +} diff --git a/src/Keycloak.AuthServices.Sdk/Keycloak.AuthServices.Sdk.csproj b/src/Keycloak.AuthServices.Sdk/Keycloak.AuthServices.Sdk.csproj index 76fe3e28..61f0c5e5 100644 --- a/src/Keycloak.AuthServices.Sdk/Keycloak.AuthServices.Sdk.csproj +++ b/src/Keycloak.AuthServices.Sdk/Keycloak.AuthServices.Sdk.csproj @@ -32,8 +32,4 @@ - - - -