keycloak-uncached

KEYCLOAK-3006 Fix admin event inconsistencies related to

5/25/2016 5:39:13 PM

Changes

Details

diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientRoleMappingsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientRoleMappingsResource.java
index ff0745b..a1c0433 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientRoleMappingsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientRoleMappingsResource.java
@@ -43,6 +43,7 @@ import javax.ws.rs.core.UriInfo;
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Properties;
 import java.util.Set;
@@ -196,12 +197,15 @@ public class ClientRoleMappingsResource {
 
         if (roles == null) {
             Set<RoleModel> roleModels = user.getClientRoleMappings(client);
+            roles = new LinkedList<>();
+
             for (RoleModel roleModel : roleModels) {
-                if (!(roleModel.getContainer() instanceof ClientModel)) {
+                if (roleModel.getContainer() instanceof ClientModel) {
                     ClientModel client = (ClientModel) roleModel.getContainer();
                     if (!client.getId().equals(this.client.getId())) continue;
                 }
                 user.deleteRoleMapping(roleModel);
+                roles.add(ModelToRepresentation.toRepresentation(roleModel));
             }
 
         } else {
@@ -220,6 +224,7 @@ public class ClientRoleMappingsResource {
                 }
             }
         }
+
         adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).representation(roles).success();
     }
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java
index 58ccb6a..99ec68a 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java
@@ -226,9 +226,7 @@ public class RoleByIdResource extends RoleResource {
         auth.requireManage();
 
         RoleModel role = getRoleModel(id);
-        deleteComposites(roles, role);
-
-        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).representation(roles).success();
+        deleteComposites(adminEvent, uriInfo, roles, role);
     }
 
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java
index 12dfc54..e116ca3 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java
@@ -115,7 +115,8 @@ public class RoleContainerResource extends RoleResource {
             boolean scopeParamRequired = rep.isScopeParamRequired()==null ? false : rep.isScopeParamRequired();
             role.setScopeParamRequired(scopeParamRequired);
 
-            adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, role.getId()).representation(rep).success();
+            rep.setId(role.getId());
+            adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, role.getName()).representation(rep).success();
 
             return Response.created(uriInfo.getAbsolutePathBuilder().path(role.getName()).build()).build();
         } catch (ModelDuplicateException e) {
@@ -332,8 +333,7 @@ public class RoleContainerResource extends RoleResource {
         if (role == null) {
             throw new NotFoundException("Could not find role");
         }
-        deleteComposites(roles, role);
-        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
+        deleteComposites(adminEvent, uriInfo, roles, role);
     }
 
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleMapperResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleMapperResource.java
index d8fe904..79ae4dc 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/RoleMapperResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleMapperResource.java
@@ -50,6 +50,7 @@ import javax.ws.rs.core.UriInfo;
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
@@ -236,8 +237,9 @@ public class RoleMapperResource {
                 throw new NotFoundException("Role not found");
             }
             roleMapper.grantRole(roleModel);
-            adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, role.getId()).representation(roles).success();
         }
