KEYCLOAK-12473 Add possibility to specify length of event detail when storing to database
This commit is contained in:
parent
454ac3f415
commit
c3d80651bf
5 changed files with 55 additions and 6 deletions
|
@ -31,6 +31,7 @@ import org.keycloak.events.admin.OperationType;
|
|||
|
||||
import javax.persistence.EntityManager;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -44,10 +45,12 @@ public class JpaEventStoreProvider implements EventStoreProvider {
|
|||
};
|
||||
private static final Logger logger = Logger.getLogger(JpaEventStoreProvider.class);
|
||||
|
||||
private EntityManager em;
|
||||
private final EntityManager em;
|
||||
private final int maxDetailLength;
|
||||
|
||||
public JpaEventStoreProvider(EntityManager em) {
|
||||
public JpaEventStoreProvider(EntityManager em, int maxDetailLength) {
|
||||
this.em = em;
|
||||
this.maxDetailLength = maxDetailLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -104,7 +107,7 @@ public class JpaEventStoreProvider implements EventStoreProvider {
|
|||
public void close() {
|
||||
}
|
||||
|
||||
static EventEntity convertEvent(Event event) {
|
||||
private EventEntity convertEvent(Event event) {
|
||||
EventEntity eventEntity = new EventEntity();
|
||||
eventEntity.setId(UUID.randomUUID().toString());
|
||||
eventEntity.setTime(event.getTime());
|
||||
|
@ -116,13 +119,31 @@ public class JpaEventStoreProvider implements EventStoreProvider {
|
|||
eventEntity.setIpAddress(event.getIpAddress());
|
||||
eventEntity.setError(event.getError());
|
||||
try {
|
||||
eventEntity.setDetailsJson(mapper.writeValueAsString(event.getDetails()));
|
||||
if (maxDetailLength > 0 && event.getDetails() != null) {
|
||||
Map<String, String> result = new HashMap<>(event.getDetails());
|
||||
result.entrySet().forEach(t -> t.setValue(trimToMaxLength(t.getValue())));
|
||||
|
||||
eventEntity.setDetailsJson(mapper.writeValueAsString(result));
|
||||
} else {
|
||||
eventEntity.setDetailsJson(mapper.writeValueAsString(event.getDetails()));
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
logger.error("Failed to write log details", ex);
|
||||
}
|
||||
return eventEntity;
|
||||
}
|
||||
|
||||
private String trimToMaxLength(String detail) {
|
||||
if (detail != null && detail.length() > maxDetailLength) {
|
||||
// (maxDetailLength - 3) takes "..." into account
|
||||
String result = detail.substring(0, maxDetailLength - 3).concat("...");
|
||||
logger.warn("Detail was truncated to " + result);
|
||||
return result;
|
||||
} else {
|
||||
return detail;
|
||||
}
|
||||
}
|
||||
|
||||
static Event convertEvent(EventEntity eventEntity) {
|
||||
Event event = new Event();
|
||||
event.setTime(eventEntity.getTime());
|
||||
|
|
|
@ -30,15 +30,17 @@ import org.keycloak.models.KeycloakSessionFactory;
|
|||
public class JpaEventStoreProviderFactory implements EventStoreProviderFactory {
|
||||
|
||||
public static final String ID = "jpa";
|
||||
private int maxDetailLength;
|
||||
|
||||
@Override
|
||||
public EventStoreProvider create(KeycloakSession session) {
|
||||
JpaConnectionProvider connection = session.getProvider(JpaConnectionProvider.class);
|
||||
return new JpaEventStoreProvider(connection.getEntityManager());
|
||||
return new JpaEventStoreProvider(connection.getEntityManager(), maxDetailLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
maxDetailLength = config.getInt("max-detail-length", 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -21,3 +21,6 @@ echo ** Adding provider **
|
|||
module:org.keycloak.testsuite.integration-arquillian-testsuite-providers \
|
||||
] \
|
||||
)
|
||||
|
||||
echo ** Adding max-detail-length to eventsStore spi **
|
||||
/subsystem=keycloak-server/spi=eventsStore/provider=jpa/:write-attribute(name=properties.max-detail-length,value=${keycloak.eventsStore.maxDetailLength:1000})
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
*/
|
||||
package org.keycloak.testsuite.forms;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import org.jboss.arquillian.drone.api.annotation.Drone;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Assert;
|
||||
|
@ -68,6 +70,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
@ -210,6 +213,23 @@ public class LoginTest extends AbstractTestRealmKeycloakTest {
|
|||
client.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginWithLongRedirectUri() throws Exception {
|
||||
try (AutoCloseable c = new RealmAttributeUpdater(adminClient.realm("test"))
|
||||
.updateWith(r -> r.setEventsEnabled(true)).update()) {
|
||||
String randomLongString = RandomStringUtils.random(2500, true, true);
|
||||
String longRedirectUri = oauth.getRedirectUri() + "?longQueryParameterValue=" + randomLongString;
|
||||
UriBuilder longLoginUri = UriBuilder.fromUri(oauth.getLoginFormUrl()).replaceQueryParam(OAuth2Constants.REDIRECT_URI, longRedirectUri);
|
||||
|
||||
DroneUtils.getCurrentDriver().navigate().to(longLoginUri.build().toString());
|
||||
|
||||
loginPage.assertCurrent();
|
||||
loginPage.login("login-test", "password");
|
||||
|
||||
events.expectLogin().user(userId).detail(OAuth2Constants.REDIRECT_URI, longRedirectUri).assertEvent();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginChangeUserAfterInvalidPassword() {
|
||||
loginPage.open();
|
||||
|
|
|
@ -22,7 +22,10 @@
|
|||
},
|
||||
|
||||
"eventsStore": {
|
||||
"provider": "${keycloak.eventsStore.provider:jpa}"
|
||||
"provider": "${keycloak.eventsStore.provider:jpa}",
|
||||
"jpa": {
|
||||
"max-detail-length": "${keycloak.eventsStore.maxDetailLength:1000}"
|
||||
}
|
||||
},
|
||||
|
||||
"eventsListener": {
|
||||
|
|
Loading…
Reference in a new issue