diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..510562dfb --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +end_of_line = lf +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space +indent_size = 4 + +[*.json] +indent_size = 2 + diff --git a/CHANGELOG.md b/CHANGELOG.md index df7207ef8..9261922e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,8 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `import.file` is removed. Use `import.path` instead for files and directories. - `keycloak.migrationKey` is removed. Use `import.cache-key` instead. - `keycloak.realm` is removed. Use `import.login-realm` to define the realm to login. -- If you have defined requiredActions, components or subcomponents in your realm configure, make sure you have defined all in your json files. All not defined - actions will removed now by keycloak-config-cli. See: [docs/MANAGED.md](docs/MANAGED.md) +- If you have defined requiredActions, components, authentications flows or subcomponents in your realm configure, make sure you have defined all in your json files. All not defined + actions will removed now by keycloak-config-cli unless `import.state=true` is set (default). See: [docs/MANAGED.md](docs/MANAGED.md) ### Added @@ -21,15 +21,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - _Experimental_ GraalVM support. Run keycloak-config-cli without Java! - Throw errors on unknown properties in config files - Add, update and remove clientScopes -- Removed required actions if they not defined in import json. -- Removed components if they not defined in import json. -- Removed subcomponents if they not defined in import json. -- Contrib behaivor of purging ressource via `import.manage.` property. See: [docs/MANAGED.md](docs/MANAGED.md) +- Remove required actions if they not defined in import json. +- Remove components if they not defined in import json. +- Remove subcomponents if they not defined in import json. +- Remove authentication flows if they not defined in import json. +- Control behavior of purging ressource via `import.manage.` property. See: [docs/MANAGED.md](docs/MANAGED.md) +- State management for `requriedActions`, `clients`, `components` ### Changed - Reduce docker image size -- Bump SpringBoot from 2.2.7 to 2.3.0 +- Bump SpringBoot from 2.2.7 to 2.3.1 - Bump keycloak from 10.0.0 to 10.0.2 - Used keycloak parent pom instead manage versions of 3rd party libs - Add experimental profile for spring native builds diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 0f5d8b2bc..c03c3c536 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -14,22 +14,22 @@ appearance, race, religion, or sexual identity and orientation. Examples of behavior that contributes to creating a positive environment include: -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members Examples of unacceptable behavior by participants include: -* The use of sexualized language or imagery and unwelcome sexual attention or - advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting +- The use of sexualized language or imagery and unwelcome sexual attention or + advances +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or electronic + address, without explicit permission +- Other conduct which could reasonably be considered inappropriate in a + professional setting ## Our Responsibilities diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f3d960038..96d46a3c2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,11 +1,11 @@ # Contributing -When contributing to this repository, please first discuss the change you wish to make via issue before making a change. +When contributing to this repository, please first discuss the change you wish to make via issue before making a change. Please note we have a code of conduct, please follow it in all your interactions with the project. ## Pull Request Process -1. Update the [README.md](README.md) or [DOCUMENTATION.md](DOCUMENTATION.md) with details of changes to the interface, this includes new environment +1. Update the [README.md](README.md) or [DOCUMENTATION.md](DOCUMENTATION.md) with details of changes to the interface, this includes new environment variables, useful file locations and other parameters. 2. If possible add test casse to cover the issues or new feature. diff --git a/README.md b/README.md index 3d80a8219..7fbfeb9a2 100644 --- a/README.md +++ b/README.md @@ -85,18 +85,19 @@ $ docker run \ #### Environment Variables -| Variable | Description | Default | -| -------------------- | ------------------------------------------------------- | ----------- | -| WAIT_TIME_IN_SECONDS | Timeout in seconds for waiting keycloak until reachable | `120` | -| KEYCLOAK_URL | Keycloak Url without `/auth` | - | -| KEYCLOAK_USER | login user name | `admin` | -| KEYCLOAK_PASSWORD | login user name | - | -| KEYCLOAK_CLIENTID | login clientId | `admin-cli` | -| KEYCLOAK_LOGINREALM | login realm | `master` | -| KEYCLOAK_SSLVERIFY | Verify ssl connection to keycloak | `true` | -| IMPORT_PATH | Location of config files | `/config` | -| IMPORT_FORCE | Enable force import of realm config | `false` | -| IMPORT_CACHEKEY | Cache key for importing config. | `default` | +| Variable | Description | Default | +| -------------------- | ---------------------------------------------------------------------------- | ----------- | +| WAIT_TIME_IN_SECONDS | Timeout in seconds for waiting keycloak until reachable | `120` | +| KEYCLOAK_URL | Keycloak Url without `/auth` | - | +| KEYCLOAK_USER | login user name | `admin` | +| KEYCLOAK_PASSWORD | login user name | - | +| KEYCLOAK_CLIENTID | login clientId | `admin-cli` | +| KEYCLOAK_LOGINREALM | login realm | `master` | +| KEYCLOAK_SSLVERIFY | Verify ssl connection to keycloak | `true` | +| IMPORT_PATH | Location of config files | `/config` | +| IMPORT_FORCE | Enable force import of realm config | `false` | +| IMPORT_CACHEKEY | Cache key for importing config. | `default` | +| IMPORT_STATE | Enable state management. Purge only resources managed by kecloak-config-cli. | `true` | ### Experimental native build diff --git a/contrib/native/test-with-import-files.sh b/contrib/native/test-with-import-files.sh index 9cfdd5395..7437121c5 100755 --- a/contrib/native/test-with-import-files.sh +++ b/contrib/native/test-with-import-files.sh @@ -9,13 +9,13 @@ export SPRING_PROFILES_ACTIVE=dev ./target/keycloak-config-cli-native --import.force=true while read -r file; do - ./target/keycloak-config-cli-native --import.path="${file}" + ./target/keycloak-config-cli-native --import.path="${file}" done < <( - find src/test/resources/import-files \ - -type f \ - -name '*.json' \ - ! -path '*cli*' \ - -and ! -path '*exported-realm*' \ - -and ! -name '*invalid*' \ - -and ! -name '*try*' | sort -n + find src/test/resources/import-files \ + -type f \ + -name '*.json' \ + ! -path '*/cli/*' \ + -and ! -path '*exported-realm*' \ + -and ! -name '*invalid*' \ + -and ! -name '*try*' | sort -n ) diff --git a/docs/FEATURES.md b/docs/FEATURES.md index 93cb39b5d..79dde2f4b 100644 --- a/docs/FEATURES.md +++ b/docs/FEATURES.md @@ -16,6 +16,7 @@ | Remove role from user | 1.0.0 | Remove realm-level or client-level roles from user while updating realm | | Add authentication flows and executions | 1.0.0 | Add authentication flows and executions while creating or updating realms | | Update authentication flows and executions | 1.0.0 | Update authentication flow properties and executions while updating realms | +| Remove authentication flows and executions | 2.0.0 | Remove existing authentication flow properties and executions while updating realms | | Add components | 1.0.0 | Add components while creating or updating realms | | Update components | 1.0.0 | Update components properties while updating realms | | Remove components | 2.0.0 | Remove existing sub-components while creating or updating realms | diff --git a/docs/MANAGED.md b/docs/MANAGED.md index 01bbdcaa8..ff48fa0b3 100644 --- a/docs/MANAGED.md +++ b/docs/MANAGED.md @@ -24,16 +24,30 @@ For example if you define `groups` but set an empty array, keycloak will delete ## Supported full managed entities -| Type | Additional Information | -| ---------------- | ----------------------------------------------------------- | -| Groups | - | -| Required Actions | You have to copy the default one to you import json. | -| Client Scopes | - | -| Scope Mappings | - | -| Components | You have to copy the default components to you import json. | -| Sub Components | You have to copy the default components to you import json. | +| Type | Additional Information | +| -------------------- | ----------------------------------------------------------- | +| Groups | - | +| Required Actions | You have to copy the default one to you import json. | +| Client Scopes | - | +| Scope Mappings | - | +| Components | You have to copy the default components to you import json. | +| Sub Components | You have to copy the default components to you import json. | +| Authentication Flows | You have to copy the default components to you import json. | ## Disable deletion of managed entities If you won't delete properties of a specific type, you can disable this behavior by default a properties like `import.managed.=`, e.g.: `import.managed.required-actions=no-delete` + +## State management + +If `import.state` is set to `true` (default value), keycloak-config-cli will purge only resources they created before by keycloak-config-cli. +If `import.state` is set to `false`, keycloak-config-cli will purge all existing entities if they not defined in import json. + +### Supported entities + +Following entities does have saved state: + +* Required Actions +* Clients +* Components diff --git a/pom.xml b/pom.xml index 1e86278ce..eaeddc171 100644 --- a/pom.xml +++ b/pom.xml @@ -113,11 +113,11 @@ - org.springframework.boot - spring-boot-starter-validation - + org.springframework.boot + spring-boot-starter-validation + - + org.springframework.boot spring-boot-configuration-processor true @@ -142,16 +142,16 @@ org.junit.vintage junit-vintage-engine - - - + + + - - org.testcontainers - testcontainers - ${testcontainers.version} - test - + + org.testcontainers + testcontainers + ${testcontainers.version} + test + org.testcontainers @@ -364,19 +364,19 @@ pmd - - - - org.apache.maven.plugins - maven-pmd-plugin - 3.13.0 - - false - - - - - check + + + + org.apache.maven.plugins + maven-pmd-plugin + 3.13.0 + + false + + + + + check diff --git a/src/main/java/de/adorsys/keycloak/config/model/RealmImport.java b/src/main/java/de/adorsys/keycloak/config/model/RealmImport.java index 3ef153a6e..2840d63c5 100644 --- a/src/main/java/de/adorsys/keycloak/config/model/RealmImport.java +++ b/src/main/java/de/adorsys/keycloak/config/model/RealmImport.java @@ -25,7 +25,6 @@ import org.springframework.stereotype.Component; import java.util.ArrayList; -import java.util.Collections; import java.util.List; @Component @@ -41,7 +40,7 @@ public class RealmImport extends RealmRepresentation { public List getAuthenticationFlows() { List result; if (authenticationFlowImports == null) { - result = Collections.emptyList(); + result = null; } else { result = new ArrayList<>(authenticationFlowImports); } diff --git a/src/main/java/de/adorsys/keycloak/config/properties/ImportConfigProperties.java b/src/main/java/de/adorsys/keycloak/config/properties/ImportConfigProperties.java index 1cd903080..fd1df32b7 100644 --- a/src/main/java/de/adorsys/keycloak/config/properties/ImportConfigProperties.java +++ b/src/main/java/de/adorsys/keycloak/config/properties/ImportConfigProperties.java @@ -30,6 +30,7 @@ @Validated public class ImportConfigProperties { public static final String REALM_CHECKSUM_ATTRIBUTE_PREFIX_KEY = "de.adorsys.keycloak.config.import-checksum-{0}"; + public static final String REALM_STATE_ATTRIBUTE_PREFIX_KEY = "de.adorsys.keycloak.config.state-{0}-{1}"; @NotBlank private final String path; @@ -40,12 +41,16 @@ public class ImportConfigProperties { @NotBlank private final String cacheKey; + @NotNull + private final boolean state; + private final ImportManagedProperties managed; - public ImportConfigProperties(String path, boolean force, String cacheKey, ImportManagedProperties managed) { + public ImportConfigProperties(String path, boolean force, String cacheKey, boolean state, ImportManagedProperties managed) { this.path = path; this.force = force; this.cacheKey = cacheKey; + this.state = state; this.managed = managed; } @@ -65,12 +70,16 @@ public ImportManagedProperties getManaged() { return managed; } + public boolean isState() { + return state; + } + public static class ImportManagedProperties { @NotNull - private final ImportManagedPropertiesValues group; + private final ImportManagedPropertiesValues requiredAction; @NotNull - private final ImportManagedPropertiesValues requiredAction; + private final ImportManagedPropertiesValues group; @NotNull private final ImportManagedPropertiesValues clientScope; @@ -84,21 +93,21 @@ public static class ImportManagedProperties { @NotNull private final ImportManagedPropertiesValues subComponent; + @NotNull + private final ImportManagedPropertiesValues authenticationFlow; + public ImportManagedProperties( - ImportManagedPropertiesValues group, ImportManagedPropertiesValues requiredAction, - ImportManagedPropertiesValues clientScope, ImportManagedPropertiesValues scopeMapping, - ImportManagedPropertiesValues component, ImportManagedPropertiesValues subComponent - ) { - this.group = group; + ImportManagedPropertiesValues requiredAction, ImportManagedPropertiesValues group, + ImportManagedPropertiesValues clientScope, ImportManagedPropertiesValues scopeMapping, + ImportManagedPropertiesValues component, ImportManagedPropertiesValues subComponent, + ImportManagedPropertiesValues authenticationFlow) { this.requiredAction = requiredAction; + this.group = group; this.clientScope = clientScope; this.scopeMapping = scopeMapping; this.component = component; this.subComponent = subComponent; - } - - public ImportManagedPropertiesValues getGroup() { - return group; + this.authenticationFlow = authenticationFlow; } public ImportManagedPropertiesValues getRequiredAction() { @@ -121,6 +130,14 @@ public ImportManagedPropertiesValues getSubComponent() { return subComponent; } + public ImportManagedPropertiesValues getAuthenticationFlow() { + return authenticationFlow; + } + + public ImportManagedPropertiesValues getGroup() { + return group; + } + public enum ImportManagedPropertiesValues { FULL, NO_DELETE diff --git a/src/main/java/de/adorsys/keycloak/config/repository/ComponentRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/ComponentRepository.java index 0b38a5dd6..200dce506 100644 --- a/src/main/java/de/adorsys/keycloak/config/repository/ComponentRepository.java +++ b/src/main/java/de/adorsys/keycloak/config/repository/ComponentRepository.java @@ -82,19 +82,15 @@ public ComponentRepresentation get(String realm, String providerType, String nam } public List getAllComponents(String realm) { - RealmResource realmResource = realmRepository.loadRealm(realm); - String realmId = realmResource.toRepresentation().getId(); - - List subComponents = realmResource.components().query(realmId); + return getAllComponents(realm, null); + } - if (subComponents == null) { - return Collections.emptyList(); + public List getAllComponents(String realm, String parentId) { + if (parentId == null) { + RealmResource realmResource = realmRepository.loadRealm(realm); + parentId = realmResource.toRepresentation().getId(); } - return subComponents; - } - - public List getAllSubComponentsByParentId(String realm, String parentId) { RealmResource realmResource = realmRepository.loadRealm(realm); List subComponents = realmResource.components().query(parentId); diff --git a/src/main/java/de/adorsys/keycloak/config/repository/StateRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/StateRepository.java new file mode 100644 index 000000000..ac8a603f2 --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/repository/StateRepository.java @@ -0,0 +1,105 @@ +/* + * Copyright 2019-2020 adorsys GmbH & Co. KG @ https://adorsys.de + * + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package de.adorsys.keycloak.config.repository; + +import com.fasterxml.jackson.databind.ObjectMapper; +import de.adorsys.keycloak.config.exception.ImportProcessingException; +import de.adorsys.keycloak.config.model.RealmImport; +import de.adorsys.keycloak.config.properties.ImportConfigProperties; +import org.keycloak.representations.idm.RealmRepresentation; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.text.MessageFormat; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +@Component +public class StateRepository { + private final RealmRepository realmRepository; + private final ObjectMapper objectMapper; + private final ImportConfigProperties importConfigProperties; + + private Map customAttributes; + + public StateRepository(RealmRepository realmRepository, ObjectMapper objectMapper, ImportConfigProperties importConfigProperties) { + this.realmRepository = realmRepository; + this.objectMapper = objectMapper; + this.importConfigProperties = importConfigProperties; + } + + public List getState(String entity) { + String state = customAttributes.get(getCustomAttributeKey(entity)); + + if (state == null) { + return Collections.emptyList(); + } + + return fromJson(state); + } + + public void loadCustomAttributes(String realm) { + customAttributes = retrieveCustomAttributes(realm); + } + + public void setState(String entity, List values) { + + String valuesAsString = toJson(values); + + customAttributes.put(getCustomAttributeKey(entity), valuesAsString); + } + + public void update(RealmImport realmImport) { + RealmRepresentation existingRealm = realmRepository.get(realmImport.getRealm()); + Map realmAttributes = existingRealm.getAttributes(); + realmAttributes.putAll(customAttributes); + + realmRepository.update(existingRealm); + } + + private String getCustomAttributeKey(String entity) { + return MessageFormat.format( + ImportConfigProperties.REALM_STATE_ATTRIBUTE_PREFIX_KEY, + importConfigProperties.getCacheKey(), + entity + ); + } + + private List fromJson(String value) { + try { + return objectMapper.readValue(value, objectMapper.getTypeFactory().constructCollectionType(List.class, Object.class)); + } catch (IOException e) { + throw new ImportProcessingException(e); + } + } + + private String toJson(List value) { + try { + return objectMapper.writeValueAsString(value); + } catch (IOException e) { + throw new ImportProcessingException(e); + } + } + + private Map retrieveCustomAttributes(String realm) { + RealmRepresentation existingRealm = realmRepository.get(realm); + return existingRealm.getAttributes(); + } +} diff --git a/src/main/java/de/adorsys/keycloak/config/service/AuthenticationFlowsImportService.java b/src/main/java/de/adorsys/keycloak/config/service/AuthenticationFlowsImportService.java index daf622514..b540d9194 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/AuthenticationFlowsImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/AuthenticationFlowsImportService.java @@ -21,12 +21,16 @@ import de.adorsys.keycloak.config.exception.InvalidImportException; import de.adorsys.keycloak.config.factory.UsedAuthenticationFlowWorkaroundFactory; import de.adorsys.keycloak.config.model.RealmImport; +import de.adorsys.keycloak.config.properties.ImportConfigProperties; +import de.adorsys.keycloak.config.properties.ImportConfigProperties.ImportManagedProperties.ImportManagedPropertiesValues; import de.adorsys.keycloak.config.repository.AuthenticationFlowRepository; import de.adorsys.keycloak.config.repository.ExecutionFlowRepository; +import de.adorsys.keycloak.config.repository.RealmRepository; import de.adorsys.keycloak.config.util.AuthenticationFlowUtil; import de.adorsys.keycloak.config.util.CloneUtil; import org.keycloak.representations.idm.AuthenticationExecutionInfoRepresentation; import org.keycloak.representations.idm.AuthenticationFlowRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -34,6 +38,7 @@ import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; /** * We have to import authentication-flows separately because in case of an existing realm, keycloak is ignoring or @@ -47,22 +52,29 @@ public class AuthenticationFlowsImportService { private static final Logger logger = LoggerFactory.getLogger(AuthenticationFlowsImportService.class); + private final RealmRepository realmRepository; private final AuthenticationFlowRepository authenticationFlowRepository; private final ExecutionFlowsImportService executionFlowsImportService; private final ExecutionFlowRepository executionFlowRepository; private final UsedAuthenticationFlowWorkaroundFactory workaroundFactory; + private final ImportConfigProperties importConfigProperties; + @Autowired public AuthenticationFlowsImportService( + RealmRepository realmRepository, AuthenticationFlowRepository authenticationFlowRepository, ExecutionFlowsImportService executionFlowsImportService, ExecutionFlowRepository executionFlowRepository, - UsedAuthenticationFlowWorkaroundFactory workaroundFactory + UsedAuthenticationFlowWorkaroundFactory workaroundFactory, + ImportConfigProperties importConfigProperties ) { + this.realmRepository = realmRepository; this.authenticationFlowRepository = authenticationFlowRepository; this.executionFlowsImportService = executionFlowsImportService; this.executionFlowRepository = executionFlowRepository; this.workaroundFactory = workaroundFactory; + this.importConfigProperties = importConfigProperties; } /** @@ -74,8 +86,23 @@ public AuthenticationFlowsImportService( * --- if nothing of above: do nothing */ public void doImport(RealmImport realmImport) { + List authenticationFlows = realmImport.getAuthenticationFlows(); + if (authenticationFlows == null) return; + List topLevelFlowsToImport = AuthenticationFlowUtil.getTopLevelFlows(realmImport); createOrUpdateTopLevelFlows(realmImport, topLevelFlowsToImport); + setupFlowsInRealm(realmImport); + + if (importConfigProperties.getManaged().getAuthenticationFlow() == ImportManagedPropertiesValues.FULL) { + deleteTopLevelFlowsMissingInImport(realmImport, topLevelFlowsToImport); + } + } + + private void setupFlowsInRealm(RealmImport realmImport) { + RealmRepresentation existingRealm = realmRepository.get(realmImport.getRealm()); + RealmRepresentation realmToUpdate = CloneUtil.deepPatchFieldsOnly(existingRealm, realmImport, RealmImportService.patchingPropertiesForFlowImport); + + realmRepository.update(realmToUpdate); } /** @@ -204,4 +231,28 @@ private void recreateTopLevelFlow( workaround.resetFlowIfNeeded(); } + + private void deleteTopLevelFlowsMissingInImport(RealmImport realmImport, List topLevelFlowsToImport) { + String realm = realmImport.getRealm(); + List existingTopLevelFlows = authenticationFlowRepository.getTopLevelFlows(realm); + existingTopLevelFlows = existingTopLevelFlows.stream().filter(flow -> !flow.isBuiltIn()).collect(Collectors.toList()); + + /* + if (importConfigProperties.isState()) { + // ignore all object there are not in state + existingTopLevelFlows = stateService.getTopLevelFlows(existingTopLevelFlows); + } + */ + + for (AuthenticationFlowRepresentation existingTopLevelFlow : existingTopLevelFlows) { + if (checkIfTopLevelFlowMissingImport(existingTopLevelFlow, topLevelFlowsToImport)) { + logger.debug("Delete authentication flow: {}", existingTopLevelFlow.getAlias()); + authenticationFlowRepository.deleteTopLevelFlow(realm, existingTopLevelFlow.getId()); + } + } + } + + private boolean checkIfTopLevelFlowMissingImport(AuthenticationFlowRepresentation existingTopLevelFlow, List topLevelFlowsToImport) { + return topLevelFlowsToImport.stream().noneMatch(topLevelFlow -> existingTopLevelFlow.getAlias().equals(topLevelFlow.getAlias())); + } } diff --git a/src/main/java/de/adorsys/keycloak/config/service/AuthenticatorConfigImportService.java b/src/main/java/de/adorsys/keycloak/config/service/AuthenticatorConfigImportService.java index 45b3d6217..ceb68a359 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/AuthenticatorConfigImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/AuthenticatorConfigImportService.java @@ -110,6 +110,4 @@ private List getUnusedAuthenticatorConfigs(Re x -> !authExecutionsWithAuthenticatorConfigs.contains(x.getAlias())) .collect(Collectors.toList()); } - - } diff --git a/src/main/java/de/adorsys/keycloak/config/service/ComponentImportService.java b/src/main/java/de/adorsys/keycloak/config/service/ComponentImportService.java index 5d9b79ff4..7c96b88ab 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/ComponentImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/ComponentImportService.java @@ -24,6 +24,7 @@ import de.adorsys.keycloak.config.properties.ImportConfigProperties; import de.adorsys.keycloak.config.properties.ImportConfigProperties.ImportManagedProperties.ImportManagedPropertiesValues; import de.adorsys.keycloak.config.repository.ComponentRepository; +import de.adorsys.keycloak.config.service.state.StateService; import de.adorsys.keycloak.config.util.CloneUtil; import org.keycloak.common.util.MultivaluedHashMap; import org.keycloak.representations.idm.ComponentExportRepresentation; @@ -43,11 +44,13 @@ public class ComponentImportService { private final ComponentRepository componentRepository; private final ImportConfigProperties importConfigProperties; + private final StateService stateService; @Autowired - public ComponentImportService(ComponentRepository componentRepository, ImportConfigProperties importConfigProperties) { + public ComponentImportService(ComponentRepository componentRepository, ImportConfigProperties importConfigProperties, StateService stateService) { this.componentRepository = componentRepository; this.importConfigProperties = importConfigProperties; + this.stateService = stateService; } public void doImport(RealmImport realmImport) { @@ -57,10 +60,11 @@ public void doImport(RealmImport realmImport) { return; } - importComponents(realmImport.getRealm(), components); + String realm = realmImport.getRealm(); + importComponents(realm, components); if (importConfigProperties.getManaged().getComponent() == ImportManagedPropertiesValues.FULL) { - deleteComponentsMissingInImport(realmImport.getRealm(), components); + deleteComponentsMissingInImport(realm, components, null); } } @@ -130,7 +134,7 @@ private void createComponent( } if (importConfigProperties.getManaged().getComponent() == ImportManagedPropertiesValues.FULL) { - deleteSubComponentsMissingInImport(realm, subComponents, exitingComponent.getId()); + deleteComponentsMissingInImport(realm, subComponents, exitingComponent); } } @@ -173,7 +177,7 @@ private void updateComponent( } if (importConfigProperties.getManaged().getSubComponent() == ImportManagedPropertiesValues.FULL) { - deleteSubComponentsMissingInImport(realm, subComponents, patchedComponent.getId()); + deleteComponentsMissingInImport(realm, subComponents, patchedComponent); } } } @@ -200,8 +204,8 @@ private void createOrUpdateSubComponent(String realm, String parentId, String pr } } - private void deleteComponentsMissingInImport(String realm, MultivaluedHashMap componentsToImport) { - List existingComponents = componentRepository.getAllComponents(realm); + private void deleteComponentsMissingInImport(String realm, MultivaluedHashMap componentsToImport, ComponentRepresentation parentComponent) { + List existingComponents = getAllComponentsFromState(realm, parentComponent); for (ComponentRepresentation existingComponent : existingComponents) { if (checkIfComponentMissingImport(existingComponent, componentsToImport)) { @@ -211,15 +215,18 @@ private void deleteComponentsMissingInImport(String realm, MultivaluedHashMap subComponentsToImport, String parentId) { - List existingSubComponents = componentRepository.getAllSubComponentsByParentId(realm, parentId); + private List getAllComponentsFromState(String realm, ComponentRepresentation parentComponent) { + String parentId = parentComponent != null ? parentComponent.getId() : null; - for (ComponentRepresentation existingSubComponent : existingSubComponents) { - if (checkIfComponentMissingImport(existingSubComponent, subComponentsToImport)) { - logger.debug("Delete component: {}/{}", existingSubComponent.getProviderType(), existingSubComponent.getName()); - componentRepository.delete(realm, existingSubComponent); - } + List existingComponents = componentRepository.getAllComponents(realm, parentId); + if (!importConfigProperties.isState()) { + return existingComponents; } + + String parentName = parentComponent != null ? parentComponent.getName() : null; + + // ignore all object there are not in state + return stateService.getComponents(existingComponents, parentName); } private boolean checkIfComponentMissingImport(ComponentRepresentation existingComponent, MultivaluedHashMap componentsToImport) { diff --git a/src/main/java/de/adorsys/keycloak/config/service/GroupImportService.java b/src/main/java/de/adorsys/keycloak/config/service/GroupImportService.java index 9a146ebc0..3f2d0b369 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/GroupImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/GroupImportService.java @@ -48,29 +48,17 @@ public void importGroups(RealmImport realmImport) { if (groups == null) { logger.debug("No groups to import into realm '{}'", realm); - } else { - importGroups(realm, groups); + return; } - } - private void importGroups(String realm, List groups) { List existingGroups = groupRepository.getGroups(realm); - if (groups.isEmpty()) { - if (importConfigProperties.getManaged().getClientScope() == ImportManagedPropertiesValues.NO_DELETE) { - logger.info("Skip deletion of groups"); - return; - } - - deleteAllExistingGroups(realm, existingGroups); - } else { - if (importConfigProperties.getManaged().getClientScope() == ImportManagedPropertiesValues.FULL) { - deleteGroupsMissingInImport(realm, groups, existingGroups); - } + for (GroupRepresentation group : groups) { + createOrUpdateRealmGroup(realm, group); + } - for (GroupRepresentation group : groups) { - createOrUpdateRealmGroup(realm, group); - } + if (importConfigProperties.getManaged().getGroup() == ImportManagedPropertiesValues.FULL) { + deleteGroupsMissingInImport(realm, groups, existingGroups); } } @@ -83,13 +71,6 @@ private void deleteGroupsMissingInImport(String realm, List } } - private void deleteAllExistingGroups(String realm, List existingGroups) { - for (GroupRepresentation existingGroup : existingGroups) { - logger.debug("Delete group '{}' in realm '{}'", existingGroup.getName(), realm); - groupRepository.deleteGroup(realm, existingGroup.getId()); - } - } - private boolean hasGroupWithName(List groups, String groupName) { return groups.stream().anyMatch(g -> Objects.equals(g.getName(), groupName)); } diff --git a/src/main/java/de/adorsys/keycloak/config/service/RealmImportService.java b/src/main/java/de/adorsys/keycloak/config/service/RealmImportService.java index 361219844..4f8887ed0 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/RealmImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/RealmImportService.java @@ -23,6 +23,7 @@ import de.adorsys.keycloak.config.provider.KeycloakProvider; import de.adorsys.keycloak.config.repository.RealmRepository; import de.adorsys.keycloak.config.service.checksum.ChecksumService; +import de.adorsys.keycloak.config.service.state.StateService; import de.adorsys.keycloak.config.util.CloneUtil; import org.keycloak.representations.idm.RealmRepresentation; import org.slf4j.Logger; @@ -32,9 +33,7 @@ @Service public class RealmImportService { - private static final Logger logger = LoggerFactory.getLogger(RealmImportService.class); - - private final String[] ignoredPropertiesForCreation = new String[]{ + static final String[] ignoredPropertiesForCreation = new String[]{ "users", "groups", "browserFlow", @@ -46,8 +45,7 @@ public class RealmImportService { "components", "authenticationFlows" }; - - private final String[] ignoredPropertiesForUpdate = new String[]{ + static final String[] ignoredPropertiesForUpdate = new String[]{ "clients", "roles", "users", @@ -63,8 +61,7 @@ public class RealmImportService { "authenticationFlows", "requiredActions" }; - - private final String[] patchingPropertiesForFlowImport = new String[]{ + static final String[] patchingPropertiesForFlowImport = new String[]{ "browserFlow", "directGrantFlow", "clientAuthenticationFlow", @@ -72,7 +69,7 @@ public class RealmImportService { "registrationFlow", "resetCredentialsFlow", }; - + private static final Logger logger = LoggerFactory.getLogger(RealmImportService.class); private final KeycloakProvider keycloakProvider; private final RealmRepository realmRepository; @@ -92,6 +89,7 @@ public class RealmImportService { private final ImportConfigProperties importProperties; private final ChecksumService checksumService; + private final StateService stateService; @Autowired public RealmImportService( @@ -110,8 +108,8 @@ public RealmImportService( CustomImportService customImportService, ScopeMappingImportService scopeMappingImportService, IdentityProviderImportService identityProviderImportService, - ChecksumService checksumService - ) { + ChecksumService checksumService, + StateService stateService) { this.importProperties = importProperties; this.keycloakProvider = keycloakProvider; this.realmRepository = realmRepository; @@ -128,6 +126,7 @@ public RealmImportService( this.scopeMappingImportService = scopeMappingImportService; this.identityProviderImportService = identityProviderImportService; this.checksumService = checksumService; + this.stateService = stateService; } public void doImport(RealmImport realmImport) { @@ -142,31 +141,34 @@ public void doImport(RealmImport realmImport) { keycloakProvider.close(); } + private void updateRealmIfNecessary(RealmImport realmImport) { + if (importProperties.isForce() || checksumService.hasToBeUpdated(realmImport)) { + updateRealm(realmImport); + } else { + logger.debug( + "No need to update realm '{}', import checksum same: '{}'", + realmImport.getRealm(), + realmImport.getChecksum() + ); + } + } + private void createRealm(RealmImport realmImport) { logger.debug("Creating realm '{}' ...", realmImport.getRealm()); RealmRepresentation realmForCreation = CloneUtil.deepClone(realmImport, RealmRepresentation.class, ignoredPropertiesForCreation); realmRepository.create(realmForCreation); + stateService.loadState(realmImport); + userImportService.doImport(realmImport); groupImportService.importGroups(realmImport); authenticationFlowsImportService.doImport(realmImport); - setupFlows(realmImport); componentImportService.doImport(realmImport); customImportService.doImport(realmImport); - checksumService.doImport(realmImport); - } - private void updateRealmIfNecessary(RealmImport realmImport) { - if (importProperties.isForce() || checksumService.hasToBeUpdated(realmImport)) { - updateRealm(realmImport); - } else { - logger.debug( - "No need to update realm '{}', import checksum same: '{}'", - realmImport.getRealm(), - realmImport.getChecksum() - ); - } + stateService.doImport(realmImport); + checksumService.doImport(realmImport); } private void updateRealm(RealmImport realmImport) { @@ -175,6 +177,8 @@ private void updateRealm(RealmImport realmImport) { RealmRepresentation realmToUpdate = CloneUtil.deepClone(realmImport, RealmRepresentation.class, ignoredPropertiesForUpdate); realmRepository.update(realmToUpdate); + stateService.loadState(realmImport); + clientImportService.doImport(realmImport); roleImportService.doImport(realmImport); groupImportService.importGroups(realmImport); @@ -183,19 +187,12 @@ private void updateRealm(RealmImport realmImport) { requiredActionsImportService.doImport(realmImport); authenticationFlowsImportService.doImport(realmImport); authenticatorConfigImportService.doImport(realmImport); - setupFlows(realmImport); componentImportService.doImport(realmImport); scopeMappingImportService.doImport(realmImport); identityProviderImportService.doImport(realmImport); customImportService.doImport(realmImport); + stateService.doImport(realmImport); checksumService.doImport(realmImport); } - - private void setupFlows(RealmImport realmImport) { - RealmRepresentation existingRealm = realmRepository.get(realmImport.getRealm()); - RealmRepresentation realmToUpdate = CloneUtil.deepPatchFieldsOnly(existingRealm, realmImport, patchingPropertiesForFlowImport); - - realmRepository.update(realmToUpdate); - } } diff --git a/src/main/java/de/adorsys/keycloak/config/service/RequiredActionsImportService.java b/src/main/java/de/adorsys/keycloak/config/service/RequiredActionsImportService.java index f53e4ba44..b455136f1 100644 --- a/src/main/java/de/adorsys/keycloak/config/service/RequiredActionsImportService.java +++ b/src/main/java/de/adorsys/keycloak/config/service/RequiredActionsImportService.java @@ -23,6 +23,7 @@ import de.adorsys.keycloak.config.properties.ImportConfigProperties; import de.adorsys.keycloak.config.properties.ImportConfigProperties.ImportManagedProperties.ImportManagedPropertiesValues; import de.adorsys.keycloak.config.repository.RequiredActionRepository; +import de.adorsys.keycloak.config.service.state.StateService; import de.adorsys.keycloak.config.util.CloneUtil; import org.keycloak.representations.idm.RequiredActionProviderRepresentation; import org.keycloak.representations.idm.RequiredActionProviderSimpleRepresentation; @@ -42,12 +43,14 @@ public class RequiredActionsImportService { private final RequiredActionRepository requiredActionRepository; private final ImportConfigProperties importConfigProperties; + private final StateService stateService; public RequiredActionsImportService( RequiredActionRepository requiredActionRepository, - ImportConfigProperties importConfigProperties) { + ImportConfigProperties importConfigProperties, StateService stateService) { this.requiredActionRepository = requiredActionRepository; this.importConfigProperties = importConfigProperties; + this.stateService = stateService; } public void doImport(RealmImport realmImport) { @@ -61,22 +64,13 @@ public void doImport(RealmImport realmImport) { public void doImport(String realm, List requiredActions) { List existingRequiredActions = requiredActionRepository.getRequiredActions(realm); - if (requiredActions.isEmpty()) { - if (importConfigProperties.getManaged().getClientScope() == ImportManagedPropertiesValues.NO_DELETE) { - logger.info("Skip deletion of requiredActions"); - return; - } - - deleteAllExistingRequiredActions(realm, existingRequiredActions); - } else { - if (importConfigProperties.getManaged().getClientScope() == ImportManagedPropertiesValues.FULL) { - deleteRequiredActionsMissingInImport(realm, requiredActions, existingRequiredActions); - } + if (importConfigProperties.getManaged().getClientScope() == ImportManagedPropertiesValues.FULL) { + deleteRequiredActionsMissingInImport(realm, requiredActions, existingRequiredActions); + } - for (RequiredActionProviderRepresentation requiredActionToImport : requiredActions) { - throwErrorIfInvalid(requiredActionToImport); - createOrUpdateRequireAction(realm, requiredActionToImport); - } + for (RequiredActionProviderRepresentation requiredActionToImport : requiredActions) { + throwErrorIfInvalid(requiredActionToImport); + createOrUpdateRequireAction(realm, requiredActionToImport); } } @@ -151,14 +145,12 @@ private void updateRequiredAction( requiredActionRepository.updateRequiredAction(realm, requiredActionToBeConfigured); } - private void deleteAllExistingRequiredActions(String realm, List existingRequiredActions) { - for (RequiredActionProviderRepresentation existingRequiredAction : existingRequiredActions) { - logger.debug("Delete requiredAction '{}' in realm '{}'", existingRequiredAction.getName(), realm); - requiredActionRepository.deleteRequiredAction(realm, existingRequiredAction); + private void deleteRequiredActionsMissingInImport(String realm, List requiredActions, List existingRequiredActions) { + if (importConfigProperties.isState()) { + // ignore all object there are not in state + existingRequiredActions = stateService.getRequiredActions(existingRequiredActions); } - } - private void deleteRequiredActionsMissingInImport(String realm, List requiredActions, List existingRequiredActions) { for (RequiredActionProviderRepresentation existingRequiredAction : existingRequiredActions) { if (!hasRequiredActionWithAlias(existingRequiredAction.getAlias(), requiredActions)) { logger.debug("Delete requiredAction '{}' in realm '{}'", existingRequiredAction.getName(), realm); diff --git a/src/main/java/de/adorsys/keycloak/config/service/state/StateService.java b/src/main/java/de/adorsys/keycloak/config/service/state/StateService.java new file mode 100644 index 000000000..e3a827bdb --- /dev/null +++ b/src/main/java/de/adorsys/keycloak/config/service/state/StateService.java @@ -0,0 +1,163 @@ +/* + * Copyright 2019-2020 adorsys GmbH & Co. KG @ https://adorsys.de + * + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package de.adorsys.keycloak.config.service.state; + +import de.adorsys.keycloak.config.model.RealmImport; +import de.adorsys.keycloak.config.properties.ImportConfigProperties; +import de.adorsys.keycloak.config.repository.StateRepository; +import de.adorsys.keycloak.config.util.AuthenticationFlowUtil; +import org.keycloak.common.util.MultivaluedHashMap; +import org.keycloak.representations.idm.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Service +public class StateService { + private static final Logger logger = LoggerFactory.getLogger(StateService.class); + + private final StateRepository stateRepository; + private final ImportConfigProperties importConfigProperties; + + @Autowired + public StateService(StateRepository stateRepository, ImportConfigProperties importConfigProperties) { + this.stateRepository = stateRepository; + this.importConfigProperties = importConfigProperties; + } + + public void loadState(RealmImport realmImport) { + stateRepository.loadCustomAttributes(realmImport.getRealm()); + } + + public void doImport(RealmImport realmImport) { + if (!importConfigProperties.isState()) { + return; + } + + String realm = realmImport.getRealm(); + + setClients(realmImport); + setRequiredActions(realmImport); + setComponents(realmImport); + setTopLevelFlows(realmImport); + + stateRepository.update(realmImport); + logger.debug("Updated states of realm '{}'", realm); + } + + private void setClients(RealmImport realmImport) { + List clients = realmImport.getClients(); + if (clients == null) return; + + List state = clients.stream().map(ClientRepresentation::getName).collect(Collectors.toList()); + + stateRepository.setState("clients", state); + } + + public List getRequiredActions(List requiredActions) { + List requiredActionFromState = stateRepository.getState("required-actions"); + return requiredActions.stream() + .filter(requiredAction -> requiredActionFromState.contains(requiredAction.getAlias())) + .collect(Collectors.toList()); + } + + private void setRequiredActions(RealmImport realmImport) { + + + List requiredActions = realmImport.getRequiredActions(); + if (requiredActions == null) return; + + List state = requiredActions.stream().map(RequiredActionProviderRepresentation::getAlias).collect(Collectors.toList()); + + stateRepository.setState("required-actions", state); + } + + public List getComponents(List components, String parentComponentName) { + List componentsFromState = (parentComponentName != null) + ? stateRepository.getState("sub-components-" + parentComponentName) + : stateRepository.getState("components"); + + return components.stream() + .filter(component -> componentsFromState.contains(component.getName())) + .collect(Collectors.toList()); + } + + private void setComponents(RealmImport realmImport) { + MultivaluedHashMap components = realmImport.getComponents(); + if (components == null) return; + + List state = new ArrayList<>(); + + for (Map.Entry> entry : components.entrySet()) { + for (ComponentExportRepresentation component : entry.getValue()) { + String componentName = component.getName(); + state.add(componentName); + + setSubComponents(component); + } + } + + stateRepository.setState("components", state); + } + + private void setSubComponents(ComponentExportRepresentation component) { + MultivaluedHashMap subComponents = component.getSubComponents(); + if (subComponents == null || subComponents.isEmpty()) { + return; + } + + List state = new ArrayList<>(); + for (Map.Entry> subEntry : subComponents.entrySet()) { + List nameOfSubComponents = subEntry.getValue().stream() + .map(ComponentExportRepresentation::getName) + .collect(Collectors.toList()); + + state.addAll(nameOfSubComponents); + } + + stateRepository.setState("sub-components-" + component.getName(), state); + } + + /* + public List getTopLevelFlows(List topLevelFlows) { + List topLevelFlowsFromState = stateRepository.getState("top-flows"); + + return topLevelFlows.stream() + .filter(topLevelFlow -> topLevelFlowsFromState.contains(topLevelFlow.getAlias())) + .collect(Collectors.toList()); + } + */ + + private void setTopLevelFlows(RealmImport realmImport) { + List authenticationFlows = realmImport.getAuthenticationFlows(); + if (authenticationFlows == null) return; + + List topLevelFlows = AuthenticationFlowUtil.getTopLevelFlows(realmImport); + + List state = topLevelFlows.stream().map(AuthenticationFlowRepresentation::getAlias).collect(Collectors.toList()); + + stateRepository.setState("top-flows", state); + } +} diff --git a/src/main/java/de/adorsys/keycloak/config/util/AuthenticationFlowUtil.java b/src/main/java/de/adorsys/keycloak/config/util/AuthenticationFlowUtil.java index a2e59885a..03706eb60 100644 --- a/src/main/java/de/adorsys/keycloak/config/util/AuthenticationFlowUtil.java +++ b/src/main/java/de/adorsys/keycloak/config/util/AuthenticationFlowUtil.java @@ -51,15 +51,13 @@ private static Optional tryToGetNonTopLevelFlo } private static List getNonTopLevelFlows(RealmImport realmImport) { - return realmImport.getAuthenticationFlows() - .stream() + return StreamUtil.collectionAsStream(realmImport.getAuthenticationFlows()) .filter(f -> !f.isTopLevel()) .collect(Collectors.toList()); } public static List getTopLevelFlows(RealmImport realmImport) { - return realmImport.getAuthenticationFlows() - .stream() + return StreamUtil.collectionAsStream(realmImport.getAuthenticationFlows()) .filter(AuthenticationFlowRepresentation::isTopLevel) .collect(Collectors.toList()); } diff --git a/src/main/java/de/adorsys/keycloak/config/util/CloneUtil.java b/src/main/java/de/adorsys/keycloak/config/util/CloneUtil.java index 6a370fc20..e8825237b 100644 --- a/src/main/java/de/adorsys/keycloak/config/util/CloneUtil.java +++ b/src/main/java/de/adorsys/keycloak/config/util/CloneUtil.java @@ -20,13 +20,13 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.type.MapType; import de.adorsys.keycloak.config.exception.ImportProcessingException; import java.io.IOException; @@ -37,10 +37,6 @@ import java.util.stream.StreamSupport; public class CloneUtil { - CloneUtil() { - throw new IllegalStateException("Utility class"); - } - private static final ObjectMapper nonNullMapper; private static final ObjectMapper nonFailingMapper; @@ -53,6 +49,10 @@ public class CloneUtil { nonFailingMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } + CloneUtil() { + throw new IllegalStateException("Utility class"); + } + public static T deepClone(S object, Class targetClass, String... ignoredProperties) { if (object == null) return null; @@ -121,9 +121,7 @@ private static Map toMap(S object, String... ignoredProperti } private static Map jsonNodeToMap(JsonNode objectAsNode) { - TypeReference> typeRef = new TypeReference>() { - }; - + MapType typeRef = nonFailingMapper.getTypeFactory().constructMapType(Map.class, String.class, Object.class); Map objectAsMap; try { diff --git a/src/main/resources/application-http-debug.properties b/src/main/resources/application-http-debug.properties new file mode 100644 index 000000000..ccdd67461 --- /dev/null +++ b/src/main/resources/application-http-debug.properties @@ -0,0 +1 @@ +logging.level.org.apache.http.wire=debug diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f3e3cc1bd..8f95c3500 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -14,9 +14,11 @@ keycloak.client-id=admin-cli keycloak.ssl-verify=true import.cache-key=default import.force=false +import.state=true +import.managed.authentication-flow=full import.managed.group=full import.managed.required-action=full import.managed.client-scope=full import.managed.scope-mapping=full -import.managed.component=no_delete +import.managed.component=full import.managed.sub-component=full diff --git a/src/test/java/de/adorsys/keycloak/config/ImportAuthenticationFlowsIT.java b/src/test/java/de/adorsys/keycloak/config/ImportAuthenticationFlowsIT.java index c6a4825aa..acd6bdaba 100644 --- a/src/test/java/de/adorsys/keycloak/config/ImportAuthenticationFlowsIT.java +++ b/src/test/java/de/adorsys/keycloak/config/ImportAuthenticationFlowsIT.java @@ -28,10 +28,10 @@ import org.keycloak.representations.idm.RealmRepresentation; import java.util.List; -import java.util.Optional; +import java.util.stream.Collectors; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.*; import static org.hamcrest.core.Is.is; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -45,7 +45,7 @@ class ImportAuthenticationFlowsIT extends AbstractImportTest { @Test @Order(0) void shouldCreateRealmWithFlows() { - doImport("0_create_realm_with_flows.json"); + doImport("00_create_realm_with_flows.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); @@ -71,7 +71,7 @@ void shouldCreateRealmWithFlows() { @Test @Order(1) void shouldAddExecutionToFlow() { - doImport("1_update_realm__add_execution_to_flow.json"); + doImport("01_update_realm__add_execution_to_flow.json"); RealmRepresentation updatedRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); @@ -103,7 +103,7 @@ void shouldAddExecutionToFlow() { @Test @Order(2) void shouldChangeExecutionRequirement() { - doImport("2_update_realm__change_execution_requirement.json"); + doImport("02_update_realm__change_execution_requirement.json"); RealmRepresentation updatedRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); @@ -135,7 +135,7 @@ void shouldChangeExecutionRequirement() { @Test @Order(3) void shouldChangeExecutionPriorities() { - doImport("3_update_realm__change_execution_priorities.json"); + doImport("03_update_realm__change_execution_priorities.json"); RealmRepresentation updatedRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); @@ -167,7 +167,7 @@ void shouldChangeExecutionPriorities() { @Test @Order(4) void shouldAddFlowWithExecutionFlow() { - doImport("4_update_realm__add_flow_with_execution_flow.json"); + doImport("04_update_realm__add_flow_with_execution_flow.json"); RealmRepresentation updatedRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); @@ -210,7 +210,7 @@ void shouldAddFlowWithExecutionFlow() { @Test @Order(5) void shouldFailWhenTryAddFlowWithDefectiveExecutionFlow() { - RealmImport foundImport = getImport("4.1_try_to_update_realm__add_flow_with_defective_execution_flow.json"); + RealmImport foundImport = getImport("04.1_try_to_update_realm__add_flow_with_defective_execution_flow.json"); ImportProcessingException thrown = assertThrows(ImportProcessingException.class, () -> realmImportService.doImport(foundImport)); @@ -220,7 +220,7 @@ void shouldFailWhenTryAddFlowWithDefectiveExecutionFlow() { @Test @Order(6) void shouldChangeFlowRequirementWithExecutionFlow() { - doImport("5_update_realm__change_requirement_flow_with_execution_flow.json"); + doImport("05_update_realm__change_requirement_flow_with_execution_flow.json"); RealmRepresentation updatedRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); @@ -263,7 +263,7 @@ void shouldChangeFlowRequirementWithExecutionFlow() { @Test @Order(7) void shouldFailWhenTryToUpdateDefectiveFlowRequirementWithExecutionFlow() { - RealmImport foundImport = getImport("5.1_try_to_update_realm__change_requirement_in defective_flow_with_execution_flow.json"); + RealmImport foundImport = getImport("05.1_try_to_update_realm__change_requirement_in defective_flow_with_execution_flow.json"); ImportProcessingException thrown = assertThrows(ImportProcessingException.class, () -> realmImportService.doImport(foundImport)); @@ -273,7 +273,7 @@ void shouldFailWhenTryToUpdateDefectiveFlowRequirementWithExecutionFlow() { @Test @Order(8) void shouldFailWhenTryToUpdateFlowRequirementWithExecutionFlowWithNotExistingExecution() { - RealmImport foundImport = getImport("5.2_try_to_update_realm__change_requirement_flow_with_execution_flow_with_not_existing_execution.json"); + RealmImport foundImport = getImport("05.2_try_to_update_realm__change_requirement_flow_with_execution_flow_with_not_existing_execution.json"); ImportProcessingException thrown = assertThrows(ImportProcessingException.class, () -> realmImportService.doImport(foundImport)); @@ -283,7 +283,7 @@ void shouldFailWhenTryToUpdateFlowRequirementWithExecutionFlowWithNotExistingExe @Test @Order(9) void shouldFailWhenTryToUpdateFlowRequirementWithExecutionFlowWithDefectiveExecution() { - RealmImport foundImport = getImport("5.3_try_to_update_realm__change_requirement_flow_with_execution_flow_with_defective_execution.json"); + RealmImport foundImport = getImport("05.3_try_to_update_realm__change_requirement_flow_with_execution_flow_with_defective_execution.json"); ImportProcessingException thrown = assertThrows(ImportProcessingException.class, () -> realmImportService.doImport(foundImport)); @@ -293,7 +293,7 @@ void shouldFailWhenTryToUpdateFlowRequirementWithExecutionFlowWithDefectiveExecu @Test @Order(10) void shouldFailWhenTryToUpdateFlowRequirementWithDefectiveExecutionFlow() { - RealmImport foundImport = getImport("5.4_try_to_update_realm__change_requirement_flow_with_defective_execution_flow.json"); + RealmImport foundImport = getImport("05.4_try_to_update_realm__change_requirement_flow_with_defective_execution_flow.json"); ImportProcessingException thrown = assertThrows(ImportProcessingException.class, () -> realmImportService.doImport(foundImport)); @@ -303,7 +303,7 @@ void shouldFailWhenTryToUpdateFlowRequirementWithDefectiveExecutionFlow() { @Test @Order(11) void shouldChangeFlowPriorityWithExecutionFlow() { - doImport("6_update_realm__change_priority_flow_with_execution_flow.json"); + doImport("06_update_realm__change_priority_flow_with_execution_flow.json"); RealmRepresentation updatedRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); @@ -346,7 +346,7 @@ void shouldChangeFlowPriorityWithExecutionFlow() { @Test @Order(12) void shouldSetRegistrationFlow() { - doImport("7_update_realm__set_registration_flow.json"); + doImport("07_update_realm__set_registration_flow.json"); RealmRepresentation updatedRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); @@ -359,7 +359,7 @@ void shouldSetRegistrationFlow() { @Test @Order(13) void shouldChangeRegistrationFlow() { - doImport("8_update_realm__change_registration_flow.json"); + doImport("08_update_realm__change_registration_flow.json"); RealmRepresentation updatedRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); @@ -375,7 +375,7 @@ void shouldChangeRegistrationFlow() { @Test @Order(14) void shouldAddAndSetResetCredentialsFlow() { - doImport("9_update_realm__add_and_set_custom_reset-credentials-flow.json"); + doImport("09_update_realm__add_and_set_custom_reset-credentials-flow.json"); RealmRepresentation updatedRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); @@ -608,26 +608,196 @@ void shouldFailWhenTryingToUpdateWithNonExistingFlow() { assertThat(thrown.getMessage(), is("Non-toplevel flow not found: non existing sub flow")); } - private AuthenticationExecutionExportRepresentation getExecutionFromFlow(AuthenticationFlowRepresentation unchangedFlow, String executionAuthenticator) { + @Test + @Order(96) + void shouldRemoveNonTopLevelFlow() { + doImport("96_update_realm__update-remove-non-top-level-flow.json"); + + RealmRepresentation updatedRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); + + assertThat(updatedRealm.getRealm(), is(REALM_NAME)); + assertThat(updatedRealm.isEnabled(), is(true)); + + AuthenticationFlowRepresentation unchangedFlow = getAuthenticationFlow(updatedRealm, "my auth flow"); + assertThat(unchangedFlow.getDescription(), is("My auth flow for testing with pseudo-id")); + assertThat(unchangedFlow.getProviderId(), is("basic-flow")); + assertThat(unchangedFlow.isBuiltIn(), is(false)); + assertThat(unchangedFlow.isTopLevel(), is(true)); + List importedExecutions = unchangedFlow.getAuthenticationExecutions(); + assertThat(importedExecutions, hasSize(1)); - Optional maybeImportedExecution = importedExecutions.stream() - .filter(e -> e.getAuthenticator().equals(executionAuthenticator)) - .findFirst(); + AuthenticationExecutionExportRepresentation importedExecution = getExecutionFromFlow(unchangedFlow, "http-basic-authenticator"); + assertThat(importedExecution.getAuthenticator(), is("http-basic-authenticator")); + assertThat(importedExecution.getRequirement(), is("DISABLED")); + assertThat(importedExecution.getPriority(), is(0)); + assertThat(importedExecution.isAutheticatorFlow(), is(false)); + + AuthenticationFlowRepresentation topLevelFlow = getAuthenticationFlow(updatedRealm, "my registration"); + assertThat(topLevelFlow.getDescription(), is("My registration flow")); + assertThat(topLevelFlow.getProviderId(), is("basic-flow")); + assertThat(topLevelFlow.isBuiltIn(), is(false)); + assertThat(topLevelFlow.isTopLevel(), is(true)); + + List executionFlows = topLevelFlow.getAuthenticationExecutions(); + assertThat(executionFlows, hasSize(1)); + + AuthenticationExecutionExportRepresentation execution = getExecutionFromFlow(topLevelFlow, "registration-page-form"); + assertThat(execution.getAuthenticator(), is("registration-page-form")); + assertThat(execution.getRequirement(), is("REQUIRED")); + assertThat(execution.getPriority(), is(0)); + assertThat(execution.isAutheticatorFlow(), is(true)); + + AuthenticationFlowRepresentation nonTopLevelFlow = getAuthenticationFlow(updatedRealm, "my registration form"); + + List nonTopLevelFlowExecutions = nonTopLevelFlow.getAuthenticationExecutions(); + assertThat(nonTopLevelFlowExecutions, hasSize(2)); - assertThat(maybeImportedExecution.isPresent(), is(true)); + execution = getExecutionFromFlow(nonTopLevelFlow, "registration-profile-action"); + assertThat(execution.getAuthenticator(), is("registration-profile-action")); + assertThat(execution.getRequirement(), is("REQUIRED")); + assertThat(execution.getPriority(), is(0)); + assertThat(execution.isAutheticatorFlow(), is(false)); - return maybeImportedExecution.orElse(null); + execution = getExecutionFromFlow(nonTopLevelFlow, "registration-user-creation"); + assertThat(execution.getAuthenticator(), is("registration-user-creation")); + assertThat(execution.getRequirement(), is("REQUIRED")); + assertThat(execution.getPriority(), is(1)); + assertThat(execution.isAutheticatorFlow(), is(false)); + } + + @Test + @Order(97) + void shouldSkipRemoveTopLevelFlow() { + doImport("97_update_realm__skip-remove-top-level-flow.json"); + + RealmRepresentation updatedRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); + + assertThat(updatedRealm.getRealm(), is(REALM_NAME)); + assertThat(updatedRealm.isEnabled(), is(true)); + + AuthenticationFlowRepresentation unchangedFlow = getAuthenticationFlow(updatedRealm, "my auth flow"); + assertThat(unchangedFlow.getDescription(), is("My auth flow for testing with pseudo-id")); + assertThat(unchangedFlow.getProviderId(), is("basic-flow")); + assertThat(unchangedFlow.isBuiltIn(), is(false)); + assertThat(unchangedFlow.isTopLevel(), is(true)); + + List importedExecutions = unchangedFlow.getAuthenticationExecutions(); + assertThat(importedExecutions, hasSize(1)); + + AuthenticationExecutionExportRepresentation importedExecution = getExecutionFromFlow(unchangedFlow, "http-basic-authenticator"); + assertThat(importedExecution.getAuthenticator(), is("http-basic-authenticator")); + assertThat(importedExecution.getRequirement(), is("DISABLED")); + assertThat(importedExecution.getPriority(), is(0)); + assertThat(importedExecution.isAutheticatorFlow(), is(false)); + + AuthenticationFlowRepresentation topLevelFlow = getAuthenticationFlow(updatedRealm, "my registration"); + assertThat(topLevelFlow.getDescription(), is("My registration flow")); + assertThat(topLevelFlow.getProviderId(), is("basic-flow")); + assertThat(topLevelFlow.isBuiltIn(), is(false)); + assertThat(topLevelFlow.isTopLevel(), is(true)); + + List executionFlows = topLevelFlow.getAuthenticationExecutions(); + assertThat(executionFlows, hasSize(1)); + + AuthenticationExecutionExportRepresentation execution = getExecutionFromFlow(topLevelFlow, "registration-page-form"); + assertThat(execution.getAuthenticator(), is("registration-page-form")); + assertThat(execution.getRequirement(), is("REQUIRED")); + assertThat(execution.getPriority(), is(0)); + assertThat(execution.isAutheticatorFlow(), is(true)); + + AuthenticationFlowRepresentation nonTopLevelFlow = getAuthenticationFlow(updatedRealm, "my registration form"); + + List nonTopLevelFlowExecutions = nonTopLevelFlow.getAuthenticationExecutions(); + assertThat(nonTopLevelFlowExecutions, hasSize(2)); + + execution = getExecutionFromFlow(nonTopLevelFlow, "registration-profile-action"); + assertThat(execution.getAuthenticator(), is("registration-profile-action")); + assertThat(execution.getRequirement(), is("REQUIRED")); + assertThat(execution.getPriority(), is(0)); + assertThat(execution.isAutheticatorFlow(), is(false)); + + execution = getExecutionFromFlow(nonTopLevelFlow, "registration-user-creation"); + assertThat(execution.getAuthenticator(), is("registration-user-creation")); + assertThat(execution.getRequirement(), is("REQUIRED")); + assertThat(execution.getPriority(), is(1)); + assertThat(execution.isAutheticatorFlow(), is(false)); + } + + @Test + @Order(98) + void shouldRemoveTopLevelFlow() { + doImport("98_update_realm__update-remove-top-level-flow.json"); + + RealmRepresentation updatedRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); + + assertThat(updatedRealm.getRealm(), is(REALM_NAME)); + assertThat(updatedRealm.isEnabled(), is(true)); + + AuthenticationFlowRepresentation unchangedFlow = getAuthenticationFlow(updatedRealm, "my auth flow"); + assertThat(unchangedFlow.getDescription(), is("My auth flow for testing with pseudo-id")); + assertThat(unchangedFlow.getProviderId(), is("basic-flow")); + assertThat(unchangedFlow.isBuiltIn(), is(false)); + assertThat(unchangedFlow.isTopLevel(), is(true)); + + List importedExecutions = unchangedFlow.getAuthenticationExecutions(); + assertThat(importedExecutions, hasSize(1)); + + AuthenticationExecutionExportRepresentation importedExecution = getExecutionFromFlow(unchangedFlow, "http-basic-authenticator"); + assertThat(importedExecution.getAuthenticator(), is("http-basic-authenticator")); + assertThat(importedExecution.getRequirement(), is("DISABLED")); + assertThat(importedExecution.getPriority(), is(0)); + assertThat(importedExecution.isAutheticatorFlow(), is(false)); + + AuthenticationFlowRepresentation deletedTopLevelFlow = getAuthenticationFlow(updatedRealm, "my registration"); + + assertThat(deletedTopLevelFlow, is(nullValue())); + + deletedTopLevelFlow = getAuthenticationFlow(updatedRealm, "my registration from"); + assertThat(deletedTopLevelFlow, is(nullValue())); + } + + @Test + @Order(99) + void shouldRemoveAllTopLevelFlow() { + doImport("99_update_realm__update-remove-all-top-level-flow.json"); + + RealmRepresentation updatedRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); + + assertThat(updatedRealm.getRealm(), is(REALM_NAME)); + assertThat(updatedRealm.isEnabled(), is(true)); + + AuthenticationFlowRepresentation deletedTopLevelFlow; + deletedTopLevelFlow = getAuthenticationFlow(updatedRealm, "my auth flow"); + assertThat(deletedTopLevelFlow, is(nullValue())); + + deletedTopLevelFlow = getAuthenticationFlow(updatedRealm, "my registration"); + assertThat(deletedTopLevelFlow, is(nullValue())); + + deletedTopLevelFlow = getAuthenticationFlow(updatedRealm, "my registration from"); + assertThat(deletedTopLevelFlow, is(nullValue())); + + List allTopLevelFlow = updatedRealm.getAuthenticationFlows() + .stream().filter(e -> !e.isBuiltIn()) + .collect(Collectors.toList()); + + assertThat(allTopLevelFlow, is(empty())); + } + + private AuthenticationExecutionExportRepresentation getExecutionFromFlow(AuthenticationFlowRepresentation unchangedFlow, String executionAuthenticator) { + List importedExecutions = unchangedFlow.getAuthenticationExecutions(); + + return importedExecutions.stream() + .filter(e -> e.getAuthenticator().equals(executionAuthenticator)) + .findFirst() + .orElse(null); } private AuthenticationFlowRepresentation getAuthenticationFlow(RealmRepresentation updatedRealm, String flowAlias) { List authenticationFlows = updatedRealm.getAuthenticationFlows(); - Optional maybeImportedFlow = authenticationFlows.stream() + return authenticationFlows.stream() .filter(f -> f.getAlias().equals(flowAlias)) - .findFirst(); - - assertThat("Cannot find authentication-flow '" + flowAlias + "'", maybeImportedFlow.isPresent(), is(true)); - - return maybeImportedFlow.orElse(null); + .findFirst() + .orElse(null); } } diff --git a/src/test/java/de/adorsys/keycloak/config/ImportClientScopesIT.java b/src/test/java/de/adorsys/keycloak/config/ImportClientScopesIT.java index 074547ad6..74c2d4099 100644 --- a/src/test/java/de/adorsys/keycloak/config/ImportClientScopesIT.java +++ b/src/test/java/de/adorsys/keycloak/config/ImportClientScopesIT.java @@ -45,7 +45,7 @@ class ImportClientScopesIT extends AbstractImportTest { @Test @Order(0) void shouldCreateRealmWithClientScope() { - doImport("0_create_realm_with_clientScope.json"); + doImport("00_create_realm_with_clientScope.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -67,7 +67,7 @@ void shouldCreateRealmWithClientScope() { @Test @Order(1) void shouldAddClientScope() { - doImport("1_update_realm__add_clientScope.json"); + doImport("01_update_realm__add_clientScope.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -89,7 +89,7 @@ void shouldAddClientScope() { @Test @Order(2) void shouldChangeClientScope() { - doImport("2_update_realm__change_clientScope.json"); + doImport("02_update_realm__change_clientScope.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -111,7 +111,7 @@ void shouldChangeClientScope() { @Test @Order(3) void shouldChangeClientScopeWithAddProtocolMapper() { - doImport("3_update_realm__change_clientScope_add_protocolMapper.json"); + doImport("03_update_realm__change_clientScope_add_protocolMapper.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -145,7 +145,7 @@ void shouldChangeClientScopeWithAddProtocolMapper() { @Test @Order(4) void shouldChangeClientScopeWithChangeProtocolMapper() { - doImport("4_update_realm__change_clientScope_change_protocolMapper.json"); + doImport("04_update_realm__change_clientScope_change_protocolMapper.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -179,7 +179,7 @@ void shouldChangeClientScopeWithChangeProtocolMapper() { @Test @Order(5) void shouldChangeClientScopeWithReplaceProtocolMapper() { - doImport("5_update_realm__change_clientScope_replace_protocolMapper.json"); + doImport("05_update_realm__change_clientScope_replace_protocolMapper.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -213,7 +213,7 @@ void shouldChangeClientScopeWithReplaceProtocolMapper() { @Test @Order(6) void shouldDeleteClientScope() { - doImport("6_update_realm__delete_clientScope.json"); + doImport("97_update_realm__delete_clientScope.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -228,9 +228,9 @@ void shouldDeleteClientScope() { } @Test - @Order(7) + @Order(98) void shouldDeleteNothingWithNonExistingClientScopes() { - doImport("7_update_realm__delete_none.json"); + doImport("98_update_realm__skip_delete.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -249,9 +249,9 @@ void shouldDeleteNothingWithNonExistingClientScopes() { } @Test - @Order(8) + @Order(99) void shouldDeleteEverythingExpectDefaultScopesWithEmptyClientScopes() { - doImport("8_update_realm__delete_all.json"); + doImport("99_update_realm__delete_all.json"); RealmResource createdRealmResource = keycloakProvider.get().realm(REALM_NAME); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); diff --git a/src/test/java/de/adorsys/keycloak/config/ImportClientsIT.java b/src/test/java/de/adorsys/keycloak/config/ImportClientsIT.java index aadc14197..f0de59b2a 100644 --- a/src/test/java/de/adorsys/keycloak/config/ImportClientsIT.java +++ b/src/test/java/de/adorsys/keycloak/config/ImportClientsIT.java @@ -43,7 +43,7 @@ class ImportClientsIT extends AbstractImportTest { @Test @Order(1) void shouldCreateRealmWithClient() { - doImport("0_create_realm_with_client.json"); + doImport("00_create_realm_with_client.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -69,7 +69,7 @@ void shouldCreateRealmWithClient() { @Test @Order(2) void shouldUpdateRealmByAddingClient() { - doImport("1_update_realm__add_client.json"); + doImport("01_update_realm__add_client.json"); RealmRepresentation realm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -95,7 +95,7 @@ void shouldUpdateRealmByAddingClient() { @Test @Order(2) void shouldUpdateRealmWithChangedClientProperties() { - doImport("2_update_realm__change_clients_properties.json"); + doImport("02_update_realm__change_clients_properties.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -121,7 +121,7 @@ void shouldUpdateRealmWithChangedClientProperties() { @Test @Order(3) void shouldUpdateRealmAddProtocolMapper() { - doImport("3_update_realm__add_protocol-mapper.json"); + doImport("03_update_realm__add_protocol-mapper.json"); RealmRepresentation realm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -195,7 +195,7 @@ void shouldUpdateRealmAddProtocolMapper() { @Test @Order(4) void shouldUpdateRealmAddMoreProtocolMapper() { - doImport("4_update_realm__add_more_protocol-mapper.json"); + doImport("04_update_realm__add_more_protocol-mapper.json"); RealmRepresentation realm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -245,7 +245,7 @@ void shouldUpdateRealmAddMoreProtocolMapper() { @Test @Order(5) void shouldUpdateRealmChangeProtocolMapper() { - doImport("5_update_realm__change_protocol-mapper.json"); + doImport("05_update_realm__change_protocol-mapper.json"); RealmRepresentation realm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -295,7 +295,7 @@ void shouldUpdateRealmChangeProtocolMapper() { @Test @Order(6) void shouldUpdateRealmIgnoreProtocolMapper() { - doImport("6_update_realm__ignore_protocol-mapper.json"); + doImport("06_update_realm__ignore_protocol-mapper.json"); RealmRepresentation realm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); diff --git a/src/test/java/de/adorsys/keycloak/config/ImportComponentsIT.java b/src/test/java/de/adorsys/keycloak/config/ImportComponentsIT.java index 2b38c8480..4c9b434ae 100644 --- a/src/test/java/de/adorsys/keycloak/config/ImportComponentsIT.java +++ b/src/test/java/de/adorsys/keycloak/config/ImportComponentsIT.java @@ -49,7 +49,7 @@ class ImportComponentsIT extends AbstractImportTest { @Test @Order(1) void shouldCreateRealmWithComponent() { - doImport("0_create_realm_with_component.json"); + doImport("00_create_realm_with_component.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -73,7 +73,7 @@ void shouldCreateRealmWithComponent() { @Test @Order(2) void shouldUpdateComponentsConfig() { - doImport("1_update_realm__change_component_config.json"); + doImport("01_update_realm__change_component_config.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -97,7 +97,7 @@ void shouldUpdateComponentsConfig() { @Test @Order(3) void shouldUpdateAddComponentsConfig() { - doImport("2_update_realm__add_component_with_config.json"); + doImport("02_update_realm__add_component_with_config.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -132,7 +132,7 @@ void shouldUpdateAddComponentsConfig() { @Test @Order(4) void shouldAddComponentForSameProviderType() { - doImport("3_update_realm__add_component_for_same_providerType.json"); + doImport("03_update_realm__add_component_for_same_providerType.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -157,7 +157,7 @@ void shouldAddComponentForSameProviderType() { @Test @Order(5) void shouldAddComponentWithSubComponent() { - doImport("4_update_realm__add_component_with_subcomponent.json"); + doImport("04_update_realm__add_component_with_subcomponent.json"); ComponentExportRepresentation createdComponent = exportComponent( REALM_NAME, @@ -197,7 +197,7 @@ void shouldAddComponentWithSubComponent() { @Test @Order(6) void shouldUpdateConfigOfSubComponent() { - doImport("5_update_realm__update_config_in_subcomponent.json"); + doImport("05_update_realm__update_config_in_subcomponent.json"); ComponentExportRepresentation createdComponent = exportComponent( REALM_NAME, @@ -239,12 +239,12 @@ void shouldUpdateConfigOfSubComponent() { @Test @Order(7) void shouldUpdateComponentAddSubComponent() { - doImport("6_create_realm__with_component_without_subcomponent.json"); - doImport("7_update_realm__update_component_add_subcomponent.json"); + doImport("06_create_realm__with_component_without_subcomponent.json"); + doImport("07_update_realm__update_component_add_subcomponent.json"); ComponentRepresentation rsaComponent = getComponent( - "org.keycloak.keys.KeyProvider", - "rsa-generated" + "org.keycloak.keys.KeyProvider", + "rsa-generated" ); assertThat(rsaComponent.getName(), is("rsa-generated")); @@ -293,7 +293,7 @@ void shouldUpdateComponentAddSubComponent() { @Test @Order(8) void shouldUpdateComponentAddMoreSubComponent() { - doImport("8_update_realm__update_component_add_more_subcomponent.json"); + doImport("08_update_realm__update_component_add_more_subcomponent.json"); ComponentRepresentation rsaComponent = getComponent( "org.keycloak.keys.KeyProvider", @@ -364,7 +364,7 @@ void shouldUpdateComponentAddMoreSubComponent() { @Test @Order(9) void shouldUpdateComponentUpdateSubComponent() { - doImport("9_update_realm__update_component_update_subcomponent.json"); + doImport("09_update_realm__update_component_update_subcomponent.json"); ComponentRepresentation rsaComponent = getComponent( "org.keycloak.keys.KeyProvider", @@ -580,19 +580,24 @@ void shouldUpdateComponentRemoveAllSubComponent() { assertThat(keySize, hasSize(1)); assertThat(keySize.get(0), is("2048")); - ComponentExportRepresentation createdComponent = exportComponent( + ComponentExportRepresentation subComponent = exportComponent( "realmWithSubComponents", "org.keycloak.storage.UserStorageProvider", "my-realm-userstorage" ); - assertThat(createdComponent, is(notNullValue())); - assertThat(createdComponent.getName(), is("my-realm-userstorage")); - assertThat(createdComponent.getProviderId(), is("ldap")); + assertThat(subComponent, is(notNullValue())); + assertThat(subComponent.getName(), is("my-realm-userstorage")); + assertThat(subComponent.getProviderId(), is("ldap")); - MultivaluedHashMap subComponentsMap = createdComponent.getSubComponents(); + MultivaluedHashMap subComponentsMap = subComponent.getSubComponents(); + ComponentExportRepresentation subComponent2 = getSubComponent( + subComponentsMap, + "org.keycloak.storage.ldap.mappers.LDAPStorageMapper", + "picture" + ); - assertThat(subComponentsMap, is(anEmptyMap())); + assertThat(subComponent2, is(nullValue())); } @Test @@ -613,19 +618,24 @@ void shouldUpdateSkipComponents() { assertThat(keySize, hasSize(1)); assertThat(keySize.get(0), is("2048")); - ComponentExportRepresentation createdComponent = exportComponent( + ComponentExportRepresentation subComponent = exportComponent( "realmWithSubComponents", "org.keycloak.storage.UserStorageProvider", "my-realm-userstorage" ); - assertThat(createdComponent, is(notNullValue())); - assertThat(createdComponent.getName(), is("my-realm-userstorage")); - assertThat(createdComponent.getProviderId(), is("ldap")); + assertThat(subComponent, is(notNullValue())); + assertThat(subComponent.getName(), is("my-realm-userstorage")); + assertThat(subComponent.getProviderId(), is("ldap")); - MultivaluedHashMap subComponentsMap = createdComponent.getSubComponents(); + MultivaluedHashMap subComponentsMap = subComponent.getSubComponents(); + ComponentExportRepresentation subComponent2 = getSubComponent( + subComponentsMap, + "org.keycloak.storage.ldap.mappers.LDAPStorageMapper", + "picture" + ); - assertThat(subComponentsMap, is(anEmptyMap())); + assertThat(subComponent2, is(nullValue())); } @Test diff --git a/src/test/java/de/adorsys/keycloak/config/ImportGroupsIT.java b/src/test/java/de/adorsys/keycloak/config/ImportGroupsIT.java index 46eeec1f4..c68ef72a5 100644 --- a/src/test/java/de/adorsys/keycloak/config/ImportGroupsIT.java +++ b/src/test/java/de/adorsys/keycloak/config/ImportGroupsIT.java @@ -47,7 +47,7 @@ class ImportGroupsIT extends AbstractImportTest { @Test @Order(0) void shouldCreateRealmWithGroups() { - doImport("0_create_realm_with_group.json"); + doImport("00_create_realm_with_group.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); assertThat(createdRealm.getRealm(), is(REALM_NAME)); @@ -66,7 +66,7 @@ void shouldCreateRealmWithGroups() { @Test @Order(1) void shouldUpdateRealmAddGroup() { - doImport("1_update_realm_add_group.json"); + doImport("01_update_realm_add_group.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); assertThat(createdRealm.getRealm(), is(REALM_NAME)); @@ -94,7 +94,7 @@ void shouldUpdateRealmAddGroup() { @Test @Order(2) void shouldUpdateRealmAddGroupWithAttribute() { - doImport("2_update_realm_add_group_with_attribute.json"); + doImport("02_update_realm_add_group_with_attribute.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); assertThat(createdRealm.getRealm(), is(REALM_NAME)); @@ -116,7 +116,7 @@ void shouldUpdateRealmAddGroupWithAttribute() { @Test @Order(3) void shouldUpdateRealmAddGroupWithRealmRole() { - doImport("3_update_realm_add_group_with_realm_role.json"); + doImport("03_update_realm_add_group_with_realm_role.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); assertThat(createdRealm.getRealm(), is(REALM_NAME)); @@ -135,7 +135,7 @@ void shouldUpdateRealmAddGroupWithRealmRole() { @Test @Order(4) void shouldUpdateRealmAddGroupWithClientRole() { - doImport("4_update_realm_add_group_with_client_role.json"); + doImport("04_update_realm_add_group_with_client_role.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); assertThat(createdRealm.getRealm(), is(REALM_NAME)); @@ -157,7 +157,7 @@ void shouldUpdateRealmAddGroupWithClientRole() { @Test @Order(5) void shouldUpdateRealmAddGroupWithSubGroup() { - doImport("5_update_realm_add_group_with_subgroup.json"); + doImport("05_update_realm_add_group_with_subgroup.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); assertThat(createdRealm.getRealm(), is(REALM_NAME)); @@ -186,7 +186,7 @@ void shouldUpdateRealmAddGroupWithSubGroup() { @Test @Order(6) void shouldUpdateRealmAddGroupWithSubGroupWithRealmRole() { - doImport("6_update_realm_add_group_with_subgroup_with_realm_role.json"); + doImport("06_update_realm_add_group_with_subgroup_with_realm_role.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); assertThat(createdRealm.getRealm(), is(REALM_NAME)); @@ -215,7 +215,7 @@ void shouldUpdateRealmAddGroupWithSubGroupWithRealmRole() { @Test @Order(7) void shouldUpdateRealmAddGroupWithSubGroupWithClientRole() { - doImport("7_update_realm_add_group_with_subgroup_with_client_role.json"); + doImport("07_update_realm_add_group_with_subgroup_with_client_role.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); assertThat(createdRealm.getRealm(), is(REALM_NAME)); @@ -247,7 +247,7 @@ void shouldUpdateRealmAddGroupWithSubGroupWithClientRole() { @Test @Order(8) void shouldUpdateRealmAddGroupWithSubGroupWithSubGroup() { - doImport("8_update_realm_add_group_with_subgroup_with_subgroup.json"); + doImport("08_update_realm_add_group_with_subgroup_with_subgroup.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); assertThat(createdRealm.getRealm(), is(REALM_NAME)); @@ -288,7 +288,7 @@ void shouldUpdateRealmAddGroupWithSubGroupWithSubGroup() { @Test @Order(9) void shouldUpdateRealmUpdateGroupAddAttribute() { - doImport("9_update_realm_update_group_add_attribute.json"); + doImport("09_update_realm_update_group_add_attribute.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); assertThat(createdRealm.getRealm(), is(REALM_NAME)); diff --git a/src/test/java/de/adorsys/keycloak/config/ImportManagedNoDeleteIT.java b/src/test/java/de/adorsys/keycloak/config/ImportManagedNoDeleteIT.java index 9e4ab1afb..d090f9b4f 100644 --- a/src/test/java/de/adorsys/keycloak/config/ImportManagedNoDeleteIT.java +++ b/src/test/java/de/adorsys/keycloak/config/ImportManagedNoDeleteIT.java @@ -23,6 +23,7 @@ import org.keycloak.representations.idm.*; import org.springframework.test.context.TestPropertySource; +import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @@ -30,12 +31,13 @@ import static org.hamcrest.Matchers.hasSize; @TestPropertySource(properties = { - "import.managed.group=no-delete", - "import.managed.required-action=no-delete", - "import.managed.client-scope=no-delete", - "import.managed.scope-mapping=no-delete", - "import.managed.component=no-delete", - "import.managed.sub-component=no-delete", + "import.managed.authentication-flow=no-delete", + "import.managed.group=no-delete", + "import.managed.required-action=no-delete", + "import.managed.client-scope=no-delete", + "import.managed.scope-mapping=no-delete", + "import.managed.component=no-delete", + "import.managed.sub-component=no-delete", }) class ImportManagedNoDeleteIT extends AbstractImportTest { private static final String REALM_NAME = "realmWithNoDelete"; @@ -75,14 +77,14 @@ private void assertRealm() { assertThat(createdGroup, hasSize(2)); List createdRequiredActions = createdRealm.getRequiredActions() - .stream() - .filter((action) -> action.getAlias().equals("MY_CONFIGURE_TOTP") || action.getAlias().equals("my_terms_and_conditions")) - .collect(Collectors.toList()); + .stream() + .filter((action) -> action.getAlias().equals("MY_CONFIGURE_TOTP") || action.getAlias().equals("my_terms_and_conditions")) + .collect(Collectors.toList()); assertThat(createdRequiredActions, hasSize(2)); List createdClientScopes = createdRealm.getClientScopes() - .stream() - .filter((clientScope) -> clientScope.getName().equals("my_clientScope") || clientScope.getName().equals("my_other_clientScope")) + .stream() + .filter((clientScope) -> clientScope.getName().equals("my_clientScope") || clientScope.getName().equals("my_other_clientScope")) .collect(Collectors.toList()); assertThat(createdClientScopes, hasSize(2)); @@ -93,13 +95,20 @@ private void assertRealm() { assertThat(createdScopeMappings, hasSize(1)); List createdComponents = createdRealm.getComponents().get("org.keycloak.storage.UserStorageProvider") - .stream() - .filter(c -> c.getName().equals("my-realm-userstorage")) - .collect(Collectors.toList()); + .stream() + .filter(c -> c.getName().equals("my-realm-userstorage")) + .collect(Collectors.toList()); assertThat(createdComponents, hasSize(1)); List createdSubComponents = createdComponents.get(0) - .getSubComponents().getList("org.keycloak.storage.ldap.mappers.LDAPStorageMapper"); + .getSubComponents().getList("org.keycloak.storage.ldap.mappers.LDAPStorageMapper"); assertThat(createdSubComponents, hasSize(10)); + + List authenticationFlowsList = Arrays.asList("my auth flow", "my registration", "my registration form"); + List createdAuthenticationFlows = createdRealm.getAuthenticationFlows() + .stream() + .filter((authenticationFlow) -> authenticationFlowsList.contains(authenticationFlow.getAlias())) + .collect(Collectors.toList()); + assertThat(createdAuthenticationFlows, hasSize(3)); } } diff --git a/src/test/java/de/adorsys/keycloak/config/ImportRequiredActionsIT.java b/src/test/java/de/adorsys/keycloak/config/ImportRequiredActionsIT.java index 6e24303da..ded6217fc 100644 --- a/src/test/java/de/adorsys/keycloak/config/ImportRequiredActionsIT.java +++ b/src/test/java/de/adorsys/keycloak/config/ImportRequiredActionsIT.java @@ -42,7 +42,7 @@ class ImportRequiredActionsIT extends AbstractImportTest { @Test @Order(0) void shouldCreateRealmWithRequiredActions() { - doImport("0_create_realm_with_required-action.json"); + doImport("00_create_realm_with_required-action.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); @@ -62,7 +62,7 @@ void shouldCreateRealmWithRequiredActions() { @Test @Order(1) void shouldFailIfAddingInvalidRequiredActionName() { - RealmImport foundImport = getImport("1_update_realm__try_adding_invalid_required-action.json"); + RealmImport foundImport = getImport("01_update_realm__try_adding_invalid_required-action.json"); InvalidImportException thrown = assertThrows(InvalidImportException.class, () -> realmImportService.doImport(foundImport)); @@ -72,7 +72,7 @@ void shouldFailIfAddingInvalidRequiredActionName() { @Test @Order(2) void shouldAddDefaultRequiredAction() { - doImport("2_update_realm__add_default_required-action.json"); + doImport("02_update_realm__add_default_required-action.json"); RealmRepresentation updatedRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); @@ -100,7 +100,7 @@ void shouldAddDefaultRequiredAction() { @Test @Order(3) void shouldChangeRequiredActionName() { - doImport("3_update_realm__change_name_of_required-action.json"); + doImport("03_update_realm__change_name_of_required-action.json"); RealmRepresentation updatedRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); @@ -128,7 +128,7 @@ void shouldChangeRequiredActionName() { @Test @Order(4) void shouldEnableRequiredAction() { - doImport("4_update_realm__enable_required-action.json"); + doImport("04_update_realm__enable_required-action.json"); RealmRepresentation updatedRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); @@ -156,7 +156,7 @@ void shouldEnableRequiredAction() { @Test @Order(5) void shouldChangePriorities() { - doImport("5_update_realm__change_priorities_required-action.json"); + doImport("05_update_realm__change_priorities_required-action.json"); RealmRepresentation updatedRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); @@ -184,7 +184,7 @@ void shouldChangePriorities() { @Test @Order(6) void shouldAddRequiredAction() { - doImport("6_update_realm__delete_and_add_required-action.json"); + doImport("06_update_realm__delete_and_add_required-action.json"); RealmRepresentation updatedRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); @@ -215,7 +215,7 @@ void shouldAddRequiredAction() { @Test @Order(7) void shouldSkipRequiredAction() { - doImport("7_update_realm__skip_required-action.json"); + doImport("07_update_realm__skip_required-action.json"); RealmRepresentation updatedRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); @@ -244,9 +244,9 @@ void shouldSkipRequiredAction() { } @Test - @Order(8) + @Order(98) void shouldDeleteRequiredAction() { - doImport("8_update_realm__delete_required-action.json"); + doImport("98_update_realm__delete_required-action.json"); RealmRepresentation updatedRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); @@ -266,9 +266,9 @@ void shouldDeleteRequiredAction() { } @Test - @Order(9) + @Order(99) void shouldDeleteAllRequiredAction() { - doImport("9_update_realm__delete_all_required-action.json"); + doImport("99_update_realm__delete_all_required-action.json"); RealmRepresentation updatedRealm = keycloakProvider.get().realm(REALM_NAME).partialExport(true, true); diff --git a/src/test/java/de/adorsys/keycloak/config/ImportRolesIT.java b/src/test/java/de/adorsys/keycloak/config/ImportRolesIT.java index e44ad25aa..f3d0df98f 100644 --- a/src/test/java/de/adorsys/keycloak/config/ImportRolesIT.java +++ b/src/test/java/de/adorsys/keycloak/config/ImportRolesIT.java @@ -40,7 +40,7 @@ class ImportRolesIT extends AbstractImportTest { @Test @Order(0) void shouldCreateRealmWithRoles() { - doImport("0_create_realm_with_roles.json"); + doImport("00_create_realm_with_roles.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -72,7 +72,7 @@ void shouldCreateRealmWithRoles() { @Test @Order(1) void shouldAddRealmRole() { - doImport("1_update_realm__add_realm_role.json"); + doImport("01_update_realm__add_realm_role.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -93,7 +93,7 @@ void shouldAddRealmRole() { @Test @Order(2) void shouldAddClientRole() { - doImport("2_update_realm__add_client_role.json"); + doImport("02_update_realm__add_client_role.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -114,7 +114,7 @@ void shouldAddClientRole() { @Test @Order(3) void shouldChangeRealmRole() { - doImport("3_update_realm__change_realm_role.json"); + doImport("03_update_realm__change_realm_role.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -135,7 +135,7 @@ void shouldChangeRealmRole() { @Test @Order(4) void shouldChangeClientRole() { - doImport("4_update_realm__change_client_role.json"); + doImport("04_update_realm__change_client_role.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -156,7 +156,7 @@ void shouldChangeClientRole() { @Test @Order(5) void shouldAddUserWithRealmRole() { - doImport("5_update_realm__add_user_with_realm_role.json"); + doImport("05_update_realm__add_user_with_realm_role.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -174,7 +174,7 @@ void shouldAddUserWithRealmRole() { @Test @Order(6) void shouldAddUserWithClientRole() { - doImport("6_update_realm__add_user_with_client_role.json"); + doImport("06_update_realm__add_user_with_client_role.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -193,7 +193,7 @@ void shouldAddUserWithClientRole() { @Test @Order(7) void shouldChangeUserAddRealmRole() { - doImport("7_update_realm__change_user_add_realm_role.json"); + doImport("07_update_realm__change_user_add_realm_role.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -211,7 +211,7 @@ void shouldChangeUserAddRealmRole() { @Test @Order(8) void shouldChangeUserAddClientRole() { - doImport("8_update_realm__change_user_add_client_role.json"); + doImport("08_update_realm__change_user_add_client_role.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); @@ -230,7 +230,7 @@ void shouldChangeUserAddClientRole() { @Test @Order(9) void shouldChangeUserRemoveRealmRole() { - doImport("9_update_realm__change_user_remove_realm_role.json"); + doImport("09_update_realm__change_user_remove_realm_role.json"); RealmRepresentation createdRealm = keycloakProvider.get().realm(REALM_NAME).toRepresentation(); diff --git a/src/test/java/de/adorsys/keycloak/config/properties/ImportConfigPropertiesTest.java b/src/test/java/de/adorsys/keycloak/config/properties/ImportConfigPropertiesTest.java index 90185c931..35c896c70 100644 --- a/src/test/java/de/adorsys/keycloak/config/properties/ImportConfigPropertiesTest.java +++ b/src/test/java/de/adorsys/keycloak/config/properties/ImportConfigPropertiesTest.java @@ -38,6 +38,8 @@ "import.cache-key=custom", "import.force=true", "import.path=other", + "import.state=false", + "import.managed.authentication-flow=no-delete", "import.managed.group=no-delete", "import.managed.required-action=no-delete", "import.managed.client-scope=no-delete", @@ -55,6 +57,8 @@ void shouldPopulateConfigurationProperties() { assertThat(properties.getPath(), is("other")); assertThat(properties.isForce(), is(true)); assertThat(properties.getCacheKey(), is("custom")); + assertThat(properties.isState(), is(false)); + assertThat(properties.getManaged().getAuthenticationFlow(), is(ImportManagedPropertiesValues.NO_DELETE)); assertThat(properties.getManaged().getGroup(), is(ImportManagedPropertiesValues.NO_DELETE)); assertThat(properties.getManaged().getRequiredAction(), is(ImportManagedPropertiesValues.NO_DELETE)); assertThat(properties.getManaged().getClientScope(), is(ImportManagedPropertiesValues.NO_DELETE)); diff --git a/src/test/resources/application-IT.properties b/src/test/resources/application-IT.properties index 948f7e1ea..74f464e44 100644 --- a/src/test/resources/application-IT.properties +++ b/src/test/resources/application-IT.properties @@ -1,9 +1,5 @@ -keycloak.login-realm=master -keycloak.client-id=admin-cli -keycloak.user=admin keycloak.password=admin123 keycloak.url=http://localhost:8080 -keycloak.sslVerify=true import.path=default -import.cache-key=default +import.state=true spring.profiles.include=debug diff --git a/src/test/resources/import-files/auth-flows/0_create_realm_with_flows.json b/src/test/resources/import-files/auth-flows/00_create_realm_with_flows.json similarity index 100% rename from src/test/resources/import-files/auth-flows/0_create_realm_with_flows.json rename to src/test/resources/import-files/auth-flows/00_create_realm_with_flows.json diff --git a/src/test/resources/import-files/auth-flows/1_update_realm__add_execution_to_flow.json b/src/test/resources/import-files/auth-flows/01_update_realm__add_execution_to_flow.json similarity index 100% rename from src/test/resources/import-files/auth-flows/1_update_realm__add_execution_to_flow.json rename to src/test/resources/import-files/auth-flows/01_update_realm__add_execution_to_flow.json diff --git a/src/test/resources/import-files/auth-flows/2_update_realm__change_execution_requirement.json b/src/test/resources/import-files/auth-flows/02_update_realm__change_execution_requirement.json similarity index 100% rename from src/test/resources/import-files/auth-flows/2_update_realm__change_execution_requirement.json rename to src/test/resources/import-files/auth-flows/02_update_realm__change_execution_requirement.json diff --git a/src/test/resources/import-files/auth-flows/3_update_realm__change_execution_priorities.json b/src/test/resources/import-files/auth-flows/03_update_realm__change_execution_priorities.json similarity index 100% rename from src/test/resources/import-files/auth-flows/3_update_realm__change_execution_priorities.json rename to src/test/resources/import-files/auth-flows/03_update_realm__change_execution_priorities.json diff --git a/src/test/resources/import-files/auth-flows/4.1_try_to_update_realm__add_flow_with_defective_execution_flow.json b/src/test/resources/import-files/auth-flows/04.1_try_to_update_realm__add_flow_with_defective_execution_flow.json similarity index 100% rename from src/test/resources/import-files/auth-flows/4.1_try_to_update_realm__add_flow_with_defective_execution_flow.json rename to src/test/resources/import-files/auth-flows/04.1_try_to_update_realm__add_flow_with_defective_execution_flow.json diff --git a/src/test/resources/import-files/auth-flows/4_update_realm__add_flow_with_execution_flow.json b/src/test/resources/import-files/auth-flows/04_update_realm__add_flow_with_execution_flow.json similarity index 100% rename from src/test/resources/import-files/auth-flows/4_update_realm__add_flow_with_execution_flow.json rename to src/test/resources/import-files/auth-flows/04_update_realm__add_flow_with_execution_flow.json diff --git a/src/test/resources/import-files/auth-flows/5.1_try_to_update_realm__change_requirement_in defective_flow_with_execution_flow.json b/src/test/resources/import-files/auth-flows/05.1_try_to_update_realm__change_requirement_in defective_flow_with_execution_flow.json similarity index 100% rename from src/test/resources/import-files/auth-flows/5.1_try_to_update_realm__change_requirement_in defective_flow_with_execution_flow.json rename to src/test/resources/import-files/auth-flows/05.1_try_to_update_realm__change_requirement_in defective_flow_with_execution_flow.json diff --git a/src/test/resources/import-files/auth-flows/5.2_try_to_update_realm__change_requirement_flow_with_execution_flow_with_not_existing_execution.json b/src/test/resources/import-files/auth-flows/05.2_try_to_update_realm__change_requirement_flow_with_execution_flow_with_not_existing_execution.json similarity index 100% rename from src/test/resources/import-files/auth-flows/5.2_try_to_update_realm__change_requirement_flow_with_execution_flow_with_not_existing_execution.json rename to src/test/resources/import-files/auth-flows/05.2_try_to_update_realm__change_requirement_flow_with_execution_flow_with_not_existing_execution.json diff --git a/src/test/resources/import-files/auth-flows/5.3_try_to_update_realm__change_requirement_flow_with_execution_flow_with_defective_execution.json b/src/test/resources/import-files/auth-flows/05.3_try_to_update_realm__change_requirement_flow_with_execution_flow_with_defective_execution.json similarity index 100% rename from src/test/resources/import-files/auth-flows/5.3_try_to_update_realm__change_requirement_flow_with_execution_flow_with_defective_execution.json rename to src/test/resources/import-files/auth-flows/05.3_try_to_update_realm__change_requirement_flow_with_execution_flow_with_defective_execution.json diff --git a/src/test/resources/import-files/auth-flows/5.4_try_to_update_realm__change_requirement_flow_with_defective_execution_flow.json b/src/test/resources/import-files/auth-flows/05.4_try_to_update_realm__change_requirement_flow_with_defective_execution_flow.json similarity index 100% rename from src/test/resources/import-files/auth-flows/5.4_try_to_update_realm__change_requirement_flow_with_defective_execution_flow.json rename to src/test/resources/import-files/auth-flows/05.4_try_to_update_realm__change_requirement_flow_with_defective_execution_flow.json diff --git a/src/test/resources/import-files/auth-flows/5_update_realm__change_requirement_flow_with_execution_flow.json b/src/test/resources/import-files/auth-flows/05_update_realm__change_requirement_flow_with_execution_flow.json similarity index 100% rename from src/test/resources/import-files/auth-flows/5_update_realm__change_requirement_flow_with_execution_flow.json rename to src/test/resources/import-files/auth-flows/05_update_realm__change_requirement_flow_with_execution_flow.json diff --git a/src/test/resources/import-files/auth-flows/6_update_realm__change_priority_flow_with_execution_flow.json b/src/test/resources/import-files/auth-flows/06_update_realm__change_priority_flow_with_execution_flow.json similarity index 100% rename from src/test/resources/import-files/auth-flows/6_update_realm__change_priority_flow_with_execution_flow.json rename to src/test/resources/import-files/auth-flows/06_update_realm__change_priority_flow_with_execution_flow.json diff --git a/src/test/resources/import-files/auth-flows/7_update_realm__set_registration_flow.json b/src/test/resources/import-files/auth-flows/07_update_realm__set_registration_flow.json similarity index 100% rename from src/test/resources/import-files/auth-flows/7_update_realm__set_registration_flow.json rename to src/test/resources/import-files/auth-flows/07_update_realm__set_registration_flow.json diff --git a/src/test/resources/import-files/auth-flows/8_update_realm__change_registration_flow.json b/src/test/resources/import-files/auth-flows/08_update_realm__change_registration_flow.json similarity index 100% rename from src/test/resources/import-files/auth-flows/8_update_realm__change_registration_flow.json rename to src/test/resources/import-files/auth-flows/08_update_realm__change_registration_flow.json diff --git a/src/test/resources/import-files/auth-flows/9_update_realm__add_and_set_custom_reset-credentials-flow.json b/src/test/resources/import-files/auth-flows/09_update_realm__add_and_set_custom_reset-credentials-flow.json similarity index 100% rename from src/test/resources/import-files/auth-flows/9_update_realm__add_and_set_custom_reset-credentials-flow.json rename to src/test/resources/import-files/auth-flows/09_update_realm__add_and_set_custom_reset-credentials-flow.json diff --git a/src/test/resources/import-files/auth-flows/96_update_realm__update-remove-non-top-level-flow.json b/src/test/resources/import-files/auth-flows/96_update_realm__update-remove-non-top-level-flow.json new file mode 100644 index 000000000..28d75694b --- /dev/null +++ b/src/test/resources/import-files/auth-flows/96_update_realm__update-remove-non-top-level-flow.json @@ -0,0 +1,70 @@ +{ + "enabled": true, + "realm": "realmWithFlow", + "browserFlow": "browser", + "registrationFlow": "my registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "authenticationFlows": [ + { + "id": "76ba4376-5728-4b05-8c16-1792fda7eff2", + "alias": "my auth flow", + "description": "My auth flow for testing with pseudo-id", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": false, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "requirement": "DISABLED", + "priority": 0, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "alias": "my registration", + "description": "My registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": false, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "requirement": "REQUIRED", + "priority": 0, + "flowAlias": "my registration form", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "f9037ea2-61c8-4a62-b564-9dfdac233d93", + "alias": "my registration form", + "description": "My registration form with pseudo-id", + "providerId": "form-flow", + "topLevel": false, + "builtIn": false, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "requirement": "REQUIRED", + "priority": 1, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-profile-action", + "requirement": "REQUIRED", + "priority": 0, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + } + ] +} diff --git a/src/test/resources/import-files/auth-flows/97_update_realm__skip-remove-top-level-flow.json b/src/test/resources/import-files/auth-flows/97_update_realm__skip-remove-top-level-flow.json new file mode 100644 index 000000000..2d10e2517 --- /dev/null +++ b/src/test/resources/import-files/auth-flows/97_update_realm__skip-remove-top-level-flow.json @@ -0,0 +1,10 @@ +{ + "enabled": true, + "realm": "realmWithFlow", + "browserFlow": "browser", + "registrationFlow": "my registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth" +} diff --git a/src/test/resources/import-files/auth-flows/98_update_realm__update-remove-top-level-flow.json b/src/test/resources/import-files/auth-flows/98_update_realm__update-remove-top-level-flow.json new file mode 100644 index 000000000..a85b86bfd --- /dev/null +++ b/src/test/resources/import-files/auth-flows/98_update_realm__update-remove-top-level-flow.json @@ -0,0 +1,29 @@ +{ + "enabled": true, + "realm": "realmWithFlow", + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "authenticationFlows": [ + { + "id": "76ba4376-5728-4b05-8c16-1792fda7eff2", + "alias": "my auth flow", + "description": "My auth flow for testing with pseudo-id", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": false, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "requirement": "DISABLED", + "priority": 0, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + } + ] +} diff --git a/src/test/resources/import-files/auth-flows/99_update_realm__update-remove-all-top-level-flow.json b/src/test/resources/import-files/auth-flows/99_update_realm__update-remove-all-top-level-flow.json new file mode 100644 index 000000000..1d2353b14 --- /dev/null +++ b/src/test/resources/import-files/auth-flows/99_update_realm__update-remove-all-top-level-flow.json @@ -0,0 +1,11 @@ +{ + "enabled": true, + "realm": "realmWithFlow", + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "authenticationFlows": [] +} diff --git a/src/test/resources/import-files/client-scopes/0_create_realm_with_clientScope.json b/src/test/resources/import-files/client-scopes/00_create_realm_with_clientScope.json similarity index 100% rename from src/test/resources/import-files/client-scopes/0_create_realm_with_clientScope.json rename to src/test/resources/import-files/client-scopes/00_create_realm_with_clientScope.json diff --git a/src/test/resources/import-files/client-scopes/1_update_realm__add_clientScope.json b/src/test/resources/import-files/client-scopes/01_update_realm__add_clientScope.json similarity index 100% rename from src/test/resources/import-files/client-scopes/1_update_realm__add_clientScope.json rename to src/test/resources/import-files/client-scopes/01_update_realm__add_clientScope.json diff --git a/src/test/resources/import-files/client-scopes/2_update_realm__change_clientScope.json b/src/test/resources/import-files/client-scopes/02_update_realm__change_clientScope.json similarity index 100% rename from src/test/resources/import-files/client-scopes/2_update_realm__change_clientScope.json rename to src/test/resources/import-files/client-scopes/02_update_realm__change_clientScope.json diff --git a/src/test/resources/import-files/client-scopes/3_update_realm__change_clientScope_add_protocolMapper.json b/src/test/resources/import-files/client-scopes/03_update_realm__change_clientScope_add_protocolMapper.json similarity index 100% rename from src/test/resources/import-files/client-scopes/3_update_realm__change_clientScope_add_protocolMapper.json rename to src/test/resources/import-files/client-scopes/03_update_realm__change_clientScope_add_protocolMapper.json diff --git a/src/test/resources/import-files/client-scopes/4_update_realm__change_clientScope_change_protocolMapper.json b/src/test/resources/import-files/client-scopes/04_update_realm__change_clientScope_change_protocolMapper.json similarity index 100% rename from src/test/resources/import-files/client-scopes/4_update_realm__change_clientScope_change_protocolMapper.json rename to src/test/resources/import-files/client-scopes/04_update_realm__change_clientScope_change_protocolMapper.json diff --git a/src/test/resources/import-files/client-scopes/5_update_realm__change_clientScope_replace_protocolMapper.json b/src/test/resources/import-files/client-scopes/05_update_realm__change_clientScope_replace_protocolMapper.json similarity index 100% rename from src/test/resources/import-files/client-scopes/5_update_realm__change_clientScope_replace_protocolMapper.json rename to src/test/resources/import-files/client-scopes/05_update_realm__change_clientScope_replace_protocolMapper.json diff --git a/src/test/resources/import-files/client-scopes/6_update_realm__delete_clientScope.json b/src/test/resources/import-files/client-scopes/97_update_realm__delete_clientScope.json similarity index 100% rename from src/test/resources/import-files/client-scopes/6_update_realm__delete_clientScope.json rename to src/test/resources/import-files/client-scopes/97_update_realm__delete_clientScope.json diff --git a/src/test/resources/import-files/client-scopes/7_update_realm__delete_none.json b/src/test/resources/import-files/client-scopes/98_update_realm__skip_delete.json similarity index 100% rename from src/test/resources/import-files/client-scopes/7_update_realm__delete_none.json rename to src/test/resources/import-files/client-scopes/98_update_realm__skip_delete.json diff --git a/src/test/resources/import-files/client-scopes/8_update_realm__delete_all.json b/src/test/resources/import-files/client-scopes/99_update_realm__delete_all.json similarity index 100% rename from src/test/resources/import-files/client-scopes/8_update_realm__delete_all.json rename to src/test/resources/import-files/client-scopes/99_update_realm__delete_all.json diff --git a/src/test/resources/import-files/clients/0_create_realm_with_client.json b/src/test/resources/import-files/clients/00_create_realm_with_client.json similarity index 100% rename from src/test/resources/import-files/clients/0_create_realm_with_client.json rename to src/test/resources/import-files/clients/00_create_realm_with_client.json diff --git a/src/test/resources/import-files/clients/1_update_realm__add_client.json b/src/test/resources/import-files/clients/01_update_realm__add_client.json similarity index 100% rename from src/test/resources/import-files/clients/1_update_realm__add_client.json rename to src/test/resources/import-files/clients/01_update_realm__add_client.json diff --git a/src/test/resources/import-files/clients/2_update_realm__change_clients_properties.json b/src/test/resources/import-files/clients/02_update_realm__change_clients_properties.json similarity index 100% rename from src/test/resources/import-files/clients/2_update_realm__change_clients_properties.json rename to src/test/resources/import-files/clients/02_update_realm__change_clients_properties.json diff --git a/src/test/resources/import-files/clients/3_update_realm__add_protocol-mapper.json b/src/test/resources/import-files/clients/03_update_realm__add_protocol-mapper.json similarity index 100% rename from src/test/resources/import-files/clients/3_update_realm__add_protocol-mapper.json rename to src/test/resources/import-files/clients/03_update_realm__add_protocol-mapper.json diff --git a/src/test/resources/import-files/clients/4_update_realm__add_more_protocol-mapper.json b/src/test/resources/import-files/clients/04_update_realm__add_more_protocol-mapper.json similarity index 100% rename from src/test/resources/import-files/clients/4_update_realm__add_more_protocol-mapper.json rename to src/test/resources/import-files/clients/04_update_realm__add_more_protocol-mapper.json diff --git a/src/test/resources/import-files/clients/5_update_realm__change_protocol-mapper.json b/src/test/resources/import-files/clients/05_update_realm__change_protocol-mapper.json similarity index 100% rename from src/test/resources/import-files/clients/5_update_realm__change_protocol-mapper.json rename to src/test/resources/import-files/clients/05_update_realm__change_protocol-mapper.json diff --git a/src/test/resources/import-files/clients/6_update_realm__ignore_protocol-mapper.json b/src/test/resources/import-files/clients/06_update_realm__ignore_protocol-mapper.json similarity index 100% rename from src/test/resources/import-files/clients/6_update_realm__ignore_protocol-mapper.json rename to src/test/resources/import-files/clients/06_update_realm__ignore_protocol-mapper.json diff --git a/src/test/resources/import-files/components/0_create_realm_with_component.json b/src/test/resources/import-files/components/00_create_realm_with_component.json similarity index 100% rename from src/test/resources/import-files/components/0_create_realm_with_component.json rename to src/test/resources/import-files/components/00_create_realm_with_component.json diff --git a/src/test/resources/import-files/components/1_update_realm__change_component_config.json b/src/test/resources/import-files/components/01_update_realm__change_component_config.json similarity index 100% rename from src/test/resources/import-files/components/1_update_realm__change_component_config.json rename to src/test/resources/import-files/components/01_update_realm__change_component_config.json diff --git a/src/test/resources/import-files/components/2_update_realm__add_component_with_config.json b/src/test/resources/import-files/components/02_update_realm__add_component_with_config.json similarity index 100% rename from src/test/resources/import-files/components/2_update_realm__add_component_with_config.json rename to src/test/resources/import-files/components/02_update_realm__add_component_with_config.json diff --git a/src/test/resources/import-files/components/3_update_realm__add_component_for_same_providerType.json b/src/test/resources/import-files/components/03_update_realm__add_component_for_same_providerType.json similarity index 100% rename from src/test/resources/import-files/components/3_update_realm__add_component_for_same_providerType.json rename to src/test/resources/import-files/components/03_update_realm__add_component_for_same_providerType.json diff --git a/src/test/resources/import-files/components/4_update_realm__add_component_with_subcomponent.json b/src/test/resources/import-files/components/04_update_realm__add_component_with_subcomponent.json similarity index 100% rename from src/test/resources/import-files/components/4_update_realm__add_component_with_subcomponent.json rename to src/test/resources/import-files/components/04_update_realm__add_component_with_subcomponent.json diff --git a/src/test/resources/import-files/components/5_update_realm__update_config_in_subcomponent.json b/src/test/resources/import-files/components/05_update_realm__update_config_in_subcomponent.json similarity index 100% rename from src/test/resources/import-files/components/5_update_realm__update_config_in_subcomponent.json rename to src/test/resources/import-files/components/05_update_realm__update_config_in_subcomponent.json diff --git a/src/test/resources/import-files/components/6_create_realm__with_component_without_subcomponent.json b/src/test/resources/import-files/components/06_create_realm__with_component_without_subcomponent.json similarity index 100% rename from src/test/resources/import-files/components/6_create_realm__with_component_without_subcomponent.json rename to src/test/resources/import-files/components/06_create_realm__with_component_without_subcomponent.json diff --git a/src/test/resources/import-files/components/7_update_realm__update_component_add_subcomponent.json b/src/test/resources/import-files/components/07_update_realm__update_component_add_subcomponent.json similarity index 100% rename from src/test/resources/import-files/components/7_update_realm__update_component_add_subcomponent.json rename to src/test/resources/import-files/components/07_update_realm__update_component_add_subcomponent.json diff --git a/src/test/resources/import-files/components/8_update_realm__update_component_add_more_subcomponent.json b/src/test/resources/import-files/components/08_update_realm__update_component_add_more_subcomponent.json similarity index 100% rename from src/test/resources/import-files/components/8_update_realm__update_component_add_more_subcomponent.json rename to src/test/resources/import-files/components/08_update_realm__update_component_add_more_subcomponent.json diff --git a/src/test/resources/import-files/components/9_update_realm__update_component_update_subcomponent.json b/src/test/resources/import-files/components/09_update_realm__update_component_update_subcomponent.json similarity index 100% rename from src/test/resources/import-files/components/9_update_realm__update_component_update_subcomponent.json rename to src/test/resources/import-files/components/09_update_realm__update_component_update_subcomponent.json diff --git a/src/test/resources/import-files/groups/0_create_realm_with_group.json b/src/test/resources/import-files/groups/00_create_realm_with_group.json similarity index 100% rename from src/test/resources/import-files/groups/0_create_realm_with_group.json rename to src/test/resources/import-files/groups/00_create_realm_with_group.json diff --git a/src/test/resources/import-files/groups/1_update_realm_add_group.json b/src/test/resources/import-files/groups/01_update_realm_add_group.json similarity index 100% rename from src/test/resources/import-files/groups/1_update_realm_add_group.json rename to src/test/resources/import-files/groups/01_update_realm_add_group.json diff --git a/src/test/resources/import-files/groups/2_update_realm_add_group_with_attribute.json b/src/test/resources/import-files/groups/02_update_realm_add_group_with_attribute.json similarity index 100% rename from src/test/resources/import-files/groups/2_update_realm_add_group_with_attribute.json rename to src/test/resources/import-files/groups/02_update_realm_add_group_with_attribute.json diff --git a/src/test/resources/import-files/groups/3_update_realm_add_group_with_realm_role.json b/src/test/resources/import-files/groups/03_update_realm_add_group_with_realm_role.json similarity index 100% rename from src/test/resources/import-files/groups/3_update_realm_add_group_with_realm_role.json rename to src/test/resources/import-files/groups/03_update_realm_add_group_with_realm_role.json diff --git a/src/test/resources/import-files/groups/4_update_realm_add_group_with_client_role.json b/src/test/resources/import-files/groups/04_update_realm_add_group_with_client_role.json similarity index 100% rename from src/test/resources/import-files/groups/4_update_realm_add_group_with_client_role.json rename to src/test/resources/import-files/groups/04_update_realm_add_group_with_client_role.json diff --git a/src/test/resources/import-files/groups/5_update_realm_add_group_with_subgroup.json b/src/test/resources/import-files/groups/05_update_realm_add_group_with_subgroup.json similarity index 100% rename from src/test/resources/import-files/groups/5_update_realm_add_group_with_subgroup.json rename to src/test/resources/import-files/groups/05_update_realm_add_group_with_subgroup.json diff --git a/src/test/resources/import-files/groups/6_update_realm_add_group_with_subgroup_with_realm_role.json b/src/test/resources/import-files/groups/06_update_realm_add_group_with_subgroup_with_realm_role.json similarity index 100% rename from src/test/resources/import-files/groups/6_update_realm_add_group_with_subgroup_with_realm_role.json rename to src/test/resources/import-files/groups/06_update_realm_add_group_with_subgroup_with_realm_role.json diff --git a/src/test/resources/import-files/groups/7_update_realm_add_group_with_subgroup_with_client_role.json b/src/test/resources/import-files/groups/07_update_realm_add_group_with_subgroup_with_client_role.json similarity index 100% rename from src/test/resources/import-files/groups/7_update_realm_add_group_with_subgroup_with_client_role.json rename to src/test/resources/import-files/groups/07_update_realm_add_group_with_subgroup_with_client_role.json diff --git a/src/test/resources/import-files/groups/8_update_realm_add_group_with_subgroup_with_subgroup.json b/src/test/resources/import-files/groups/08_update_realm_add_group_with_subgroup_with_subgroup.json similarity index 100% rename from src/test/resources/import-files/groups/8_update_realm_add_group_with_subgroup_with_subgroup.json rename to src/test/resources/import-files/groups/08_update_realm_add_group_with_subgroup_with_subgroup.json diff --git a/src/test/resources/import-files/groups/9_update_realm_update_group_add_attribute.json b/src/test/resources/import-files/groups/09_update_realm_update_group_add_attribute.json similarity index 100% rename from src/test/resources/import-files/groups/9_update_realm_update_group_add_attribute.json rename to src/test/resources/import-files/groups/09_update_realm_update_group_add_attribute.json diff --git a/src/test/resources/import-files/managed-no-delete/0_create_simple-realm.json b/src/test/resources/import-files/managed-no-delete/0_create_simple-realm.json index 7eba07681..5918274e4 100644 --- a/src/test/resources/import-files/managed-no-delete/0_create_simple-realm.json +++ b/src/test/resources/import-files/managed-no-delete/0_create_simple-realm.json @@ -9,6 +9,65 @@ "name": "My second Group" } ], + "authenticationFlows": [ + { + "id": "76ba4376-5728-4b05-8c16-1792fda7eff2", + "alias": "my auth flow", + "description": "My auth flow for testing with pseudo-id", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": false, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "requirement": "DISABLED", + "priority": 0, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "alias": "my registration", + "description": "My registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": false, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "requirement": "REQUIRED", + "priority": 0, + "flowAlias": "my registration form", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "alias": "my registration form", + "description": "My registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": false, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "requirement": "REQUIRED", + "priority": 0, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-profile-action", + "requirement": "DISABLED", + "priority": 1, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + } + ], "requiredActions": [ { "alias": "MY_CONFIGURE_TOTP", diff --git a/src/test/resources/import-files/managed-no-delete/1_update-realm_not-delete-one.json b/src/test/resources/import-files/managed-no-delete/1_update-realm_not-delete-one.json index b377f6af4..aadf52638 100644 --- a/src/test/resources/import-files/managed-no-delete/1_update-realm_not-delete-one.json +++ b/src/test/resources/import-files/managed-no-delete/1_update-realm_not-delete-one.json @@ -6,6 +6,25 @@ "name": "My Group" } ], + "authenticationFlows": [ + { + "id": "76ba4376-5728-4b05-8c16-1792fda7eff2", + "alias": "my auth flow", + "description": "My auth flow for testing with pseudo-id", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": false, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "requirement": "DISABLED", + "priority": 0, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + } + ], "requiredActions": [ { "alias": "MY_CONFIGURE_TOTP", diff --git a/src/test/resources/import-files/managed-no-delete/2_update-realm_not-delete-all.json b/src/test/resources/import-files/managed-no-delete/2_update-realm_not-delete-all.json index 0375660cb..36b8f1532 100644 --- a/src/test/resources/import-files/managed-no-delete/2_update-realm_not-delete-all.json +++ b/src/test/resources/import-files/managed-no-delete/2_update-realm_not-delete-all.json @@ -2,6 +2,7 @@ "enabled": true, "realm": "realmWithNoDelete", "groups": [], + "authenticationFlows": [], "requiredActions": [], "clientScopes": [], "scopeMappings": [], diff --git a/src/test/resources/import-files/required-actions/0_create_realm_with_required-action.json b/src/test/resources/import-files/required-actions/00_create_realm_with_required-action.json similarity index 100% rename from src/test/resources/import-files/required-actions/0_create_realm_with_required-action.json rename to src/test/resources/import-files/required-actions/00_create_realm_with_required-action.json diff --git a/src/test/resources/import-files/required-actions/1_update_realm__try_adding_invalid_required-action.json b/src/test/resources/import-files/required-actions/01_update_realm__try_adding_invalid_required-action.json similarity index 100% rename from src/test/resources/import-files/required-actions/1_update_realm__try_adding_invalid_required-action.json rename to src/test/resources/import-files/required-actions/01_update_realm__try_adding_invalid_required-action.json diff --git a/src/test/resources/import-files/required-actions/2_update_realm__add_default_required-action.json b/src/test/resources/import-files/required-actions/02_update_realm__add_default_required-action.json similarity index 100% rename from src/test/resources/import-files/required-actions/2_update_realm__add_default_required-action.json rename to src/test/resources/import-files/required-actions/02_update_realm__add_default_required-action.json diff --git a/src/test/resources/import-files/required-actions/3_update_realm__change_name_of_required-action.json b/src/test/resources/import-files/required-actions/03_update_realm__change_name_of_required-action.json similarity index 100% rename from src/test/resources/import-files/required-actions/3_update_realm__change_name_of_required-action.json rename to src/test/resources/import-files/required-actions/03_update_realm__change_name_of_required-action.json diff --git a/src/test/resources/import-files/required-actions/4_update_realm__enable_required-action.json b/src/test/resources/import-files/required-actions/04_update_realm__enable_required-action.json similarity index 100% rename from src/test/resources/import-files/required-actions/4_update_realm__enable_required-action.json rename to src/test/resources/import-files/required-actions/04_update_realm__enable_required-action.json diff --git a/src/test/resources/import-files/required-actions/5_update_realm__change_priorities_required-action.json b/src/test/resources/import-files/required-actions/05_update_realm__change_priorities_required-action.json similarity index 100% rename from src/test/resources/import-files/required-actions/5_update_realm__change_priorities_required-action.json rename to src/test/resources/import-files/required-actions/05_update_realm__change_priorities_required-action.json diff --git a/src/test/resources/import-files/required-actions/6_update_realm__delete_and_add_required-action.json b/src/test/resources/import-files/required-actions/06_update_realm__delete_and_add_required-action.json similarity index 100% rename from src/test/resources/import-files/required-actions/6_update_realm__delete_and_add_required-action.json rename to src/test/resources/import-files/required-actions/06_update_realm__delete_and_add_required-action.json diff --git a/src/test/resources/import-files/required-actions/7_update_realm__skip_required-action.json b/src/test/resources/import-files/required-actions/07_update_realm__skip_required-action.json similarity index 100% rename from src/test/resources/import-files/required-actions/7_update_realm__skip_required-action.json rename to src/test/resources/import-files/required-actions/07_update_realm__skip_required-action.json diff --git a/src/test/resources/import-files/required-actions/8_update_realm__delete_required-action.json b/src/test/resources/import-files/required-actions/98_update_realm__delete_required-action.json similarity index 100% rename from src/test/resources/import-files/required-actions/8_update_realm__delete_required-action.json rename to src/test/resources/import-files/required-actions/98_update_realm__delete_required-action.json diff --git a/src/test/resources/import-files/required-actions/9_update_realm__delete_all_required-action.json b/src/test/resources/import-files/required-actions/99_update_realm__delete_all_required-action.json similarity index 100% rename from src/test/resources/import-files/required-actions/9_update_realm__delete_all_required-action.json rename to src/test/resources/import-files/required-actions/99_update_realm__delete_all_required-action.json diff --git a/src/test/resources/import-files/roles/0_create_realm_with_roles.json b/src/test/resources/import-files/roles/00_create_realm_with_roles.json similarity index 100% rename from src/test/resources/import-files/roles/0_create_realm_with_roles.json rename to src/test/resources/import-files/roles/00_create_realm_with_roles.json diff --git a/src/test/resources/import-files/roles/1_update_realm__add_realm_role.json b/src/test/resources/import-files/roles/01_update_realm__add_realm_role.json similarity index 100% rename from src/test/resources/import-files/roles/1_update_realm__add_realm_role.json rename to src/test/resources/import-files/roles/01_update_realm__add_realm_role.json diff --git a/src/test/resources/import-files/roles/2_update_realm__add_client_role.json b/src/test/resources/import-files/roles/02_update_realm__add_client_role.json similarity index 100% rename from src/test/resources/import-files/roles/2_update_realm__add_client_role.json rename to src/test/resources/import-files/roles/02_update_realm__add_client_role.json diff --git a/src/test/resources/import-files/roles/3_update_realm__change_realm_role.json b/src/test/resources/import-files/roles/03_update_realm__change_realm_role.json similarity index 100% rename from src/test/resources/import-files/roles/3_update_realm__change_realm_role.json rename to src/test/resources/import-files/roles/03_update_realm__change_realm_role.json diff --git a/src/test/resources/import-files/roles/4_update_realm__change_client_role.json b/src/test/resources/import-files/roles/04_update_realm__change_client_role.json similarity index 100% rename from src/test/resources/import-files/roles/4_update_realm__change_client_role.json rename to src/test/resources/import-files/roles/04_update_realm__change_client_role.json diff --git a/src/test/resources/import-files/roles/5_update_realm__add_user_with_realm_role.json b/src/test/resources/import-files/roles/05_update_realm__add_user_with_realm_role.json similarity index 100% rename from src/test/resources/import-files/roles/5_update_realm__add_user_with_realm_role.json rename to src/test/resources/import-files/roles/05_update_realm__add_user_with_realm_role.json diff --git a/src/test/resources/import-files/roles/6_update_realm__add_user_with_client_role.json b/src/test/resources/import-files/roles/06_update_realm__add_user_with_client_role.json similarity index 100% rename from src/test/resources/import-files/roles/6_update_realm__add_user_with_client_role.json rename to src/test/resources/import-files/roles/06_update_realm__add_user_with_client_role.json diff --git a/src/test/resources/import-files/roles/7_update_realm__change_user_add_realm_role.json b/src/test/resources/import-files/roles/07_update_realm__change_user_add_realm_role.json similarity index 100% rename from src/test/resources/import-files/roles/7_update_realm__change_user_add_realm_role.json rename to src/test/resources/import-files/roles/07_update_realm__change_user_add_realm_role.json diff --git a/src/test/resources/import-files/roles/8_update_realm__change_user_add_client_role.json b/src/test/resources/import-files/roles/08_update_realm__change_user_add_client_role.json similarity index 100% rename from src/test/resources/import-files/roles/8_update_realm__change_user_add_client_role.json rename to src/test/resources/import-files/roles/08_update_realm__change_user_add_client_role.json diff --git a/src/test/resources/import-files/roles/9_update_realm__change_user_remove_realm_role.json b/src/test/resources/import-files/roles/09_update_realm__change_user_remove_realm_role.json similarity index 100% rename from src/test/resources/import-files/roles/9_update_realm__change_user_remove_realm_role.json rename to src/test/resources/import-files/roles/09_update_realm__change_user_remove_realm_role.json