diff --git a/model/jpa/src/main/java/org/keycloak/events/jpa/JpaAdminEventQuery.java b/model/jpa/src/main/java/org/keycloak/events/jpa/JpaAdminEventQuery.java index 2b8fe2c27d..0be7295fd8 100755 --- a/model/jpa/src/main/java/org/keycloak/events/jpa/JpaAdminEventQuery.java +++ b/model/jpa/src/main/java/org/keycloak/events/jpa/JpaAdminEventQuery.java @@ -20,6 +20,7 @@ package org.keycloak.events.jpa; import org.keycloak.events.admin.AdminEvent; import org.keycloak.events.admin.AdminEventQuery; import org.keycloak.events.admin.OperationType; +import org.keycloak.events.admin.ResourceType; import javax.persistence.EntityManager; import javax.persistence.TypedQuery; @@ -76,8 +77,14 @@ public class JpaAdminEventQuery implements AdminEventQuery { } @Override - public AdminEventQuery resourceType(List resourceTypes) { - predicates.add(root.get("resourceType").in(resourceTypes)); + public AdminEventQuery resourceType(ResourceType... resourceTypes) { + + List resourceTypeStrings = new LinkedList(); + for (ResourceType e : resourceTypes) { + resourceTypeStrings.add(e.toString()); + } + predicates.add(root.get("resourceType").in(resourceTypeStrings)); + return this; } diff --git a/model/jpa/src/main/java/org/keycloak/events/jpa/JpaEventStoreProvider.java b/model/jpa/src/main/java/org/keycloak/events/jpa/JpaEventStoreProvider.java index 323d3088af..a9ebfbc739 100755 --- a/model/jpa/src/main/java/org/keycloak/events/jpa/JpaEventStoreProvider.java +++ b/model/jpa/src/main/java/org/keycloak/events/jpa/JpaEventStoreProvider.java @@ -210,7 +210,11 @@ public class JpaEventStoreProvider implements EventStoreProvider { adminEventEntity.setRealmId(adminEvent.getRealmId()); setAuthDetails(adminEventEntity, adminEvent.getAuthDetails()); adminEventEntity.setOperationType(adminEvent.getOperationType().toString()); - adminEventEntity.setResourceType(adminEvent.getResourceType()); + + if (adminEvent.getResourceTypeAsString() != null) { + adminEventEntity.setResourceType(adminEvent.getResourceTypeAsString()); + } + adminEventEntity.setResourcePath(adminEvent.getResourcePath()); adminEventEntity.setError(adminEvent.getError()); @@ -227,7 +231,11 @@ public class JpaEventStoreProvider implements EventStoreProvider { adminEvent.setRealmId(adminEventEntity.getRealmId()); setAuthDetails(adminEvent, adminEventEntity); adminEvent.setOperationType(OperationType.valueOf(adminEventEntity.getOperationType())); - adminEvent.setResourceType(adminEventEntity.getResourceType()); + + if (adminEventEntity.getResourceType() != null) { + adminEvent.setResourceTypeAsString(adminEventEntity.getResourceType()); + } + adminEvent.setResourcePath(adminEventEntity.getResourcePath()); adminEvent.setError(adminEventEntity.getError()); diff --git a/model/map/src/main/java/org/keycloak/models/map/events/EventUtils.java b/model/map/src/main/java/org/keycloak/models/map/events/EventUtils.java index 4bc919f82b..e5fa0334a8 100644 --- a/model/map/src/main/java/org/keycloak/models/map/events/EventUtils.java +++ b/model/map/src/main/java/org/keycloak/models/map/events/EventUtils.java @@ -50,7 +50,7 @@ public class EventUtils { adminEvent.setRealmId(adminEventEntity.getRealmId()); setAuthDetails(adminEvent, adminEventEntity); adminEvent.setOperationType(adminEventEntity.getOperationType()); - adminEvent.setResourceType(adminEventEntity.getResourceType()); + adminEvent.setResourceTypeAsString(adminEventEntity.getResourceType()); adminEvent.setResourcePath(adminEventEntity.getResourcePath()); adminEvent.setError(adminEventEntity.getError()); @@ -68,7 +68,7 @@ public class EventUtils { mapAdminEvent.setRealmId(adminEvent.getRealmId()); setAuthDetails(mapAdminEvent, adminEvent.getAuthDetails()); mapAdminEvent.setOperationType(adminEvent.getOperationType()); - mapAdminEvent.setResourceType(adminEvent.getResourceType()); + mapAdminEvent.setResourceType(adminEvent.getResourceTypeAsString()); mapAdminEvent.setResourcePath(adminEvent.getResourcePath()); mapAdminEvent.setError(adminEvent.getError()); diff --git a/model/map/src/main/java/org/keycloak/models/map/events/MapAdminEventQuery.java b/model/map/src/main/java/org/keycloak/models/map/events/MapAdminEventQuery.java index 2aeabf3b2f..d2d33a2a76 100644 --- a/model/map/src/main/java/org/keycloak/models/map/events/MapAdminEventQuery.java +++ b/model/map/src/main/java/org/keycloak/models/map/events/MapAdminEventQuery.java @@ -21,12 +21,12 @@ import org.keycloak.events.admin.AdminEvent; import org.keycloak.events.admin.AdminEvent.SearchableFields; import org.keycloak.events.admin.AdminEventQuery; import org.keycloak.events.admin.OperationType; +import org.keycloak.events.admin.ResourceType; import org.keycloak.models.map.storage.QueryParameters; import org.keycloak.models.map.storage.criteria.DefaultModelCriteria; import java.util.Arrays; import java.util.Date; -import java.util.List; import java.util.function.Function; import java.util.stream.Stream; @@ -86,8 +86,8 @@ public class MapAdminEventQuery implements AdminEventQuery { } @Override - public AdminEventQuery resourceType(List resourceTypes) { - mcb = mcb.compare(SearchableFields.RESOURCE_TYPE, IN, resourceTypes); + public AdminEventQuery resourceType(ResourceType... resourceTypes) { + mcb = mcb.compare(SearchableFields.RESOURCE_TYPE, IN, Arrays.stream(resourceTypes)); return this; } diff --git a/server-spi-private/src/main/java/org/keycloak/events/admin/AdminEvent.java b/server-spi-private/src/main/java/org/keycloak/events/admin/AdminEvent.java index 1d47c2b0a0..5240d37963 100644 --- a/server-spi-private/src/main/java/org/keycloak/events/admin/AdminEvent.java +++ b/server-spi-private/src/main/java/org/keycloak/events/admin/AdminEvent.java @@ -64,7 +64,7 @@ public class AdminEvent { this.time = toCopy.getTime(); this.realmId = toCopy.getRealmId(); this.authDetails = new AuthDetails(toCopy.getAuthDetails()); - this.resourceType = toCopy.getResourceType(); + this.resourceType = toCopy.getResourceTypeAsString(); this.operationType = toCopy.getOperationType(); this.resourcePath = toCopy.getResourcePath(); this.representation = toCopy.getRepresentation(); @@ -186,11 +186,35 @@ public class AdminEvent { * * @return */ - public String getResourceType() { + public ResourceType getResourceType() { + if (resourceType == null) { + return null; + } + try { + return ResourceType.valueOf(resourceType); + } + catch (IllegalArgumentException e) { + return ResourceType.CUSTOM; + } + } + + public void setResourceType(ResourceType resourceType) { + this.resourceType = resourceType == null ? null : resourceType.toString(); + } + + /** + * Returns the type as string. Custom resource types with values different from {@link ResourceType} are possible. In this case {@link #getResourceType()} returns CUSTOM. + * + * @return + */ + public String getResourceTypeAsString() { return resourceType; } - public void setResourceType(String resourceType) { + /** + * Setter for custom resource types with values different from {@link ResourceType}. + */ + public void setResourceTypeAsString(String resourceType) { this.resourceType = resourceType; } } diff --git a/server-spi-private/src/main/java/org/keycloak/events/admin/AdminEventQuery.java b/server-spi-private/src/main/java/org/keycloak/events/admin/AdminEventQuery.java index b7f1bb1aa0..47ce3ed819 100644 --- a/server-spi-private/src/main/java/org/keycloak/events/admin/AdminEventQuery.java +++ b/server-spi-private/src/main/java/org/keycloak/events/admin/AdminEventQuery.java @@ -80,7 +80,7 @@ public interface AdminEventQuery { * @param resourceTypes * @return this for method chaining */ - AdminEventQuery resourceType(List resourceTypes); + AdminEventQuery resourceType(ResourceType ... resourceTypes); /** * Search by resource path. Supports wildcard *. For example: diff --git a/server-spi-private/src/main/java/org/keycloak/events/admin/ResourceType.java b/server-spi-private/src/main/java/org/keycloak/events/admin/ResourceType.java index 534518292f..6198cfe07a 100644 --- a/server-spi-private/src/main/java/org/keycloak/events/admin/ResourceType.java +++ b/server-spi-private/src/main/java/org/keycloak/events/admin/ResourceType.java @@ -21,38 +21,170 @@ package org.keycloak.events.admin; * * @author Thomas Darimont */ -public interface ResourceType { +public enum ResourceType { - public static String REALM = "REALM"; - public static String REALM_ROLE = "REALM_ROLE"; - public static String REALM_ROLE_MAPPING = "REALM_ROLE_MAPPING"; - public static String REALM_SCOPE_MAPPING = "REALM_SCOPE_MAPPING"; - public static String AUTH_FLOW = "AUTH_FLOW"; - public static String AUTH_EXECUTION_FLOW = "AUTH_EXECUTION_FLOW"; - public static String AUTH_EXECUTION = "AUTH_EXECUTION"; - public static String AUTHENTICATOR_CONFIG = "AUTHENTICATOR_CONFIG"; - public static String REQUIRED_ACTION = "REQUIRED_ACTION"; - public static String IDENTITY_PROVIDER = "IDENTITY_PROVIDER"; - public static String IDENTITY_PROVIDER_MAPPER = "IDENTITY_PROVIDER_MAPPER"; - public static String PROTOCOL_MAPPER = "PROTOCOL_MAPPER"; - public static String USER = "USER"; - public static String USER_LOGIN_FAILURE = "USER_LOGIN_FAILURE"; - public static String USER_SESSION = "USER_SESSION"; - public static String USER_FEDERATION_PROVIDER = "USER_FEDERATION_PROVIDER"; - public static String USER_FEDERATION_MAPPER = "USER_FEDERATION_MAPPER"; - public static String GROUP = "GROUP"; - public static String GROUP_MEMBERSHIP = "GROUP_MEMBERSHIP"; - public static String CLIENT = "CLIENT"; - public static String CLIENT_INITIAL_ACCESS_MODEL = "CLIENT_INITIAL_ACCESS_MODEL"; - public static String CLIENT_ROLE = "CLIENT_ROLE"; - public static String CLIENT_ROLE_MAPPING = "CLIENT_ROLE_MAPPING"; - public static String CLIENT_SCOPE = "CLIENT_SCOPE"; - public static String CLIENT_SCOPE_MAPPING = "CLIENT_SCOPE_MAPPING"; - public static String CLIENT_SCOPE_CLIENT_MAPPING = "CLIENT_SCOPE_CLIENT_MAPPING"; - public static String CLUSTER_NODE = "CLUSTER_NODE"; - public static String COMPONENT = "COMPONENT"; - public static String AUTHORIZATION_RESOURCE_SERVER = "AUTHORIZATION_RESOURCE_SERVER"; - public static String AUTHORIZATION_RESOURCE = "AUTHORIZATION_RESOURCE"; - public static String AUTHORIZATION_SCOPE = "AUTHORIZATION_SCOPE"; - public static String AUTHORIZATION_POLICY = "AUTHORIZATION_POLICY"; + /** + * + */ + REALM + + /** + * + */ + , REALM_ROLE + + /** + * + */ + , REALM_ROLE_MAPPING + + /** + * + */ + , REALM_SCOPE_MAPPING + + /** + * + */ + , AUTH_FLOW + + /** + * + */ + , AUTH_EXECUTION_FLOW + + /** + * + */ + , AUTH_EXECUTION + + /** + * + */ + , AUTHENTICATOR_CONFIG + + /** + * + */ + , REQUIRED_ACTION + + /** + * + */ + , IDENTITY_PROVIDER + + /** + * + */ + , IDENTITY_PROVIDER_MAPPER + + /** + * + */ + , PROTOCOL_MAPPER + + /** + * + */ + , USER + + /** + * + */ + , USER_LOGIN_FAILURE + + /** + * + */ + , USER_SESSION + + /** + * + */ + , USER_FEDERATION_PROVIDER + + /** + * + */ + , USER_FEDERATION_MAPPER + + /** + * + */ + , GROUP + + /** + * + */ + , GROUP_MEMBERSHIP + + /** + * + */ + , CLIENT + + /** + * + */ + , CLIENT_INITIAL_ACCESS_MODEL + + /** + * + */ + , CLIENT_ROLE + + /** + * + */ + , CLIENT_ROLE_MAPPING + + /** + * + */ + , CLIENT_SCOPE + + /** + * + */ + , CLIENT_SCOPE_MAPPING + + /** + * + */ + , CLIENT_SCOPE_CLIENT_MAPPING + + /** + * + */ + , CLUSTER_NODE + + /** + * + */ + , COMPONENT + + /** + * + */ + , AUTHORIZATION_RESOURCE_SERVER + + /** + * + */ + , AUTHORIZATION_RESOURCE + + /** + * + */ + , AUTHORIZATION_SCOPE + + /** + * + */ + , AUTHORIZATION_POLICY + + /** + * + */ + , CUSTOM; } diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java index 4dedbfafad..3c83a78159 100755 --- a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java +++ b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java @@ -282,7 +282,9 @@ public class ModelToRepresentation { rep.setAuthDetails(toRepresentation(adminEvent.getAuthDetails())); } rep.setOperationType(adminEvent.getOperationType().toString()); - rep.setResourceType(adminEvent.getResourceType()); + if (adminEvent.getResourceTypeAsString() != null) { + rep.setResourceType(adminEvent.getResourceTypeAsString()); + } rep.setResourcePath(adminEvent.getResourcePath()); rep.setRepresentation(adminEvent.getRepresentation()); rep.setError(adminEvent.getError()); diff --git a/services/src/main/java/org/keycloak/events/log/JBossLoggingEventListenerProvider.java b/services/src/main/java/org/keycloak/events/log/JBossLoggingEventListenerProvider.java index cdd018151e..f76a8726a0 100755 --- a/services/src/main/java/org/keycloak/events/log/JBossLoggingEventListenerProvider.java +++ b/services/src/main/java/org/keycloak/events/log/JBossLoggingEventListenerProvider.java @@ -136,7 +136,7 @@ public class JBossLoggingEventListenerProvider implements EventListenerProvider sb.append(", ipAddress="); sb.append(adminEvent.getAuthDetails().getIpAddress()); sb.append(", resourceType="); - sb.append(adminEvent.getResourceType()); + sb.append(adminEvent.getResourceTypeAsString()); sb.append(", resourcePath="); sb.append(adminEvent.getResourcePath()); diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminEventBuilder.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminEventBuilder.java index 7ef42bd16d..ba0db2b340 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/AdminEventBuilder.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminEventBuilder.java @@ -24,6 +24,7 @@ import org.keycloak.events.EventStoreProvider; import org.keycloak.events.admin.AdminEvent; import org.keycloak.events.admin.AuthDetails; import org.keycloak.events.admin.OperationType; +import org.keycloak.events.admin.ResourceType; import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; @@ -112,11 +113,19 @@ public class AdminEventBuilder { return this; } - public AdminEventBuilder resource(String resourceType){ + public AdminEventBuilder resource(ResourceType resourceType){ adminEvent.setResourceType(resourceType); return this; } + /** + * Setter for custom resource types with values different from {@link ResourceType}. + */ + public AdminEventBuilder resource(String resourceType){ + adminEvent.setResourceTypeAsString(resourceType); + return this; + } + public AdminEventBuilder authRealm(RealmModel realm) { AuthDetails authDetails = adminEvent.getAuthDetails(); if(authDetails == null) { diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java index 4beaa0e60a..77af995175 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java @@ -849,9 +849,15 @@ public class RealmAdminResource { } if (resourceTypes != null && !resourceTypes.isEmpty()) { - query.resourceType(resourceTypes); + ResourceType[] t = new ResourceType[resourceTypes.size()]; + for (int i = 0; i < t.length; i++) { + t[i] = ResourceType.valueOf(resourceTypes.get(i)); + } + query.resourceType(t); } + + if(dateFrom != null) { SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); Date from = null; diff --git a/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java index 6079c21433..87abc2933b 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java @@ -25,6 +25,7 @@ import org.keycloak.common.Profile; import org.keycloak.component.ComponentFactory; import org.keycloak.events.EventType; import org.keycloak.events.admin.OperationType; +import org.keycloak.events.admin.ResourceType; import org.keycloak.models.KeycloakSession; import org.keycloak.models.utils.ModelToRepresentation; import org.keycloak.policy.PasswordPolicyProvider; @@ -74,7 +75,7 @@ import java.util.stream.Stream; */ public class ServerInfoAdminResource { - private static final Map> ENUMS = createEnumsMap(EventType.class, OperationType.class); + private static final Map> ENUMS = createEnumsMap(EventType.class, OperationType.class, ResourceType.class); @Context private KeycloakSession session; diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java index aa3ffb0814..9013ff5c48 100644 --- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java +++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java @@ -559,7 +559,9 @@ public class TestingResourceProvider implements RealmResourceProvider { event.setAuthDetails(repToModel(rep.getAuthDetails())); event.setError(rep.getError()); event.setOperationType(OperationType.valueOf(rep.getOperationType())); - event.setResourceType(rep.getResourceType()); + if (rep.getResourceType() != null) { + event.setResourceTypeAsString(rep.getResourceType()); + } event.setRealmId(rep.getRealmId()); event.setRepresentation(rep.getRepresentation()); event.setResourcePath(rep.getResourcePath()); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/AssertAdminEvents.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/AssertAdminEvents.java index 6e85f477b2..67befd17ae 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/AssertAdminEvents.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/AssertAdminEvents.java @@ -27,6 +27,7 @@ import org.junit.runners.model.Statement; import org.keycloak.common.util.ObjectUtil; import org.keycloak.common.util.reflections.Reflections; import org.keycloak.events.admin.OperationType; +import org.keycloak.events.admin.ResourceType; import org.keycloak.jose.jws.JWSInput; import org.keycloak.jose.jws.JWSInputException; import org.keycloak.representations.AccessToken; @@ -96,19 +97,19 @@ public class AssertAdminEvents implements TestRule { - public AdminEventRepresentation assertEvent(String realmId, OperationType operationType, String resourcePath, String resourceType) { + public AdminEventRepresentation assertEvent(String realmId, OperationType operationType, String resourcePath, ResourceType resourceType) { return assertEvent(realmId, operationType, resourcePath, null, resourceType); } - public AdminEventRepresentation assertEvent(String realmId, OperationType operationType, Matcher resourcePath, String resourceType) { + public AdminEventRepresentation assertEvent(String realmId, OperationType operationType, Matcher resourcePath, ResourceType resourceType) { return assertEvent(realmId, operationType, resourcePath, null, resourceType); } - public AdminEventRepresentation assertEvent(String realmId, OperationType operationType, String resourcePath, Object representation, String resourceType) { + public AdminEventRepresentation assertEvent(String realmId, OperationType operationType, String resourcePath, Object representation, ResourceType resourceType) { return assertEvent(realmId, operationType, Matchers.equalTo(resourcePath), representation, resourceType); } - public AdminEventRepresentation assertEvent(String realmId, OperationType operationType, Matcher resourcePath, Object representation, String resourceType) { + public AdminEventRepresentation assertEvent(String realmId, OperationType operationType, Matcher resourcePath, Object representation, ResourceType resourceType) { return expect().realmId(realmId) .operationType(operationType) .resourcePath(resourcePath) @@ -123,7 +124,7 @@ public class AssertAdminEvents implements TestRule { private AdminEventRepresentation expected = new AdminEventRepresentation(); private Matcher resourcePath; - private String resourceType; + private ResourceType resourceType; private Object expectedRep; public ExpectedAdminEvent realmId(String realmId) { @@ -150,8 +151,8 @@ public class AssertAdminEvents implements TestRule { return this; } - public ExpectedAdminEvent resourceType(String resourceType){ - expected.setResourceType(resourceType); + public ExpectedAdminEvent resourceType(ResourceType resourceType){ + expected.setResourceType(resourceType.toString()); return this; }