-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Keycloak Refactor #3624
Keycloak Refactor #3624
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Net.Http; | ||
using System.Threading.Tasks; | ||
using Pims.Keycloak.Models; | ||
|
||
namespace Pims.Keycloak | ||
{ | ||
public interface IKeycloakRepository | ||
{ | ||
#region Users | ||
|
||
Task<UserModel> GetUserAsync(Guid id); | ||
|
||
Task<List<UserModel>> GetUsersAsync(Guid id); | ||
|
||
Task<HttpResponseMessage> AddRolesToUser(string username, IEnumerable<RoleModel> roles); | ||
|
||
Task<HttpResponseMessage> DeleteRoleFromUsers(string username, string roleName); | ||
|
||
Task<RoleModel[]> GetUserGroupsAsync(Guid id); | ||
|
||
Task ModifyUserRoleMappings(IEnumerable<UserRoleOperation> operations); | ||
|
||
Task<ResponseWrapper<RoleModel>> GetAllRoles(); | ||
|
||
Task<ResponseWrapper<RoleModel>> GetAllGroupRoles(string groupName); | ||
|
||
Task<ResponseWrapper<RoleModel>> GetUserRoles(string username); | ||
|
||
Task<HttpResponseMessage> AddKeycloakRole(RoleModel role); | ||
|
||
Task<HttpResponseMessage> AddKeycloakRolesToGroup(string groupName, IEnumerable<RoleModel> roles); | ||
|
||
Task<HttpResponseMessage> DeleteRole(string roleName); | ||
|
||
Task<HttpResponseMessage> DeleteRoleFromGroup(string groupName, string roleName); | ||
#endregion | ||
} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Net.Http; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Microsoft.Extensions.Options; | ||
using Pims.Core.Extensions; | ||
using Pims.Core.Http; | ||
using Pims.Keycloak.Extensions; | ||
using Pims.Keycloak.Models; | ||
|
||
namespace Pims.Keycloak | ||
{ | ||
/// <summary> | ||
/// KeycloakRepository class, provides a service for sending HTTP requests to the keycloak admin API. | ||
/// - https://www.keycloak.org/docs-api/5.0/rest-api/index.html#_overview. | ||
/// </summary> | ||
public partial class KeycloakRepository : IKeycloakRepository | ||
{ | ||
#region Variables | ||
private readonly IOpenIdConnectRequestClient _client; | ||
#endregion | ||
|
||
#region Properties | ||
|
||
/// <summary> | ||
/// get - The configuration options for keycloak. | ||
/// </summary> | ||
public Configuration.KeycloakOptions Options { get; } | ||
#endregion | ||
|
||
#region Constructors | ||
|
||
/// <summary> | ||
/// Creates a new instance of a KeycloakAdmin class, initializes it with the specified arguments. | ||
/// </summary> | ||
/// <param name="client"></param> | ||
/// <param name="options"></param> | ||
public KeycloakRepository(IOpenIdConnectRequestClient client, IOptions<Configuration.KeycloakOptions> options) | ||
{ | ||
this.Options = options.Value; | ||
this.Options.Validate(); | ||
this.Options.ServiceAccount.Validate(); | ||
_client = client; | ||
_client.AuthClientOptions.Audience = this.Options.ServiceAccount.Audience ?? this.Options.Audience; | ||
_client.AuthClientOptions.Authority = this.Options.ServiceAccount.Authority ?? this.Options.Authority; | ||
_client.AuthClientOptions.Client = this.Options.ServiceAccount.Client; | ||
_client.AuthClientOptions.Secret = this.Options.ServiceAccount.Secret; | ||
} | ||
|
||
/// <summary> | ||
/// Get the user for the specified 'id'. | ||
/// </summary> | ||
/// <param name="id"></param> | ||
/// <returns></returns> | ||
public async Task<UserModel> GetUserAsync(Guid id) | ||
{ | ||
var users = await GetUsersAsync(id); | ||
return users.FirstOrDefault(); | ||
} | ||
|
||
public async Task<List<UserModel>> GetUsersAsync(Guid id) | ||
{ | ||
var response = await _client.GetAsync($"{this.Options.ServiceAccount.Api}/{this.Options.ServiceAccount.Environment}/idir/users?guid={id.ToString().Replace("-", string.Empty)}"); | ||
var result = await response.HandleResponseAsync<ResponseWrapper<UserModel>>(); | ||
|
||
return result.Data.ToList(); | ||
} | ||
|
||
public async Task<HttpResponseMessage> AddRolesToUser(string username, IEnumerable<RoleModel> roles) | ||
{ | ||
return await _client.PostJsonAsync($"{GetIntegrationUrl()}/users/{Uri.EscapeDataString(username)}/roles", roles); | ||
} | ||
|
||
public async Task<HttpResponseMessage> DeleteRoleFromUsers(string username, string roleName) | ||
{ | ||
return await _client.DeleteAsync($"{GetIntegrationUrl()}/users/{Uri.EscapeDataString(username)}/roles/{Uri.EscapeDataString(roleName)}"); | ||
} | ||
|
||
/// <summary> | ||
/// Get an array of the groups the user for the specified 'id' is a member of. | ||
/// </summary> | ||
/// <param name="id"></param> | ||
/// <returns></returns> | ||
public async Task<RoleModel[]> GetUserGroupsAsync(Guid id) | ||
{ | ||
var response = await _client.GetAsync($"{GetIntegrationUrl()}/user-role-mappings/?username={id.ToString().Replace("-", string.Empty)}@idir"); | ||
|
||
var userRoleModel = await response.HandleResponseAsync<UserRoleModel>(); | ||
|
||
return userRoleModel.Roles.Where(r => r.Composite.HasValue && r.Composite.Value).ToArray(); | ||
} | ||
|
||
/// <summary> | ||
/// Get the total number of groups the user for the specified 'id' is a member of. | ||
/// </summary> | ||
/// <param name="id"></param> | ||
/// <returns></returns> | ||
public async Task<int> GetUserGroupCountAsync(Guid id) | ||
{ | ||
var response = await GetUserGroupsAsync(id); | ||
return response.Length; | ||
} | ||
|
||
/// <summary> | ||
/// execute all passed operations. | ||
/// </summary> | ||
/// <param name="operations"></param> | ||
/// <returns></returns> | ||
public async Task ModifyUserRoleMappings(IEnumerable<UserRoleOperation> operations) | ||
{ | ||
foreach (UserRoleOperation operation in operations) | ||
{ | ||
var json = operation.Serialize(); | ||
using var content = new StringContent(json, Encoding.UTF8, "application/json"); | ||
var response = await _client.PostAsync($"{GetIntegrationUrl()}/user-role-mappings", content); | ||
await response.HandleResponseAsync<UserRoleModel>(); | ||
} | ||
} | ||
|
||
public async Task<ResponseWrapper<RoleModel>> GetAllRoles() | ||
{ | ||
var response = await _client.GetAsync($"{GetIntegrationUrl()}/roles"); | ||
|
||
var allKeycloakRoles = await response.HandleResponseAsync<ResponseWrapper<RoleModel>>(); | ||
return allKeycloakRoles; | ||
} | ||
|
||
public async Task<ResponseWrapper<RoleModel>> GetAllGroupRoles(string groupName) | ||
{ | ||
var response = await _client.GetAsync($"{GetIntegrationUrl()}/roles/{Uri.EscapeDataString(groupName)}/composite-roles"); | ||
|
||
var groupedRoles = await response.HandleResponseAsync<ResponseWrapper<RoleModel>>(); | ||
return groupedRoles; | ||
} | ||
|
||
public async Task<ResponseWrapper<RoleModel>> GetUserRoles(string username) | ||
{ | ||
var response = await _client.GetAsync($"{GetIntegrationUrl()}/users/{Uri.EscapeDataString(username)}/roles"); | ||
|
||
var groupedRoles = await response.HandleResponseAsync<ResponseWrapper<RoleModel>>(); | ||
return groupedRoles; | ||
} | ||
|
||
public async Task<HttpResponseMessage> AddKeycloakRole(RoleModel role) | ||
{ | ||
var response = await _client.PostJsonAsync($"{GetIntegrationUrl()}/roles", role); | ||
return response; | ||
} | ||
|
||
public async Task<HttpResponseMessage> AddKeycloakRolesToGroup(string groupName, IEnumerable<RoleModel> roles) | ||
{ | ||
var response = await _client.PostJsonAsync($"{GetIntegrationUrl()}/roles/{Uri.EscapeDataString(groupName)}/composite-roles", roles); | ||
return response; | ||
} | ||
|
||
public async Task<HttpResponseMessage> DeleteRole(string roleName) | ||
{ | ||
var response = await _client.DeleteAsync($"{GetIntegrationUrl()}/roles/{Uri.EscapeDataString(roleName)}"); | ||
return response; | ||
} | ||
|
||
public async Task<HttpResponseMessage> DeleteRoleFromGroup(string groupName, string roleName) | ||
{ | ||
var response = await _client.DeleteAsync($"{GetIntegrationUrl()}/roles/{Uri.EscapeDataString(groupName)}/composite-roles/{Uri.EscapeDataString(roleName)}"); | ||
return response; | ||
} | ||
|
||
private string GetIntegrationUrl() | ||
{ | ||
return $"{this.Options.ServiceAccount.Api}/integrations/{this.Options.ServiceAccount.Integration}/{this.Options.ServiceAccount.Environment}"; | ||
} | ||
#endregion | ||
|
||
#region Methods | ||
#endregion | ||
} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,7 +15,7 @@ public class RoleModel | |
/// <summary> | ||
/// get/set - whether or not this role is a composite role. | ||
/// </summary> | ||
public bool Composite { get; set; } | ||
public bool? Composite { get; set; } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was this incorrect in the current implementation? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It was inconsistent between the two models |
||
#endregion | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was actually renamed to IKeycloackRepository.cs same with the implementation file