From f4d4405c2033305f3b3bb70341e9bb453bebaa93 Mon Sep 17 00:00:00 2001 From: Bill Burke Date: Wed, 15 Jul 2015 14:17:23 -0400 Subject: [PATCH] export/import flows --- ...AuthenticationExecutionRepresentation.java | 87 +++++++++++++++++++ .../idm/AuthenticationFlowRepresentation.java | 76 ++++++++++++++++ .../AuthenticatorConfigRepresentation.java | 44 ++++++++++ .../idm/RealmRepresentation.java | 16 ++++ .../utils/DefaultAuthenticationFlows.java | 5 +- .../models/utils/ModelToRepresentation.java | 61 ++++++++++++- .../models/utils/RepresentationToModel.java | 65 +++++++++++++- .../models/file/adapter/RealmAdapter.java | 9 +- .../org/keycloak/models/jpa/RealmAdapter.java | 12 ++- .../mongo/keycloak/adapters/RealmAdapter.java | 9 +- 10 files changed, 369 insertions(+), 15 deletions(-) create mode 100755 core/src/main/java/org/keycloak/representations/idm/AuthenticationExecutionRepresentation.java create mode 100755 core/src/main/java/org/keycloak/representations/idm/AuthenticationFlowRepresentation.java create mode 100755 core/src/main/java/org/keycloak/representations/idm/AuthenticatorConfigRepresentation.java diff --git a/core/src/main/java/org/keycloak/representations/idm/AuthenticationExecutionRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/AuthenticationExecutionRepresentation.java new file mode 100755 index 0000000000..8ca78d4e2c --- /dev/null +++ b/core/src/main/java/org/keycloak/representations/idm/AuthenticationExecutionRepresentation.java @@ -0,0 +1,87 @@ +package org.keycloak.representations.idm; + +import java.io.Serializable; +import java.util.Comparator; + +/** +* @author Bill Burke +* @version $Revision: 1 $ +*/ +public class AuthenticationExecutionRepresentation implements Serializable { + private static final long serialVersionUID = 1L; + + private String authenticatorConfig; + private String authenticator; + private String flowId; + private boolean autheticatorFlow; + private String requirement; + private boolean userSetupAllowed; + private int priority; + + public String getAuthenticatorConfig() { + return authenticatorConfig; + } + + public void setAuthenticatorConfig(String authenticatorConfig) { + this.authenticatorConfig = authenticatorConfig; + } + + public String getAuthenticator() { + return authenticator; + } + + public void setAuthenticator(String authenticator) { + this.authenticator = authenticator; + } + + public String getRequirement() { + return requirement; + } + + public void setRequirement(String requirement) { + this.requirement = requirement; + } + + public int getPriority() { + return priority; + } + + public void setPriority(int priority) { + this.priority = priority; + } + + public boolean isUserSetupAllowed() { + return userSetupAllowed; + } + + public void setUserSetupAllowed(boolean userSetupAllowed) { + this.userSetupAllowed = userSetupAllowed; + } + + /** + * If this execution is a flow, this is the flowId pointing to an AuthenticationFlowModel + * + * @return + */ + public String getFlowId() { + return flowId; + } + + public void setFlowId(String flowId) { + this.flowId = flowId; + } + + /** + * Is the referenced authenticator a flow? + * + * @return + */ + public boolean isAutheticatorFlow() { + return autheticatorFlow; + } + + public void setAutheticatorFlow(boolean autheticatorFlow) { + this.autheticatorFlow = autheticatorFlow; + } + +} diff --git a/core/src/main/java/org/keycloak/representations/idm/AuthenticationFlowRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/AuthenticationFlowRepresentation.java new file mode 100755 index 0000000000..a6ad705fae --- /dev/null +++ b/core/src/main/java/org/keycloak/representations/idm/AuthenticationFlowRepresentation.java @@ -0,0 +1,76 @@ +package org.keycloak.representations.idm; + +import java.io.Serializable; +import java.util.List; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class AuthenticationFlowRepresentation implements Serializable { + private static final long serialVersionUID = 1L; + + private String id; + private String alias; + private String description; + private String providerId; + private boolean topLevel; + private boolean builtIn; + protected List authenticationExecutions; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getAlias() { + return alias; + } + + public void setAlias(String alias) { + this.alias = alias; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getProviderId() { + return providerId; + } + + public void setProviderId(String providerId) { + this.providerId = providerId; + } + + public boolean isTopLevel() { + return topLevel; + } + + public void setTopLevel(boolean topLevel) { + this.topLevel = topLevel; + } + + public boolean isBuiltIn() { + return builtIn; + } + + public void setBuiltIn(boolean builtIn) { + this.builtIn = builtIn; + } + + public List getAuthenticationExecutions() { + return authenticationExecutions; + } + + public void setAuthenticationExecutions(List authenticationExecutions) { + this.authenticationExecutions = authenticationExecutions; + } +} diff --git a/core/src/main/java/org/keycloak/representations/idm/AuthenticatorConfigRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/AuthenticatorConfigRepresentation.java new file mode 100755 index 0000000000..e3f48e09f7 --- /dev/null +++ b/core/src/main/java/org/keycloak/representations/idm/AuthenticatorConfigRepresentation.java @@ -0,0 +1,44 @@ +package org.keycloak.representations.idm; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +/** +* @author Bill Burke +* @version $Revision: 1 $ +*/ +public class AuthenticatorConfigRepresentation implements Serializable { + private static final long serialVersionUID = 1L; + + private String id; + private String alias; + private Map config = new HashMap(); + + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getAlias() { + return alias; + } + + public void setAlias(String alias) { + this.alias = alias; + } + + + + public Map getConfig() { + return config; + } + + public void setConfig(Map config) { + this.config = config; + } +} diff --git a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java index dabc8dbf6d..25ff0a34c4 100755 --- a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java @@ -76,6 +76,8 @@ public class RealmRepresentation { protected Boolean internationalizationEnabled; protected Set supportedLocales; protected String defaultLocale; + protected List authenticationFlows; + protected List authenticatorConfig; @Deprecated protected Boolean social; @@ -626,5 +628,19 @@ public class RealmRepresentation { identityProviderMappers.add(rep); } + public List getAuthenticationFlows() { + return authenticationFlows; + } + public void setAuthenticationFlows(List authenticationFlows) { + this.authenticationFlows = authenticationFlows; + } + + public List getAuthenticatorConfig() { + return authenticatorConfig; + } + + public void setAuthenticatorConfig(List authenticatorConfig) { + this.authenticatorConfig = authenticatorConfig; + } } diff --git a/model/api/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java b/model/api/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java index dee5d4f3d8..d3f5622078 100755 --- a/model/api/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java +++ b/model/api/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java @@ -20,9 +20,8 @@ public class DefaultAuthenticationFlows { public static final String LOGIN_FORMS_FLOW = "forms"; public static void addFlows(RealmModel realm) { - browserFlow(realm); - registrationFlow(realm); - + if (realm.getFlowByAlias(BROWSER_FLOW) == null) browserFlow(realm); + if (realm.getFlowByAlias(REGISTRATION_FLOW) == null) registrationFlow(realm); } public static void registrationFlow(RealmModel realm) { diff --git a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java index 27a05396ff..19c4e81594 100755 --- a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java +++ b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java @@ -1,5 +1,8 @@ package org.keycloak.models.utils; +import org.keycloak.models.AuthenticationExecutionModel; +import org.keycloak.models.AuthenticationFlowModel; +import org.keycloak.models.AuthenticatorConfigModel; import org.keycloak.models.ClientModel; import org.keycloak.models.ClientSessionModel; import org.keycloak.models.FederatedIdentityModel; @@ -17,6 +20,9 @@ import org.keycloak.models.UserFederationProviderModel; import org.keycloak.models.UserModel; import org.keycloak.models.UserSessionModel; +import org.keycloak.representations.idm.AuthenticationExecutionRepresentation; +import org.keycloak.representations.idm.AuthenticationFlowRepresentation; +import org.keycloak.representations.idm.AuthenticatorConfigRepresentation; import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.FederatedIdentityRepresentation; @@ -183,10 +189,30 @@ public class ModelToRepresentation { rep.setInternationalizationEnabled(realm.isInternationalizationEnabled()); rep.getSupportedLocales().addAll(realm.getSupportedLocales()); rep.setDefaultLocale(realm.getDefaultLocale()); - + if (internal) { + exportAuthenticationFlows(realm, rep); + } return rep; } + public static void exportAuthenticationFlows(RealmModel realm, RealmRepresentation rep) { + rep.setAuthenticationFlows(new LinkedList()); + rep.setAuthenticatorConfig(new LinkedList()); + for (AuthenticationFlowModel model : realm.getAuthenticationFlows()) { + AuthenticationFlowRepresentation flowRep = toRepresentation(model); + flowRep.setAuthenticationExecutions(new LinkedList()); + for (AuthenticationExecutionModel execution : realm.getAuthenticationExecutions(model.getId())) { + flowRep.getAuthenticationExecutions().add(toRepresentation(execution)); + } + rep.getAuthenticationFlows().add(flowRep); + } + for (AuthenticatorConfigModel model : realm.getAuthenticatorConfigs()) { + rep.getAuthenticatorConfig().add(toRepresentation(model)); + } + + } + + public static RealmEventsConfigRepresentation toEventsConfigReprensetation(RealmModel realm) { RealmEventsConfigRepresentation rep = new RealmEventsConfigRepresentation(); rep.setEventsEnabled(realm.isEventsEnabled()); @@ -404,4 +430,37 @@ public class ModelToRepresentation { return consentRep; } + public static AuthenticationFlowRepresentation toRepresentation(AuthenticationFlowModel model) { + AuthenticationFlowRepresentation rep = new AuthenticationFlowRepresentation(); + rep.setBuiltIn(model.isBuiltIn()); + rep.setTopLevel(model.isTopLevel()); + rep.setProviderId(model.getProviderId()); + rep.setId(model.getId()); + rep.setAlias(model.getAlias()); + rep.setDescription(model.getDescription()); + return rep; + + } + + public static AuthenticationExecutionRepresentation toRepresentation(AuthenticationExecutionModel model) { + AuthenticationExecutionRepresentation rep = new AuthenticationExecutionRepresentation(); + rep.setAuthenticatorConfig(model.getAuthenticatorConfig()); + rep.setAuthenticator(model.getAuthenticator()); + rep.setAutheticatorFlow(model.isAutheticatorFlow()); + rep.setFlowId(model.getFlowId()); + rep.setPriority(model.getPriority()); + rep.setUserSetupAllowed(model.isUserSetupAllowed()); + rep.setRequirement(model.getRequirement().name()); + return rep; + } + + public static AuthenticatorConfigRepresentation toRepresentation(AuthenticatorConfigModel model) { + AuthenticatorConfigRepresentation rep = new AuthenticatorConfigRepresentation(); + rep.setId(model.getId()); + rep.setAlias(model.getAlias()); + rep.setConfig(model.getConfig()); + return rep; + } + + } diff --git a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java index 2b7195ad6f..e0a328e87f 100755 --- a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java +++ b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java @@ -4,6 +4,9 @@ import net.iharder.Base64; import org.jboss.logging.Logger; import org.keycloak.enums.SslRequired; import org.keycloak.migration.MigrationProvider; +import org.keycloak.models.AuthenticationExecutionModel; +import org.keycloak.models.AuthenticationFlowModel; +import org.keycloak.models.AuthenticatorConfigModel; import org.keycloak.models.BrowserSecurityHeaders; import org.keycloak.models.ClaimMask; import org.keycloak.models.ClientModel; @@ -23,6 +26,9 @@ import org.keycloak.models.UserFederationMapperModel; import org.keycloak.models.UserFederationProviderModel; import org.keycloak.models.UserModel; import org.keycloak.representations.idm.ApplicationRepresentation; +import org.keycloak.representations.idm.AuthenticationExecutionRepresentation; +import org.keycloak.representations.idm.AuthenticationFlowRepresentation; +import org.keycloak.representations.idm.AuthenticatorConfigRepresentation; import org.keycloak.representations.idm.ClaimRepresentation; import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.CredentialRepresentation; @@ -288,6 +294,30 @@ public class RepresentationToModel { if(rep.getDefaultLocale() != null){ newRealm.setDefaultLocale(rep.getDefaultLocale()); } + + importAuthenticationFlows(newRealm, rep); + } + + public static void importAuthenticationFlows(RealmModel newRealm, RealmRepresentation rep) { + if (rep.getAuthenticationFlows() == null) { + // assume this is an old version being imported + DefaultAuthenticationFlows.addFlows(newRealm); + } else { + for (AuthenticationFlowRepresentation flowRep : rep.getAuthenticationFlows()) { + AuthenticationFlowModel model = toModel(flowRep); + model = newRealm.addAuthenticationFlow(model); + for (AuthenticationExecutionRepresentation exeRep : flowRep.getAuthenticationExecutions()) { + AuthenticationExecutionModel execution = toModel(exeRep); + execution.setParentFlow(model.getId()); + newRealm.addAuthenticatorExecution(execution); + } + } + for (AuthenticatorConfigRepresentation configRep : rep.getAuthenticatorConfig()) { + AuthenticatorConfigModel model = toModel(configRep); + newRealm.addAuthenticatorConfig(model); + } + } + } private static void convertDeprecatedSocialProviders(RealmRepresentation rep) { @@ -921,7 +951,7 @@ public class RepresentationToModel { } } } - public static IdentityProviderModel toModel(IdentityProviderRepresentation representation) { + public static IdentityProviderModel toModel(IdentityProviderRepresentation representation) { IdentityProviderModel identityProviderModel = new IdentityProviderModel(); identityProviderModel.setInternalId(representation.getInternalId()); @@ -1009,4 +1039,37 @@ public class RepresentationToModel { return consentModel; } + public static AuthenticationFlowModel toModel(AuthenticationFlowRepresentation rep) { + AuthenticationFlowModel model = new AuthenticationFlowModel(); + model.setBuiltIn(rep.isBuiltIn()); + model.setTopLevel(rep.isTopLevel()); + model.setProviderId(rep.getProviderId()); + model.setId(rep.getId()); + model.setAlias(rep.getAlias()); + model.setDescription(rep.getDescription()); + return model; + + } + + public static AuthenticationExecutionModel toModel(AuthenticationExecutionRepresentation rep) { + AuthenticationExecutionModel model = new AuthenticationExecutionModel(); + model.setAuthenticatorConfig(rep.getAuthenticatorConfig()); + model.setAuthenticator(rep.getAuthenticator()); + model.setAutheticatorFlow(rep.isAutheticatorFlow()); + model.setFlowId(rep.getFlowId()); + model.setPriority(rep.getPriority()); + model.setUserSetupAllowed(rep.isUserSetupAllowed()); + model.setRequirement(AuthenticationExecutionModel.Requirement.valueOf(rep.getRequirement())); + return model; + } + + public static AuthenticatorConfigModel toModel(AuthenticatorConfigRepresentation rep) { + AuthenticatorConfigModel model = new AuthenticatorConfigModel(); + model.setId(rep.getId()); + model.setAlias(rep.getAlias()); + model.setConfig(rep.getConfig()); + return model; + } + + } diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java index 04358734f3..086541e7e7 100755 --- a/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java +++ b/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java @@ -1278,7 +1278,8 @@ public class RealmAdapter implements RealmModel { @Override public AuthenticationFlowModel addAuthenticationFlow(AuthenticationFlowModel model) { AuthenticationFlowEntity entity = new AuthenticationFlowEntity(); - entity.setId(KeycloakModelUtils.generateId()); + String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId(); + entity.setId(id); entity.setAlias(model.getAlias()); entity.setDescription(model.getDescription()); entity.setProviderId(model.getProviderId()); @@ -1339,7 +1340,8 @@ public class RealmAdapter implements RealmModel { @Override public AuthenticationExecutionModel addAuthenticatorExecution(AuthenticationExecutionModel model) { AuthenticationExecutionEntity entity = new AuthenticationExecutionEntity(); - entity.setId(KeycloakModelUtils.generateId()); + String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId(); + entity.setId(id); entity.setAuthenticator(model.getAuthenticator()); entity.setPriority(model.getPriority()); entity.setRequirement(model.getRequirement()); @@ -1399,7 +1401,8 @@ public class RealmAdapter implements RealmModel { @Override public AuthenticatorConfigModel addAuthenticatorConfig(AuthenticatorConfigModel model) { AuthenticatorConfigEntity auth = new AuthenticatorConfigEntity(); - auth.setId(KeycloakModelUtils.generateId()); + String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId(); + auth.setId(id); auth.setAlias(model.getAlias()); auth.setConfig(model.getConfig()); realm.getAuthenticatorConfigs().add(auth); diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java index 1891f4cb0d..eb83947884 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java @@ -1579,7 +1579,8 @@ public class RealmAdapter implements RealmModel { @Override public AuthenticationFlowModel addAuthenticationFlow(AuthenticationFlowModel model) { AuthenticationFlowEntity entity = new AuthenticationFlowEntity(); - entity.setId(KeycloakModelUtils.generateId()); + String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId(); + entity.setId(id); entity.setAlias(model.getAlias()); entity.setDescription(model.getDescription()); entity.setProviderId(model.getProviderId()); @@ -1633,7 +1634,8 @@ public class RealmAdapter implements RealmModel { @Override public AuthenticationExecutionModel addAuthenticatorExecution(AuthenticationExecutionModel model) { AuthenticationExecutionEntity entity = new AuthenticationExecutionEntity(); - entity.setId(KeycloakModelUtils.generateId()); + String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId(); + entity.setId(id); entity.setAuthenticator(model.getAuthenticator()); entity.setPriority(model.getPriority()); entity.setFlowId(model.getFlowId()); @@ -1678,7 +1680,8 @@ public class RealmAdapter implements RealmModel { @Override public AuthenticatorConfigModel addAuthenticatorConfig(AuthenticatorConfigModel model) { AuthenticatorConfigEntity auth = new AuthenticatorConfigEntity(); - auth.setId(KeycloakModelUtils.generateId()); + String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId(); + auth.setId(id); auth.setAlias(model.getAlias()); auth.setRealm(realm); auth.setConfig(model.getConfig()); @@ -1742,7 +1745,8 @@ public class RealmAdapter implements RealmModel { @Override public RequiredActionProviderModel addRequiredActionProvider(RequiredActionProviderModel model) { RequiredActionProviderEntity auth = new RequiredActionProviderEntity(); - auth.setId(KeycloakModelUtils.generateId()); + String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId(); + auth.setId(id); auth.setAlias(model.getAlias()); auth.setName(model.getName()); auth.setRealm(realm); diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java index a56d5f2be2..a3ebacedc1 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java @@ -1352,7 +1352,8 @@ public class RealmAdapter extends AbstractMongoAdapter impleme @Override public AuthenticationFlowModel addAuthenticationFlow(AuthenticationFlowModel model) { AuthenticationFlowEntity entity = new AuthenticationFlowEntity(); - entity.setId(KeycloakModelUtils.generateId()); + String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId(); + entity.setId(id); entity.setAlias(model.getAlias()); entity.setDescription(model.getDescription()); entity.setProviderId(model.getProviderId()); @@ -1414,7 +1415,8 @@ public class RealmAdapter extends AbstractMongoAdapter impleme @Override public AuthenticationExecutionModel addAuthenticatorExecution(AuthenticationExecutionModel model) { AuthenticationExecutionEntity entity = new AuthenticationExecutionEntity(); - entity.setId(KeycloakModelUtils.generateId()); + String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId(); + entity.setId(id); entity.setAuthenticator(model.getAuthenticator()); entity.setPriority(model.getPriority()); entity.setRequirement(model.getRequirement()); @@ -1478,7 +1480,8 @@ public class RealmAdapter extends AbstractMongoAdapter impleme @Override public AuthenticatorConfigModel addAuthenticatorConfig(AuthenticatorConfigModel model) { AuthenticatorConfigEntity auth = new AuthenticatorConfigEntity(); - auth.setId(KeycloakModelUtils.generateId()); + String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId(); + auth.setId(id); auth.setAlias(model.getAlias()); auth.setConfig(model.getConfig()); realm.getAuthenticatorConfigs().add(auth);