Skip to content

Commit

Permalink
Normalize Required Actions
Browse files Browse the repository at this point in the history
  • Loading branch information
sonOfRa committed Dec 21, 2022
1 parent 855fcbe commit 3328a8b
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RequiredActionProviderRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
Expand Down Expand Up @@ -114,6 +115,7 @@ private JaversBuilder commonJavers() {
.registerEntity(new EntityDefinition(GroupRepresentation.class, "path", List.of("id", "subGroups", "attributes", "clientRoles")))
.registerEntity(new EntityDefinition(AuthenticationFlowRepresentation.class, "alias", List.of("id", "authenticationExecutions")))
.registerEntity(new EntityDefinition(IdentityProviderRepresentation.class, "alias", List.of("internalId")))
.registerEntity(new EntityDefinition(IdentityProviderMapperRepresentation.class, "name", List.of("id")));
.registerEntity(new EntityDefinition(IdentityProviderMapperRepresentation.class, "name", List.of("id")))
.registerEntity(new EntityDefinition(RequiredActionProviderRepresentation.class, "alias"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public class RealmNormalizationService {
private final GroupNormalizationService groupNormalizationService;
private final AuthFlowNormalizationService authFlowNormalizationService;
private final IdentityProviderNormalizationService identityProviderNormalizationService;
private final RequiredActionNormalizationService requiredActionNormalizationService;
private final JaversUtil javersUtil;

@Autowired
Expand All @@ -67,6 +68,7 @@ public RealmNormalizationService(NormalizationKeycloakConfigProperties keycloakC
GroupNormalizationService groupNormalizationService,
AuthFlowNormalizationService authFlowNormalizationService,
IdentityProviderNormalizationService identityProviderNormalizationService,
RequiredActionNormalizationService requiredActionNormalizationService,
JaversUtil javersUtil) {
this.keycloakConfigProperties = keycloakConfigProperties;
this.javers = javers;
Expand All @@ -80,6 +82,7 @@ public RealmNormalizationService(NormalizationKeycloakConfigProperties keycloakC
this.groupNormalizationService = groupNormalizationService;
this.authFlowNormalizationService = authFlowNormalizationService;
this.identityProviderNormalizationService = identityProviderNormalizationService;
this.requiredActionNormalizationService = requiredActionNormalizationService;
this.javersUtil = javersUtil;

// TODO allow extra "default" values to be ignored?
Expand Down Expand Up @@ -154,6 +157,9 @@ public RealmRepresentation normalizeRealm(RealmRepresentation exportedRealm) {
baselineRealm.getIdentityProviders()));
minimizedRealm.setIdentityProviderMappers(identityProviderNormalizationService.normalizeMappers(exportedRealm.getIdentityProviderMappers(),
baselineRealm.getIdentityProviderMappers()));

minimizedRealm.setRequiredActions(requiredActionNormalizationService.normalizeRequiredActions(exportedRealm.getRequiredActions(),
baselineRealm.getRequiredActions()));
return minimizedRealm;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*-
* ---license-start
* keycloak-config-cli
* ---
* Copyright (C) 2017 - 2022 adorsys GmbH & Co. KG @ https://adorsys.com
* ---
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://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.
* ---license-end
*/

package de.adorsys.keycloak.config.service.normalize;

import de.adorsys.keycloak.config.util.JaversUtil;
import org.javers.core.Javers;
import org.javers.core.diff.changetype.PropertyChange;
import org.keycloak.representations.idm.RequiredActionProviderRepresentation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@ConditionalOnProperty(prefix = "run", name = "operation", havingValue = "NORMALIZE")
public class RequiredActionNormalizationService {

private static final Logger logger = LoggerFactory.getLogger(RequiredActionNormalizationService.class);

private final Javers javers;
private final JaversUtil javersUtil;

public RequiredActionNormalizationService(Javers javers, JaversUtil javersUtil) {
this.javers = javers;
this.javersUtil = javersUtil;
}

public List<RequiredActionProviderRepresentation> normalizeRequiredActions(List<RequiredActionProviderRepresentation> exportedActions,
List<RequiredActionProviderRepresentation> baselineActions) {
List<RequiredActionProviderRepresentation> exportedOrEmpty = exportedActions == null ? List.of() : exportedActions;
List<RequiredActionProviderRepresentation> baselineOrEmpty = baselineActions == null ? List.of() : baselineActions;

var exportedMap = exportedOrEmpty.stream()
.collect(Collectors.toMap(RequiredActionProviderRepresentation::getAlias, Function.identity()));
var baselineMap = baselineOrEmpty.stream()
.collect(Collectors.toMap(RequiredActionProviderRepresentation::getAlias, Function.identity()));

var normalizedActions = new ArrayList<RequiredActionProviderRepresentation>();
for (var entry : baselineMap.entrySet()) {
var alias = entry.getKey();
var exportedAction = exportedMap.remove(alias);
if (exportedAction == null) {
logger.warn("Default realm requiredAction '{}' was deleted in exported realm. It may be reintroduced during import", alias);
continue;
}
var baselineAction = entry.getValue();

var diff = javers.compare(baselineAction, exportedAction);
if (diff.hasChanges()) {
var normalizedAction = new RequiredActionProviderRepresentation();
normalizedAction.setAlias(alias);
for (var change : diff.getChangesByType(PropertyChange.class)) {
javersUtil.applyChange(normalizedAction, change);
}
normalizedAction.setEnabled(exportedAction.isEnabled());
normalizedAction.setDefaultAction(exportedAction.isDefaultAction());
normalizedActions.add(normalizedAction);
}
}
normalizedActions.addAll(exportedMap.values());
return normalizedActions.isEmpty() ? null : normalizedActions;
}
}

0 comments on commit 3328a8b

Please sign in to comment.