Allow a partial import to overwrite the default role

Closes #9891
This commit is contained in:
Alexander Schwartz 2022-10-28 12:12:48 +02:00 committed by Pedro Igor
parent f6985949b6
commit dd5a60c321
3 changed files with 52 additions and 18 deletions

View file

@ -1051,6 +1051,7 @@ public class RealmAdapter implements CachedRealmModel {
@Override @Override
public RoleModel getDefaultRole() { public RoleModel getDefaultRole() {
if (isUpdated()) return updated.getDefaultRole();
return cached.getDefaultRoleId() == null ? null : cacheSession.getRoleById(this, cached.getDefaultRoleId()); return cached.getDefaultRoleId() == null ? null : cacheSession.getRoleById(this, cached.getDefaultRoleId());
} }

View file

@ -18,6 +18,7 @@ package org.keycloak.partialimport;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.models.utils.RepresentationToModel; import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.representations.idm.PartialImportRepresentation; import org.keycloak.representations.idm.PartialImportRepresentation;
@ -29,6 +30,7 @@ import org.keycloak.services.ServicesLogger;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Set; import java.util.Set;
/** /**
@ -54,6 +56,7 @@ public class RolesPartialImport implements PartialImport<RolesRepresentation> {
private final RealmRolesPartialImport realmRolesPI = new RealmRolesPartialImport(); private final RealmRolesPartialImport realmRolesPI = new RealmRolesPartialImport();
private final ClientRolesPartialImport clientRolesPI = new ClientRolesPartialImport(); private final ClientRolesPartialImport clientRolesPI = new ClientRolesPartialImport();
private RoleRepresentation newDefaultRole;
@Override @Override
public void prepare(PartialImportRepresentation rep, RealmModel realm, KeycloakSession session) throws ErrorResponseException { public void prepare(PartialImportRepresentation rep, RealmModel realm, KeycloakSession session) throws ErrorResponseException {
@ -66,6 +69,16 @@ public class RolesPartialImport implements PartialImport<RolesRepresentation> {
realmRolesPI.prepare(rep, realm, session); realmRolesPI.prepare(rep, realm, session);
this.realmRolesToOverwrite = realmRolesPI.getToOverwrite(); this.realmRolesToOverwrite = realmRolesPI.getToOverwrite();
if (realmRolesToOverwrite.size() > 0) {
String defaultRoleName = realm.getDefaultRole().getName();
for (RoleRepresentation representation : realmRolesToOverwrite) {
if (Objects.equals(defaultRoleName, representation.getName())) {
this.newDefaultRole = representation;
break;
}
}
}
this.realmRolesToSkip = realmRolesPI.getToSkip(); this.realmRolesToSkip = realmRolesPI.getToSkip();
} }
@ -94,6 +107,11 @@ public class RolesPartialImport implements PartialImport<RolesRepresentation> {
if (rep.hasRealmRoles()) setUniqueIds(rep.getRoles().getRealm()); if (rep.hasRealmRoles()) setUniqueIds(rep.getRoles().getRealm());
if (rep.hasClientRoles()) setUniqueIds(rep.getRoles().getClient()); if (rep.hasClientRoles()) setUniqueIds(rep.getRoles().getClient());
if (newDefaultRole != null) {
RoleModel defaultRole = RepresentationToModel.createRole(realm, newDefaultRole);
realm.setDefaultRole(defaultRole);
}
try { try {
RepresentationToModel.importRoles(rep.getRoles(), realm); RepresentationToModel.importRoles(rep.getRoles(), realm);
} catch (Exception e) { } catch (Exception e) {

View file

@ -49,6 +49,7 @@ import org.keycloak.testsuite.util.RealmBuilder;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -268,7 +269,7 @@ public class PartialImportTest extends AbstractAuthTest {
piRep.setGroups(groups); piRep.setGroups(groups);
} }
private void addClients(boolean withServiceAccounts) throws IOException { private void addClients(boolean withServiceAccounts) {
List<ClientRepresentation> clients = new ArrayList<>(); List<ClientRepresentation> clients = new ArrayList<>();
List<UserRepresentation> serviceAccounts = new ArrayList<>(); List<UserRepresentation> serviceAccounts = new ArrayList<>();
@ -440,7 +441,7 @@ public class PartialImportTest extends AbstractAuthTest {
doImport(); doImport();
UserRepresentation user = createUserRepresentation(USER_PREFIX + 999, USER_PREFIX + 1 + "@foo.com", "foo", "bar", true); UserRepresentation user = createUserRepresentation(USER_PREFIX + 999, USER_PREFIX + 1 + "@foo.com", "foo", "bar", true);
piRep.setUsers(Arrays.asList(user)); piRep.setUsers(List.of(user));
PartialImportResults results = doImport(); PartialImportResults results = doImport();
assertEquals(1, results.getAdded()); assertEquals(1, results.getAdded());
@ -479,7 +480,7 @@ public class PartialImportTest extends AbstractAuthTest {
} }
@Test @Test
public void testAddClients() throws IOException { public void testAddClients() {
setFail(); setFail();
addClients(false); addClients(false);
@ -495,7 +496,7 @@ public class PartialImportTest extends AbstractAuthTest {
} }
@Test @Test
public void testAddClientsWithServiceAccountsAndAuthorization() throws IOException { public void testAddClientsWithServiceAccountsAndAuthorization() {
setFail(); setFail();
addClients(true); addClients(true);
@ -621,7 +622,7 @@ public class PartialImportTest extends AbstractAuthTest {
} }
@Test @Test
public void testAddClientsFail() throws IOException { public void testAddClientsFail() {
addClients(false); addClients(false);
testFail(); testFail();
} }
@ -676,13 +677,13 @@ public class PartialImportTest extends AbstractAuthTest {
} }
@Test @Test
public void testAddClientsSkip() throws IOException { public void testAddClientsSkip() {
addClients(false); addClients(false);
testSkip(); testSkip();
} }
@Test @Test
public void testAddClientsSkipWithServiceAccountsAndAuthorization() throws IOException { public void testAddClientsSkipWithServiceAccountsAndAuthorization() {
addClients(true); addClients(true);
setSkip(); setSkip();
PartialImportResults results = doImport(); PartialImportResults results = doImport();
@ -742,13 +743,13 @@ public class PartialImportTest extends AbstractAuthTest {
} }
@Test @Test
public void testAddClientsOverwrite() throws IOException { public void testAddClientsOverwrite() {
addClients(false); addClients(false);
testOverwrite(); testOverwrite();
} }
@Test @Test
public void testAddClientsOverwriteWithServiceAccountsAndAuthorization() throws IOException { public void testAddClientsOverwriteWithServiceAccountsAndAuthorization() {
addClients(true); addClients(true);
setOverwrite(); setOverwrite();
PartialImportResults results = doImport(); PartialImportResults results = doImport();
@ -759,7 +760,7 @@ public class PartialImportTest extends AbstractAuthTest {
} }
@Test @Test
public void testAddClientsOverwriteServiceAccountsWithNoServiceAccounts() throws IOException { public void testAddClientsOverwriteServiceAccountsWithNoServiceAccounts() {
addClients(true); addClients(true);
setOverwrite(); setOverwrite();
PartialImportResults results = doImport(); PartialImportResults results = doImport();
@ -806,7 +807,7 @@ public class PartialImportTest extends AbstractAuthTest {
testOverwrite(); testOverwrite();
} }
private void importEverything(boolean withServiceAccounts) throws IOException { private void importEverything(boolean withServiceAccounts) {
addUsers(); addUsers();
addGroups(); addGroups();
addClients(withServiceAccounts); addClients(withServiceAccounts);
@ -824,7 +825,7 @@ public class PartialImportTest extends AbstractAuthTest {
} }
@Test @Test
public void testEverythingFail() throws IOException { public void testEverythingFail() {
setFail(); setFail();
importEverything(false); importEverything(false);
PartialImportResults results = doImport(); // second import will fail because not allowed to skip or overwrite PartialImportResults results = doImport(); // second import will fail because not allowed to skip or overwrite
@ -832,7 +833,7 @@ public class PartialImportTest extends AbstractAuthTest {
} }
@Test @Test
public void testEverythingSkip() throws IOException { public void testEverythingSkip() {
setSkip(); setSkip();
importEverything(false); importEverything(false);
PartialImportResults results = doImport(); PartialImportResults results = doImport();
@ -840,7 +841,7 @@ public class PartialImportTest extends AbstractAuthTest {
} }
@Test @Test
public void testEverythingSkipWithServiceAccounts() throws IOException { public void testEverythingSkipWithServiceAccounts() {
setSkip(); setSkip();
importEverything(true); importEverything(true);
PartialImportResults results = doImport(); PartialImportResults results = doImport();
@ -848,7 +849,7 @@ public class PartialImportTest extends AbstractAuthTest {
} }
@Test @Test
public void testEverythingOverwrite() throws IOException { public void testEverythingOverwrite() {
setOverwrite(); setOverwrite();
importEverything(false); importEverything(false);
PartialImportResults results = doImport(); PartialImportResults results = doImport();
@ -856,7 +857,7 @@ public class PartialImportTest extends AbstractAuthTest {
} }
@Test @Test
public void testEverythingOverwriteWithServiceAccounts() throws IOException { public void testEverythingOverwriteWithServiceAccounts() {
setOverwrite(); setOverwrite();
importEverything(true); importEverything(true);
PartialImportResults results = doImport(); PartialImportResults results = doImport();
@ -877,7 +878,7 @@ public class PartialImportTest extends AbstractAuthTest {
RolesRepresentation roles = new RolesRepresentation(); RolesRepresentation roles = new RolesRepresentation();
roles.setClient(clients); roles.setClient(clients);
piRep.setClients(Arrays.asList(client)); piRep.setClients(List.of(client));
piRep.setRoles(roles); piRep.setRoles(roles);
doImport(); doImport();
@ -898,7 +899,7 @@ public class PartialImportTest extends AbstractAuthTest {
@Test @Test
public void testOverwriteExistingClientWithServiceAccount() { public void testOverwriteExistingClientWithServiceAccount() {
setOverwrite(); setOverwrite();
piRep.setClients(Arrays.asList(testRealmResource().clients().findByClientId(CLIENT_SERVICE_ACCOUNT).get(0))); piRep.setClients(Collections.singletonList(testRealmResource().clients().findByClientId(CLIENT_SERVICE_ACCOUNT).get(0)));
Assert.assertEquals(1, doImport().getOverwritten()); Assert.assertEquals(1, doImport().getOverwritten());
@ -906,4 +907,18 @@ public class PartialImportTest extends AbstractAuthTest {
testRealmResource().clients().get(client.getId()).getServiceAccountUser(); testRealmResource().clients().get(client.getId()).getServiceAccountUser();
} }
@Test
public void testOverwriteDefaultRole() {
setOverwrite();
RolesRepresentation roles = new RolesRepresentation();
RoleRepresentation oldDefaultRole = testRealmResource().toRepresentation().getDefaultRole();
roles.setRealm(Collections.singletonList(oldDefaultRole));
piRep.setRoles(roles);
Assert.assertEquals("default role should have been overwritten", 1, doImport().getOverwritten());
Assert.assertNotEquals("when overwriting, the ID of the role changes",
testRealmResource().toRepresentation().getDefaultRole().getId(), oldDefaultRole.getId());
}
} }