KEYCLOAK-2101 - Ensure consistent order for properties in json configuration export.

We now explicitly order the AuthenticatorFlows, AuthenticatorConfig, as well
as RequiredActions to ensure a consistent order for the configuration export to make
it easier to diff / version keycloak configuration files.
Previously the order of the json properties of an configuration export were
non deterministic. The configuration file could look partially different after a
 export, import, export sequence even if no changes were made.
This commit is contained in:
Thomas Darimont 2015-11-17 22:26:32 +01:00
parent 67fca8f1f3
commit c81d0c0898

View file

@ -44,13 +44,7 @@ import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.representations.idm.UserSessionRepresentation; import org.keycloak.representations.idm.UserSessionRepresentation;
import org.keycloak.common.util.Time; import org.keycloak.common.util.Time;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -292,19 +286,50 @@ public class ModelToRepresentation {
public static void exportAuthenticationFlows(RealmModel realm, RealmRepresentation rep) { public static void exportAuthenticationFlows(RealmModel realm, RealmRepresentation rep) {
rep.setAuthenticationFlows(new LinkedList<AuthenticationFlowRepresentation>()); rep.setAuthenticationFlows(new LinkedList<AuthenticationFlowRepresentation>());
rep.setAuthenticatorConfig(new LinkedList<AuthenticatorConfigRepresentation>()); rep.setAuthenticatorConfig(new LinkedList<AuthenticatorConfigRepresentation>());
for (AuthenticationFlowModel model : realm.getAuthenticationFlows()) {
List<AuthenticationFlowModel> authenticationFlows = new ArrayList<>(realm.getAuthenticationFlows());
//ensure consistent ordering of authenticationFlows.
Collections.sort(authenticationFlows, new Comparator<AuthenticationFlowModel>() {
@Override
public int compare(AuthenticationFlowModel left, AuthenticationFlowModel right) {
return left.getAlias().compareTo(right.getAlias());
}
});
for (AuthenticationFlowModel model : authenticationFlows) {
AuthenticationFlowRepresentation flowRep = toRepresentation(realm, model); AuthenticationFlowRepresentation flowRep = toRepresentation(realm, model);
rep.getAuthenticationFlows().add(flowRep); rep.getAuthenticationFlows().add(flowRep);
} }
for (AuthenticatorConfigModel model : realm.getAuthenticatorConfigs()) {
List<AuthenticatorConfigModel> authenticatorConfigs = new ArrayList<>(realm.getAuthenticatorConfigs());
//ensure consistent ordering of authenticatorConfigs.
Collections.sort(authenticatorConfigs, new Comparator<AuthenticatorConfigModel>() {
@Override
public int compare(AuthenticatorConfigModel left, AuthenticatorConfigModel right) {
return left.getAlias().compareTo(right.getAlias());
}
});
for (AuthenticatorConfigModel model : authenticatorConfigs) {
rep.getAuthenticatorConfig().add(toRepresentation(model)); rep.getAuthenticatorConfig().add(toRepresentation(model));
} }
} }
public static void exportRequiredActions(RealmModel realm, RealmRepresentation rep) { public static void exportRequiredActions(RealmModel realm, RealmRepresentation rep) {
rep.setRequiredActions(new LinkedList<RequiredActionProviderRepresentation>()); rep.setRequiredActions(new LinkedList<RequiredActionProviderRepresentation>());
for (RequiredActionProviderModel model : realm.getRequiredActionProviders()) {
List<RequiredActionProviderModel> requiredActionProviders = realm.getRequiredActionProviders();
//ensure consistent ordering of requiredActionProviders.
Collections.sort(requiredActionProviders, new Comparator<RequiredActionProviderModel>() {
@Override
public int compare(RequiredActionProviderModel left, RequiredActionProviderModel right) {
return left.getAlias().compareTo(right.getAlias());
}
});
for (RequiredActionProviderModel model : requiredActionProviders) {
RequiredActionProviderRepresentation action = toRepresentation(model); RequiredActionProviderRepresentation action = toRepresentation(model);
rep.getRequiredActions().add(action); rep.getRequiredActions().add(action);
} }