KEYCLOAK-16502 Migration of DELETE_ACCOUNT role
This commit is contained in:
parent
6a6dba5d6e
commit
cd9e01af90
12 changed files with 54 additions and 20 deletions
|
@ -1,9 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2020 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
package org.keycloak.migration.migrators;
|
package org.keycloak.migration.migrators;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.keycloak.migration.ModelVersion;
|
import org.keycloak.migration.ModelVersion;
|
||||||
import org.keycloak.models.AccountRoles;
|
import org.keycloak.models.AccountRoles;
|
||||||
|
import org.keycloak.models.Constants;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RequiredActionProviderModel;
|
import org.keycloak.models.RequiredActionProviderModel;
|
||||||
|
|
||||||
|
@ -26,14 +43,13 @@ public class MigrateTo12_0_0 implements Migration {
|
||||||
@Override
|
@Override
|
||||||
public void migrate(KeycloakSession session) {
|
public void migrate(KeycloakSession session) {
|
||||||
session.realms()
|
session.realms()
|
||||||
.getRealms()
|
.getRealmsStream()
|
||||||
.stream()
|
.map(realm -> realm.getClientByClientId(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID))
|
||||||
.map(realm -> realm.getClientByClientId("account"))
|
|
||||||
.filter(client -> Objects.isNull(client.getRole(AccountRoles.DELETE_ACCOUNT)))
|
.filter(client -> Objects.isNull(client.getRole(AccountRoles.DELETE_ACCOUNT)))
|
||||||
.forEach(client -> client.addRole(AccountRoles.DELETE_ACCOUNT)
|
.forEach(client -> client.addRole(AccountRoles.DELETE_ACCOUNT)
|
||||||
.setDescription("${role_"+AccountRoles.DELETE_ACCOUNT+"}"));
|
.setDescription("${role_"+AccountRoles.DELETE_ACCOUNT+"}"));
|
||||||
|
|
||||||
session.realms().getRealms().stream().filter(realm -> Objects.isNull(realm.getRequiredActionProviderByAlias("delete_account"))).forEach(realm -> realm.addRequiredActionProvider(deleteAccount));
|
session.realms().getRealmsStream().filter(realm -> Objects.isNull(realm.getRequiredActionProviderByAlias("delete_account"))).forEach(realm -> realm.addRequiredActionProvider(deleteAccount));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -84,7 +84,10 @@ public class DefaultRequiredActions {
|
||||||
}
|
}
|
||||||
|
|
||||||
addUpdateLocaleAction(realm);
|
addUpdateLocaleAction(realm);
|
||||||
|
addDeleteAccountAction(realm);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addDeleteAccountAction(RealmModel realm) {
|
||||||
if (realm.getRequiredActionProviderByAlias("delete_account") == null) {
|
if (realm.getRequiredActionProviderByAlias("delete_account") == null) {
|
||||||
RequiredActionProviderModel deleteAccount = new RequiredActionProviderModel();
|
RequiredActionProviderModel deleteAccount = new RequiredActionProviderModel();
|
||||||
deleteAccount.setEnabled(false);
|
deleteAccount.setEnabled(false);
|
||||||
|
|
|
@ -62,6 +62,7 @@ import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
import org.keycloak.models.AccountRoles;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set of helper methods, which are useful in various model implementations.
|
* Set of helper methods, which are useful in various model implementations.
|
||||||
|
@ -350,6 +351,13 @@ public final class KeycloakModelUtils {
|
||||||
return offlineRole;
|
return offlineRole;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setupDeleteAccount(ClientModel accountClient) {
|
||||||
|
RoleModel deleteOwnAccount = accountClient.getRole(AccountRoles.DELETE_ACCOUNT);
|
||||||
|
if (deleteOwnAccount == null) {
|
||||||
|
deleteOwnAccount = accountClient.addRole(AccountRoles.DELETE_ACCOUNT);
|
||||||
|
}
|
||||||
|
deleteOwnAccount.setDescription("${role_" + AccountRoles.DELETE_ACCOUNT + "}");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively find all AuthenticationExecutionModel from specified flow or all it's subflows
|
* Recursively find all AuthenticationExecutionModel from specified flow or all it's subflows
|
||||||
|
|
|
@ -294,6 +294,7 @@ public class RepresentationToModel {
|
||||||
|
|
||||||
newRealm.addRequiredActionProvider(model);
|
newRealm.addRequiredActionProvider(model);
|
||||||
}
|
}
|
||||||
|
DefaultRequiredActions.addDeleteAccountAction(newRealm);
|
||||||
} else {
|
} else {
|
||||||
DefaultRequiredActions.addActions(newRealm);
|
DefaultRequiredActions.addActions(newRealm);
|
||||||
}
|
}
|
||||||
|
|
|
@ -443,8 +443,7 @@ public class RealmManager {
|
||||||
manageConsentRole.setDescription("${role_" + AccountRoles.MANAGE_CONSENT + "}");
|
manageConsentRole.setDescription("${role_" + AccountRoles.MANAGE_CONSENT + "}");
|
||||||
manageConsentRole.addCompositeRole(viewConsentRole);
|
manageConsentRole.addCompositeRole(viewConsentRole);
|
||||||
|
|
||||||
RoleModel deleteOwnAccount = accountClient.addRole(AccountRoles.DELETE_ACCOUNT);
|
KeycloakModelUtils.setupDeleteAccount(accountClient);
|
||||||
deleteOwnAccount.setDescription("${role_"+AccountRoles.DELETE_ACCOUNT+"}");
|
|
||||||
|
|
||||||
ClientModel accountConsoleClient = realm.getClientByClientId(Constants.ACCOUNT_CONSOLE_CLIENT_ID);
|
ClientModel accountConsoleClient = realm.getClientByClientId(Constants.ACCOUNT_CONSOLE_CLIENT_ID);
|
||||||
if (accountConsoleClient == null) {
|
if (accountConsoleClient == null) {
|
||||||
|
@ -550,6 +549,7 @@ public class RealmManager {
|
||||||
setupOfflineTokens(realm, rep);
|
setupOfflineTokens(realm, rep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (rep.getClientScopes() == null) {
|
if (rep.getClientScopes() == null) {
|
||||||
createDefaultClientScopes(realm);
|
createDefaultClientScopes(realm);
|
||||||
}
|
}
|
||||||
|
@ -583,6 +583,10 @@ public class RealmManager {
|
||||||
setupAuthenticationFlows(realm);
|
setupAuthenticationFlows(realm);
|
||||||
setupRequiredActions(realm);
|
setupRequiredActions(realm);
|
||||||
|
|
||||||
|
if (!hasRealmRole(rep, AccountRoles.DELETE_ACCOUNT)) {
|
||||||
|
KeycloakModelUtils.setupDeleteAccount(realm.getClientByClientId(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID));
|
||||||
|
}
|
||||||
|
|
||||||
// Refresh periodic sync tasks for configured storageProviders
|
// Refresh periodic sync tasks for configured storageProviders
|
||||||
UserStorageSyncManager storageSync = new UserStorageSyncManager();
|
UserStorageSyncManager storageSync = new UserStorageSyncManager();
|
||||||
realm.getUserStorageProvidersStream()
|
realm.getUserStorageProvidersStream()
|
||||||
|
|
|
@ -286,16 +286,16 @@ public abstract class AbstractMigrationTest extends AbstractKeycloakTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void testMigrationTo12_0_0() {
|
protected void testMigrationTo12_0_0() {
|
||||||
testAccountConsoleClientHasDeleteUserRole(masterRealm);
|
testDeleteAccount(masterRealm);
|
||||||
testAccountConsoleClientHasDeleteUserRole(migrationRealm);
|
testDeleteAccount(migrationRealm);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testAccountConsoleClientHasDeleteUserRole(RealmResource realm) {
|
private void testDeleteAccount(RealmResource realm) {
|
||||||
ClientRepresentation accountClient = realm.clients().findByClientId(ACCOUNT_MANAGEMENT_CLIENT_ID).get(0);
|
ClientRepresentation accountClient = realm.clients().findByClientId(ACCOUNT_MANAGEMENT_CLIENT_ID).get(0);
|
||||||
|
|
||||||
ClientResource accountResource = realm.clients().get(accountClient.getId());
|
ClientResource accountResource = realm.clients().get(accountClient.getId());
|
||||||
RoleRepresentation deleteUserRole = accountResource.roles().get(AccountRoles.DELETE_ACCOUNT).toRepresentation();
|
|
||||||
assertNotNull(deleteUserRole);
|
assertNotNull(accountResource.roles().get(AccountRoles.DELETE_ACCOUNT).toRepresentation());
|
||||||
|
assertNotNull(realm.flows().getRequiredAction("delete_account"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testAccountClient(RealmResource realm) {
|
private void testAccountClient(RealmResource realm) {
|
||||||
|
|
|
@ -70,6 +70,7 @@ public class JsonFileImport198MigrationTest extends AbstractJsonFileImportMigrat
|
||||||
testMigrationTo7_x(false);
|
testMigrationTo7_x(false);
|
||||||
testMigrationTo8_x();
|
testMigrationTo8_x();
|
||||||
testMigrationTo9_x();
|
testMigrationTo9_x();
|
||||||
|
testMigrationTo12_x();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -64,6 +64,7 @@ public class JsonFileImport255MigrationTest extends AbstractJsonFileImportMigrat
|
||||||
testMigrationTo7_x(true);
|
testMigrationTo7_x(true);
|
||||||
testMigrationTo8_x();
|
testMigrationTo8_x();
|
||||||
testMigrationTo9_x();
|
testMigrationTo9_x();
|
||||||
|
testMigrationTo12_x();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,7 @@ public class JsonFileImport343MigrationTest extends AbstractJsonFileImportMigrat
|
||||||
testMigrationTo7_x(true);
|
testMigrationTo7_x(true);
|
||||||
testMigrationTo8_x();
|
testMigrationTo8_x();
|
||||||
testMigrationTo9_x();
|
testMigrationTo9_x();
|
||||||
|
testMigrationTo12_x();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,7 @@ public class JsonFileImport483MigrationTest extends AbstractJsonFileImportMigrat
|
||||||
testMigrationTo7_x(true);
|
testMigrationTo7_x(true);
|
||||||
testMigrationTo8_x();
|
testMigrationTo8_x();
|
||||||
testMigrationTo9_x();
|
testMigrationTo9_x();
|
||||||
|
testMigrationTo12_x();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ public class JsonFileImport903MigrationTest extends AbstractJsonFileImportMigrat
|
||||||
@Test
|
@Test
|
||||||
public void migration9_0_3Test() throws Exception {
|
public void migration9_0_3Test() throws Exception {
|
||||||
checkRealmsImported();
|
checkRealmsImported();
|
||||||
// testMigrationTo10_x();
|
testMigrationTo12_x();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,17 +57,11 @@ public class MigrationTest extends AbstractMigrationTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
@Migration(versionFrom = "12.")
|
|
||||||
public void migration12_xTest() {
|
|
||||||
testMigrationTo12_x();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Migration(versionFrom = "9.")
|
@Migration(versionFrom = "9.")
|
||||||
public void migration9_xTest() throws Exception {
|
public void migration9_xTest() throws Exception {
|
||||||
testMigratedData(false);
|
testMigratedData(false);
|
||||||
// testMigrationTo10_x();
|
testMigrationTo12_x();
|
||||||
|
|
||||||
// Always test offline-token login during migration test
|
// Always test offline-token login during migration test
|
||||||
testOfflineTokenLogin();
|
testOfflineTokenLogin();
|
||||||
|
@ -82,6 +76,7 @@ public class MigrationTest extends AbstractMigrationTest {
|
||||||
testMigrationTo7_x(true);
|
testMigrationTo7_x(true);
|
||||||
testMigrationTo8_x();
|
testMigrationTo8_x();
|
||||||
testMigrationTo9_x();
|
testMigrationTo9_x();
|
||||||
|
testMigrationTo12_x();
|
||||||
|
|
||||||
// Always test offline-token login during migration test
|
// Always test offline-token login during migration test
|
||||||
testOfflineTokenLogin();
|
testOfflineTokenLogin();
|
||||||
|
@ -97,6 +92,7 @@ public class MigrationTest extends AbstractMigrationTest {
|
||||||
testMigrationTo7_x(true);
|
testMigrationTo7_x(true);
|
||||||
testMigrationTo8_x();
|
testMigrationTo8_x();
|
||||||
testMigrationTo9_x();
|
testMigrationTo9_x();
|
||||||
|
testMigrationTo12_x();
|
||||||
|
|
||||||
// Always test offline-token login during migration test
|
// Always test offline-token login during migration test
|
||||||
testOfflineTokenLogin();
|
testOfflineTokenLogin();
|
||||||
|
@ -113,6 +109,7 @@ public class MigrationTest extends AbstractMigrationTest {
|
||||||
testMigrationTo7_x(true);
|
testMigrationTo7_x(true);
|
||||||
testMigrationTo8_x();
|
testMigrationTo8_x();
|
||||||
testMigrationTo9_x();
|
testMigrationTo9_x();
|
||||||
|
testMigrationTo12_x();
|
||||||
|
|
||||||
// Always test offline-token login during migration test
|
// Always test offline-token login during migration test
|
||||||
testOfflineTokenLogin();
|
testOfflineTokenLogin();
|
||||||
|
@ -130,6 +127,7 @@ public class MigrationTest extends AbstractMigrationTest {
|
||||||
testMigrationTo7_x(false);
|
testMigrationTo7_x(false);
|
||||||
testMigrationTo8_x();
|
testMigrationTo8_x();
|
||||||
testMigrationTo9_x();
|
testMigrationTo9_x();
|
||||||
|
testMigrationTo12_x();
|
||||||
|
|
||||||
// Always test offline-token login during migration test
|
// Always test offline-token login during migration test
|
||||||
testOfflineTokenLogin();
|
testOfflineTokenLogin();
|
||||||
|
|
Loading…
Reference in a new issue