+
+        adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(roles).success();
     }
 
     /**
@@ -258,10 +260,13 @@ public class RoleMapperResource {
         logger.debug("deleteRealmRoleMappings");
         if (roles == null) {
             Set<RoleModel> roleModels = roleMapper.getRealmRoleMappings();
+            roles = new LinkedList<>();
+
             for (RoleModel roleModel : roleModels) {
                 roleMapper.deleteRoleMapping(roleModel);
+                roles.add(ModelToRepresentation.toRepresentation(roleModel));
             }
-            adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(roles).success();
+
         } else {
             for (RoleRepresentation role : roles) {
                 RoleModel roleModel = realm.getRole(role.getName());
@@ -276,11 +281,12 @@ public class RoleMapperResource {
                     throw new ErrorResponseException(me.getMessage(), MessageFormat.format(messages.getProperty(me.getMessage(), me.getMessage()), me.getParameters()),
                             Response.Status.BAD_REQUEST);
                 }
-
-                adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo, role.getId()).representation(roles).success();
             }
+
         }
 
+        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).representation(roles).success();
+
     }
 
     @Path("clients/{client}")
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java
index 34df0c6..f05572e 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java
@@ -65,9 +65,9 @@ public abstract class RoleResource {
                 throw new NotFoundException("Could not find composite role");
             }
             role.addCompositeRole(composite);
-
-            adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, rep.getId()).representation(roles).success();
         }
+
+        adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(roles).success();
     }
 
     protected Set<RoleRepresentation> getRoleComposites(RoleModel role) {
@@ -102,7 +102,7 @@ public abstract class RoleResource {
         return composites;
     }
 
-    protected void deleteComposites(List<RoleRepresentation> roles, RoleModel role) {
+    protected void deleteComposites(AdminEventBuilder adminEvent, UriInfo uriInfo, List<RoleRepresentation> roles, RoleModel role) {
         for (RoleRepresentation rep : roles) {
             RoleModel composite = realm.getRoleById(rep.getId());
             if (composite == null) {
@@ -110,5 +110,7 @@ public abstract class RoleResource {
             }
             role.removeCompositeRole(composite);
         }
+
+        adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).representation(roles).success();
     }
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedClientResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedClientResource.java
index 2ff4d2f..eb685e4 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedClientResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedClientResource.java
@@ -38,6 +38,7 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 
 import java.util.ArrayList;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
 
@@ -151,8 +152,9 @@ public class ScopeMappedClientResource {
                 throw new NotFoundException("Role not found");
             }
             scopeContainer.addScopeMapping(roleModel);
-            adminEvent.operation(OperationType.CREATE).resourcePath(session.getContext().getUri(), roleModel.getId()).representation(roles).success();
         }
+
+        adminEvent.operation(OperationType.CREATE).resourcePath(session.getContext().getUri()).representation(roles).success();
     }
 
     /**
@@ -171,10 +173,13 @@ public class ScopeMappedClientResource {
 
         if (roles == null) {
             Set<RoleModel> roleModels = KeycloakModelUtils.getClientScopeMappings(scopedClient, scopeContainer);//scopedClient.getClientScopeMappings(client);
+            roles = new LinkedList<>();
+
             for (RoleModel roleModel : roleModels) {
                 scopeContainer.deleteScopeMapping(roleModel);
+                roles.add(ModelToRepresentation.toRepresentation(roleModel));
             }
-            adminEvent.operation(OperationType.DELETE).resourcePath(session.getContext().getUri()).representation(roles).success();
+
         } else {
             for (RoleRepresentation role : roles) {
                 RoleModel roleModel = scopedClient.getRole(role.getName());
@@ -182,8 +187,9 @@ public class ScopeMappedClientResource {
                     throw new NotFoundException("Role not found");
                 }
                 scopeContainer.deleteScopeMapping(roleModel);
-                adminEvent.operation(OperationType.DELETE).resourcePath(session.getContext().getUri(), roleModel.getId()).representation(roles).success();
             }
         }
+
+        adminEvent.operation(OperationType.DELETE).resourcePath(session.getContext().getUri()).representation(roles).success();
     }
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java
index 1f2fbe7..bf3cb88 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java
@@ -42,6 +42,7 @@ import javax.ws.rs.core.MediaType;
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -220,8 +221,9 @@ public class ScopeMappedResource {
                 throw new NotFoundException("Role not found");
             }
             scopeContainer.addScopeMapping(roleModel);
-            adminEvent.operation(OperationType.CREATE).resourcePath(session.getContext().getUri(), role.getId()).representation(roles).success();
         }
+
+        adminEvent.operation(OperationType.CREATE).resourcePath(session.getContext().getUri()).representation(roles).success();
     }
 
     /**
@@ -241,10 +243,13 @@ public class ScopeMappedResource {
 
         if (roles == null) {
             Set<RoleModel> roleModels = scopeContainer.getRealmScopeMappings();
+            roles = new LinkedList<>();
+
             for (RoleModel roleModel : roleModels) {
                 scopeContainer.deleteScopeMapping(roleModel);
+                roles.add(ModelToRepresentation.toRepresentation(roleModel));
             }
-            adminEvent.operation(OperationType.DELETE).resourcePath(session.getContext().getUri()).representation(roles).success();
+
        } else {
             for (RoleRepresentation role : roles) {
                 RoleModel roleModel = realm.getRoleById(role.getId());
@@ -252,10 +257,11 @@ public class ScopeMappedResource {
                     throw new NotFoundException("Client not found");
                 }
                 scopeContainer.deleteScopeMapping(roleModel);
-                adminEvent.operation(OperationType.DELETE).resourcePath(session.getContext().getUri(), roleModel.getId()).representation(roles).success();
             }
         }
 
+        adminEvent.operation(OperationType.DELETE).resourcePath(session.getContext().getUri()).representation(roles).success();
+
     }
 
     @Path("clients/{client}")
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientRolesTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientRolesTest.java
index 19c9822..aed3461 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientRolesTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientRolesTest.java
@@ -17,7 +17,6 @@
 
 package org.keycloak.testsuite.admin.client;
 
-import org.hamcrest.Matchers;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -27,7 +26,6 @@ import org.keycloak.events.admin.OperationType;
 import org.keycloak.representations.idm.RoleRepresentation;
 import org.keycloak.testsuite.Assert;
 import org.keycloak.testsuite.util.AdminEventPaths;
-import org.keycloak.testsuite.util.RoleBuilder;
 
 import java.util.LinkedList;
 import java.util.List;
@@ -75,15 +73,17 @@ public class ClientRolesTest extends AbstractClientTest {
 
     @Test
     public void testAddRole() {
-        rolesRsc.create(makeRole("role1"));
-        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, Matchers.startsWith(AdminEventPaths.clientRolesResourcePath(clientDbId)));
+        RoleRepresentation role1 = makeRole("role1");
+        rolesRsc.create(role1);
+        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, AdminEventPaths.clientRoleResourcePath(clientDbId, "role1"), role1);
         assertTrue(hasRole(rolesRsc, "role1"));
     }
 
     @Test
     public void testRemoveRole() {
-        rolesRsc.create(makeRole("role2"));
-        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, Matchers.startsWith(AdminEventPaths.clientRolesResourcePath(clientDbId)));
+        RoleRepresentation role2 = makeRole("role2");
+        rolesRsc.create(role2);
+        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, AdminEventPaths.clientRoleResourcePath(clientDbId, "role2"), role2);
 
         rolesRsc.deleteRole("role2");
         assertAdminEvents.assertEvent(getRealmId(), OperationType.DELETE, AdminEventPaths.clientRoleResourcePath(clientDbId, "role2"));
@@ -93,25 +93,26 @@ public class ClientRolesTest extends AbstractClientTest {
 
     @Test
     public void testComposites() {
-        rolesRsc.create(makeRole("role-a"));
-        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, Matchers.startsWith(AdminEventPaths.clientRolesResourcePath(clientDbId)));
+        RoleRepresentation roleA = makeRole("role-a");
+        rolesRsc.create(roleA);
+        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, AdminEventPaths.clientRoleResourcePath(clientDbId, "role-a"), roleA);
 
         assertFalse(rolesRsc.get("role-a").toRepresentation().isComposite());
         assertEquals(0, rolesRsc.get("role-a").getRoleComposites().size());
 
-        rolesRsc.create(makeRole("role-b"));
-        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, Matchers.startsWith(AdminEventPaths.clientRolesResourcePath(clientDbId)));
+        RoleRepresentation roleB = makeRole("role-b");
+        rolesRsc.create(roleB);
+        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, AdminEventPaths.clientRoleResourcePath(clientDbId, "role-b"), roleB);
 
-        testRealmResource().roles().create(makeRole("role-c"));
-        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, Matchers.startsWith(AdminEventPaths.rolesResourcePath()));
+        RoleRepresentation roleC = makeRole("role-c");
+        testRealmResource().roles().create(roleC);
+        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, AdminEventPaths.roleResourcePath("role-c"), roleC);
 
         List<RoleRepresentation> l = new LinkedList<>();
         l.add(rolesRsc.get("role-b").toRepresentation());
         l.add(testRealmResource().roles().get("role-c").toRepresentation());
         rolesRsc.get("role-a").addComposites(l);
-        // TODO adminEvents: Fix once composite roles events will be fixed...
-        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, Matchers.startsWith(AdminEventPaths.clientRoleResourceCompositesPath(clientDbId, "role-a")));
-        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, Matchers.startsWith(AdminEventPaths.clientRoleResourceCompositesPath(clientDbId, "role-a")));
+        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, AdminEventPaths.clientRoleResourceCompositesPath(clientDbId, "role-a"), l);
 
         Set<RoleRepresentation> composites = rolesRsc.get("role-a").getRoleComposites();
 
@@ -125,7 +126,7 @@ public class ClientRolesTest extends AbstractClientTest {
         Assert.assertNames(clientComposites, "role-b");
 
         rolesRsc.get("role-a").deleteComposites(l);
-        assertAdminEvents.assertEvent(getRealmId(), OperationType.DELETE, AdminEventPaths.clientRoleResourceCompositesPath(clientDbId, "role-a"));
+        assertAdminEvents.assertEvent(getRealmId(), OperationType.DELETE, AdminEventPaths.clientRoleResourceCompositesPath(clientDbId, "role-a"), l);
 
         assertFalse(rolesRsc.get("role-a").toRepresentation().isComposite());
         assertEquals(0, rolesRsc.get("role-a").getRoleComposites().size());
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientTemplateProtocolMapperTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientTemplateProtocolMapperTest.java
index 39fd220..1036005 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientTemplateProtocolMapperTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientTemplateProtocolMapperTest.java
@@ -26,7 +26,6 @@ import org.junit.Before;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
 import org.junit.runners.MethodSorters;
-import org.keycloak.admin.client.resource.ClientTemplateResource;
 import org.keycloak.admin.client.resource.ClientTemplatesResource;
 import org.keycloak.admin.client.resource.ProtocolMappersResource;
 import org.keycloak.events.admin.OperationType;
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientTemplateTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientTemplateTest.java
index 86ab249..2b469a9 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientTemplateTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientTemplateTest.java
@@ -27,7 +27,6 @@ import javax.ws.rs.BadRequestException;
 import javax.ws.rs.NotFoundException;
 import javax.ws.rs.core.Response;
 
-import org.hamcrest.Matchers;
 import org.junit.Assert;
 import org.junit.Test;
 import org.keycloak.admin.client.resource.ClientTemplatesResource;
@@ -162,7 +161,7 @@ public class ClientTemplateTest extends AbstractClientTest {
 
         // Add role2 as composite to role1
         testRealmResource().roles().get("role1").addComposites(Collections.singletonList(roleRep2));
-        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, Matchers.startsWith(AdminEventPaths.roleResourceCompositesPath("role1")));
+        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, AdminEventPaths.roleResourceCompositesPath("role1"), Collections.singletonList(roleRep2));
 
         // create client template
         ClientTemplateRepresentation templateRep = new ClientTemplateRepresentation();
@@ -176,10 +175,10 @@ public class ClientTemplateTest extends AbstractClientTest {
         RoleMappingResource scopesResource = clientTemplates().get(templateId).getScopeMappings();
 
         scopesResource.realmLevel().add(Collections.singletonList(roleRep1));
-        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, AdminEventPaths.clientTemplateScopeMappingsRealmLevelPath(templateId) + "/" + roleRep1.getId());
+        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, AdminEventPaths.clientTemplateScopeMappingsRealmLevelPath(templateId), Collections.singletonList(roleRep1));
 
         scopesResource.clientLevel(accountMgmtId).add(Collections.singletonList(viewAccountRoleRep));
-        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, AdminEventPaths.clientTemplateScopeMappingsClientLevelPath(templateId, accountMgmtId) + "/" + viewAccountRoleRep.getId());
+        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, AdminEventPaths.clientTemplateScopeMappingsClientLevelPath(templateId, accountMgmtId), Collections.singletonList(viewAccountRoleRep));
 
         // test that scopes are available (also through composite role)
         List<RoleRepresentation> allRealm = scopesResource.realmLevel().listAll();
@@ -198,10 +197,10 @@ public class ClientTemplateTest extends AbstractClientTest {
 
         // remove scopes
         scopesResource.realmLevel().remove(Collections.singletonList(roleRep1));
-        assertAdminEvents.assertEvent(getRealmId(), OperationType.DELETE, AdminEventPaths.clientTemplateScopeMappingsRealmLevelPath(templateId) + "/" + roleRep1.getId());
+        assertAdminEvents.assertEvent(getRealmId(), OperationType.DELETE, AdminEventPaths.clientTemplateScopeMappingsRealmLevelPath(templateId), Collections.singletonList(roleRep1));
 
         scopesResource.clientLevel(accountMgmtId).remove(Collections.singletonList(viewAccountRoleRep));
-        assertAdminEvents.assertEvent(getRealmId(), OperationType.DELETE, AdminEventPaths.clientTemplateScopeMappingsClientLevelPath(templateId, accountMgmtId) + "/" + viewAccountRoleRep.getId());
+        assertAdminEvents.assertEvent(getRealmId(), OperationType.DELETE, AdminEventPaths.clientTemplateScopeMappingsClientLevelPath(templateId, accountMgmtId), Collections.singletonList(viewAccountRoleRep));
 
         // assert scopes are removed
         allRealm = scopesResource.realmLevel().listAll();
@@ -256,7 +255,7 @@ public class ClientTemplateTest extends AbstractClientTest {
 
         // Add realm role to scopes of clientTemplate
         clientTemplates().get(templateId).getScopeMappings().realmLevel().add(Collections.singletonList(roleRep));
-        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, AdminEventPaths.clientTemplateScopeMappingsRealmLevelPath(templateId) + "/" + roleRep.getId());
+        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, AdminEventPaths.clientTemplateScopeMappingsRealmLevelPath(templateId), Collections.singletonList(roleRep));
 
         List<RoleRepresentation> roleReps = clientTemplates().get(templateId).getScopeMappings().realmLevel().listAll();
         Assert.assertEquals(1, roleReps.size());
@@ -279,7 +278,7 @@ public class ClientTemplateTest extends AbstractClientTest {
         roleRep.setName(roleName);
         testRealmResource().roles().create(roleRep);
 
-        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, Matchers.startsWith(AdminEventPaths.rolesResourcePath()));
+        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, AdminEventPaths.roleResourcePath(roleName), roleRep);
 
         return testRealmResource().roles().get(roleName).toRepresentation();
     }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ClientTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ClientTest.java
index d9d60e5..fc7a341 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ClientTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ClientTest.java
@@ -17,7 +17,6 @@
 
 package org.keycloak.testsuite.admin;
 
-import org.hamcrest.Matchers;
 import org.junit.Test;
 import org.keycloak.OAuth2Constants;
 import org.keycloak.admin.client.resource.ClientResource;
@@ -43,10 +42,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import org.keycloak.services.resources.admin.ScopeMappedResource;
 import org.keycloak.testsuite.Assert;
 import org.keycloak.testsuite.util.AdminEventPaths;
-import org.keycloak.testsuite.util.AssertAdminEvents;
 import org.keycloak.testsuite.util.ClientBuilder;
 import org.keycloak.testsuite.util.CredentialBuilder;
 import org.keycloak.testsuite.util.OAuthClient;
@@ -154,7 +151,7 @@ public class ClientTest extends AbstractAdminTest {
         RoleRepresentation role = new RoleRepresentation("test", "test", false);
         realm.clients().get(id).roles().create(role);
 
-        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, Matchers.startsWith(AdminEventPaths.clientRolesResourcePath(id)), role);
+        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientRoleResourcePath(id, "test"), role);
 
         ClientRepresentation foundClientRep = realm.clients().get(id).toRepresentation();
         foundClientRep.setDefaultRoles(new String[]{"test"});
@@ -327,28 +324,24 @@ public class ClientTest extends AbstractAdminTest {
         realm.roles().create(roleRep1);
         realm.roles().create(roleRep2);
 
-        AssertAdminEvents.ExpectedAdminEvent adminEvent = assertAdminEvents.expect()
-                .realmId(realmId)
-                .operationType(OperationType.CREATE)
-                .resourcePath(Matchers.startsWith(AdminEventPaths.rolesResourcePath()));
-        adminEvent.representation(roleRep1).assertEvent();
-        adminEvent.representation(roleRep2).assertEvent();
+        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.roleResourcePath("role1"), roleRep1);
+        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.roleResourcePath("role2"), roleRep2);
 
         roleRep1 = realm.roles().get("role1").toRepresentation();
         roleRep2 = realm.roles().get("role2").toRepresentation();
 
         realm.roles().get("role1").addComposites(Collections.singletonList(roleRep2));
 
-        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, Matchers.startsWith(AdminEventPaths.roleResourceCompositesPath("role1")));
+        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.roleResourceCompositesPath("role1"), Collections.singletonList(roleRep2));
 
         String accountMgmtId = realm.clients().findByClientId(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID).get(0).getId();
         RoleRepresentation viewAccountRoleRep = realm.clients().get(accountMgmtId).roles().get(AccountRoles.VIEW_PROFILE).toRepresentation();
 
         scopesResource.realmLevel().add(Collections.singletonList(roleRep1));
-        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientScopeMappingsRealmLevelPath(id) + "/" + roleRep1.getId());
+        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientScopeMappingsRealmLevelPath(id), Collections.singletonList(roleRep1));
 
         scopesResource.clientLevel(accountMgmtId).add(Collections.singletonList(viewAccountRoleRep));
-        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientScopeMappingsClientLevelPath(id, accountMgmtId) + "/" + viewAccountRoleRep.getId());
+        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientScopeMappingsClientLevelPath(id, accountMgmtId), Collections.singletonList(viewAccountRoleRep));
 
         Assert.assertNames(scopesResource.realmLevel().listAll(), "role1");
         Assert.assertNames(scopesResource.realmLevel().listEffective(), "role1", "role2");
@@ -362,10 +355,10 @@ public class ClientTest extends AbstractAdminTest {
         Assert.assertNames(scopesResource.getAll().getClientMappings().get(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID).getMappings(), AccountRoles.VIEW_PROFILE);
 
         scopesResource.realmLevel().remove(Collections.singletonList(roleRep1));
-        assertAdminEvents.assertEvent(realmId, OperationType.DELETE, AdminEventPaths.clientScopeMappingsRealmLevelPath(id) + "/" + roleRep1.getId());
+        assertAdminEvents.assertEvent(realmId, OperationType.DELETE, AdminEventPaths.clientScopeMappingsRealmLevelPath(id), Collections.singletonList(roleRep1));
 
         scopesResource.clientLevel(accountMgmtId).remove(Collections.singletonList(viewAccountRoleRep));
-        assertAdminEvents.assertEvent(realmId, OperationType.DELETE, AdminEventPaths.clientScopeMappingsClientLevelPath(id, accountMgmtId) + "/" + viewAccountRoleRep.getId());
+        assertAdminEvents.assertEvent(realmId, OperationType.DELETE, AdminEventPaths.clientScopeMappingsClientLevelPath(id, accountMgmtId), Collections.singletonList(viewAccountRoleRep));
 
         Assert.assertNames(scopesResource.realmLevel().listAll());
         Assert.assertNames(scopesResource.realmLevel().listEffective());
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupTest.java
index 174688a..dcc70b1 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupTest.java
@@ -23,6 +23,7 @@ import org.junit.Test;
 import org.keycloak.admin.client.resource.RealmResource;
 import org.keycloak.admin.client.resource.RoleMappingResource;
 import org.keycloak.events.admin.OperationType;
+import org.keycloak.models.RoleModel;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.idm.CredentialRepresentation;
@@ -109,7 +110,7 @@ public class GroupTest extends AbstractGroupTest {
         RoleRepresentation role = new RoleRepresentation();
         role.setName("foo-role");
         realm.clients().get(client.getId()).roles().create(role);
-        assertAdminEvents.assertEvent("test", OperationType.CREATE, Matchers.startsWith(AdminEventPaths.clientRolesResourcePath(clientUuid)), role);
+        assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.clientRoleResourcePath(clientUuid, "foo-role"), role);
         role = realm.clients().get(client.getId()).roles().get("foo-role").toRepresentation();
 
         GroupRepresentation group = new GroupRepresentation();
@@ -119,7 +120,7 @@ public class GroupTest extends AbstractGroupTest {
         List<RoleRepresentation> list = new LinkedList<>();
         list.add(role);
         realm.groups().group(group.getId()).roles().clientLevel(client.getId()).add(list);
-        assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.groupRolesClientRolesPath(group.getId(), clientUuid));
+        assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.groupRolesClientRolesPath(group.getId(), clientUuid), list);
 
         realm.clients().get(client.getId()).remove();
         assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.clientResourcePath(clientUuid));
@@ -170,7 +171,7 @@ public class GroupTest extends AbstractGroupTest {
         List<RoleRepresentation> roles = new LinkedList<>();
         roles.add(topRole);
         realm.groups().group(topGroup.getId()).roles().realmLevel().add(roles);
-        assertAdminEvents.assertEvent("test", OperationType.CREATE, Matchers.startsWith(AdminEventPaths.groupRolesRealmRolesPath(topGroup.getId())));
+        assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.groupRolesRealmRolesPath(topGroup.getId()), roles);
 
         GroupRepresentation level2Group = new GroupRepresentation();
         level2Group.setName("level2");
@@ -197,7 +198,7 @@ public class GroupTest extends AbstractGroupTest {
         roles.clear();
         roles.add(level2Role);
         realm.groups().group(level2Group.getId()).roles().realmLevel().add(roles);
-        assertAdminEvents.assertEvent("test", OperationType.CREATE, Matchers.startsWith(AdminEventPaths.groupRolesRealmRolesPath(level2Group.getId())));
+        assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.groupRolesRealmRolesPath(level2Group.getId()), roles);
 
         GroupRepresentation level3Group = new GroupRepresentation();
         level3Group.setName("level3");
@@ -210,7 +211,7 @@ public class GroupTest extends AbstractGroupTest {
         roles.clear();
         roles.add(level3Role);
         realm.groups().group(level3Group.getId()).roles().realmLevel().add(roles);
-        assertAdminEvents.assertEvent("test", OperationType.CREATE, Matchers.startsWith(AdminEventPaths.groupRolesRealmRolesPath(level3Group.getId())));
+        assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.groupRolesRealmRolesPath(level3Group.getId()), roles);
 
         topGroup = realm.getGroupByPath("/top");
         assertEquals(1, topGroup.getRealmRoles().size());
@@ -418,14 +419,15 @@ public class GroupTest extends AbstractGroupTest {
         l.add(realm.roles().get("realm-role").toRepresentation());
         l.add(realm.roles().get("realm-composite").toRepresentation());
         roles.realmLevel().add(l);
-        assertAdminEvents.assertEvent("test", OperationType.CREATE, Matchers.startsWith(AdminEventPaths.groupRolesRealmRolesPath(group.getId())));
-        assertAdminEvents.assertEvent("test", OperationType.CREATE, Matchers.startsWith(AdminEventPaths.groupRolesRealmRolesPath(group.getId())));
+        assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.groupRolesRealmRolesPath(group.getId()), l);
 
         // Add client roles
-        roles.clientLevel(clientId).add(Collections.singletonList(realm.clients().get(clientId).roles().get("client-role").toRepresentation()));
-        roles.clientLevel(clientId).add(Collections.singletonList(realm.clients().get(clientId).roles().get("client-composite").toRepresentation()));
-        assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.groupRolesClientRolesPath(group.getId(), clientId));
-        assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.groupRolesClientRolesPath(group.getId(), clientId));
+        RoleRepresentation clientRole = realm.clients().get(clientId).roles().get("client-role").toRepresentation();
+        RoleRepresentation clientComposite = realm.clients().get(clientId).roles().get("client-composite").toRepresentation();
+        roles.clientLevel(clientId).add(Collections.singletonList(clientRole));
+        roles.clientLevel(clientId).add(Collections.singletonList(clientComposite));
+        assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.groupRolesClientRolesPath(group.getId(), clientId), Collections.singletonList(clientRole));
+        assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.groupRolesClientRolesPath(group.getId(), clientId), Collections.singletonList(clientComposite));
 
         // List realm roles
         assertNames(roles.realmLevel().listAll(), "realm-role", "realm-composite");
@@ -444,16 +446,15 @@ public class GroupTest extends AbstractGroupTest {
         assertNames(all.getClientMappings().get("myclient").getMappings(), "client-role", "client-composite");
 
         // Remove realm role
-        // TODO adminEvents: DEleting group realmRole mapping has ID in the end. For deleting clientRole not.
         RoleRepresentation realmRoleRep = realm.roles().get("realm-role").toRepresentation();
         roles.realmLevel().remove(Collections.singletonList(realmRoleRep));
-        assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.groupRolesRealmRolesPath(group.getId()) + "/" + realmRoleRep.getId());
+        assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.groupRolesRealmRolesPath(group.getId()), Collections.singletonList(realmRoleRep));
         assertNames(roles.realmLevel().listAll(), "realm-composite");
 
         // Remove client role
         RoleRepresentation clientRoleRep = realm.clients().get(clientId).roles().get("client-role").toRepresentation();
         roles.clientLevel(clientId).remove(Collections.singletonList(clientRoleRep));
-        assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.groupRolesClientRolesPath(group.getId(), clientId));
+        assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.groupRolesClientRolesPath(group.getId(), clientId), Collections.singletonList(clientRoleRep));
         assertNames(roles.clientLevel(clientId).listAll(), "client-composite");
     }
 
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmRolesTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmRolesTest.java
index ad54e4f..04221c0 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmRolesTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmRolesTest.java
@@ -17,10 +17,8 @@
 
 package org.keycloak.testsuite.admin.realm;
 
-import org.hamcrest.Matchers;
 import org.junit.Before;
 import org.junit.Test;
-import org.keycloak.admin.client.resource.RoleByIdResource;
 import org.keycloak.admin.client.resource.RolesResource;
 import org.keycloak.events.admin.OperationType;
 import org.keycloak.representations.idm.ClientRepresentation;
@@ -80,12 +78,11 @@ public class RealmRolesTest extends AbstractAdminTest {
 
         resource = adminClient.realm(REALM_NAME).roles();
 
-        // ResourcePath for event for creating role contains roleID instead of roleName (looks like a bug...)
-        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.roleResourcePath(ids.get("role-a")), roleA);
-        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.roleResourcePath(ids.get("role-b")), roleB);
+        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.roleResourcePath("role-a"), roleA);
+        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.roleResourcePath("role-b"), roleB);
 
         assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientResourcePath(clientUuid), clientRep);
-        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientRoleResourcePath(clientUuid, ids.get("role-c")), roleC);
+        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientRoleResourcePath(clientUuid, "role-c"), roleC);
     }
 
     @Test
@@ -138,9 +135,8 @@ public class RealmRolesTest extends AbstractAdminTest {
         l.add(RoleBuilder.create().id(ids.get("role-b")).build());
         l.add(RoleBuilder.create().id(ids.get("role-c")).build());
         resource.get("role-a").addComposites(l);
-        // TODO adminEvents: Fix once composite roles events will be fixed...
-        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, Matchers.startsWith(AdminEventPaths.roleResourceCompositesPath("role-a")));
-        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, Matchers.startsWith(AdminEventPaths.roleResourceCompositesPath("role-a")));
+
+        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.roleResourceCompositesPath("role-a"), l);
 
         Set<RoleRepresentation> composites = resource.get("role-a").getRoleComposites();
 
@@ -154,7 +150,7 @@ public class RealmRolesTest extends AbstractAdminTest {
         Assert.assertNames(clientComposites, "role-c");
 
         resource.get("role-a").deleteComposites(l);
-        assertAdminEvents.assertEvent(realmId, OperationType.DELETE, AdminEventPaths.roleResourceCompositesPath("role-a"));
+        assertAdminEvents.assertEvent(realmId, OperationType.DELETE, AdminEventPaths.roleResourceCompositesPath("role-a"), l);
 
         assertFalse(resource.get("role-a").toRepresentation().isComposite());
         assertEquals(0, resource.get("role-a").getRoleComposites().size());
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmTest.java
index bad49c2..2ba3c5c 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmTest.java
@@ -282,7 +282,7 @@ public class RealmTest extends AbstractAdminTest {
     public void deleteDefaultRole() {
         RoleRepresentation role = new RoleRepresentation("test", "test", false);
         realm.roles().create(role);
-        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, Matchers.startsWith(AdminEventPaths.rolesResourcePath()));
+        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.roleResourcePath("test"), role);
 
         assertNotNull(realm.roles().get("test").toRepresentation());
 
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/RoleByIdResourceTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/RoleByIdResourceTest.java
index e26bcbc..6db07e1 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/RoleByIdResourceTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/RoleByIdResourceTest.java
@@ -17,7 +17,6 @@
 
 package org.keycloak.testsuite.admin;
 
-import org.hamcrest.Matchers;
 import org.junit.Before;
 import org.junit.Test;
 import org.keycloak.admin.client.resource.RoleByIdResource;
@@ -120,9 +119,7 @@ public class RoleByIdResourceTest extends AbstractAdminTest {
         l.add(RoleBuilder.create().id(ids.get("role-c")).build());
         resource.addComposites(ids.get("role-a"), l);
 
-        // TODO adminEvents: Fix once composite roles events will be fixed...
-        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, Matchers.startsWith(AdminEventPaths.roleByIdResourceCompositesPath(ids.get("role-a"))));
-        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, Matchers.startsWith(AdminEventPaths.roleByIdResourceCompositesPath(ids.get("role-a"))));
+        assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.roleByIdResourceCompositesPath(ids.get("role-a")), l);
 
         Set<RoleRepresentation> composites = resource.getRoleComposites(ids.get("role-a"));
 
@@ -136,7 +133,7 @@ public class RoleByIdResourceTest extends AbstractAdminTest {
         Assert.assertNames(clientComposites, "role-c");
 
         resource.deleteComposites(ids.get("role-a"), l);
-        assertAdminEvents.assertEvent(realmId, OperationType.DELETE, AdminEventPaths.roleByIdResourceCompositesPath(ids.get("role-a")));
+        assertAdminEvents.assertEvent(realmId, OperationType.DELETE, AdminEventPaths.roleByIdResourceCompositesPath(ids.get("role-a")), l);
 
         assertFalse(resource.getRole(ids.get("role-a")).isComposite());
         assertEquals(0, resource.getRoleComposites(ids.get("role-a")).size());
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserTest.java
index aa0af1d..19645a8 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserTest.java
@@ -796,14 +796,16 @@ public class UserTest extends AbstractAdminTest {
         l.add(realm.roles().get("realm-role").toRepresentation());
         l.add(realm.roles().get("realm-composite").toRepresentation());
         roles.realmLevel().add(l);
-        assertAdminEvents.assertEvent("test", OperationType.CREATE, Matchers.startsWith(AdminEventPaths.userRealmRoleMappingsPath(userId)));
-        assertAdminEvents.assertEvent("test", OperationType.CREATE, Matchers.startsWith(AdminEventPaths.userRealmRoleMappingsPath(userId)));
+        assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.userRealmRoleMappingsPath(userId), l);
 
         // Add client roles
-        roles.clientLevel(clientUuid).add(Collections.singletonList(realm.clients().get(clientUuid).roles().get("client-role").toRepresentation()));
-        roles.clientLevel(clientUuid).add(Collections.singletonList(realm.clients().get(clientUuid).roles().get("client-composite").toRepresentation()));
-        assertAdminEvents.assertEvent("test", OperationType.CREATE, Matchers.startsWith(AdminEventPaths.userClientRoleMappingsPath(userId, clientUuid)));
-        assertAdminEvents.assertEvent("test", OperationType.CREATE, Matchers.startsWith(AdminEventPaths.userClientRoleMappingsPath(userId, clientUuid)));
+        List<RoleRepresentation> list = Collections.singletonList(realm.clients().get(clientUuid).roles().get("client-role").toRepresentation());
+        roles.clientLevel(clientUuid).add(list);
+        assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.userClientRoleMappingsPath(userId, clientUuid), list);
+
+        list = Collections.singletonList(realm.clients().get(clientUuid).roles().get("client-composite").toRepresentation());
+        roles.clientLevel(clientUuid).add(list);
+        assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.userClientRoleMappingsPath(userId, clientUuid), list);
 
         // List realm roles
         assertNames(roles.realmLevel().listAll(), "realm-role", "realm-composite", "user", "offline_access");
@@ -825,16 +827,14 @@ public class UserTest extends AbstractAdminTest {
         // Remove realm role
         RoleRepresentation realmRoleRep = realm.roles().get("realm-role").toRepresentation();
         roles.realmLevel().remove(Collections.singletonList(realmRoleRep));
-        assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.userRealmRoleMappingsPath(userId) + "/" + realmRoleRep.getId());
+        assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.userRealmRoleMappingsPath(userId), Collections.singletonList(realmRoleRep));
 
         assertNames(roles.realmLevel().listAll(), "realm-composite", "user", "offline_access");
 
         // Remove client role
         RoleRepresentation clientRoleRep = realm.clients().get(clientUuid).roles().get("client-role").toRepresentation();
         roles.clientLevel(clientUuid).remove(Collections.singletonList(clientRoleRep));
-
-        // TODO: Inconsistency between event for delete realm role mapping and client role mapping (the latter doesn't have roleRep.getId() in the path)
-        assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.userClientRoleMappingsPath(userId, clientUuid));
+        assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.userClientRoleMappingsPath(userId, clientUuid), Collections.singletonList(clientRoleRep));
 
         assertNames(roles.clientLevel(clientUuid).listAll(), "client-composite");
     }
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 398dc81..58f8e9a 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
@@ -17,12 +17,18 @@
 
 package org.keycloak.testsuite.util;
 
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import javax.ws.rs.core.Response;
 
+import com.fasterxml.jackson.core.type.TypeReference;
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
 import org.hamcrest.Matchers;
@@ -37,7 +43,9 @@ import org.keycloak.jose.jws.JWSInputException;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.representations.idm.AdminEventRepresentation;
 import org.keycloak.representations.idm.AuthDetailsRepresentation;
+import org.keycloak.representations.idm.ProtocolMapperRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
 import org.keycloak.testsuite.AbstractKeycloakTest;
 import org.keycloak.testsuite.Assert;
 import org.keycloak.util.JsonSerialization;
@@ -200,16 +208,34 @@ public class AssertAdminEvents implements TestRule {
                 Assert.assertEquals(expectedAuth.getClientId(), actualAuth.getClientId());
             }
 
-            // Representation - compare the non-null fields of "expected" representation with the actual representation
+            // Representation comparison
             if (expectedRep != null) {
                 if (actual.getRepresentation() == null) {
                     Assert.fail("Expected representation " + expectedRep + " but no representation was available on actual event");
                 } else {
                     try {
-                        Object actualRep = JsonSerialization.readValue(actual.getRepresentation(), expectedRep.getClass());
 
-                        if (expectedRep instanceof Map) {
-                            // Special comparing of representations of type map. All of "expected" must be available on "actual"
+                        if (expectedRep instanceof List) {
+                            // List of roles. All must be available in actual representation
+                            List<RoleRepresentation> expectedRoles = (List<RoleRepresentation>) expectedRep;
+                            List<RoleRepresentation> actualRoles = JsonSerialization.readValue(new ByteArrayInputStream(actual.getRepresentation().getBytes()), new TypeReference<List<RoleRepresentation>>() {
+                            });
+
+                            Map<String, String> expectedRolesMap = new HashMap<>();
+                            for (RoleRepresentation role : expectedRoles) {
+                                expectedRolesMap.put(role.getId(), role.getName());
+                            }
+
+                            Map<String, String> actualRolesMap = new HashMap<>();
+                            for (RoleRepresentation role : actualRoles) {
+                                actualRolesMap.put(role.getId(), role.getName());
+                            }
+                            Assert.assertEquals(expectedRolesMap, actualRolesMap);
+
+                        } else if (expectedRep instanceof Map) {
+                            Object actualRep = JsonSerialization.readValue(actual.getRepresentation(), Map.class);
+
+                            // Comparing of map representations. All of "expected" key-values must be available on "actual" map from the event
                             Map<?, ?> expectedRepMap = (Map) expectedRep;
                             Map<?, ?> actualRepMap = (Map) actualRep;
 
@@ -221,7 +247,9 @@ public class AssertAdminEvents implements TestRule {
                                 }
                             }
                         } else {
-                            // Reflection-baseed comparing for other types
+                            Object actualRep = JsonSerialization.readValue(actual.getRepresentation(), expectedRep.getClass());
+
+                            // Reflection-based comparing for other types - compare the non-null fields of "expected" representation with the "actual" representation from the event
                             for (Method method : Reflections.getAllDeclaredMethods(expectedRep.getClass())) {
                                 if (method.getName().startsWith("get") || method.getName().startsWith("is")) {
                                     Object expectedValue = Reflections.invokeMethod(method, expectedRep);