diff --git a/source/backend/api/Pims.Api.csproj b/source/backend/api/Pims.Api.csproj
index b10d75ea6b..b4f44470ea 100644
--- a/source/backend/api/Pims.Api.csproj
+++ b/source/backend/api/Pims.Api.csproj
@@ -2,8 +2,8 @@
0ef6255f-9ea0-49ec-8c65-c172304b4926
- 4.0.0-67.25
- 4.0.0-67.25
+ 4.0.0-67.27
+ 4.0.0-67.27
4.0.0.67
true
16BC0468-78F6-4C91-87DA-7403C919E646
diff --git a/source/backend/dal.keycloak/Extensions/ServiceCollectionExtensions.cs b/source/backend/dal.keycloak/Extensions/ServiceCollectionExtensions.cs
index 0e2342285f..76ce80847c 100644
--- a/source/backend/dal.keycloak/Extensions/ServiceCollectionExtensions.cs
+++ b/source/backend/dal.keycloak/Extensions/ServiceCollectionExtensions.cs
@@ -16,7 +16,7 @@ public static class ServiceCollectionExtensions
public static IServiceCollection AddPimsKeycloakService(this IServiceCollection services)
{
return services.AddScoped()
- .AddScoped();
+ .AddScoped();
}
}
}
diff --git a/source/backend/dal.keycloak/PimsKeycloakService.cs b/source/backend/dal.keycloak/PimsKeycloakService.cs
index fa6669c39d..fc5381b454 100644
--- a/source/backend/dal.keycloak/PimsKeycloakService.cs
+++ b/source/backend/dal.keycloak/PimsKeycloakService.cs
@@ -20,7 +20,7 @@ namespace Pims.Dal.Keycloak
public class PimsKeycloakService : IPimsKeycloakService
{
#region Variable
- private readonly IKeycloakService _keycloakService;
+ private readonly IKeycloakRepository _keycloakRepository;
private readonly IUserRepository _userRepository;
private readonly IRoleRepository _roleRepository;
private readonly IAccessRequestRepository _accessRequestRepository;
@@ -33,19 +33,19 @@ public class PimsKeycloakService : IPimsKeycloakService
///
/// Creates a new instance of a PimsKeycloakService object, initializes with the specified arguments.
///
- ///
+ ///
///
///
///
///
public PimsKeycloakService(
- IKeycloakService keycloakService,
+ IKeycloakRepository keycloakRepository,
IUserRepository userRepository,
IRoleRepository roleRepository,
IAccessRequestRepository accessRequestRepository,
ClaimsPrincipal user)
{
- _keycloakService = keycloakService;
+ _keycloakRepository = keycloakRepository;
_userRepository = userRepository;
_roleRepository = roleRepository;
_accessRequestRepository = accessRequestRepository;
@@ -63,7 +63,7 @@ public PimsKeycloakService(
///
public async Task UpdateUserAsync(Entity.PimsUser user)
{
- var kuser = await _keycloakService.GetUserAsync(user.GuidIdentifierValue.Value) ?? throw new KeyNotFoundException("User does not exist in Keycloak");
+ var kuser = await _keycloakRepository.GetUserAsync(user.GuidIdentifierValue.Value) ?? throw new KeyNotFoundException("User does not exist in Keycloak");
var euser = _userRepository.GetTrackingById(user.Internal_Id);
return await SaveUserChanges(user, euser, kuser, true);
@@ -77,7 +77,7 @@ public PimsKeycloakService(
///
public async Task AppendToUserAsync(Entity.PimsUser update)
{
- var kuser = await _keycloakService.GetUserAsync(update.GuidIdentifierValue.Value) ?? throw new KeyNotFoundException("User does not exist in Keycloak");
+ var kuser = await _keycloakRepository.GetUserAsync(update.GuidIdentifierValue.Value) ?? throw new KeyNotFoundException("User does not exist in Keycloak");
var euser = _userRepository.GetTrackingById(update.Internal_Id);
return await SaveUserChanges(update, euser, kuser, true);
@@ -165,13 +165,13 @@ public PimsKeycloakService(
var roles = update.IsDisabled.HasValue && update.IsDisabled.Value ? System.Array.Empty() : euser.PimsUserRoles.Select(ur => _roleRepository.Find(ur.RoleId));
// Now update keycloak
- var keycloakUserGroups = await _keycloakService.GetUserGroupsAsync(euser.GuidIdentifierValue.Value);
+ var keycloakUserGroups = await _keycloakRepository.GetUserGroupsAsync(euser.GuidIdentifierValue.Value);
var newRolesToAdd = roles.Where(r => keycloakUserGroups.All(crr => crr.Name != r.Name));
var rolesToRemove = keycloakUserGroups.Where(r => roles.All(crr => crr.Name != r.Name));
var addOperations = newRolesToAdd.Select(nr => new UserRoleOperation() { Operation = "add", RoleName = nr.Name, Username = update.GetIdirUsername() });
var removeOperations = rolesToRemove.Select(rr => new UserRoleOperation() { Operation = "del", RoleName = rr.Name, Username = update.GetIdirUsername() });
- await _keycloakService.ModifyUserRoleMappings(addOperations.Concat(removeOperations));
+ await _keycloakRepository.ModifyUserRoleMappings(addOperations.Concat(removeOperations));
_userRepository.CommitTransaction();
return _userRepository.GetById(euser.Internal_Id);
diff --git a/source/backend/keycloak/Extensions/ServiceCollectionExtensions.cs b/source/backend/keycloak/Extensions/ServiceCollectionExtensions.cs
index aec90e7bfb..00bea060b9 100644
--- a/source/backend/keycloak/Extensions/ServiceCollectionExtensions.cs
+++ b/source/backend/keycloak/Extensions/ServiceCollectionExtensions.cs
@@ -12,9 +12,9 @@ public static class ServiceCollectionExtensions
///
///
///
- public static IServiceCollection AddKeycloakService(this IServiceCollection services)
+ public static IServiceCollection AddKeycloakRepository(this IServiceCollection services)
{
- return services.AddScoped();
+ return services.AddScoped();
}
}
}
diff --git a/source/backend/keycloak/IKeycloakRepository.cs b/source/backend/keycloak/IKeycloakRepository.cs
new file mode 100644
index 0000000000..bec4b6fba6
--- /dev/null
+++ b/source/backend/keycloak/IKeycloakRepository.cs
@@ -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 GetUserAsync(Guid id);
+
+ Task> GetUsersAsync(Guid id);
+
+ Task AddRolesToUser(string username, IEnumerable roles);
+
+ Task DeleteRoleFromUsers(string username, string roleName);
+
+ Task GetUserGroupsAsync(Guid id);
+
+ Task ModifyUserRoleMappings(IEnumerable operations);
+
+ Task> GetAllRoles();
+
+ Task> GetAllGroupRoles(string groupName);
+
+ Task> GetUserRoles(string username);
+
+ Task AddKeycloakRole(RoleModel role);
+
+ Task AddKeycloakRolesToGroup(string groupName, IEnumerable roles);
+
+ Task DeleteRole(string roleName);
+
+ Task DeleteRoleFromGroup(string groupName, string roleName);
+ #endregion
+ }
+}
diff --git a/source/backend/keycloak/IKeycloakService.cs b/source/backend/keycloak/IKeycloakService.cs
deleted file mode 100644
index 467897c8a8..0000000000
--- a/source/backend/keycloak/IKeycloakService.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using Pims.Keycloak.Models;
-
-namespace Pims.Keycloak
-{
- public interface IKeycloakService
- {
- #region Users
-
- Task GetUserAsync(Guid id);
-
- Task GetUserGroupsAsync(Guid id);
-
- Task ModifyUserRoleMappings(IEnumerable operations);
- #endregion
- }
-}
diff --git a/source/backend/keycloak/KeycloakRepository.cs b/source/backend/keycloak/KeycloakRepository.cs
new file mode 100644
index 0000000000..10c1177650
--- /dev/null
+++ b/source/backend/keycloak/KeycloakRepository.cs
@@ -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
+{
+ ///
+ /// 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.
+ ///
+ public partial class KeycloakRepository : IKeycloakRepository
+ {
+ #region Variables
+ private readonly IOpenIdConnectRequestClient _client;
+ #endregion
+
+ #region Properties
+
+ ///
+ /// get - The configuration options for keycloak.
+ ///
+ public Configuration.KeycloakOptions Options { get; }
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Creates a new instance of a KeycloakAdmin class, initializes it with the specified arguments.
+ ///
+ ///
+ ///
+ public KeycloakRepository(IOpenIdConnectRequestClient client, IOptions 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;
+ }
+
+ ///
+ /// Get the user for the specified 'id'.
+ ///
+ ///
+ ///
+ public async Task GetUserAsync(Guid id)
+ {
+ var users = await GetUsersAsync(id);
+ return users.FirstOrDefault();
+ }
+
+ public async Task> 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>();
+
+ return result.Data.ToList();
+ }
+
+ public async Task AddRolesToUser(string username, IEnumerable roles)
+ {
+ return await _client.PostJsonAsync($"{GetIntegrationUrl()}/users/{Uri.EscapeDataString(username)}/roles", roles);
+ }
+
+ public async Task DeleteRoleFromUsers(string username, string roleName)
+ {
+ return await _client.DeleteAsync($"{GetIntegrationUrl()}/users/{Uri.EscapeDataString(username)}/roles/{Uri.EscapeDataString(roleName)}");
+ }
+
+ ///
+ /// Get an array of the groups the user for the specified 'id' is a member of.
+ ///
+ ///
+ ///
+ public async Task GetUserGroupsAsync(Guid id)
+ {
+ var response = await _client.GetAsync($"{GetIntegrationUrl()}/user-role-mappings/?username={id.ToString().Replace("-", string.Empty)}@idir");
+
+ var userRoleModel = await response.HandleResponseAsync();
+
+ return userRoleModel.Roles.Where(r => r.Composite.HasValue && r.Composite.Value).ToArray();
+ }
+
+ ///
+ /// Get the total number of groups the user for the specified 'id' is a member of.
+ ///
+ ///
+ ///
+ public async Task GetUserGroupCountAsync(Guid id)
+ {
+ var response = await GetUserGroupsAsync(id);
+ return response.Length;
+ }
+
+ ///
+ /// execute all passed operations.
+ ///
+ ///
+ ///
+ public async Task ModifyUserRoleMappings(IEnumerable 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();
+ }
+ }
+
+ public async Task> GetAllRoles()
+ {
+ var response = await _client.GetAsync($"{GetIntegrationUrl()}/roles");
+
+ var allKeycloakRoles = await response.HandleResponseAsync>();
+ return allKeycloakRoles;
+ }
+
+ public async Task> GetAllGroupRoles(string groupName)
+ {
+ var response = await _client.GetAsync($"{GetIntegrationUrl()}/roles/{Uri.EscapeDataString(groupName)}/composite-roles");
+
+ var groupedRoles = await response.HandleResponseAsync>();
+ return groupedRoles;
+ }
+
+ public async Task> GetUserRoles(string username)
+ {
+ var response = await _client.GetAsync($"{GetIntegrationUrl()}/users/{Uri.EscapeDataString(username)}/roles");
+
+ var groupedRoles = await response.HandleResponseAsync>();
+ return groupedRoles;
+ }
+
+ public async Task AddKeycloakRole(RoleModel role)
+ {
+ var response = await _client.PostJsonAsync($"{GetIntegrationUrl()}/roles", role);
+ return response;
+ }
+
+ public async Task AddKeycloakRolesToGroup(string groupName, IEnumerable roles)
+ {
+ var response = await _client.PostJsonAsync($"{GetIntegrationUrl()}/roles/{Uri.EscapeDataString(groupName)}/composite-roles", roles);
+ return response;
+ }
+
+ public async Task DeleteRole(string roleName)
+ {
+ var response = await _client.DeleteAsync($"{GetIntegrationUrl()}/roles/{Uri.EscapeDataString(roleName)}");
+ return response;
+ }
+
+ public async Task 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
+ }
+}
diff --git a/source/backend/keycloak/KeycloakService.cs b/source/backend/keycloak/KeycloakService.cs
deleted file mode 100644
index c36c23fcf5..0000000000
--- a/source/backend/keycloak/KeycloakService.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-using Microsoft.Extensions.Options;
-using Pims.Core.Http;
-
-namespace Pims.Keycloak
-{
- ///
- /// KeycloakService 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.
- ///
- public partial class KeycloakService : IKeycloakService
- {
- #region Variables
- private readonly IOpenIdConnectRequestClient _client;
- #endregion
-
- #region Properties
-
- ///
- /// get - The configuration options for keycloak.
- ///
- public Configuration.KeycloakOptions Options { get; }
- #endregion
-
- #region Constructors
-
- ///
- /// Creates a new instance of a KeycloakAdmin class, initializes it with the specified arguments.
- ///
- ///
- ///
- public KeycloakService(IOpenIdConnectRequestClient client, IOptions 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;
- }
- #endregion
-
- #region Methods
- #endregion
- }
-}
diff --git a/source/backend/keycloak/Models/RoleModel.cs b/source/backend/keycloak/Models/RoleModel.cs
index 90c710da26..86da4ce803 100644
--- a/source/backend/keycloak/Models/RoleModel.cs
+++ b/source/backend/keycloak/Models/RoleModel.cs
@@ -15,7 +15,7 @@ public class RoleModel
///
/// get/set - whether or not this role is a composite role.
///
- public bool Composite { get; set; }
+ public bool? Composite { get; set; }
#endregion
}
}
diff --git a/source/backend/keycloak/Partials/KeycloakServiceUsers.cs b/source/backend/keycloak/Partials/KeycloakServiceUsers.cs
deleted file mode 100644
index 2a65acde05..0000000000
--- a/source/backend/keycloak/Partials/KeycloakServiceUsers.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Net.Http;
-using System.Text;
-using System.Threading.Tasks;
-using Pims.Core.Extensions;
-using Pims.Keycloak.Extensions;
-using Pims.Keycloak.Models;
-
-namespace Pims.Keycloak
-{
- ///
- /// KeycloakService class, provides a service for sending HTTP requests to the keycloak admin API.
- /// - https://api.loginproxy.gov.bc.ca/openapi/swagger#/ .
- ///
- public partial class KeycloakService : IKeycloakService
- {
- #region Methods
-
- ///
- /// Get the user for the specified 'id'.
- ///
- ///
- ///
- public async Task GetUserAsync(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>();
-
- return result.Data.FirstOrDefault();
- }
-
- ///
- /// Get an array of the groups the user for the specified 'id' is a member of.
- ///
- ///
- ///
- public async Task GetUserGroupsAsync(Guid id)
- {
- var response = await _client.GetAsync($"{this.Options.ServiceAccount.Api}/integrations/{this.Options.ServiceAccount.Integration}/{this.Options.ServiceAccount.Environment}/user-role-mappings/?username={id.ToString().Replace("-", string.Empty)}@idir");
-
- var userRoleModel = await response.HandleResponseAsync();
-
- return userRoleModel.Roles.Where(r => r.Composite).ToArray();
- }
-
- ///
- /// Get the total number of groups the user for the specified 'id' is a member of.
- ///
- ///
- ///
- public async Task GetUserGroupCountAsync(Guid id)
- {
- var response = await GetUserGroupsAsync(id);
- return response.Length;
- }
-
- ///
- /// execute all passed operations.
- ///
- ///
- ///
- public async Task ModifyUserRoleMappings(IEnumerable 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($"{this.Options.ServiceAccount.Api}/integrations/{this.Options.ServiceAccount.Integration}/{this.Options.ServiceAccount.Environment}/user-role-mappings", content);
- await response.HandleResponseAsync();
- }
- }
- #endregion
- }
-}
diff --git a/source/backend/tests/unit/dal/Libraries/Keycloak/KeycloakServiceTest.cs b/source/backend/tests/unit/dal/Libraries/Keycloak/KeycloakServiceTest.cs
index 51f7a8fd8c..13cfd43163 100644
--- a/source/backend/tests/unit/dal/Libraries/Keycloak/KeycloakServiceTest.cs
+++ b/source/backend/tests/unit/dal/Libraries/Keycloak/KeycloakServiceTest.cs
@@ -37,7 +37,7 @@ public void CreateKeycloakService_NoAuthority()
// Act
// Assert
- var result = Assert.Throws(() => helper.Create(options, user));
+ var result = Assert.Throws(() => helper.Create(options, user));
result.Message.Should().Be("The configuration for Keycloak:Authority is invalid or missing.");
}
@@ -60,7 +60,7 @@ public void CreateKeycloakService_NoAudience()
// Act
// Assert
- var result = Assert.Throws(() => helper.Create(options, user));
+ var result = Assert.Throws(() => helper.Create(options, user));
result.Message.Should().Be("The configuration for Keycloak:Audience is invalid or missing.");
}
@@ -84,7 +84,7 @@ public void CreateKeycloakService_NoClient()
// Act
// Assert
- var result = Assert.Throws(() => helper.Create(options, user));
+ var result = Assert.Throws(() => helper.Create(options, user));
result.Message.Should().Be("The configuration for Keycloak:Client is invalid or missing.");
}
@@ -109,7 +109,7 @@ public void CreateKeycloakService_NoServiceAccount()
// Act
// Assert
- var result = Assert.Throws(() => helper.Create(options, user));
+ var result = Assert.Throws(() => helper.Create(options, user));
result.Message.Should().Be("The configuration for Keycloak:ServiceAccount is invalid or missing.");
}
@@ -135,7 +135,7 @@ public void CreateKeycloakService_NoServiceAccountClient()
// Act
// Assert
- var result = Assert.Throws(() => helper.Create(options, user));
+ var result = Assert.Throws(() => helper.Create(options, user));
result.Message.Should().Be("The configuration for Keycloak:ServiceAccount:Client is invalid or missing.");
}
@@ -164,7 +164,7 @@ public void CreateKeycloakService_NoServiceAccountSecret()
// Act
// Assert
- var result = Assert.Throws(() => helper.Create(options, user));
+ var result = Assert.Throws(() => helper.Create(options, user));
result.Message.Should().Be("The configuration for Keycloak:ServiceAccount:Secret is invalid or missing.");
}
@@ -196,7 +196,7 @@ public void CreateKeycloakService()
helper.AddSingleton(openIdConnect.Object);
// Act
- var service = helper.Create(options, user);
+ var service = helper.Create(options, user);
// Assert
openIdConnect.Object.AuthClientOptions.Audience.Should().Be(options.Value.Audience);
@@ -235,7 +235,7 @@ public void CreateKeycloakService_ServiceAccount()
helper.AddSingleton(openIdConnect.Object);
// Act
- var service = helper.Create(options, user);
+ var service = helper.Create(options, user);
// Assert
openIdConnect.Object.AuthClientOptions.Audience.Should().Be(options.Value.ServiceAccount.Audience);
diff --git a/source/backend/tests/unit/dal/Libraries/Keycloak/PimsKeycloakUserServiceTest.cs b/source/backend/tests/unit/dal/Libraries/Keycloak/PimsKeycloakUserServiceTest.cs
index 84c5a8dd8f..699664fe5d 100644
--- a/source/backend/tests/unit/dal/Libraries/Keycloak/PimsKeycloakUserServiceTest.cs
+++ b/source/backend/tests/unit/dal/Libraries/Keycloak/PimsKeycloakUserServiceTest.cs
@@ -41,7 +41,7 @@ public async Task UpdateUserAsync_Success()
removeRole.RoleId = 1;
removeRole.KeycloakGroupId = Guid.NewGuid();
- var keycloakServiceMock = helper.GetMock();
+ var keycloakServiceMock = helper.GetMock();
var kuser = new Pims.Keycloak.Models.UserModel()
{
Username = euser.BusinessIdentifierValue,
@@ -112,7 +112,7 @@ public async Task UpdateUserAsync_Success_KeycloakRoleNotInPims()
removeRole.RoleId = 1;
removeRole.KeycloakGroupId = Guid.NewGuid();
- var keycloakServiceMock = helper.GetMock();
+ var keycloakServiceMock = helper.GetMock();
var groups = new string[] { Guid.NewGuid().ToString() };
var kuser = new Pims.Keycloak.Models.UserModel()
{
@@ -180,7 +180,7 @@ public async Task UpdateUserAsync_MissingKeycloakUser()
var euser = EntityHelper.CreateUser("test");
- var keycloakServiceMock = helper.GetMock();
+ var keycloakServiceMock = helper.GetMock();
keycloakServiceMock.Setup(m => m.GetUserAsync(It.IsAny())).ReturnsAsync((Pims.Keycloak.Models.UserModel)null);
// Act
@@ -204,7 +204,7 @@ public async Task UpdateUserAsync_KeycloakUserDoesNotMatch()
removeRole.RoleId = 1;
removeRole.KeycloakGroupId = Guid.NewGuid();
- var keycloakServiceMock = helper.GetMock();
+ var keycloakServiceMock = helper.GetMock();
var groups = new[] { euser.GuidIdentifierValue.Value.ToString() };
var kuser = new Pims.Keycloak.Models.UserModel()
{
@@ -254,7 +254,7 @@ public async Task UpdateUserAsync_AddRoleDoesNotExistInPims()
var removeRole = euser.GetRoles().First();
removeRole.KeycloakGroupId = Guid.NewGuid();
- var keycloakServiceMock = helper.GetMock();
+ var keycloakServiceMock = helper.GetMock();
var groups = new string[] { removeRole.KeycloakGroupId.ToString() };
var kuser = new Pims.Keycloak.Models.UserModel()
{
@@ -300,7 +300,7 @@ public async Task UpdateUserAsync_RemoveRoleDoesNotExistInPims()
removeRole.RoleId = 1;
removeRole.KeycloakGroupId = Guid.NewGuid();
- var keycloakServiceMock = helper.GetMock();
+ var keycloakServiceMock = helper.GetMock();
var groups = new string[] { removeRole.KeycloakGroupId.ToString() };
var kuser = new Pims.Keycloak.Models.UserModel()
{
@@ -346,7 +346,7 @@ public async Task AppendToUserAsync_Success_AddRole()
existingRole.RoleId = 1;
existingRole.KeycloakGroupId = Guid.NewGuid();
- var keycloakServiceMock = helper.GetMock();
+ var keycloakServiceMock = helper.GetMock();
var groups = new string[] { existingRole.KeycloakGroupId.ToString() };
var kuser = new Pims.Keycloak.Models.UserModel()
{
@@ -406,7 +406,7 @@ public async Task AppendToUserAsync_Success_AddContactMethod()
existingRole.RoleId = 1;
existingRole.KeycloakGroupId = Guid.NewGuid();
- var keycloakServiceMock = helper.GetMock();
+ var keycloakServiceMock = helper.GetMock();
var groups = new string[] { existingRole.KeycloakGroupId.ToString() };
var kuser = new Pims.Keycloak.Models.UserModel()
{
@@ -453,7 +453,7 @@ public async Task AppendToUserAsync_AddRole_KeycloakGroupIdNotFound()
existingRole.RoleId = 1;
existingRole.KeycloakGroupId = Guid.NewGuid();
- var keycloakServiceMock = helper.GetMock();
+ var keycloakServiceMock = helper.GetMock();
var groups = new string[] { existingRole.KeycloakGroupId.ToString() };
var kuser = new Pims.Keycloak.Models.UserModel()
{
@@ -489,7 +489,7 @@ public async Task AppendToUserAsync_AddRole_KeyNotFound()
existingRole.RoleId = 1;
existingRole.KeycloakGroupId = Guid.NewGuid();
- var keycloakServiceMock = helper.GetMock();
+ var keycloakServiceMock = helper.GetMock();
var groups = new string[] { existingRole.KeycloakGroupId.ToString() };
var kuser = new Pims.Keycloak.Models.UserModel()
{
@@ -525,7 +525,7 @@ public async Task UpdateAccessRequestAsync_Recieved()
var eRole = EntityHelper.CreateRole("test-role");
eRole.KeycloakGroupId = Guid.NewGuid();
- var keycloakServiceMock = helper.GetMock();
+ var keycloakServiceMock = helper.GetMock();
var groups = new string[] { eRole.KeycloakGroupId.ToString() };
var kuser = new Pims.Keycloak.Models.UserModel()
{
@@ -575,7 +575,7 @@ public async Task UpdateAccessRequestAsync_Approved()
var eRole = EntityHelper.CreateRole("test-role");
eRole.KeycloakGroupId = Guid.NewGuid();
- var keycloakServiceMock = helper.GetMock();
+ var keycloakServiceMock = helper.GetMock();
var groups = new string[] { eRole.KeycloakGroupId.ToString() };
var kuser = new Pims.Keycloak.Models.UserModel()
{
@@ -628,7 +628,7 @@ public async Task UpdateAccessRequestAsync_Approved_RegionUpdate()
var eRole = EntityHelper.CreateRole("test-role");
eRole.KeycloakGroupId = Guid.NewGuid();
- var keycloakServiceMock = helper.GetMock();
+ var keycloakServiceMock = helper.GetMock();
var groups = new string[] { eRole.KeycloakGroupId.ToString() };
var kuser = new Pims.Keycloak.Models.UserModel()
{
@@ -687,7 +687,7 @@ public async Task UpdateAccessRequestAsync_NotAuthorized()
var eAccessRequest = EntityHelper.CreateAccessRequest(1);
- var keycloakServiceMock = helper.GetMock();
+ var keycloakServiceMock = helper.GetMock();
var updatedAccessRequest = new Entity.PimsAccessRequest()
{
AccessRequestId = eAccessRequest.AccessRequestId,
diff --git a/source/backend/tests/unit/dal/Libraries/Keycloak/ServiceCollectionExtensionsTest.cs b/source/backend/tests/unit/dal/Libraries/Keycloak/ServiceCollectionExtensionsTest.cs
index 100160fe95..1c0dab6d6b 100644
--- a/source/backend/tests/unit/dal/Libraries/Keycloak/ServiceCollectionExtensionsTest.cs
+++ b/source/backend/tests/unit/dal/Libraries/Keycloak/ServiceCollectionExtensionsTest.cs
@@ -51,9 +51,9 @@ public void AddKeycloakService_Success()
services.AddScoped((s) => mockOpenIdConnectRequestClient.Object);
// Act
- var result = services.AddKeycloakService();
+ var result = services.AddKeycloakRepository();
var provider = result.BuildServiceProvider();
- var service = provider.GetService();
+ var service = provider.GetService();
// Assert
result.Should().NotBeNull();
@@ -63,7 +63,7 @@ public void AddKeycloakService_Success()
}
[Fact]
- public void AddPimsKeycloakService_Success()
+ public void AddPimsKeycloakRepository_Success()
{
// Arrange
var services = new ServiceCollection();
diff --git a/source/frontend/package.json b/source/frontend/package.json
index ebb33b8e86..b257711306 100644
--- a/source/frontend/package.json
+++ b/source/frontend/package.json
@@ -1,6 +1,6 @@
{
"name": "frontend",
- "version": "4.0.0-67.25",
+ "version": "4.0.0-67.27",
"private": true,
"dependencies": {
"@bcgov/bc-sans": "1.0.1",
diff --git a/source/frontend/src/features/mapSideBar/acquisition/tabs/compensation/update/UpdateCompensationRequisitionForm.tsx b/source/frontend/src/features/mapSideBar/acquisition/tabs/compensation/update/UpdateCompensationRequisitionForm.tsx
index a085766206..8f5277bcf0 100644
--- a/source/frontend/src/features/mapSideBar/acquisition/tabs/compensation/update/UpdateCompensationRequisitionForm.tsx
+++ b/source/frontend/src/features/mapSideBar/acquisition/tabs/compensation/update/UpdateCompensationRequisitionForm.tsx
@@ -352,10 +352,9 @@ const UpdateCompensationRequisitionForm: React.FCError: ,
- `You have selected an alternate project that is the same as the file project, please select a different project`,
+ `You have selected an alternate project that is the same as the file project, please select a different project.`,
]}
- okButtonText="Ok"
+ okButtonText="Close"
handleOk={() => {
setShowAltProjectError(false);
formikRef.current?.setFieldValue('alternateProject', '');
diff --git a/tools/core/Keycloak/Configuration/KeycloakAdminOptions.cs b/tools/core/Keycloak/Configuration/KeycloakAdminOptions.cs
deleted file mode 100644
index e89b85dd51..0000000000
--- a/tools/core/Keycloak/Configuration/KeycloakAdminOptions.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using Pims.Core.Http.Configuration;
-
-namespace Pims.Tools.Core.Keycloak.Configuration
-{
- ///
- /// KeycloakManagementOptions class, provides a way to configure the connection to Keycloak.
- ///
- public class KeycloakManagementOptions : AuthClientOptions
- {
- #region Properties
-
- ///
- /// get/set - The keycloak api route.
- ///
- public string Api { get; set; }
-
- ///
- /// get/set - The api environment.
- ///
- public string Environment { get; set; }
-
- ///
- /// get/set - The integration id.
- ///
- public int Integration { get; set; }
- #endregion
- }
-}
diff --git a/tools/core/Keycloak/Configuration/KeycloakOptions.cs b/tools/core/Keycloak/Configuration/KeycloakOptions.cs
deleted file mode 100644
index 1ac1122424..0000000000
--- a/tools/core/Keycloak/Configuration/KeycloakOptions.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using Pims.Core.Http.Configuration;
-
-namespace Pims.Tools.Core.Keycloak.Configuration
-{
- ///
- /// KeycloakOptions class, provides a way to configure the connection to Keycloak.
- ///
- public class KeycloakOptions : AuthClientOptions
- {
- #region Properties
-
- ///
- /// get/set - The keycloak realm.
- ///
- public string Realm { get; set; }
- #endregion
- }
-}
diff --git a/tools/core/Keycloak/IKeycloakRequestClient.cs b/tools/core/Keycloak/IKeycloakRequestClient.cs
deleted file mode 100644
index 05536af63c..0000000000
--- a/tools/core/Keycloak/IKeycloakRequestClient.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-namespace Pims.Tools.Core.Keycloak
-{
- ///
- /// IRequestClient interface, provides an HTTP client to make requests and handle refresh token.
- ///
- public interface IKeycloakRequestClient : IRequestClient
- {
- public string GetIntegrationEnvUri();
-
- public string GetIntegrationUri();
-
- public string GetEnvUri();
- }
-}
diff --git a/tools/core/Keycloak/KeycloakRequestClient.cs b/tools/core/Keycloak/KeycloakRequestClient.cs
deleted file mode 100644
index 6780af833f..0000000000
--- a/tools/core/Keycloak/KeycloakRequestClient.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-using System.IdentityModel.Tokens.Jwt;
-using System.Net.Http;
-using System.Text.Json;
-using System.Threading.Tasks;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
-using Pims.Core.Http.Configuration;
-using Pims.Tools.Core.Configuration;
-using Pims.Tools.Core.Keycloak.Configuration;
-
-namespace Pims.Tools.Core.Keycloak
-{
-
- ///
- /// KeycloakRequestClient class, provides a way to make HTTP requests to the keycloak management api provided by sso gold.
- ///
- public class KeycloakRequestClient : RequestClient, IKeycloakRequestClient
- {
- #region Variables
- private readonly KeycloakManagementOptions _keycloakManagementOptions;
- #endregion
-
- #region Constructors
-
- ///
- /// Creates a new instance of an KeycloakRequestClient class, initializes it with the specified arguments.
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public KeycloakRequestClient(
- IHttpClientFactory clientFactory,
- JwtSecurityTokenHandler tokenHandler,
- IOptionsMonitor keycloakManagementOptions,
- IOptionsMonitor openIdConnectOptions,
- IOptionsMonitor requestOptions,
- IOptionsMonitor serializerOptions,
- ILogger logger)
- : base(clientFactory, tokenHandler, keycloakManagementOptions, openIdConnectOptions, requestOptions, serializerOptions, logger)
- {
- this.OpenIdConnectOptions.Token = $"{keycloakManagementOptions.CurrentValue.Authority}{this.OpenIdConnectOptions.Token}";
- _keycloakManagementOptions = keycloakManagementOptions.CurrentValue;
- }
- #endregion
-
- #region Methods
-
- // Override the provided url with the base url provided with for the keycloak management api.
- public override Task SendAsync(string url, HttpMethod method = null, HttpContent content = null)
- {
- return base.SendAsync($"{_keycloakManagementOptions.Api}/{url}", method, content);
- }
-
- public override Task SendJsonAsync(string url, HttpMethod method = null, T data = null)
- {
- return base.SendJsonAsync($"{_keycloakManagementOptions.Api}/{url}", method, data);
- }
-
- // Get the integrations endpoint for a specific environment provided by the appsettings file.
- public string GetIntegrationEnvUri()
- {
- return $"integrations/{_keycloakManagementOptions.Integration}/{_keycloakManagementOptions.Environment}";
- }
-
- // Get just the integration endpoint provided by the appsettings file.
- public string GetIntegrationUri()
- {
- return $"integrations/{_keycloakManagementOptions.Integration}";
- }
-
- // Get just the environment from the appsettings file.
- public string GetEnvUri()
- {
- return $"{_keycloakManagementOptions.Environment}";
- }
- #endregion
- }
-}
diff --git a/tools/core/Keycloak/Models/ClientModel.cs b/tools/core/Keycloak/Models/ClientModel.cs
deleted file mode 100644
index c21eb8cd97..0000000000
--- a/tools/core/Keycloak/Models/ClientModel.cs
+++ /dev/null
@@ -1,206 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-namespace Pims.Tools.Core.Keycloak.Models
-{
- ///
- /// ClientModel class, provides a model to represent a keycloak client.
- ///
- public class ClientModel
- {
- #region Properties
-
- ///
- /// get/set - A unique primary key id.
- ///
- public Guid? Id { get; set; }
-
- ///
- /// get/set - A unique key identity for the client.
- ///
- public string ClientId { get; set; }
-
- ///
- /// get/set - A unique name to identify this client.
- ///
- public string Name { get; set; }
-
- ///
- /// get/set - Client description.
- ///
- public string Description { get; set; }
-
- ///
- /// get/set - Whether the client is enabled.
- ///
- public bool Enabled { get; set; }
-
- ///
- /// get/set - The client protocol.
- ///
- public string Protocol { get; set; }
-
- ///
- /// get/set - Access configuration.
- ///
- public Dictionary Access { get; set; }
-
- ///
- /// get/set - Authentication flow binding configuration.
- ///
- public Dictionary AuthenticationFlowBindingOverrides { get; set; }
-
- // public ResourceServerModel AuthorizationServicesEnabled { get; set; }
-
- ///
- /// get/set - Client authentictor type.
- ///
- public string ClientAuthenticatorType { get; set; }
-
- ///
- /// get/set - Whether consent is required.
- ///
- public bool ConsentRequired { get; set; }
-
- ///
- /// get/set - Default client scopes.
- ///
- public string[] DefaultClientScopes { get; set; }
-
- ///
- /// get/set - Default roles for new users.
- ///
- public string[] DefaultRoles { get; set; }
-
- ///
- /// get/set - Frontchannel logout.
- ///
- public bool FrontchannelLogout { get; set; }
-
- ///
- /// get/set - Whether full scope is allowed.
- ///
- public bool FullScopeAllowed { get; set; }
-
- ///
- /// get/set - Node regregistration timeout.
- ///
- public int NodeReRegistrationTimeout { get; set; } = -1;
-
- ///
- /// get/set - Not before.
- ///
- public int NotBefore { get; set; }
-
- ///
- /// get/set - Optional client scopes.
- ///
- public string[] OptionalClientScopes { get; set; }
-
- ///
- /// get/set - An array of protocol mappers.
- ///
- public ProtocolMapperModel[] ProtocolMappers { get; set; }
-
- ///
- /// get/set - Whether this is a public client.
- ///
- public bool PublicClient { get; set; }
-
- ///
- /// get/set - A dictionary of registered nodes.
- ///
- public Dictionary RegisteredNodes { get; set; }
-
- ///
- /// get/set - Registration access token.
- ///
- public string RegistrationAccessToken { get; set; }
-
- ///
- /// get/set - Whether surrogate authentication is required.
- ///
- public bool SurrogateAuthRequired { get; set; }
-
- ///
- /// get/set - Whether authorization services are enabled.
- ///
- public bool AuthorizationServicesEnabled { get; set; }
-
- ///
- /// get/set - Whether this client is a bearer only.
- ///
- public bool BearerOnly { get; set; }
-
- ///
- /// get/set - Whether client allows direct access.
- ///
- public bool DirectAccessGrantsEnabled { get; set; }
-
- ///
- /// get/set - Whether client allows implicit flow.
- ///
- public bool ImplicitFlowEnabled { get; set; }
-
- ///
- /// get/set - Whether client has a service account.
- ///
- public bool ServiceAccountsEnabled { get; set; }
-
- ///
- /// get/set - Whether client has standard flow.
- ///
- public bool StandardFlowEnabled { get; set; }
-
- ///
- /// get/set - Client secret.
- ///
- public string Secret { get; set; }
-
- ///
- /// get/set - Client base URL.
- ///
- public string BaseUrl { get; set; }
-
- ///
- /// get/set - Client root URL.
- ///
- public string RootUrl { get; set; }
-
- ///
- /// get/set - Client redirect URIs.
- ///
- public string[] RedirectUris { get; set; }
-
- ///
- /// get/set - Client origin.
- ///
- public string Origin { get; set; }
-
- ///
- /// get/set - Client web origins.
- ///
- public string[] WebOrigins { get; set; }
-
- ///
- /// get/set - Client admin URL.
- ///
- public string AdminUrl { get; set; }
-
- ///
- /// get/set - Dictionary of attributes.
- ///
- public Dictionary Attributes { get; set; }
- #endregion
-
- #region Constructors
-
- ///
- /// Creates a new instance of a ClientModel class.
- ///
- public ClientModel()
- {
- }
- #endregion
- }
-}
diff --git a/tools/core/Keycloak/Models/GroupModel.cs b/tools/core/Keycloak/Models/GroupModel.cs
deleted file mode 100644
index 9e07adcf6b..0000000000
--- a/tools/core/Keycloak/Models/GroupModel.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-namespace Pims.Tools.Core.Keycloak.Models
-{
- ///
- /// GroupModel class, provides a model to represent a keycloak group.
- ///
- public class GroupModel
- {
- #region Properties
-
- ///
- /// get/set - A unique primary key.
- ///
- public Guid? Id { get; set; }
-
- ///
- /// get/set - A unique name to identify this group.
- ///
- public string Name { get; set; }
-
- ///
- /// get/set - The full path to the group.
- ///
- public string Path { get; set; }
-
- ///
- /// get/set - An array of role names associated to this group.
- ///
- public string[] RealmRoles { get; set; }
-
- ///
- /// get/set - A dictionary of client roles.
- ///
- public Dictionary ClientRoles { get; set; }
-
- ///
- /// get/set - An array of sub-groups.
- ///
- public string[] SubGroups { get; set; }
-
- ///
- /// get/set - A dictionary of attributes.
- ///
- public Dictionary Attributes { get; set; }
- #endregion
-
- #region Constructors
-
- ///
- /// Creates a new instance of a GroupModel class.
- ///
- public GroupModel()
- {
- }
- #endregion
- }
-}
diff --git a/tools/core/Keycloak/Models/ProtocolMapperModel.cs b/tools/core/Keycloak/Models/ProtocolMapperModel.cs
deleted file mode 100644
index 3f856218c9..0000000000
--- a/tools/core/Keycloak/Models/ProtocolMapperModel.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using System.Collections.Generic;
-
-namespace Pims.Tools.Core.Keycloak.Models
-{
- ///
- /// ProtocolMapperModel class, provides a model to represent a keycloak protocol mapper.
- ///
- public class ProtocolMapperModel
- {
- #region Properties
-
- ///
- /// get/set - A primary key for the protocol mapper.
- ///
- public string Id { get; set; }
-
- ///
- /// get/set - A unique name to identify the protocol mapper.
- ///
- public string Name { get; set; }
-
- ///
- /// get/set - A protocol.
- ///
- public string Protocol { get; set; }
-
- ///
- /// get/set - The protocol mapper.
- ///
- public string ProtocolMapper { get; set; }
-
- ///
- /// get/set - The protocol mapper configuration.
- ///
- public Dictionary Config { get; set; }
- #endregion
-
- #region Constructors
-
- ///
- /// Creates a new instance of a ProtocolMapperModel class.
- ///
- public ProtocolMapperModel()
- {
- }
- #endregion
- }
-}
diff --git a/tools/core/Keycloak/Models/ResponseWrapperModel.cs b/tools/core/Keycloak/Models/ResponseWrapperModel.cs
deleted file mode 100644
index d644c95aed..0000000000
--- a/tools/core/Keycloak/Models/ResponseWrapperModel.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Pims.Tools.Core.Keycloak.Models
-{
- public class ResponseWrapperModel
- {
- #region properties
- public T Data { get; set; }
- #endregion
- }
-}
diff --git a/tools/core/Keycloak/Models/RoleModel.cs b/tools/core/Keycloak/Models/RoleModel.cs
deleted file mode 100644
index 6cc55b2086..0000000000
--- a/tools/core/Keycloak/Models/RoleModel.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-namespace Pims.Tools.Core.Keycloak.Models
-{
- ///
- /// RoleModel class, provides a model to represent a keycloak role.
- ///
- public class RoleModel
- {
- #region Properties
-
- ///
- /// get/set - A unique name to identify the role.
- ///
- public string Name { get; set; }
-
- ///
- /// get/set - true if this role has sub-roles.
- ///
- public bool? Composite { get; set; }
- #endregion
-
- #region Constructors
-
- ///
- /// Creates a new instance of a RoleModel class.
- ///
- public RoleModel()
- {
- }
- #endregion
- }
-}
diff --git a/tools/core/Keycloak/Models/UserModel.cs b/tools/core/Keycloak/Models/UserModel.cs
deleted file mode 100644
index 986d85e830..0000000000
--- a/tools/core/Keycloak/Models/UserModel.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-namespace Pims.Tools.Core.Keycloak.Models
-{
- ///
- /// UserModel class, provides a model to represent a keycloak user.
- ///
- public class UserModel
- {
- #region Properties
-
- ///
- /// get/set - The primary key IDENTITY.
- ///
- public Guid Id { get; set; }
-
- ///
- /// get/set - A unique username to identify the user.
- ///
- public string Username { get; set; }
-
- ///
- /// get/set - Whether the user is enabled.
- ///
- public bool Enabled { get; set; }
-
- ///
- /// get/set - I don't know...
- ///
- public bool Totp { get; set; }
-
- ///
- /// get/set - Whether the user's email has been verified.
- ///
- public bool EmailVerified { get; set; }
-
- ///
- /// get/set - The user's first name.
- ///
- public string FirstName { get; set; }
-
- ///
- /// get/set - The user's last name.
- ///
- public string LastName { get; set; }
-
- ///
- /// get/set - The user's email.
- ///
- public string Email { get; set; }
-
- ///
- /// get/set - A dictionary of attributes.
- ///
- public Dictionary Attributes { get; set; }
- #endregion
- }
-}
diff --git a/tools/core/Keycloak/Models/UserRoleModel.cs b/tools/core/Keycloak/Models/UserRoleModel.cs
deleted file mode 100644
index 3b42c9e498..0000000000
--- a/tools/core/Keycloak/Models/UserRoleModel.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System.Collections.Generic;
-
-namespace Pims.Tools.Core.Keycloak.Models
-{
- ///
- /// UserModel class, provides a model to represent a keycloak user.
- ///
- public class UserRoleModel
- {
- #region Properties
- public IEnumerable Users { get; set; }
-
- public IEnumerable Roles { get; set; }
- #endregion
- }
-}
diff --git a/tools/core/Keycloak/Models/UserRoleOperation.cs b/tools/core/Keycloak/Models/UserRoleOperation.cs
deleted file mode 100644
index f5f17c1ffa..0000000000
--- a/tools/core/Keycloak/Models/UserRoleOperation.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-namespace Pims.Tools.Core.Keycloak.Models
-{
- ///
- /// UserRoleOperation class, provides a model to represent a keycloak user.
- ///
- public class UserRoleOperation
- {
- #region Properties
-
- ///
- /// get/set - A unique role name to identify the role in keycloak.
- ///
- public string RoleName { get; set; }
-
- ///
- /// get/set - A unique username to identify the user in keycloak.
- ///
- public string Username { get; set; }
-
- ///
- /// get/set - An operation name, either add or remove.
- ///
- public string Operation { get; set; }
- #endregion
- }
-}
diff --git a/tools/core/Pims.Tools.Core.csproj b/tools/core/Pims.Tools.Core.csproj
deleted file mode 100644
index 8971335e88..0000000000
--- a/tools/core/Pims.Tools.Core.csproj
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
- library
- net6.0
- 1.0.0.0
- 1.0.0.0
- 561C2601-E1DB-44DE-B772-518A6FEA63D9
- Debug;Release
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tools/core/IRequestClient.cs b/tools/keycloak/sync/Client/IRequestClient.cs
similarity index 97%
rename from tools/core/IRequestClient.cs
rename to tools/keycloak/sync/Client/IRequestClient.cs
index 98e958df07..e945efcf68 100644
--- a/tools/core/IRequestClient.cs
+++ b/tools/keycloak/sync/Client/IRequestClient.cs
@@ -3,7 +3,7 @@
using System.Threading.Tasks;
using Pims.Core.Http;
-namespace Pims.Tools.Core
+namespace Pims.Tools.Keycloak.Sync
{
///
/// IRequestClient interface, provides an HTTP client to make requests and handle refresh token.
diff --git a/tools/keycloak/sync/Client/PimsRequestClient.cs b/tools/keycloak/sync/Client/PimsRequestClient.cs
index 99cc5d85d6..2df6c4abb0 100644
--- a/tools/keycloak/sync/Client/PimsRequestClient.cs
+++ b/tools/keycloak/sync/Client/PimsRequestClient.cs
@@ -5,9 +5,7 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Pims.Core.Http.Configuration;
-using Pims.Tools.Core;
-using Pims.Tools.Core.Configuration;
-using Pims.Tools.Core.Keycloak.Configuration;
+using Pims.Keycloak.Configuration;
using Pims.Tools.Keycloak.Sync.Configuration;
namespace Pims.Tools.Keycloak.Sync
diff --git a/tools/core/RequestClient.cs b/tools/keycloak/sync/Client/RequestClient.cs
similarity index 98%
rename from tools/core/RequestClient.cs
rename to tools/keycloak/sync/Client/RequestClient.cs
index 31629bb9d0..31141cbd0a 100644
--- a/tools/core/RequestClient.cs
+++ b/tools/keycloak/sync/Client/RequestClient.cs
@@ -1,7 +1,6 @@
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http;
-using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
@@ -9,11 +8,11 @@
using Microsoft.Extensions.Options;
using Pims.Core.Exceptions;
using Pims.Core.Http.Configuration;
-using Pims.Tools.Core.Configuration;
+using Pims.Tools.Keycloak.Sync.Configuration;
using Polly;
using Polly.Retry;
-namespace Pims.Tools.Core
+namespace Pims.Tools.Keycloak.Sync
{
///
/// RequestClient class, provides a way to make HTTP requests, handle errors and handle refresh tokens.
diff --git a/tools/keycloak/sync/Configuration/AuthOptions.cs b/tools/keycloak/sync/Configuration/AuthOptions.cs
index 71bd16d99b..ab98571f7b 100644
--- a/tools/keycloak/sync/Configuration/AuthOptions.cs
+++ b/tools/keycloak/sync/Configuration/AuthOptions.cs
@@ -1,5 +1,5 @@
using Pims.Core.Http.Configuration;
-using Pims.Tools.Core.Keycloak.Configuration;
+using Pims.Keycloak.Configuration;
namespace Pims.Tools.Keycloak.Sync.Configuration
{
diff --git a/tools/core/Configuration/RequestOptions.cs b/tools/keycloak/sync/Configuration/RequestOptions.cs
similarity index 94%
rename from tools/core/Configuration/RequestOptions.cs
rename to tools/keycloak/sync/Configuration/RequestOptions.cs
index 4ee47f1df5..badedeacb1 100644
--- a/tools/core/Configuration/RequestOptions.cs
+++ b/tools/keycloak/sync/Configuration/RequestOptions.cs
@@ -1,4 +1,4 @@
-namespace Pims.Tools.Core.Configuration
+namespace Pims.Tools.Keycloak.Sync.Configuration
{
///
/// RequestOptions class, provides a way to configure requests.
diff --git a/tools/keycloak/sync/Configuration/ToolOptions.cs b/tools/keycloak/sync/Configuration/ToolOptions.cs
index 6afcc5166d..4e41f14099 100644
--- a/tools/keycloak/sync/Configuration/ToolOptions.cs
+++ b/tools/keycloak/sync/Configuration/ToolOptions.cs
@@ -1,4 +1,3 @@
-using Pims.Tools.Core.Configuration;
using Pims.Tools.Keycloak.Sync.Configuration.Realm;
namespace Pims.Tools.Keycloak.Sync.Configuration
diff --git a/tools/keycloak/sync/Models/Keycloak/ClientModel.cs b/tools/keycloak/sync/Models/Keycloak/ClientModel.cs
index bac2a582fc..78e932ead3 100644
--- a/tools/keycloak/sync/Models/Keycloak/ClientModel.cs
+++ b/tools/keycloak/sync/Models/Keycloak/ClientModel.cs
@@ -1,3 +1,5 @@
+using System;
+using System.Collections.Generic;
using System.Linq;
using Pims.Tools.Keycloak.Sync.Configuration.Realm;
@@ -6,9 +8,191 @@ namespace Pims.Tools.Keycloak.Sync.Models.Keycloak
///
/// ClientModel class, provides a model to represent a keycloak client.
///
- public class ClientModel : Core.Keycloak.Models.ClientModel
+ public class ClientModel
{
#region Properties
+
+ ///
+ /// get/set - A unique primary key id.
+ ///
+ public Guid? Id { get; set; }
+
+ ///
+ /// get/set - A unique key identity for the client.
+ ///
+ public string ClientId { get; set; }
+
+ ///
+ /// get/set - A unique name to identify this client.
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// get/set - Client description.
+ ///
+ public string Description { get; set; }
+
+ ///
+ /// get/set - Whether the client is enabled.
+ ///
+ public bool Enabled { get; set; }
+
+ ///
+ /// get/set - The client protocol.
+ ///
+ public string Protocol { get; set; }
+
+ ///
+ /// get/set - Access configuration.
+ ///
+ public Dictionary Access { get; set; }
+
+ ///
+ /// get/set - Authentication flow binding configuration.
+ ///
+ public Dictionary AuthenticationFlowBindingOverrides { get; set; }
+
+ // public ResourceServerModel AuthorizationServicesEnabled { get; set; }
+
+ ///
+ /// get/set - Client authentictor type.
+ ///
+ public string ClientAuthenticatorType { get; set; }
+
+ ///
+ /// get/set - Whether consent is required.
+ ///
+ public bool ConsentRequired { get; set; }
+
+ ///
+ /// get/set - Default client scopes.
+ ///
+ public string[] DefaultClientScopes { get; set; }
+
+ ///
+ /// get/set - Default roles for new users.
+ ///
+ public string[] DefaultRoles { get; set; }
+
+ ///
+ /// get/set - Frontchannel logout.
+ ///
+ public bool FrontchannelLogout { get; set; }
+
+ ///
+ /// get/set - Whether full scope is allowed.
+ ///
+ public bool FullScopeAllowed { get; set; }
+
+ ///
+ /// get/set - Node regregistration timeout.
+ ///
+ public int NodeReRegistrationTimeout { get; set; } = -1;
+
+ ///
+ /// get/set - Not before.
+ ///
+ public int NotBefore { get; set; }
+
+ ///
+ /// get/set - Optional client scopes.
+ ///
+ public string[] OptionalClientScopes { get; set; }
+
+ ///
+ /// get/set - An array of protocol mappers.
+ ///
+ public ProtocolMapperModel[] ProtocolMappers { get; set; }
+
+ ///
+ /// get/set - Whether this is a public client.
+ ///
+ public bool PublicClient { get; set; }
+
+ ///
+ /// get/set - A dictionary of registered nodes.
+ ///
+ public Dictionary RegisteredNodes { get; set; }
+
+ ///
+ /// get/set - Registration access token.
+ ///
+ public string RegistrationAccessToken { get; set; }
+
+ ///
+ /// get/set - Whether surrogate authentication is required.
+ ///
+ public bool SurrogateAuthRequired { get; set; }
+
+ ///
+ /// get/set - Whether authorization services are enabled.
+ ///
+ public bool AuthorizationServicesEnabled { get; set; }
+
+ ///
+ /// get/set - Whether this client is a bearer only.
+ ///
+ public bool BearerOnly { get; set; }
+
+ ///
+ /// get/set - Whether client allows direct access.
+ ///
+ public bool DirectAccessGrantsEnabled { get; set; }
+
+ ///
+ /// get/set - Whether client allows implicit flow.
+ ///
+ public bool ImplicitFlowEnabled { get; set; }
+
+ ///
+ /// get/set - Whether client has a service account.
+ ///
+ public bool ServiceAccountsEnabled { get; set; }
+
+ ///
+ /// get/set - Whether client has standard flow.
+ ///
+ public bool StandardFlowEnabled { get; set; }
+
+ ///
+ /// get/set - Client secret.
+ ///
+ public string Secret { get; set; }
+
+ ///
+ /// get/set - Client base URL.
+ ///
+ public string BaseUrl { get; set; }
+
+ ///
+ /// get/set - Client root URL.
+ ///
+ public string RootUrl { get; set; }
+
+ ///
+ /// get/set - Client redirect URIs.
+ ///
+ public string[] RedirectUris { get; set; }
+
+ ///
+ /// get/set - Client origin.
+ ///
+ public string Origin { get; set; }
+
+ ///
+ /// get/set - Client web origins.
+ ///
+ public string[] WebOrigins { get; set; }
+
+ ///
+ /// get/set - Client admin URL.
+ ///
+ public string AdminUrl { get; set; }
+
+ ///
+ /// get/set - Dictionary of attributes.
+ ///
+ public Dictionary Attributes { get; set; }
#endregion
#region Constructors
diff --git a/tools/keycloak/sync/Models/Keycloak/GroupModel.cs b/tools/keycloak/sync/Models/Keycloak/GroupModel.cs
index 875b00b773..526d53d448 100644
--- a/tools/keycloak/sync/Models/Keycloak/GroupModel.cs
+++ b/tools/keycloak/sync/Models/Keycloak/GroupModel.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections.Generic;
using System.Linq;
using Pims.Tools.Keycloak.Sync.Configuration.Realm;
@@ -7,9 +8,45 @@ namespace Pims.Tools.Keycloak.Sync.Models.Keycloak
///
/// GroupModel class, provides a model to represent a keycloak group.
///
- public class GroupModel : Core.Keycloak.Models.GroupModel
+ public class GroupModel
{
#region Properties
+
+ ///
+ /// get/set - A unique primary key.
+ ///
+ public Guid? Id { get; set; }
+
+ ///
+ /// get/set - A unique name to identify this group.
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// get/set - The full path to the group.
+ ///
+ public string Path { get; set; }
+
+ ///
+ /// get/set - An array of role names associated to this group.
+ ///
+ public string[] RealmRoles { get; set; }
+
+ ///
+ /// get/set - A dictionary of client roles.
+ ///
+ public Dictionary ClientRoles { get; set; }
+
+ ///
+ /// get/set - An array of sub-groups.
+ ///
+ public string[] SubGroups { get; set; }
+
+ ///
+ /// get/set - A dictionary of attributes.
+ ///
+ public Dictionary Attributes { get; set; }
+
#endregion
#region Constructors
diff --git a/tools/keycloak/sync/Models/Keycloak/ProtocolMapperModel.cs b/tools/keycloak/sync/Models/Keycloak/ProtocolMapperModel.cs
index 965f4680e4..e35b77c51c 100644
--- a/tools/keycloak/sync/Models/Keycloak/ProtocolMapperModel.cs
+++ b/tools/keycloak/sync/Models/Keycloak/ProtocolMapperModel.cs
@@ -1,3 +1,4 @@
+using System.Collections.Generic;
using Pims.Tools.Keycloak.Sync.Configuration.Realm;
namespace Pims.Tools.Keycloak.Sync.Models.Keycloak
@@ -5,9 +6,35 @@ namespace Pims.Tools.Keycloak.Sync.Models.Keycloak
///
/// ProtocolMapperModel class, provides a model to represent a keycloak protocol mapper.
///
- public class ProtocolMapperModel : Core.Keycloak.Models.ProtocolMapperModel
+ public class ProtocolMapperModel
{
#region Properties
+
+ ///
+ /// get/set - A primary key for the protocol mapper.
+ ///
+ public string Id { get; set; }
+
+ ///
+ /// get/set - A unique name to identify the protocol mapper.
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// get/set - A protocol.
+ ///
+ public string Protocol { get; set; }
+
+ ///
+ /// get/set - The protocol mapper.
+ ///
+ public string ProtocolMapper { get; set; }
+
+ ///
+ /// get/set - The protocol mapper configuration.
+ ///
+ public Dictionary Config { get; set; }
+
#endregion
#region Constructors
diff --git a/tools/core/Keycloak/Models/RealmModel.cs b/tools/keycloak/sync/Models/Keycloak/RealmModel.cs
similarity index 100%
rename from tools/core/Keycloak/Models/RealmModel.cs
rename to tools/keycloak/sync/Models/Keycloak/RealmModel.cs
diff --git a/tools/keycloak/sync/Models/Keycloak/RoleModel.cs b/tools/keycloak/sync/Models/Keycloak/RoleModel.cs
deleted file mode 100644
index 0f6c65456d..0000000000
--- a/tools/keycloak/sync/Models/Keycloak/RoleModel.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using Pims.Tools.Keycloak.Sync.Configuration.Realm;
-
-namespace Pims.Tools.Keycloak.Sync.Models.Keycloak
-{
- ///
- /// RoleModel class, provides a model to represent a keycloak role.
- ///
- public class RoleModel : Core.Keycloak.Models.RoleModel
- {
- #region Properties
- #endregion
-
- #region Constructors
-
- ///
- /// Creates a new instance of a RoleModel class.
- ///
- public RoleModel()
- {
- }
-
- ///
- /// Creates a new instance of a RoleModel class, initializes with specified arguments.
- ///
- ///
- public RoleModel(RoleOptions role)
- {
- Name = role.Name;
- }
- #endregion
- }
-}
diff --git a/tools/keycloak/sync/Pims.Tools.Keycloak.Sync.csproj b/tools/keycloak/sync/Pims.Tools.Keycloak.Sync.csproj
index 6b9a8395d8..c097c5105a 100644
--- a/tools/keycloak/sync/Pims.Tools.Keycloak.Sync.csproj
+++ b/tools/keycloak/sync/Pims.Tools.Keycloak.Sync.csproj
@@ -36,6 +36,7 @@
+
@@ -59,7 +60,6 @@
-
diff --git a/tools/keycloak/sync/Pims.Tools.Keycloak.Sync.sln b/tools/keycloak/sync/Pims.Tools.Keycloak.Sync.sln
index c599a0a3c1..be746525eb 100644
--- a/tools/keycloak/sync/Pims.Tools.Keycloak.Sync.sln
+++ b/tools/keycloak/sync/Pims.Tools.Keycloak.Sync.sln
@@ -8,12 +8,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pims.Tools.Keycloak.Sync",
{16BC0468-78F6-4C91-87DA-7403C919E646} = {16BC0468-78F6-4C91-87DA-7403C919E646}
EndProjectSection
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pims.Tools.Core", "..\..\core\Pims.Tools.Core.csproj", "{561C2601-E1DB-44DE-B772-518A6FEA63D9}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pims.Core", "..\..\..\source\backend\core\Pims.Core.csproj", "{AC8F04FF-3164-41FB-9EDF-E468B8B77837}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pims.Api", "..\..\..\source\backend\api\Pims.Api.csproj", "{16BC0468-78F6-4C91-87DA-7403C919E646}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pims.Keycloak", "..\..\..\source\backend\keycloak\Pims.Keycloak.csproj", "{970903E9-BC53-436F-BA77-C62349546425}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -24,10 +24,6 @@ Global
{951EEA85-8BCA-4D88-9CA5-0453F447DFC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{951EEA85-8BCA-4D88-9CA5-0453F447DFC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{951EEA85-8BCA-4D88-9CA5-0453F447DFC5}.Release|Any CPU.Build.0 = Release|Any CPU
- {561C2601-E1DB-44DE-B772-518A6FEA63D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {561C2601-E1DB-44DE-B772-518A6FEA63D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {561C2601-E1DB-44DE-B772-518A6FEA63D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {561C2601-E1DB-44DE-B772-518A6FEA63D9}.Release|Any CPU.Build.0 = Release|Any CPU
{AC8F04FF-3164-41FB-9EDF-E468B8B77837}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AC8F04FF-3164-41FB-9EDF-E468B8B77837}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AC8F04FF-3164-41FB-9EDF-E468B8B77837}.Release|Any CPU.ActiveCfg = Release|Any CPU
diff --git a/tools/keycloak/sync/Program.cs b/tools/keycloak/sync/Program.cs
index 81564c8a10..270437286b 100644
--- a/tools/keycloak/sync/Program.cs
+++ b/tools/keycloak/sync/Program.cs
@@ -8,10 +8,10 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Pims.Core.Exceptions;
+using Pims.Core.Http;
using Pims.Core.Http.Configuration;
-using Pims.Tools.Core.Configuration;
-using Pims.Tools.Core.Keycloak;
-using Pims.Tools.Core.Keycloak.Configuration;
+using Pims.Keycloak;
+using Pims.Keycloak.Configuration;
using Pims.Tools.Keycloak.Sync.Configuration;
using Pims.Tools.Keycloak.Sync.Configuration.Realm;
@@ -40,7 +40,7 @@ public static async Task Main(string[] args)
.Configure(config.GetSection("Api"))
.Configure(config.GetSection("Realm"))
.Configure(config.GetSection("Auth:Keycloak"))
- .Configure(config.GetSection("Auth:Keycloak:ServiceAccount"))
+ .Configure(config.GetSection("Auth:Keycloak:ServiceAccount"))
.Configure(config.GetSection("Auth:OpenIdConnect"))
.Configure(options =>
{
@@ -78,8 +78,9 @@ public static async Task Main(string[] args)
})
.AddTransient()
.AddTransient()
- .AddScoped()
+ .AddScoped()
.AddScoped()
+ .AddScoped()
.AddTransient();
services.AddHttpClient("Pims.Tools.Keycloak.Sync", client => { });
diff --git a/tools/keycloak/sync/ISyncFactory.cs b/tools/keycloak/sync/Syncronizer/ISyncFactory.cs
similarity index 100%
rename from tools/keycloak/sync/ISyncFactory.cs
rename to tools/keycloak/sync/Syncronizer/ISyncFactory.cs
diff --git a/tools/keycloak/sync/SyncFactory.cs b/tools/keycloak/sync/Syncronizer/SyncFactory.cs
similarity index 77%
rename from tools/keycloak/sync/SyncFactory.cs
rename to tools/keycloak/sync/Syncronizer/SyncFactory.cs
index b23a229452..b91c88e093 100644
--- a/tools/keycloak/sync/SyncFactory.cs
+++ b/tools/keycloak/sync/Syncronizer/SyncFactory.cs
@@ -8,9 +8,8 @@
using Microsoft.CodeAnalysis;
using Microsoft.Extensions.Logging;
using Pims.Core.Exceptions;
-using Pims.Tools.Core.Keycloak;
-using Pims.Tools.Core.Keycloak.Models;
-using KModel = Pims.Tools.Core.Keycloak.Models;
+using Pims.Keycloak;
+using KModel = Pims.Keycloak.Models;
using PModel = Pims.Api.Models.Concepts;
namespace Pims.Tools.Keycloak.Sync
@@ -23,7 +22,7 @@ public class SyncFactory : ISyncFactory
{
#region Variables
private static readonly int MAXPAGES = 20;
- private readonly IKeycloakRequestClient _keycloakManagementClient;
+ private readonly IKeycloakRepository _keycloakRepository;
private readonly IPimsRequestClient _pimsClient;
private readonly ILogger _logger;
#endregion
@@ -33,12 +32,12 @@ public class SyncFactory : ISyncFactory
///
/// Creates a new instance of an Factory class, initializes it with the specified arguments.
///
- ///
+ ///
///
///
- public SyncFactory(IKeycloakRequestClient keycloakClient, IPimsRequestClient pimsClient, ILogger logger)
+ public SyncFactory(IKeycloakRepository keycloakRepository, IPimsRequestClient pimsClient, ILogger logger)
{
- _keycloakManagementClient = keycloakClient;
+ _keycloakRepository = keycloakRepository;
_pimsClient = pimsClient;
_logger = logger;
}
@@ -79,7 +78,7 @@ public async Task SyncAsync()
///
private async Task ActivateAccountAsync()
{
- var aRes = await _pimsClient.HandleRequestAsync (HttpMethod.Post, "auth/activate");
+ var aRes = await _pimsClient.HandleRequestAsync(HttpMethod.Post, "auth/activate");
if (!aRes.IsSuccessStatusCode)
{
throw new HttpClientRequestException(aRes);
@@ -106,7 +105,7 @@ private async Task SyncClaimsAsync(StringBuilder log, StringBuilder errorLog)
}
while (claimsPage != null && claimsPage.Items.Any() && page < MAXPAGES);
- var allKeycloakRoles = await _keycloakManagementClient.HandleRequestAsync>(HttpMethod.Get, $"{_keycloakManagementClient.GetIntegrationEnvUri()}/roles");
+ var allKeycloakRoles = await _keycloakRepository.GetAllRoles();
var keycloakRoles = allKeycloakRoles.Data.Where(x => x.Composite.HasValue && x.Composite.Value == false);
var keycloakRolesToDelete = keycloakRoles.Where(r => claims.All(crr => crr.Name != r.Name));
@@ -146,10 +145,10 @@ private async Task AddKeycloakRoleAsync(PModel.ClaimModel claim)
// Add the role to keycloak and sync with PIMS.
_logger.LogInformation($"Adding keycloak role: {claim.Name}");
- var kresponse = await _keycloakManagementClient.SendJsonAsync($"{_keycloakManagementClient.GetIntegrationEnvUri()}/roles", HttpMethod.Post, krole);
- if (kresponse.StatusCode != HttpStatusCode.Created)
+ var response = await _keycloakRepository.AddKeycloakRole(krole);
+ if (response.StatusCode != HttpStatusCode.Created)
{
- throw new HttpClientRequestException(kresponse, $"Failed to add the role '{claim.Name}' to keycloak.");
+ throw new HttpClientRequestException(response, $"Failed to add the role '{claim.Name}' to keycloak.");
}
_logger.LogInformation($"Keycloak role: {claim.Name} added");
return;
@@ -176,7 +175,7 @@ private async Task SyncRolesAsync(StringBuilder log, StringBuilder errorLog)
}
while (rolesPage != null && rolesPage.Items.Any() && page < MAXPAGES);
- var keycloakRoles = await _keycloakManagementClient.HandleRequestAsync>(HttpMethod.Get, $"{_keycloakManagementClient.GetIntegrationEnvUri()}/roles");
+ var keycloakRoles = await _keycloakRepository.GetAllRoles();
var keycloakCompositeRoles = keycloakRoles.Data.Where(x => x.Composite.HasValue && x.Composite.Value);
var keycloakRolesToDelete = keycloakCompositeRoles.Where(r => roles.All(crr => crr.Name != r.Name));
@@ -187,7 +186,7 @@ private async Task SyncRolesAsync(StringBuilder log, StringBuilder errorLog)
private async Task AddRolesFromPims(IEnumerable roles, StringBuilder log, StringBuilder errorLog)
{
- var keycloakRoles = await _keycloakManagementClient.HandleRequestAsync>(HttpMethod.Get, $"{_keycloakManagementClient.GetIntegrationEnvUri()}/roles");
+ var keycloakRoles = await _keycloakRepository.GetAllRoles();
foreach (var role in roles)
{
try
@@ -197,7 +196,7 @@ private async Task AddRolesFromPims(IEnumerable roles, StringB
{
continue;
}
-
+
_logger.LogInformation($"Adding/updating keycloak composite role '{prole.Name}'");
var matchingKeycloakGroup = keycloakRoles.Data.FirstOrDefault(r => r.Name == prole.Name);
if (matchingKeycloakGroup != null)
@@ -224,7 +223,7 @@ private async Task RemoveRolesFromPims(IEnumerable roles, Stri
try
{
_logger.LogInformation($"Deleting keycloak role '{role.Name}'");
- await _keycloakManagementClient.DeleteAsync($"{_keycloakManagementClient.GetIntegrationEnvUri()}/roles/{Uri.EscapeDataString(role.Name)}");
+ await _keycloakRepository.DeleteRole(role.Name);
LogInfo(log, $"Deleted keycloak role '{role.Name}'");
}
catch (HttpClientRequestException ex)
@@ -243,16 +242,16 @@ private async Task RemoveRolesFromPims(IEnumerable roles, Stri
///
private async Task AddGroupToKeycloak(PModel.RoleModel role)
{
- var addGroup = new KModel.RoleModel()
+ var krole = new KModel.RoleModel()
{
Name = role.Name,
};
// Add the group to keycloak and sync with PIMS.
- var response = await _keycloakManagementClient.SendJsonAsync($"{_keycloakManagementClient.GetIntegrationEnvUri()}/roles", HttpMethod.Post, addGroup);
+ var response = await _keycloakRepository.AddKeycloakRole(krole);
if (response.StatusCode == HttpStatusCode.Created)
{
- await AddRolesToGroupInKeycloak(addGroup, role);
+ await AddRolesToGroupInKeycloak(krole, role);
}
else
{
@@ -285,12 +284,12 @@ private async Task AddRolesToGroupInKeycloak(KModel.RoleModel group, PModel.Role
Name = c.Claim.Name,
}).ToArray();
- var allKeycloakGroupRolesResponse = await _keycloakManagementClient.HandleGetAsync>>($"{_keycloakManagementClient.GetIntegrationEnvUri()}/roles/{Uri.EscapeDataString(group.Name)}/composite-roles");
+ var allKeycloakGroupRolesResponse = await _keycloakRepository.GetAllGroupRoles(group.Name);
var newRolesToAdd = allPimsGroupRoles.Where(r => allKeycloakGroupRolesResponse.Data.All(crr => crr.Name != r.Name));
if (newRolesToAdd.Any())
{
_logger.LogInformation($"Adding the following roles to the composite role {role.Name}: {string.Join(',', newRolesToAdd.Select(r => r.Name))}");
- var response = await _keycloakManagementClient.SendJsonAsync($"{_keycloakManagementClient.GetIntegrationEnvUri()}/roles/{Uri.EscapeDataString(group.Name)}/composite-roles", HttpMethod.Post, newRolesToAdd);
+ var response = await _keycloakRepository.AddKeycloakRolesToGroup(group.Name, newRolesToAdd);
_logger.LogInformation($"Added the following roles to the composite role {role.Name}: {string.Join(',', newRolesToAdd.Select(r => r.Name))}");
if (!response.IsSuccessStatusCode)
{
@@ -312,14 +311,14 @@ private async Task RemoveRolesFromGroupInKeycloak(KModel.RoleModel group, PModel
Name = c.Claim.Name,
}).ToArray();
- var allKeycloakGroupRolesResponse = await _keycloakManagementClient.HandleGetAsync>>($"{_keycloakManagementClient.GetIntegrationEnvUri()}/roles/{Uri.EscapeDataString(group.Name)}/composite-roles");
+ var allKeycloakGroupRolesResponse = await _keycloakRepository.GetAllGroupRoles(group.Name);
var rolesToRemove = allKeycloakGroupRolesResponse.Data.Where(r => allPimsGroupRoles.All(crr => crr.Name != r.Name));
foreach (var roleToRemove in rolesToRemove)
{
_logger.LogInformation($"Deleting the following roles to the composite role {role.Name}: {roleToRemove}");
// Update the group in keycloak.
- var response = await _keycloakManagementClient.DeleteAsync($"{_keycloakManagementClient.GetIntegrationEnvUri()}/roles/{Uri.EscapeDataString(group.Name)}/composite-roles/{Uri.EscapeDataString(roleToRemove.Name)}");
+ var response = await _keycloakRepository.DeleteRoleFromGroup(group.Name, roleToRemove.Name);
_logger.LogInformation($"Deleting the following roles to the composite role {role.Name}: {roleToRemove}");
if (!response.IsSuccessStatusCode)
{
@@ -383,32 +382,33 @@ private async Task SyncUsersAsync(StringBuilder log, StringBuilder errorLog)
private async Task SyncUserRoles(PModel.UserModel user, StringBuilder log)
{
var username = user.GuidIdentifierValue.ToString().Replace("-", string.Empty) + "@idir";
- var kUserRoles = (await _keycloakManagementClient.HandleGetAsync>>(
- $"{_keycloakManagementClient.GetIntegrationEnvUri()}/users/{Uri.EscapeDataString(username)}/roles",
- (response) => response.StatusCode == HttpStatusCode.NotFound)).Data;
+ var response = await _keycloakRepository.GetUserRoles(username);
+ var kUserRoles = response.Data;
- IEnumerable userRolesToAdd = user.UserRoles.Where(ur => kUserRoles.All(kr => kr.Name != ur.Role.Name && ur.Role.IsDisabled == false)).Select(ur => new RoleModel() { Name = ur.Role.Name });
- IEnumerable userRolesToRemove = kUserRoles.Where(kur => user.UserRoles.All(ur => ur.Role.Name != kur.Name)).Select(ur => new RoleModel() { Name = ur.Name });
+ IEnumerable userRolesToAdd = user.UserRoles.Where(ur => kUserRoles.All(kr => kr.Name != ur.Role.Name && ur.Role.IsDisabled == false))
+ .Select(ur => new KModel.RoleModel() { Name = ur.Role.Name });
+ IEnumerable userRolesToRemove = kUserRoles.Where(kur => user.UserRoles.All(ur => ur.Role.Name != kur.Name))
+ .Select(ur => new KModel.RoleModel() { Name = ur.Name });
if (userRolesToAdd.Any())
{
_logger.LogInformation($"Executing operation 'add' on roles '{string.Join(',', userRolesToAdd.Select(r => r.Name))}' to user '{username}'");
- var response = await _keycloakManagementClient.SendJsonAsync($"{_keycloakManagementClient.GetIntegrationEnvUri()}/users/{Uri.EscapeDataString(username)}/roles", HttpMethod.Post, userRolesToAdd);
- if (!response.IsSuccessStatusCode)
+ var addResponse = await _keycloakRepository.AddRolesToUser(username, userRolesToAdd);
+ if (!addResponse.IsSuccessStatusCode)
{
- throw new HttpClientRequestException(response, $"Failed to update the user role mappings for '{username}' during operation 'add' on roles '{string.Join(',', userRolesToAdd.Select(r => r.Name))}'");
+ throw new HttpClientRequestException(addResponse, $"Failed to update the user role mappings for '{username}' during operation 'add' on roles '{string.Join(',', userRolesToAdd.Select(r => r.Name))}'");
}
LogInfo(log, $"Executed operation 'add' on roles '{string.Join(',', userRolesToAdd.Select(r => r.Name))}' to user '{username}'");
}
- foreach (RoleModel userRoleToRemove in userRolesToRemove)
+ foreach (var userRoleToRemove in userRolesToRemove)
{
_logger.LogInformation($"Executing operation 'delete' on role '{userRoleToRemove.Name}' to user '{username}'");
- var response = await _keycloakManagementClient.SendAsync($"{_keycloakManagementClient.GetIntegrationEnvUri()}/users/{Uri.EscapeDataString(username)}/roles/{Uri.EscapeDataString(userRoleToRemove.Name)}", HttpMethod.Delete);
- if (!response.IsSuccessStatusCode)
+ var deleteResponse = await _keycloakRepository.DeleteRoleFromUsers(username, userRoleToRemove.Name);
+ if (!deleteResponse.IsSuccessStatusCode)
{
- throw new HttpClientRequestException(response, $"Failed to update the user role mappings for '{username}' during operation 'delete' on role '{userRoleToRemove.Name}'");
+ throw new HttpClientRequestException(deleteResponse, $"Failed to update the user role mappings for '{username}' during operation 'delete' on role '{userRoleToRemove.Name}'");
}
LogInfo(log, $"Executed operation 'delete' on role '{userRoleToRemove.Name}' to user '{username}'");
}
@@ -425,12 +425,12 @@ private async Task SyncUserRoles(PModel.UserModel user, StringBuilder log)
try
{
// Make a request to keycloak to find a matching user.
- var response = await _keycloakManagementClient.HandleRequestAsync>>(HttpMethod.Get, $"{_keycloakManagementClient.GetEnvUri()}/idir/users?guid={user.GuidIdentifierValue.ToString().Replace("-", string.Empty)}");
- if (response.Data.Count() > 1)
+ var users = await _keycloakRepository.GetUsersAsync(user.GuidIdentifierValue);
+ if (users.Count() > 1)
{
throw new HttpClientRequestException($"Found multiple users in keycloak for GUID: user: {user.GuidIdentifierValue.ToString()}");
}
- return response.Data.FirstOrDefault();
+ return users.FirstOrDefault();
}
catch (HttpClientRequestException ex)
{