diff --git a/src/keycloak/Keycloak.Seeding/BusinessLogic/AuthenticationFlowsUpdater.cs b/src/keycloak/Keycloak.Seeding/BusinessLogic/AuthenticationFlowsUpdater.cs index 233b5b68ab..bddc3393b5 100644 --- a/src/keycloak/Keycloak.Seeding/BusinessLogic/AuthenticationFlowsUpdater.cs +++ b/src/keycloak/Keycloak.Seeding/BusinessLogic/AuthenticationFlowsUpdater.cs @@ -50,17 +50,20 @@ public async Task UpdateAuthenticationFlows(CancellationToken cancellationToken) var flows = await keycloak.GetAuthenticationFlowsAsync(_realm, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); var seedFlows = seedDataHandler.TopLevelCustomAuthenticationFlows; var topLevelCustomFlows = flows.Where(flow => !(flow.BuiltIn ?? false) && (flow.TopLevel ?? false)); - var seederConfig = seedDataHandler.Configuration; + var seederConfiguration = seedDataHandler.GetSpecificConfiguration(ConfigurationKeys.AuthenticationFlows); + var authFlowExecutionConfig = seedDataHandler.GetSpecificConfiguration(ConfigurationKeys.AuthenticationFlowExecution); + var authenticatorConfig = seedDataHandler.GetSpecificConfiguration(ConfigurationKeys.AuthenticatorConfig); - await DeleteRedundantAuthenticationFlows(topLevelCustomFlows, seedFlows, seederConfig, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); - await AddMissingAuthenticationFlows(topLevelCustomFlows, seedFlows, seederConfig, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); - await UpdateExistingAuthenticationFlows(topLevelCustomFlows, seedFlows, seederConfig, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); + await DeleteRedundantAuthenticationFlows(topLevelCustomFlows, seedFlows, seederConfiguration, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); + await AddMissingAuthenticationFlows(topLevelCustomFlows, seedFlows, seederConfiguration, authenticatorConfig, authFlowExecutionConfig, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); + await UpdateExistingAuthenticationFlows(topLevelCustomFlows, seedFlows, seederConfiguration, authenticatorConfig, authFlowExecutionConfig, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); } - private async Task DeleteRedundantAuthenticationFlows(IEnumerable topLevelCustomFlows, IEnumerable seedFlows, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private async Task DeleteRedundantAuthenticationFlows(IEnumerable topLevelCustomFlows, IEnumerable seedFlows, KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { - foreach (var delete in topLevelCustomFlows.ExceptBy(seedFlows.Select(x => x.Alias), x => x.Alias) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.AuthenticationFlows, ModificationType.Delete, x.Alias))) + foreach (var delete in topLevelCustomFlows + .Where(x => seederConfig.ModificationAllowed(ModificationType.Delete, x.Alias)) + .ExceptBy(seedFlows.Select(x => x.Alias), x => x.Alias)) { if (delete.Id == null) @@ -69,24 +72,25 @@ private async Task DeleteRedundantAuthenticationFlows(IEnumerable topLevelCustomFlows, IEnumerable seedFlows, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private async Task AddMissingAuthenticationFlows(IEnumerable topLevelCustomFlows, IEnumerable seedFlows, KeycloakSeederConfigModel seederConfig, KeycloakSeederConfigModel authenticatorConfig, KeycloakSeederConfigModel authFlowExecutionConfig, CancellationToken cancellationToken) { - foreach (var addFlow in seedFlows.ExceptBy(topLevelCustomFlows.Select(x => x.Alias), x => x.Alias)) + foreach (var addFlow in seedFlows + .ExceptBy(topLevelCustomFlows.Select(x => x.Alias), x => x.Alias)) { if (addFlow.Alias == null) throw new ConflictException($"authenticationFlow.Alias is null {addFlow.Id} {addFlow.Description}"); if (addFlow.BuiltIn ?? false) throw new ConflictException($"authenticationFlow.buildIn is true. flow cannot be added: {addFlow.Alias}"); - if (seederConfig.ModificationAllowed(ConfigurationKeys.AuthenticationFlows, ModificationType.Create, addFlow.Alias)) + if (seederConfig.ModificationAllowed(ModificationType.Create, addFlow.Alias)) { await keycloak.CreateAuthenticationFlowAsync(_realm, CreateUpdateAuthenticationFlow(null, addFlow), cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); } - await UpdateAuthenticationFlowExecutions(addFlow.Alias, seederConfig, cancellationToken); + await UpdateAuthenticationFlowExecutions(addFlow.Alias, authenticatorConfig, authFlowExecutionConfig, cancellationToken); } } - private async Task UpdateExistingAuthenticationFlows(IEnumerable topLevelCustomFlows, IEnumerable seedFlows, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private async Task UpdateExistingAuthenticationFlows(IEnumerable topLevelCustomFlows, IEnumerable seedFlows, KeycloakSeederConfigModel seederConfig, KeycloakSeederConfigModel authenticatorConfig, KeycloakSeederConfigModel authFlowExecutionConfig, CancellationToken cancellationToken) { foreach (var (flow, seed) in topLevelCustomFlows .Join( @@ -94,7 +98,7 @@ private async Task UpdateExistingAuthenticationFlows(IEnumerable x.Alias, x => x.Alias, (flow, seed) => (Flow: flow, Seed: seed)) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.AuthenticationFlows, ModificationType.Update, x.Flow.Alias))) + .Where(x => seederConfig.ModificationAllowed(ModificationType.Update, x.Flow.Alias))) { if (flow.Id == null) throw new ConflictException($"authenticationFlow.id is null {flow.Alias} {flow.Description}"); @@ -105,7 +109,7 @@ private async Task UpdateExistingAuthenticationFlows(IEnumerable executions, IEnumerable updateExecutions) => @@ -149,22 +153,22 @@ private bool CompareStructureRecursive(IReadOnlyList executions, (x.Node.Execution.AuthenticationFlow ?? false) == (x.Update.AuthenticatorFlow ?? false) && (!(x.Node.Execution.AuthenticationFlow ?? false) || CompareStructureRecursive(x.Node.Children, seedDataHandler.GetAuthenticationExecutions(x.Update.FlowAlias)))); - private async Task DeleteExecutionsRecursive(IEnumerable executionNodes, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private async Task DeleteExecutionsRecursive(IEnumerable executionNodes, KeycloakSeederConfigModel authFlowExecutionConfig, CancellationToken cancellationToken) { - foreach (var executionNode in executionNodes.Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.AuthenticationFlowExecution, ModificationType.Delete, x.Execution.Id))) + foreach (var executionNode in executionNodes.Where(x => authFlowExecutionConfig.ModificationAllowed(ModificationType.Delete, x.Execution.Id))) { if (executionNode.Execution.AuthenticationFlow ?? false) { - await DeleteExecutionsRecursive(executionNode.Children, seederConfig, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); + await DeleteExecutionsRecursive(executionNode.Children, authFlowExecutionConfig, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); } await keycloak.DeleteAuthenticationExecutionAsync(_realm, executionNode.Execution.Id ?? throw new ConflictException("authenticationFlow.Id is null"), cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); } } - private async Task AddExecutionsRecursive(string? alias, IEnumerable seedExecutions, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private async Task AddExecutionsRecursive(string? alias, IEnumerable seedExecutions, KeycloakSeederConfigModel authFlowExecutionConfig, CancellationToken cancellationToken) { - foreach (var execution in seedExecutions.Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.AuthenticationFlowExecution, ModificationType.Delete, x.FlowAlias))) + foreach (var execution in seedExecutions.Where(x => authFlowExecutionConfig.ModificationAllowed(ModificationType.Delete, x.FlowAlias))) { await (execution.AuthenticatorFlow switch { @@ -176,16 +180,16 @@ private async Task AddExecutionsRecursive(string? alias, IEnumerable executionNodes, IEnumerable seedExecutions, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private async Task UpdateExecutionsRecursive(string alias, IReadOnlyCollection executionNodes, IEnumerable seedExecutions, KeycloakSeederConfigModel authenticatorConfig, KeycloakSeederConfigModel authFlowExecutionConfig, CancellationToken cancellationToken) { if (executionNodes.Count != seedExecutions.Count()) throw new ArgumentException("number of elements in executionNodes doesn't match seedData"); - foreach (var (executionNode, update) in executionNodes.Zip(seedExecutions).Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.AuthenticationFlowExecution, ModificationType.Update, x.First.Execution.Id))) + foreach (var (executionNode, update) in executionNodes.Where(x => authFlowExecutionConfig.ModificationAllowed(ModificationType.Update, x.Execution.Id)).Zip(seedExecutions)) { if ((executionNode.Execution.AuthenticationFlow ?? false) != (update.AuthenticatorFlow ?? false)) throw new ArgumentException("execution.AuthenticatorFlow doesn't match seedData"); @@ -227,14 +231,15 @@ await UpdateExecutionsRecursive( update.FlowAlias!, executionNode.Children, executions, - seederConfig, + authenticatorConfig, + authFlowExecutionConfig, ct).ConfigureAwait(ConfigureAwaitOptions.None); } async Task UpdateAuthenticationExecution(ExecutionNode executionNode, AuthenticationExecutionModel update, CancellationToken ct) { - var (isEqual, authenticatorConfig) = await CompareExecutions(executionNode.Execution, update, ct).ConfigureAwait(ConfigureAwaitOptions.None); - if (!isEqual && seederConfig.ModificationAllowed(ConfigurationKeys.AuthenticationFlowExecution, ModificationType.Update, executionNode.Execution.Id)) + var (isEqual, config) = await CompareExecutions(executionNode.Execution, update, ct).ConfigureAwait(ConfigureAwaitOptions.None); + if (!isEqual && authFlowExecutionConfig.ModificationAllowed(ModificationType.Update, executionNode.Execution.Id)) { await keycloak.UpdateAuthenticationFlowExecutionsAsync( _realm, @@ -252,19 +257,19 @@ await keycloak.UpdateAuthenticationFlowExecutionsAsync( }, ct).ConfigureAwait(ConfigureAwaitOptions.None); - await UpdateAuthenticatorConfig(executionNode.Execution, update, authenticatorConfig, seederConfig, ct).ConfigureAwait(ConfigureAwaitOptions.None); + await UpdateAuthenticatorConfig(executionNode.Execution, update, config, authenticatorConfig, ct).ConfigureAwait(ConfigureAwaitOptions.None); } } } - private async Task UpdateAuthenticatorConfig(AuthenticationFlowExecution execution, AuthenticationExecutionModel update, AuthenticatorConfig? config, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private async Task UpdateAuthenticatorConfig(AuthenticationFlowExecution execution, AuthenticationExecutionModel update, AuthenticatorConfig? config, KeycloakSeederConfigModel authenticatorConfig, CancellationToken cancellationToken) { switch (execution.AuthenticationConfig, update.AuthenticatorConfig) { case (null, null): break; - case (null, var _) when seederConfig.ModificationAllowed(ConfigurationKeys.AuthenticatorConfig, ModificationType.Create, update.AuthenticatorConfig): + case (null, var _) when authenticatorConfig.ModificationAllowed(ModificationType.Create, update.AuthenticatorConfig): await keycloak.CreateAuthenticationExecutionConfigurationAsync( _realm, execution.Id!, @@ -276,14 +281,14 @@ await keycloak.CreateAuthenticationExecutionConfigurationAsync( cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); break; - case (var _, null) when seederConfig.ModificationAllowed(ConfigurationKeys.AuthenticatorConfig, ModificationType.Delete, update.AuthenticatorConfig): + case (var _, null) when authenticatorConfig.ModificationAllowed(ModificationType.Delete, update.AuthenticatorConfig): await keycloak.DeleteAuthenticatorConfigurationAsync( _realm, execution.AuthenticationConfig, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); break; - case var (_, _) when seederConfig.ModificationAllowed(ConfigurationKeys.AuthenticatorConfig, ModificationType.Update, update.AuthenticatorConfig): + case var (_, _) when authenticatorConfig.ModificationAllowed(ModificationType.Update, update.AuthenticatorConfig): var updateConfig = seedDataHandler.GetAuthenticatorConfig(update.AuthenticatorConfig); if (config == null) throw new UnexpectedConditionException("authenticatorConfig is null"); diff --git a/src/keycloak/Keycloak.Seeding/BusinessLogic/ClientScopeMapperUpdater.cs b/src/keycloak/Keycloak.Seeding/BusinessLogic/ClientScopeMapperUpdater.cs index 4b4c6021e9..7db91ecf43 100644 --- a/src/keycloak/Keycloak.Seeding/BusinessLogic/ClientScopeMapperUpdater.cs +++ b/src/keycloak/Keycloak.Seeding/BusinessLogic/ClientScopeMapperUpdater.cs @@ -34,7 +34,7 @@ public async Task UpdateClientScopeMapper(string instanceName, CancellationToken { var keycloak = keycloakFactory.CreateKeycloakClient(instanceName); var realm = seedDataHandler.Realm; - var seederConfig = seedDataHandler.Configuration; + var seederConfig = seedDataHandler.GetSpecificConfiguration(ConfigurationKeys.ClientScopes); var clients = await keycloak.GetClientsAsync(realm, null, true, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); foreach (var (clientName, mappingModels) in seedDataHandler.ClientScopeMappings) @@ -60,15 +60,15 @@ public async Task UpdateClientScopeMapper(string instanceName, CancellationToken } } - private static async Task AddAndDeleteRoles(KeycloakClient keycloak, string realm, string clientScopeId, string clientId, IEnumerable roles, IEnumerable updateRoles, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private static async Task AddAndDeleteRoles(KeycloakClient keycloak, string realm, string clientScopeId, string clientId, IEnumerable roles, IEnumerable updateRoles, KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { await updateRoles.ExceptBy(roles.Select(role => role.Name), roleModel => roleModel.Name) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.ClientScopes, ModificationType.Create, x.Name)) + .Where(x => seederConfig.ModificationAllowed(ModificationType.Create, x.Name)) .IfAnyAwait(rolesToAdd => keycloak.AddClientRolesScopeMappingToClientAsync(realm, clientScopeId, clientId, rolesToAdd, cancellationToken)).ConfigureAwait(false); await roles.ExceptBy(updateRoles.Select(roleModel => roleModel.Name), role => role.Name) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.ClientScopes, ModificationType.Delete, x.Name)) + .Where(x => seederConfig.ModificationAllowed(ModificationType.Delete, x.Name)) .IfAnyAwait(rolesToDelete => keycloak.RemoveClientRolesFromClientScopeForClientAsync(realm, clientScopeId, clientId, rolesToDelete, cancellationToken)).ConfigureAwait(false); } diff --git a/src/keycloak/Keycloak.Seeding/BusinessLogic/ClientScopesUpdater.cs b/src/keycloak/Keycloak.Seeding/BusinessLogic/ClientScopesUpdater.cs index 2f9e8eedb5..aa61ff9f49 100644 --- a/src/keycloak/Keycloak.Seeding/BusinessLogic/ClientScopesUpdater.cs +++ b/src/keycloak/Keycloak.Seeding/BusinessLogic/ClientScopesUpdater.cs @@ -34,19 +34,19 @@ public async Task UpdateClientScopes(string instanceName, CancellationToken canc { var keycloak = keycloakFactory.CreateKeycloakClient(instanceName); var realm = seedDataHandler.Realm; - var seederConfig = seedDataHandler.Configuration; + var seederConfig = seedDataHandler.GetSpecificConfiguration(ConfigurationKeys.ClientScopes); var clientScopes = await keycloak.GetClientScopesAsync(realm, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); var seedClientScopes = seedDataHandler.ClientScopes; - await CheckAndExecute(ConfigurationKeys.ClientScopes, ModificationType.Delete, keycloak, realm, clientScopes, seedClientScopes, seederConfig, cancellationToken, RemoveObsoleteClientScopes).ConfigureAwait(ConfigureAwaitOptions.None); - await CheckAndExecute(ConfigurationKeys.ClientScopes, ModificationType.Create, keycloak, realm, clientScopes, seedClientScopes, seederConfig, cancellationToken, CreateMissingClientScopes).ConfigureAwait(ConfigureAwaitOptions.None); - await CheckAndExecute(ConfigurationKeys.ClientScopes, ModificationType.Update, keycloak, realm, clientScopes, seedClientScopes, seederConfig, cancellationToken, UpdateExistingClientScopes).ConfigureAwait(ConfigureAwaitOptions.None); + await CheckAndExecute(ModificationType.Delete, keycloak, realm, clientScopes, seedClientScopes, seederConfig, cancellationToken, RemoveObsoleteClientScopes).ConfigureAwait(ConfigureAwaitOptions.None); + await CheckAndExecute(ModificationType.Create, keycloak, realm, clientScopes, seedClientScopes, seederConfig, cancellationToken, CreateMissingClientScopes).ConfigureAwait(ConfigureAwaitOptions.None); + await CheckAndExecute(ModificationType.Update, keycloak, realm, clientScopes, seedClientScopes, seederConfig, cancellationToken, UpdateExistingClientScopes).ConfigureAwait(ConfigureAwaitOptions.None); } - private static async Task CheckAndExecute(ConfigurationKeys configKey, ModificationType modificationType, KeycloakClient keycloak, string realm, IEnumerable clientScopes, IEnumerable seedClientScopes, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken, Func, IEnumerable, KeycloakRealmSettings, CancellationToken, Task> executeLogic) + private static async Task CheckAndExecute(ModificationType modificationType, KeycloakClient keycloak, string realm, IEnumerable clientScopes, IEnumerable seedClientScopes, KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken, Func, IEnumerable, KeycloakSeederConfigModel, CancellationToken, Task> executeLogic) { - if (!seederConfig.ModificationAllowed(configKey, modificationType)) + if (!seederConfig.ModificationAllowed(modificationType)) { return; } @@ -54,10 +54,11 @@ private static async Task CheckAndExecute(ConfigurationKeys configKey, Modificat await executeLogic(keycloak, realm, clientScopes, seedClientScopes, seederConfig, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); } - private static async Task RemoveObsoleteClientScopes(KeycloakClient keycloak, string realm, IEnumerable clientScopes, IEnumerable seedClientScopes, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private static async Task RemoveObsoleteClientScopes(KeycloakClient keycloak, string realm, IEnumerable clientScopes, IEnumerable seedClientScopes, KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { - foreach (var deleteScope in clientScopes.ExceptBy(seedClientScopes.Select(x => x.Name), x => x.Name) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.ClientScopes, ModificationType.Delete, x.Name))) + foreach (var deleteScope in clientScopes + .Where(x => seederConfig.ModificationAllowed(ModificationType.Delete, x.Name)) + .ExceptBy(seedClientScopes.Select(x => x.Name), x => x.Name)) { await keycloak.DeleteClientScopeAsync( realm, @@ -66,16 +67,16 @@ await keycloak.DeleteClientScopeAsync( } } - private static async Task CreateMissingClientScopes(KeycloakClient keycloak, string realm, IEnumerable clientScopes, IEnumerable seedClientScopes, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private static async Task CreateMissingClientScopes(KeycloakClient keycloak, string realm, IEnumerable clientScopes, IEnumerable seedClientScopes, KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { foreach (var addScope in seedClientScopes.ExceptBy(clientScopes.Select(x => x.Name), x => x.Name) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.ClientScopes, ModificationType.Create, x.Name))) + .Where(x => seederConfig.ModificationAllowed(ModificationType.Create, x.Name))) { await keycloak.CreateClientScopeAsync(realm, CreateClientScope(null, addScope, true), cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); } } - private static async Task UpdateExistingClientScopes(KeycloakClient keycloak, string realm, IEnumerable clientScopes, IEnumerable seedClientScopes, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private static async Task UpdateExistingClientScopes(KeycloakClient keycloak, string realm, IEnumerable clientScopes, IEnumerable seedClientScopes, KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { foreach (var (clientScope, update) in clientScopes .Join( @@ -83,13 +84,13 @@ private static async Task UpdateExistingClientScopes(KeycloakClient keycloak, st x => x.Name, x => x.Name, (clientScope, update) => (ClientScope: clientScope, Update: update)) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.ClientScopes, ModificationType.Update, x.Update.Name))) + .Where(x => seederConfig.ModificationAllowed(ModificationType.Update, x.Update.Name))) { await UpdateClientScopeWithProtocolMappers(keycloak, realm, clientScope, update, seederConfig, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); } } - private static async Task UpdateClientScopeWithProtocolMappers(KeycloakClient keycloak, string realm, ClientScope clientScope, ClientScopeModel update, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private static async Task UpdateClientScopeWithProtocolMappers(KeycloakClient keycloak, string realm, ClientScope clientScope, ClientScopeModel update, KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { if (clientScope.Id == null) throw new ConflictException($"clientScope.Id is null: {clientScope.Name}"); @@ -114,10 +115,11 @@ await keycloak.UpdateClientScopeAsync( await UpdateExistingProtocolMappers(keycloak, realm, clientScope.Name, clientScope.Id, mappers, updateMappers, seederConfig, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); } - private static async Task DeleteObsoleteProtocolMappers(KeycloakClient keycloak, string realm, string clientScopeName, string clientScopeId, IEnumerable mappers, IEnumerable updateMappers, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private static async Task DeleteObsoleteProtocolMappers(KeycloakClient keycloak, string realm, string clientScopeName, string clientScopeId, IEnumerable mappers, IEnumerable updateMappers, KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { - foreach (var mapper in mappers.ExceptBy(updateMappers.Select(x => x.Name), x => x.Name) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.ClientScopes, clientScopeName, ConfigurationKeys.ProtocolMappers, ModificationType.Delete, x.Name))) + foreach (var mapper in mappers + .Where(x => seederConfig.ModificationAllowed(clientScopeName, ConfigurationKeys.ProtocolMappers, ModificationType.Delete, x.Name)) + .ExceptBy(updateMappers.Select(x => x.Name), x => x.Name)) { await keycloak.DeleteProtocolMapperAsync( realm, @@ -127,10 +129,11 @@ await keycloak.DeleteProtocolMapperAsync( } } - private static async Task CreateMissingProtocolMappers(KeycloakClient keycloak, string realm, string clientScopeName, string clientScopeId, IEnumerable mappers, IEnumerable updateMappers, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private static async Task CreateMissingProtocolMappers(KeycloakClient keycloak, string realm, string clientScopeName, string clientScopeId, IEnumerable mappers, IEnumerable updateMappers, KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { - foreach (var update in updateMappers.ExceptBy(mappers.Select(x => x.Name), x => x.Name) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.ClientScopes, clientScopeName, ConfigurationKeys.ProtocolMappers, ModificationType.Create, x.Name))) + foreach (var update in updateMappers + .Where(x => seederConfig.ModificationAllowed(clientScopeName, ConfigurationKeys.ProtocolMappers, ModificationType.Create, x.Name)) + .ExceptBy(mappers.Select(x => x.Name), x => x.Name)) { await keycloak.CreateProtocolMapperAsync( realm, @@ -140,14 +143,14 @@ await keycloak.CreateProtocolMapperAsync( } } - private static async Task UpdateExistingProtocolMappers(KeycloakClient keycloak, string realm, string clientScopeName, string clientScopeId, IEnumerable mappers, IEnumerable updateMappers, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private static async Task UpdateExistingProtocolMappers(KeycloakClient keycloak, string realm, string clientScopeName, string clientScopeId, IEnumerable mappers, IEnumerable updateMappers, KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { foreach (var (mapper, update) in mappers.Join( updateMappers, x => x.Name, x => x.Name, (mapper, update) => (Mapper: mapper, Update: update)) - .Where(x => !ProtocolMappersUpdater.CompareProtocolMapper(x.Mapper, x.Update) && seederConfig.ModificationAllowed(ConfigurationKeys.ClientScopes, clientScopeName, ConfigurationKeys.ProtocolMappers, ModificationType.Update, x.Update.Name))) + .Where(x => !ProtocolMappersUpdater.CompareProtocolMapper(x.Mapper, x.Update) && seederConfig.ModificationAllowed(clientScopeName, ConfigurationKeys.ProtocolMappers, ModificationType.Update, x.Update.Name))) { await keycloak.UpdateProtocolMapperAsync( realm, diff --git a/src/keycloak/Keycloak.Seeding/BusinessLogic/ClientsUpdater.cs b/src/keycloak/Keycloak.Seeding/BusinessLogic/ClientsUpdater.cs index 35864779e4..636139fbcd 100644 --- a/src/keycloak/Keycloak.Seeding/BusinessLogic/ClientsUpdater.cs +++ b/src/keycloak/Keycloak.Seeding/BusinessLogic/ClientsUpdater.cs @@ -37,12 +37,13 @@ public Task UpdateClients(string keycloakInstanceName, CancellationToken cancell { var realm = seedDataHandler.Realm; var keycloak = keycloakFactory.CreateKeycloakClient(keycloakInstanceName); - var seederConfig = seedDataHandler.Configuration; + var seederConfig = seedDataHandler.GetSpecificConfiguration(ConfigurationKeys.Clients); + var clientScopesSeederConfig = seedDataHandler.GetSpecificConfiguration(ConfigurationKeys.ClientScopes); - return seedDataHandler.SetClientInternalIds(UpdateClientsInternal(keycloak, realm, seederConfig, cancellationToken).Where(x => x != null).Select(x => x!.Value)); + return seedDataHandler.SetClientInternalIds(UpdateClientsInternal(keycloak, realm, seederConfig, clientScopesSeederConfig, cancellationToken).Where(x => x != null).Select(x => x!.Value)); } - private async IAsyncEnumerable<(string ClientId, string Id)?> UpdateClientsInternal(KeycloakClient keycloak, string realm, KeycloakRealmSettings seederConfig, [EnumeratorCancellation] CancellationToken cancellationToken) + private async IAsyncEnumerable<(string ClientId, string Id)?> UpdateClientsInternal(KeycloakClient keycloak, string realm, KeycloakSeederConfigModel seederConfig, KeycloakSeederConfigModel clientScopesSeederConfig, [EnumeratorCancellation] CancellationToken cancellationToken) { var clientScopes = await keycloak.GetClientScopesAsync(realm, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); string GetClientScopeId(string scope) => clientScopes.SingleOrDefault(x => x.Name == scope)?.Id ?? throw new ConflictException($"id of clientScope {scope} is undefined"); @@ -55,7 +56,7 @@ public Task UpdateClients(string keycloakInstanceName, CancellationToken cancell var client = (await keycloak.GetClientsAsync(realm, clientId: update.ClientId, cancellationToken: cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None)).SingleOrDefault(x => x.ClientId == update.ClientId); if (client == null) { - if (!seederConfig.ModificationAllowed(ConfigurationKeys.Clients, ModificationType.Create, update.ClientId)) + if (!seederConfig.ModificationAllowed(ModificationType.Create, update.ClientId)) { yield return null; } @@ -64,7 +65,7 @@ public Task UpdateClients(string keycloakInstanceName, CancellationToken cancell } else { - if (seederConfig.ModificationAllowed(ConfigurationKeys.Clients, ModificationType.Update, update.ClientId)) + if (seederConfig.ModificationAllowed(ModificationType.Update, update.ClientId)) { await UpdateClient( keycloak, @@ -92,7 +93,7 @@ await UpdateDefaultClientScopes( client, update, GetClientScopeId, - seederConfig, + clientScopesSeederConfig, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); await UpdateOptionalClientScopes( @@ -102,7 +103,7 @@ await UpdateOptionalClientScopes( client, update, GetClientScopeId, - seederConfig, + clientScopesSeederConfig, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); yield return (update.ClientId, client.Id); @@ -134,23 +135,25 @@ await keycloak.UpdateClientAsync( } } - private static async Task UpdateClientProtocolMappers(KeycloakClient keycloak, string realm, string clientId, Client client, ClientModel update, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private static async Task UpdateClientProtocolMappers(KeycloakClient keycloak, string realm, string clientId, Client client, ClientModel update, KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { var clientProtocolMappers = client.ProtocolMappers ?? Enumerable.Empty(); var updateProtocolMappers = update.ProtocolMappers ?? Enumerable.Empty(); if (client.ClientId == null) throw new ConflictException("client.ClientId must never be null"); - foreach (var mapperId in clientProtocolMappers.ExceptBy(updateProtocolMappers.Select(x => x.Name), x => x.Name) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.Clients, client.ClientId, ConfigurationKeys.ClientProtocolMapper, ModificationType.Delete, x.Name)) - .Select(x => x.Id ?? throw new ConflictException($"protocolMapper.Id is null {x.Name}"))) + foreach (var mapperId in clientProtocolMappers + .Where(x => seederConfig.ModificationAllowed(client.ClientId, ConfigurationKeys.ClientProtocolMapper, ModificationType.Delete, x.Name)) + .ExceptBy(updateProtocolMappers.Select(x => x.Name), x => x.Name) + .Select(x => x.Id ?? throw new ConflictException($"protocolMapper.Id is null {x.Name}"))) { await keycloak.DeleteClientProtocolMapperAsync(realm, clientId, mapperId, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); } - foreach (var mapper in updateProtocolMappers.ExceptBy(clientProtocolMappers.Select(x => x.Name), x => x.Name) - .Select(x => ProtocolMappersUpdater.CreateProtocolMapper(null, x)) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.Clients, client.ClientId, ConfigurationKeys.ClientProtocolMapper, ModificationType.Create, x.Name))) + foreach (var mapper in updateProtocolMappers + .Where(x => seederConfig.ModificationAllowed(client.ClientId, ConfigurationKeys.ClientProtocolMapper, ModificationType.Create, x.Name)) + .ExceptBy(clientProtocolMappers.Select(x => x.Name), x => x.Name) + .Select(x => ProtocolMappersUpdater.CreateProtocolMapper(null, x))) { await keycloak.CreateClientProtocolMapperAsync(realm, clientId, mapper, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); } @@ -161,7 +164,7 @@ private static async Task UpdateClientProtocolMappers(KeycloakClient keycloak, s x => x.Name, x => x.Name, (mapper, update) => (Mapper: mapper, Update: update)) - .Where(x => !ProtocolMappersUpdater.CompareProtocolMapper(x.Mapper, x.Update) && seederConfig.ModificationAllowed(ConfigurationKeys.Clients, client.ClientId, ConfigurationKeys.ClientProtocolMapper, ModificationType.Update, x.Update.Id)) + .Where(x => !ProtocolMappersUpdater.CompareProtocolMapper(x.Mapper, x.Update) && seederConfig.ModificationAllowed(client.ClientId, ConfigurationKeys.ClientProtocolMapper, ModificationType.Update, x.Update.Id)) .Select(x => ( x.Mapper.Id ?? throw new ConflictException($"protocolMapper.Id is null {x.Mapper.Name}"), ProtocolMappersUpdater.CreateProtocolMapper(x.Mapper.Id, x.Update)))) @@ -170,41 +173,41 @@ private static async Task UpdateClientProtocolMappers(KeycloakClient keycloak, s } } - private static async Task UpdateOptionalClientScopes(KeycloakClient keycloak, string realm, string idOfClient, Client client, ClientModel update, Func getClientScopeId, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private static async Task UpdateOptionalClientScopes(KeycloakClient keycloak, string realm, string idOfClient, Client client, ClientModel update, Func getClientScopeId, KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { var optionalScopes = client.OptionalClientScopes ?? Enumerable.Empty(); var updateScopes = update.OptionalClientScopes ?? Enumerable.Empty(); foreach (var scopeId in optionalScopes.Except(updateScopes) .Select(getClientScopeId) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.ClientScopes, ModificationType.Delete, x))) + .Where(x => seederConfig.ModificationAllowed(ModificationType.Delete, x))) { await keycloak.DeleteOptionalClientScopeAsync(realm, idOfClient, scopeId, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); } foreach (var scopeId in updateScopes.Except(optionalScopes) .Select(getClientScopeId) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.ClientScopes, ModificationType.Update, x))) + .Where(x => seederConfig.ModificationAllowed(ModificationType.Update, x))) { await keycloak.UpdateOptionalClientScopeAsync(realm, idOfClient, scopeId, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); } } - private static async Task UpdateDefaultClientScopes(KeycloakClient keycloak, string realm, string idOfClient, Client client, ClientModel update, Func getClientScopeId, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private static async Task UpdateDefaultClientScopes(KeycloakClient keycloak, string realm, string idOfClient, Client client, ClientModel update, Func getClientScopeId, KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { var defaultScopes = client.DefaultClientScopes ?? Enumerable.Empty(); var updateScopes = update.DefaultClientScopes ?? Enumerable.Empty(); foreach (var scopeId in defaultScopes.Except(updateScopes) .Select(getClientScopeId) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.ClientScopes, ModificationType.Delete, x))) + .Where(x => seederConfig.ModificationAllowed(ModificationType.Delete, x))) { await keycloak.DeleteDefaultClientScopeAsync(realm, idOfClient, scopeId, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); } foreach (var scopeId in updateScopes.Except(defaultScopes) .Select(getClientScopeId) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.ClientScopes, ModificationType.Update, x))) + .Where(x => seederConfig.ModificationAllowed(ModificationType.Update, x))) { await keycloak.UpdateDefaultClientScopeAsync(realm, idOfClient, scopeId, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); } diff --git a/src/keycloak/Keycloak.Seeding/BusinessLogic/ISeedDataHandler.cs b/src/keycloak/Keycloak.Seeding/BusinessLogic/ISeedDataHandler.cs index 30e3bf8b88..727d63a020 100644 --- a/src/keycloak/Keycloak.Seeding/BusinessLogic/ISeedDataHandler.cs +++ b/src/keycloak/Keycloak.Seeding/BusinessLogic/ISeedDataHandler.cs @@ -26,7 +26,6 @@ public interface ISeedDataHandler Task Import(KeycloakRealmSettings realmSettings, CancellationToken cancellationToken); string Realm { get; } - KeycloakRealmSettings Configuration { get; } KeycloakRealm KeycloakRealm { get; } @@ -52,6 +51,7 @@ public interface ISeedDataHandler IEnumerable<(string ProviderType, ComponentModel ComponentModel)> RealmComponents { get; } IEnumerable<(string Locale, IEnumerable> Translations)> RealmLocalizations { get; } + KeycloakRealmSettings Configuration { get; } Task SetClientInternalIds(IAsyncEnumerable<(string ClientId, string Id)> clientInternalIds); @@ -62,4 +62,5 @@ public interface ISeedDataHandler IEnumerable GetAuthenticationExecutions(string? alias); AuthenticatorConfigModel GetAuthenticatorConfig(string? alias); + KeycloakSeederConfigModel GetSpecificConfiguration(ConfigurationKeys configKey); } diff --git a/src/keycloak/Keycloak.Seeding/BusinessLogic/IdentityProvidersUpdater.cs b/src/keycloak/Keycloak.Seeding/BusinessLogic/IdentityProvidersUpdater.cs index 2d7e104de5..281b1311b5 100644 --- a/src/keycloak/Keycloak.Seeding/BusinessLogic/IdentityProvidersUpdater.cs +++ b/src/keycloak/Keycloak.Seeding/BusinessLogic/IdentityProvidersUpdater.cs @@ -35,7 +35,7 @@ public async Task UpdateIdentityProviders(string keycloakInstanceName, Cancellat { var keycloak = keycloakFactory.CreateKeycloakClient(keycloakInstanceName); var realm = seedDataHandler.Realm; - var seederConfig = seedDataHandler.Configuration; + var seederConfig = seedDataHandler.GetSpecificConfiguration(ConfigurationKeys.IdentityProviders); foreach (var updateIdentityProvider in seedDataHandler.IdentityProviders) { @@ -45,7 +45,7 @@ public async Task UpdateIdentityProviders(string keycloakInstanceName, Cancellat try { var identityProvider = await keycloak.GetIdentityProviderAsync(realm, updateIdentityProvider.Alias, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); - if (!CompareIdentityProvider(identityProvider, updateIdentityProvider) && seederConfig.ModificationAllowed(ConfigurationKeys.IdentityProviders, ModificationType.Update, updateIdentityProvider.Alias)) + if (!CompareIdentityProvider(identityProvider, updateIdentityProvider) && seederConfig.ModificationAllowed(ModificationType.Update, updateIdentityProvider.Alias)) { UpdateIdentityProvider(identityProvider, updateIdentityProvider); await keycloak.UpdateIdentityProviderAsync(realm, updateIdentityProvider.Alias, identityProvider, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); @@ -53,7 +53,7 @@ public async Task UpdateIdentityProviders(string keycloakInstanceName, Cancellat } catch (KeycloakEntityNotFoundException) { - if (seederConfig.ModificationAllowed(ConfigurationKeys.IdentityProviders, ModificationType.Create, updateIdentityProvider.Alias)) + if (seederConfig.ModificationAllowed(ModificationType.Create, updateIdentityProvider.Alias)) { var identityProvider = new IdentityProvider(); UpdateIdentityProvider(identityProvider, updateIdentityProvider); @@ -70,10 +70,11 @@ public async Task UpdateIdentityProviders(string keycloakInstanceName, Cancellat } } - private static async Task CreateMissingIdentityProviderMappers(KeycloakClient keycloak, string realm, string alias, IEnumerable mappers, IEnumerable updateMappers, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private static async Task CreateMissingIdentityProviderMappers(KeycloakClient keycloak, string realm, string alias, IEnumerable mappers, IEnumerable updateMappers, KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { - foreach (var mapper in updateMappers.ExceptBy(mappers.Select(x => x.Name), x => x.Name) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.IdentityProviders, alias, ConfigurationKeys.IdentityProviderMappers, ModificationType.Create, x.Id))) + foreach (var mapper in updateMappers + .Where(x => seederConfig.ModificationAllowed(alias, ConfigurationKeys.IdentityProviderMappers, ModificationType.Create, x.Id)) + .ExceptBy(mappers.Select(x => x.Name), x => x.Name)) { await keycloak.AddIdentityProviderMapperAsync( realm, @@ -89,7 +90,7 @@ await keycloak.AddIdentityProviderMapperAsync( } } - private static async Task UpdateExistingIdentityProviderMappers(KeycloakClient keycloak, string realm, string alias, IEnumerable mappers, IEnumerable updateMappers, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private static async Task UpdateExistingIdentityProviderMappers(KeycloakClient keycloak, string realm, string alias, IEnumerable mappers, IEnumerable updateMappers, KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { foreach (var (mapper, update) in mappers .Join( @@ -97,7 +98,7 @@ private static async Task UpdateExistingIdentityProviderMappers(KeycloakClient k x => x.Name, x => x.Name, (mapper, update) => (Mapper: mapper, Update: update)) - .Where(x => !CompareIdentityProviderMapper(x.Mapper, x.Update) && seederConfig.ModificationAllowed(ConfigurationKeys.IdentityProviders, alias, ConfigurationKeys.IdentityProviderMappers, ModificationType.Update, x.Update.Id))) + .Where(x => !CompareIdentityProviderMapper(x.Mapper, x.Update) && seederConfig.ModificationAllowed(alias, ConfigurationKeys.IdentityProviderMappers, ModificationType.Update, x.Update.Id))) { await keycloak.UpdateIdentityProviderMapperAsync( realm, @@ -108,10 +109,11 @@ await keycloak.UpdateIdentityProviderMapperAsync( } } - private static async Task DeleteObsoleteIdentityProviderMappers(KeycloakClient keycloak, string realm, string alias, IEnumerable mappers, IEnumerable updateMappers, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private static async Task DeleteObsoleteIdentityProviderMappers(KeycloakClient keycloak, string realm, string alias, IEnumerable mappers, IEnumerable updateMappers, KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { - if (mappers.ExceptBy(updateMappers.Select(x => x.Name), x => x.Name) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.IdentityProviders, alias, ConfigurationKeys.IdentityProviderMappers, ModificationType.Delete, x.Id)) + if (mappers + .Where(x => seederConfig.ModificationAllowed(alias, ConfigurationKeys.IdentityProviderMappers, ModificationType.Delete, x.Id)) + .ExceptBy(updateMappers.Select(x => x.Name), x => x.Name) .IfAny(async deleteMappers => { foreach (var mapper in deleteMappers) diff --git a/src/keycloak/Keycloak.Seeding/BusinessLogic/LocalizationsUpdater.cs b/src/keycloak/Keycloak.Seeding/BusinessLogic/LocalizationsUpdater.cs index e4767f5cac..51e9203588 100644 --- a/src/keycloak/Keycloak.Seeding/BusinessLogic/LocalizationsUpdater.cs +++ b/src/keycloak/Keycloak.Seeding/BusinessLogic/LocalizationsUpdater.cs @@ -32,14 +32,14 @@ public async Task UpdateLocalizations(string keycloakInstanceName, CancellationT { var keycloak = keycloakFactory.CreateKeycloakClient(keycloakInstanceName); var realm = seedDataHandler.Realm; - var seederConfig = seedDataHandler.Configuration; + var seederConfig = seedDataHandler.GetSpecificConfiguration(ConfigurationKeys.Localizations); var localizations = await keycloak.GetLocaleAsync(realm, cancellationToken: cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); var updateRealmLocalizations = seedDataHandler.RealmLocalizations; await UpdateLocaleTranslations(keycloak, realm, localizations, updateRealmLocalizations, seederConfig, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); - foreach (var deleteTranslation in - localizations.ExceptBy(updateRealmLocalizations.Select(t => t.Locale), locale => locale) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.Localizations, ModificationType.Delete, x))) + foreach (var deleteTranslation in localizations + .Where(x => seederConfig.ModificationAllowed(ModificationType.Delete, x)) + .ExceptBy(updateRealmLocalizations.Select(t => t.Locale), locale => locale)) { await keycloak.DeleteLocaleAsync(realm, deleteTranslation, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); } @@ -47,7 +47,7 @@ public async Task UpdateLocalizations(string keycloakInstanceName, CancellationT private static async Task UpdateLocaleTranslations(KeycloakClient keycloak, string realm, IEnumerable locales, IEnumerable<(string Locale, IEnumerable> Translations)> translations, - KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { if (!await locales .Join( @@ -72,12 +72,11 @@ private static async Task UpdateLocaleTranslations(KeycloakClient keycloak, stri private static async Task DeleteLocales(KeycloakClient keycloak, string realm, IEnumerable> localizations, (string Locale, IEnumerable> Translations) update, string locale, - KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { - foreach (var deleteTranslation in - localizations.ExceptBy(update.Translations.Select(t => t.Key), - l => l.Key) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.Localizations, ModificationType.Delete, x.Key))) + foreach (var deleteTranslation in localizations + .Where(x => seederConfig.ModificationAllowed(ModificationType.Delete, x.Key)) + .ExceptBy(update.Translations.Select(t => t.Key), l => l.Key)) { await keycloak.DeleteLocaleAsync(realm, locale, deleteTranslation.Key, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); } @@ -85,11 +84,11 @@ private static async Task DeleteLocales(KeycloakClient keycloak, string realm, private static async Task UpdateLocales(KeycloakClient keycloak, string realm, (string Locale, IEnumerable> Translations) update, IEnumerable> localizations, string locale, - KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { - foreach (var missingTranslation in update.Translations.ExceptBy(localizations.Select(loc => loc.Key), - locModel => locModel.Key) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.Localizations, ModificationType.Update, x.Key))) + foreach (var missingTranslation in update.Translations + .Where(x => seederConfig.ModificationAllowed(ModificationType.Update, x.Key)) + .ExceptBy(localizations.Select(loc => loc.Key), locModel => locModel.Key)) { await keycloak.UpdateLocaleAsync(realm, locale, missingTranslation.Key, missingTranslation.Value, cancellationToken).ConfigureAwait(false); } @@ -100,16 +99,16 @@ private static async Task UpdateLocales(KeycloakClient keycloak, string realm, l => l.Key, trans => trans.Key, (l, trans) => (Key: l.Key, Update: trans)) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.Localizations, ModificationType.Update, x.Key))) + .Where(x => seederConfig.ModificationAllowed(ModificationType.Update, x.Key))) { await keycloak.UpdateLocaleAsync(realm, locale, updateTranslation.Key, updateTranslation.Update.Value, cancellationToken).ConfigureAwait(false); } } private static async Task AddLocales(KeycloakClient keycloak, string realm, IEnumerable<(string Locale, IEnumerable> Translations)> translations, - KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { - foreach (var translation in translations.SelectMany(x => x.Translations.Select(t => (x.Locale, t.Key, t.Value))).Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.Localizations, ModificationType.Create, x.Key))) + foreach (var translation in translations.SelectMany(x => x.Translations.Select(t => (x.Locale, t.Key, t.Value))).Where(x => seederConfig.ModificationAllowed(ModificationType.Create, x.Key))) { await keycloak.UpdateLocaleAsync(realm, translation.Locale, translation.Key, translation.Value, cancellationToken).ConfigureAwait(false); } diff --git a/src/keycloak/Keycloak.Seeding/BusinessLogic/RolesUpdater.cs b/src/keycloak/Keycloak.Seeding/BusinessLogic/RolesUpdater.cs index f97b988c78..0066439577 100644 --- a/src/keycloak/Keycloak.Seeding/BusinessLogic/RolesUpdater.cs +++ b/src/keycloak/Keycloak.Seeding/BusinessLogic/RolesUpdater.cs @@ -34,20 +34,21 @@ public async Task UpdateClientRoles(string keycloakInstanceName, CancellationTok { var keycloak = keycloakFactory.CreateKeycloakClient(keycloakInstanceName); var realm = seedDataHandler.Realm; - var seederConfig = seedDataHandler.Configuration; + var seederConfig = seedDataHandler.GetSpecificConfiguration(ConfigurationKeys.ClientRoles); foreach (var (clientId, updateRoles) in seedDataHandler.ClientRoles) { var id = seedDataHandler.GetIdOfClient(clientId); var roles = await keycloak.GetRolesAsync(realm, id, cancellationToken: cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); - foreach (var newRole in updateRoles.ExceptBy(roles.Select(role => role.Name), roleModel => roleModel.Name) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.ClientRoles, ModificationType.Create, x.Name))) + foreach (var newRole in updateRoles + .Where(x => seederConfig.ModificationAllowed(ModificationType.Create, x.Name)) + .ExceptBy(roles.Select(role => role.Name), roleModel => roleModel.Name)) { await keycloak.CreateRoleAsync(realm, id, CreateRole(newRole), cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); } - await UpdateAndDeleteRoles(keycloak, realm, roles, updateRoles, seederConfig, ConfigurationKeys.ClientRoles, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); + await UpdateAndDeleteRoles(keycloak, realm, roles, updateRoles, seederConfig, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); } } @@ -55,20 +56,21 @@ public async Task UpdateRealmRoles(string keycloakInstanceName, CancellationToke { var keycloak = keycloakFactory.CreateKeycloakClient(keycloakInstanceName); var realm = seedDataHandler.Realm; - var seederConfig = seedDataHandler.Configuration; + var seederConfig = seedDataHandler.GetSpecificConfiguration(ConfigurationKeys.Roles); var roles = await keycloak.GetRolesAsync(realm, cancellationToken: cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); var updateRealmRoles = seedDataHandler.RealmRoles; - foreach (var newRole in updateRealmRoles.ExceptBy(roles.Select(role => role.Name), roleModel => roleModel.Name) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.Roles, ModificationType.Create, x.Name))) + foreach (var newRole in updateRealmRoles + .Where(x => seederConfig.ModificationAllowed(ModificationType.Create, x.Name)) + .ExceptBy(roles.Select(role => role.Name), roleModel => roleModel.Name)) { await keycloak.CreateRoleAsync(realm, CreateRole(newRole), cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); } - await UpdateAndDeleteRoles(keycloak, realm, roles, updateRealmRoles, seederConfig, ConfigurationKeys.Roles, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); + await UpdateAndDeleteRoles(keycloak, realm, roles, updateRealmRoles, seederConfig, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); } - private static async Task UpdateAndDeleteRoles(KeycloakClient keycloak, string realm, IEnumerable roles, IEnumerable updateRoles, KeycloakRealmSettings seederConfig, ConfigurationKeys configKey, CancellationToken cancellationToken) + private static async Task UpdateAndDeleteRoles(KeycloakClient keycloak, string realm, IEnumerable roles, IEnumerable updateRoles, KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { foreach (var (role, update) in roles.Join( @@ -76,7 +78,7 @@ private static async Task UpdateAndDeleteRoles(KeycloakClient keycloak, string r role => role.Name, roleModel => roleModel.Name, (role, roleModel) => (Role: role, Update: roleModel)) - .Where(x => seederConfig.ModificationAllowed(configKey, ModificationType.Update, x.Role.Name))) + .Where(x => seederConfig.ModificationAllowed(ModificationType.Update, x.Role.Name))) { if (!CompareRole(role, update)) { @@ -89,9 +91,9 @@ private static async Task UpdateAndDeleteRoles(KeycloakClient keycloak, string r } } - foreach (var deleteRole in - roles.ExceptBy(updateRoles.Select(roleModel => roleModel.Name), role => role.Name) - .Where(x => seederConfig.ModificationAllowed(configKey, ModificationType.Delete, x.Name))) + foreach (var deleteRole in roles + .Where(x => seederConfig.ModificationAllowed(ModificationType.Delete, x.Name)) + .ExceptBy(updateRoles.Select(roleModel => roleModel.Name), role => role.Name)) { if (deleteRole.Id == null) throw new ConflictException($"role id must not be null: {deleteRole.Name}"); @@ -104,7 +106,7 @@ public async Task UpdateCompositeRoles(string keycloakInstanceName, Cancellation { var keycloak = keycloakFactory.CreateKeycloakClient(keycloakInstanceName); var realm = seedDataHandler.Realm; - var seederConfig = seedDataHandler.Configuration; + var seederConfig = seedDataHandler.GetSpecificConfiguration(ConfigurationKeys.Roles); foreach (var (clientId, updateRoles) in seedDataHandler.ClientRoles) { @@ -164,8 +166,8 @@ async Task RemoveAddCompositeRolesInner( Func joinUpdateKey, Func> getRoleByName) { - var updateComposites = updateRoles.Where(x => compositeRolesUpdatePredicate(x) && seederConfig.ModificationAllowed(ConfigurationKeys.Roles, ModificationType.Update, x.Name)); - var removeComposites = roles.Where(x => compositeRolesPredicate(x) && seederConfig.ModificationAllowed(ConfigurationKeys.Roles, ModificationType.Delete, x.Id)).ExceptBy(updateComposites.Select(roleModel => roleModel.Name), role => role.Name); + var updateComposites = updateRoles.Where(x => compositeRolesUpdatePredicate(x) && seederConfig.ModificationAllowed(ModificationType.Update, x.Name)); + var removeComposites = roles.Where(x => compositeRolesPredicate(x) && seederConfig.ModificationAllowed(ModificationType.Delete, x.Id)).ExceptBy(updateComposites.Select(roleModel => roleModel.Name), role => role.Name); foreach (var remove in removeComposites) { @@ -200,7 +202,7 @@ async Task RemoveAddCompositeRolesInner( .SelectAwait(x => getRoleByName(x)) .ToListAsync(cancellationToken) .ConfigureAwait(false); - await addCompositeRoles(role.Name, add.Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.Roles, ModificationType.Create, x.Name))).ConfigureAwait(ConfigureAwaitOptions.None); + await addCompositeRoles(role.Name, add.Where(x => seederConfig.ModificationAllowed(ModificationType.Create, x.Name))).ConfigureAwait(ConfigureAwaitOptions.None); } } } diff --git a/src/keycloak/Keycloak.Seeding/BusinessLogic/SeedDataHandler.cs b/src/keycloak/Keycloak.Seeding/BusinessLogic/SeedDataHandler.cs index 0d9a65db67..d1d5f85062 100644 --- a/src/keycloak/Keycloak.Seeding/BusinessLogic/SeedDataHandler.cs +++ b/src/keycloak/Keycloak.Seeding/BusinessLogic/SeedDataHandler.cs @@ -35,6 +35,8 @@ public class SeedDataHandler : ISeedDataHandler PropertyNameCaseInsensitive = false }; + private readonly IDictionary _specificConfigurations = new Dictionary(); + private KeycloakRealm? _keycloakRealm; private IReadOnlyDictionary? _idOfClients; private KeycloakRealmSettings? _realmConfiguration; @@ -149,6 +151,7 @@ public async Task SetClientInternalIds(IAsyncEnumerable<(string ClientId, string { clientIds[clientId] = id; } + _idOfClients = clientIds.ToImmutableDictionary(); } @@ -164,4 +167,16 @@ public IEnumerable GetAuthenticationExecutions(str public AuthenticatorConfigModel GetAuthenticatorConfig(string? alias) => _keycloakRealm?.AuthenticatorConfig?.SingleOrDefault(x => x.Alias == (alias ?? throw new ConflictException("alias is null"))) ?? throw new ConflictException($"authenticatorConfig {alias} does not exist"); + + public KeycloakSeederConfigModel GetSpecificConfiguration(ConfigurationKeys configKey) + { + if (_specificConfigurations.TryGetValue(configKey, out var specificConfiguration)) + { + return new KeycloakSeederConfigModel(Configuration, specificConfiguration); + } + + specificConfiguration = _realmConfiguration?.SeederConfiguration?.SingleOrDefault(); + _specificConfigurations.Add(configKey, specificConfiguration); + return new KeycloakSeederConfigModel(Configuration, specificConfiguration); + } } diff --git a/src/keycloak/Keycloak.Seeding/BusinessLogic/UserProfileUpdater.cs b/src/keycloak/Keycloak.Seeding/BusinessLogic/UserProfileUpdater.cs index d78e6ba40f..5bf8f15293 100644 --- a/src/keycloak/Keycloak.Seeding/BusinessLogic/UserProfileUpdater.cs +++ b/src/keycloak/Keycloak.Seeding/BusinessLogic/UserProfileUpdater.cs @@ -44,8 +44,8 @@ public async Task UpdateUserProfile(string keycloakInstanceName, CancellationTok var keycloak = keycloakFactory.CreateKeycloakClient(keycloakInstanceName); var realm = seedDataHandler.Realm; var userProfiles = seedDataHandler.RealmComponents.Where(x => x.ProviderType == UserProfileType); - var defaultConfig = seedDataHandler.Configuration; - if (defaultConfig.ModificationAllowed(ConfigurationKeys.UserProfile, ModificationType.Update)) + var defaultConfig = seedDataHandler.GetSpecificConfiguration(ConfigurationKeys.UserProfile); + if (defaultConfig.ModificationAllowed(ModificationType.Update)) { return; } diff --git a/src/keycloak/Keycloak.Seeding/BusinessLogic/UsersUpdater.cs b/src/keycloak/Keycloak.Seeding/BusinessLogic/UsersUpdater.cs index dd24ff98ee..c9f0f78b30 100644 --- a/src/keycloak/Keycloak.Seeding/BusinessLogic/UsersUpdater.cs +++ b/src/keycloak/Keycloak.Seeding/BusinessLogic/UsersUpdater.cs @@ -37,7 +37,7 @@ public async Task UpdateUsers(string keycloakInstanceName, CancellationToken can var realm = seedDataHandler.Realm; var keycloak = keycloakFactory.CreateKeycloakClient(keycloakInstanceName); var clientsDictionary = seedDataHandler.ClientsDictionary; - var seederConfig = seedDataHandler.Configuration; + var seederConfig = seedDataHandler.GetSpecificConfiguration(ConfigurationKeys.Users); foreach (var seedUser in seedDataHandler.Users) { @@ -46,7 +46,7 @@ public async Task UpdateUsers(string keycloakInstanceName, CancellationToken can var user = (await keycloak.GetUsersAsync(realm, username: seedUser.Username, cancellationToken: cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None)).SingleOrDefault(x => x.UserName == seedUser.Username); - if (user == null && seederConfig.ModificationAllowed(ConfigurationKeys.Users, ModificationType.Create, seedUser.Username)) + if (user == null && seederConfig.ModificationAllowed(ModificationType.Create, seedUser.Username)) { var result = await keycloak.RealmPartialImportAsync(realm, CreatePartialImportUser(seedUser), cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); if (result.Overwritten != 0 || result.Added != 1 || result.Skipped != 0) @@ -68,7 +68,7 @@ await UpdateUser( } } - private static async Task UpdateUser(KeycloakClient keycloak, string realm, User user, UserModel seedUser, IReadOnlyDictionary clientsDictionary, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private static async Task UpdateUser(KeycloakClient keycloak, string realm, User user, UserModel seedUser, IReadOnlyDictionary clientsDictionary, KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { if (user.Id == null) throw new ConflictException($"user.Id must not be null: userName {seedUser.Username}"); @@ -76,7 +76,7 @@ private static async Task UpdateUser(KeycloakClient keycloak, string realm, User if (user.UserName == null) throw new ConflictException($"user.UserName must not be null: userName {seedUser.Username}"); - if (!CompareUser(user, seedUser) && seederConfig.ModificationAllowed(ConfigurationKeys.Users, ModificationType.Update, user.UserName)) + if (!CompareUser(user, seedUser) && seederConfig.ModificationAllowed(ModificationType.Update, user.UserName)) { await keycloak.UpdateUserAsync( realm, @@ -210,7 +210,7 @@ private static bool CompareFederatedIdentity(FederatedIdentity identity, Federat identity.UserId == update.UserId && identity.UserName == update.UserName; - private static async Task UpdateFederatedIdentities(KeycloakClient keycloak, string realm, string username, string userId, IEnumerable updates, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private static async Task UpdateFederatedIdentities(KeycloakClient keycloak, string realm, string username, string userId, IEnumerable updates, KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { var identities = await keycloak.GetUserSocialLoginsAsync(realm, userId).ConfigureAwait(ConfigureAwaitOptions.None); await DeleteObsoleteFederatedIdentities(keycloak, realm, username, userId, identities, updates, seederConfig, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); @@ -218,11 +218,11 @@ private static async Task UpdateFederatedIdentities(KeycloakClient keycloak, str await UpdateExistingFederatedIdentities(keycloak, realm, username, userId, identities, updates, seederConfig, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); } - private static async Task DeleteObsoleteFederatedIdentities(KeycloakClient keycloak, string realm, string username, string userId, IEnumerable identities, IEnumerable updates, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private static async Task DeleteObsoleteFederatedIdentities(KeycloakClient keycloak, string realm, string username, string userId, IEnumerable identities, IEnumerable updates, KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { foreach (var identity in identities - .ExceptBy(updates.Select(x => x.IdentityProvider), x => x.IdentityProvider) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.Users, username, ConfigurationKeys.FederatedIdentities, ModificationType.Delete, x.IdentityProvider))) + .Where(x => seederConfig.ModificationAllowed(username, ConfigurationKeys.FederatedIdentities, ModificationType.Delete, x.IdentityProvider)) + .ExceptBy(updates.Select(x => x.IdentityProvider), x => x.IdentityProvider)) { await keycloak.RemoveUserSocialLoginProviderAsync( realm, @@ -232,10 +232,11 @@ await keycloak.RemoveUserSocialLoginProviderAsync( } } - private static async Task CreateMissingFederatedIdentities(KeycloakClient keycloak, string realm, string username, string userId, IEnumerable identities, IEnumerable updates, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private static async Task CreateMissingFederatedIdentities(KeycloakClient keycloak, string realm, string username, string userId, IEnumerable identities, IEnumerable updates, KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { - foreach (var update in updates.ExceptBy(identities.Select(x => x.IdentityProvider), x => x.IdentityProvider) - .Where(x => seederConfig.ModificationAllowed(ConfigurationKeys.Users, username, ConfigurationKeys.FederatedIdentities, ModificationType.Create, x.IdentityProvider))) + foreach (var update in updates + .Where(x => seederConfig.ModificationAllowed(username, ConfigurationKeys.FederatedIdentities, ModificationType.Create, x.IdentityProvider)) + .ExceptBy(identities.Select(x => x.IdentityProvider), x => x.IdentityProvider)) { await keycloak.AddUserSocialLoginProviderAsync( realm, @@ -251,7 +252,7 @@ await keycloak.AddUserSocialLoginProviderAsync( } } - private static async Task UpdateExistingFederatedIdentities(KeycloakClient keycloak, string realm, string username, string userId, IEnumerable identities, IEnumerable updates, KeycloakRealmSettings seederConfig, CancellationToken cancellationToken) + private static async Task UpdateExistingFederatedIdentities(KeycloakClient keycloak, string realm, string username, string userId, IEnumerable identities, IEnumerable updates, KeycloakSeederConfigModel seederConfig, CancellationToken cancellationToken) { foreach (var (identity, update) in identities .Join( @@ -259,7 +260,7 @@ private static async Task UpdateExistingFederatedIdentities(KeycloakClient keycl x => x.IdentityProvider, x => x.IdentityProvider, (identity, update) => (Identity: identity, Update: update)) - .Where(x => !CompareFederatedIdentity(x.Identity, x.Update) && seederConfig.ModificationAllowed(ConfigurationKeys.Users, username, ConfigurationKeys.FederatedIdentities, ModificationType.Update, x.Update.IdentityProvider))) + .Where(x => !CompareFederatedIdentity(x.Identity, x.Update) && seederConfig.ModificationAllowed(username, ConfigurationKeys.FederatedIdentities, ModificationType.Update, x.Update.IdentityProvider))) { await keycloak.RemoveUserSocialLoginProviderAsync( realm, diff --git a/src/keycloak/Keycloak.Seeding/Extensions/SeederConfigurationExtensions.cs b/src/keycloak/Keycloak.Seeding/Extensions/SeederConfigurationExtensions.cs index 8f2e7d2af8..0be394eee4 100644 --- a/src/keycloak/Keycloak.Seeding/Extensions/SeederConfigurationExtensions.cs +++ b/src/keycloak/Keycloak.Seeding/Extensions/SeederConfigurationExtensions.cs @@ -17,6 +17,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using Org.Eclipse.TractusX.Portal.Backend.Keycloak.Library.Models.RealmsAdmin; using Org.Eclipse.TractusX.Portal.Backend.Keycloak.Seeding.Models; namespace Org.Eclipse.TractusX.Portal.Backend.Keycloak.Seeding.Extensions; @@ -60,14 +61,14 @@ private static bool IsModificationAllowed( return false; } - public static bool ModificationAllowed(this KeycloakRealmSettings config, ConfigurationKeys configKey, ModificationType modificationType) => - config.ModificationAllowed(configKey, modificationType, null); + public static bool ModificationAllowed(this KeycloakSeederConfigModel config, ModificationType modificationType) => + config.ModificationAllowed(modificationType, null); - public static bool ModificationAllowed(this KeycloakRealmSettings config, ConfigurationKeys configKey, ModificationType modificationType, string? entityKey) + public static bool ModificationAllowed(this KeycloakSeederConfigModel config, ModificationType modificationType, string? entityKey) { - var specificConfig = config.SeederConfiguration?.SingleOrDefault(x => x.Key.Equals(configKey.ToString(), StringComparison.OrdinalIgnoreCase)); + var (defaultConfig, specificConfig) = config; if (entityKey is null) - return specificConfig?.ModifyAllowed(modificationType) ?? config.ModifyAllowed(modificationType); + return specificConfig?.ModifyAllowed(modificationType) ?? defaultConfig.ModifyAllowed(modificationType); // If we have a configuration for a specific entry return its value var specificEntry = specificConfig?.SeederConfigurations?.SingleOrDefault(c => c.Key.Equals(entityKey, StringComparison.OrdinalIgnoreCase)); @@ -77,15 +78,16 @@ public static bool ModificationAllowed(this KeycloakRealmSettings config, Config } // If we don't have a specific value return the specific configuration value if we have one - return specificConfig?.ModifyAllowed(modificationType) ?? config.ModifyAllowed(modificationType); + return specificConfig?.ModifyAllowed(modificationType) ?? defaultConfig.ModifyAllowed(modificationType); } - public static bool ModificationAllowed(this KeycloakRealmSettings config, ConfigurationKeys containingConfigKey, string containingEntityKey, ConfigurationKeys configKey, ModificationType modificationType, string? entityKey) + public static bool ModificationAllowed(this KeycloakSeederConfigModel config, string containingEntityKey, ConfigurationKeys configKey, ModificationType modificationType, string? entityKey) { - var containingEntityTypeConfig = config.SeederConfiguration?.SingleOrDefault(x => x.Key.Equals(containingConfigKey.ToString(), StringComparison.OrdinalIgnoreCase))?.SeederConfigurations?.SingleOrDefault(x => x.Key.Equals(containingEntityKey, StringComparison.OrdinalIgnoreCase))?.SeederConfigurations?.SingleOrDefault(x => x.Key.Equals(configKey.ToString())); + var containingEntityTypeConfig = config.SpecificConfiguration?.SeederConfigurations?.SingleOrDefault(x => x.Key.Equals(containingEntityKey, StringComparison.OrdinalIgnoreCase))?.SeederConfigurations?.SingleOrDefault(x => x.Key.Equals(configKey.ToString(), StringComparison.OrdinalIgnoreCase)); if (containingEntityTypeConfig is null) { - return config.ModificationAllowed(configKey, modificationType, entityKey); + var configModel = config with { SpecificConfiguration = config.DefaultSettings.SeederConfiguration?.SingleOrDefault(x => x.Key.Equals(configKey.ToString(), StringComparison.OrdinalIgnoreCase)) }; + return configModel.ModificationAllowed(modificationType, entityKey); } if (entityKey is null) @@ -95,7 +97,7 @@ public static bool ModificationAllowed(this KeycloakRealmSettings config, Config // If we have a configuration for a specific entry return its value var entity = containingEntityTypeConfig.SeederConfigurations?.SingleOrDefault(c => c.Key.Equals(entityKey, StringComparison.OrdinalIgnoreCase)); - return entity?.ModifyAllowed(modificationType) ?? config.ModificationAllowed(configKey, modificationType, entityKey); + return entity?.ModifyAllowed(modificationType) ?? config.ModificationAllowed(modificationType, entityKey); } private static bool ModifyAllowed(this KeycloakRealmSettings configuration, ModificationType modificationType) => diff --git a/src/keycloak/Keycloak.Seeding/Models/KeycloakSeederConfigModel.cs b/src/keycloak/Keycloak.Seeding/Models/KeycloakSeederConfigModel.cs new file mode 100644 index 0000000000..e37395c25a --- /dev/null +++ b/src/keycloak/Keycloak.Seeding/Models/KeycloakSeederConfigModel.cs @@ -0,0 +1,25 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +namespace Org.Eclipse.TractusX.Portal.Backend.Keycloak.Seeding.Models; + +public record KeycloakSeederConfigModel( + KeycloakRealmSettings DefaultSettings, + SeederConfiguration? SpecificConfiguration +); diff --git a/src/keycloak/Keycloak.Seeding/appsettings.example.json b/src/keycloak/Keycloak.Seeding/appsettings.example.json index 7531b38d3e..ab09b5bcd5 100644 --- a/src/keycloak/Keycloak.Seeding/appsettings.example.json +++ b/src/keycloak/Keycloak.Seeding/appsettings.example.json @@ -126,9 +126,9 @@ }, { "Key": "FederatedIdentities", - "Create": true, - "Update": true, - "Delete": true, + "Create": false, + "Update": false, + "Delete": false, "SeederConfigurations": [] }, {