[KEYCLOAK-3723] Fixed updated of protocol mappers within client updates in clients-registrations resource

This commit is contained in:
Gilles 2019-01-22 08:04:27 +01:00 committed by Marek Posolda
parent d5b28013d1
commit f295a2e303
3 changed files with 103 additions and 13 deletions

View file

@ -1336,7 +1336,6 @@ public class RepresentationToModel {
} }
} }
if (rep.getNotBefore() != null) { if (rep.getNotBefore() != null) {
resource.setNotBefore(rep.getNotBefore()); resource.setNotBefore(rep.getNotBefore());
} }
@ -1365,6 +1364,39 @@ public class RepresentationToModel {
resource.updateClient(); resource.updateClient();
} }
public static void updateClientProtocolMappers(ClientRepresentation rep, ClientModel resource) {
if (rep.getProtocolMappers() != null) {
Map<String,ProtocolMapperModel> existingProtocolMappers = new HashMap<>();
for (ProtocolMapperModel existingProtocolMapper : resource.getProtocolMappers()) {
existingProtocolMappers.put(generateProtocolNameKey(existingProtocolMapper.getProtocol(), existingProtocolMapper.getName()), existingProtocolMapper);
}
for (ProtocolMapperRepresentation protocolMapperRepresentation : rep.getProtocolMappers()) {
String protocolNameKey = generateProtocolNameKey(protocolMapperRepresentation.getProtocol(), protocolMapperRepresentation.getName());
ProtocolMapperModel existingMapper = existingProtocolMappers.get(protocolNameKey);
if (existingMapper != null) {
ProtocolMapperModel updatedProtocolMapperModel = toModel(protocolMapperRepresentation);
updatedProtocolMapperModel.setId(existingMapper.getId());
resource.updateProtocolMapper(updatedProtocolMapperModel);
existingProtocolMappers.remove(protocolNameKey);
} else {
resource.addProtocolMapper(toModel(protocolMapperRepresentation));
}
}
for (Map.Entry<String, ProtocolMapperModel> entryToDelete : existingProtocolMappers.entrySet()) {
resource.removeProtocolMapper(entryToDelete.getValue());
}
}
}
private static String generateProtocolNameKey(String protocol, String name) {
return String.format("%s%%%s", protocol, name);
}
// CLIENT SCOPES // CLIENT SCOPES
private static Map<String, ClientScopeModel> createClientScopes(KeycloakSession session, List<ClientScopeRepresentation> clientScopes, RealmModel realm) { private static Map<String, ClientScopeModel> createClientScopes(KeycloakSession session, List<ClientScopeRepresentation> clientScopes, RealmModel realm) {

View file

@ -19,11 +19,7 @@ package org.keycloak.services.clientregistration;
import org.keycloak.events.EventBuilder; import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType; import org.keycloak.events.EventType;
import org.keycloak.models.ClientInitialAccessModel; import org.keycloak.models.*;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.ModelToRepresentation; import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.RepresentationToModel; import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.ClientRepresentation;
@ -142,6 +138,8 @@ public abstract class AbstractClientRegistrationProvider implements ClientRegist
} }
RepresentationToModel.updateClient(rep, client); RepresentationToModel.updateClient(rep, client);
RepresentationToModel.updateClientProtocolMappers(rep, client);
rep = ModelToRepresentation.toRepresentation(client, session); rep = ModelToRepresentation.toRepresentation(client, session);
if (auth.isRegistrationAccessToken()) { if (auth.isRegistrationAccessToken()) {

View file

@ -24,21 +24,19 @@ import org.keycloak.client.registration.Auth;
import org.keycloak.client.registration.ClientRegistration; import org.keycloak.client.registration.ClientRegistration;
import org.keycloak.client.registration.ClientRegistrationException; import org.keycloak.client.registration.ClientRegistrationException;
import org.keycloak.client.registration.HttpErrorException; import org.keycloak.client.registration.HttpErrorException;
import org.keycloak.models.ClientModel;
import org.keycloak.models.Constants; import org.keycloak.models.Constants;
import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.testsuite.runonserver.RunOnServerDeployment; import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
import org.keycloak.testsuite.runonserver.RunOnServerTest;
import javax.ws.rs.NotFoundException; import javax.ws.rs.NotFoundException;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import static org.junit.Assert.assertEquals; import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertNotNull; import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertNull; import static org.junit.Assert.*;
import static org.junit.Assert.fail;
/** /**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -245,6 +243,68 @@ public class ClientRegistrationTest extends AbstractClientRegistrationTest {
assertEquals("mysecret", updatedClient.getSecret()); assertEquals("mysecret", updatedClient.getSecret());
} }
@Test
public void addClientProtcolMappers() throws ClientRegistrationException {
authManageClients();
ClientRepresentation initialClient = buildClient();
registerClient(initialClient);
ClientRepresentation client = reg.get(CLIENT_ID);
addProtocolMapper(client, "mapperA");
reg.update(client);
ClientRepresentation updatedClient = reg.get(CLIENT_ID);
assertThat("Adding protocolMapper failed", updatedClient.getProtocolMappers().size(), is(1));
}
@Test
public void removeClientProtcolMappers() throws ClientRegistrationException {
authManageClients();
ClientRepresentation initialClient = buildClient();
addProtocolMapper(initialClient, "mapperA");
registerClient(initialClient);
ClientRepresentation client = reg.get(CLIENT_ID);
client.setProtocolMappers(new ArrayList<>());
reg.update(client);
ClientRepresentation updatedClient = reg.get(CLIENT_ID);
assertThat("Removing protocolMapper failed", updatedClient.getProtocolMappers(), nullValue());
}
@Test
public void updateClientProtcolMappers() throws ClientRegistrationException {
authManageClients();
ClientRepresentation initialClient = buildClient();
addProtocolMapper(initialClient, "mapperA");
registerClient(initialClient);
ClientRepresentation client = reg.get(CLIENT_ID);
client.getProtocolMappers().get(0).getConfig().put("claim.name", "updatedClaimName");
reg.update(client);
ClientRepresentation updatedClient = reg.get(CLIENT_ID);
assertThat("Updating protocolMapper failed", updatedClient.getProtocolMappers().get(0).getConfig().get("claim.name"), is("updatedClaimName"));
}
private void addProtocolMapper(ClientRepresentation client, String mapperName) {
ProtocolMapperRepresentation mapper = new ProtocolMapperRepresentation();
mapper.setName(mapperName);
mapper.setProtocol("openid-connect");
mapper.setProtocolMapper("oidc-usermodel-attribute-mapper");
mapper.getConfig().put("userinfo.token.claim", "true");
mapper.getConfig().put("user.attribute", "someAttribute");
mapper.getConfig().put("id.token.claim", "true");
mapper.getConfig().put("access.token.claim", "true");
mapper.getConfig().put("claim.name", "someClaimName");
mapper.getConfig().put("jsonType.label", "long");
client.setProtocolMappers(new ArrayList<>());
client.getProtocolMappers().add(mapper);
}
@Test @Test
public void updateClientAsAdminWithCreateOnly() throws ClientRegistrationException { public void updateClientAsAdminWithCreateOnly() throws ClientRegistrationException {
authCreateClients(); authCreateClients();