Merge pull request #2889 from mposolda/master

Admin events fixes and more tests
This commit is contained in:
Stian Thorgersen 2016-05-26 08:29:51 +02:00
commit c206ae13db
42 changed files with 516 additions and 211 deletions

View file

@ -25,9 +25,18 @@ package org.keycloak.representations.idm;
*/ */
public class RequiredActionProviderSimpleRepresentation { public class RequiredActionProviderSimpleRepresentation {
private String id;
private String name; private String name;
private String providerId; private String providerId;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() { public String getName() {
return name; return name;
} }

View file

@ -115,7 +115,7 @@ public class AttackDetectionResource {
UsernameLoginFailureModel model = session.sessions().getUserLoginFailure(realm, username.toLowerCase()); UsernameLoginFailureModel model = session.sessions().getUserLoginFailure(realm, username.toLowerCase());
if (model != null) { if (model != null) {
session.sessions().removeUserLoginFailure(realm, username); session.sessions().removeUserLoginFailure(realm, username);
adminEvent.operation(OperationType.DELETE).success(); adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
} }
} }
@ -131,7 +131,7 @@ public class AttackDetectionResource {
auth.requireManage(); auth.requireManage();
session.sessions().removeAllUserLoginFailures(realm); session.sessions().removeAllUserLoginFailures(realm);
adminEvent.operation(OperationType.DELETE).success(); adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
} }

View file

@ -28,6 +28,7 @@ import org.keycloak.authentication.FormAction;
import org.keycloak.authentication.FormAuthenticator; import org.keycloak.authentication.FormAuthenticator;
import org.keycloak.authentication.RequiredActionFactory; import org.keycloak.authentication.RequiredActionFactory;
import org.keycloak.authentication.RequiredActionProvider; import org.keycloak.authentication.RequiredActionProvider;
import org.keycloak.events.admin.OperationType;
import org.keycloak.models.AuthenticationExecutionModel; import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.AuthenticationFlowModel; import org.keycloak.models.AuthenticationFlowModel;
import org.keycloak.models.AuthenticatorConfigModel; import org.keycloak.models.AuthenticatorConfigModel;
@ -212,7 +213,10 @@ public class AuthenticationManagementResource {
return ErrorResponse.exists("Flow " + flow.getAlias() + " already exists"); return ErrorResponse.exists("Flow " + flow.getAlias() + " already exists");
} }
realm.addAuthenticationFlow(RepresentationToModel.toModel(flow)); AuthenticationFlowModel createdModel = realm.addAuthenticationFlow(RepresentationToModel.toModel(flow));
flow.setId(createdModel.getId());
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, createdModel.getId()).representation(flow).success();
return Response.status(201).build(); return Response.status(201).build();
} }
@ -263,6 +267,9 @@ public class AuthenticationManagementResource {
realm.removeAuthenticatorExecution(execution); realm.removeAuthenticatorExecution(execution);
} }
realm.removeAuthenticationFlow(flow); realm.removeAuthenticationFlow(flow);
// Use just one event for top-level flow. Using separate events won't work properly for flows of depth 2 or bigger
adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
} }
/** /**
@ -299,6 +306,9 @@ public class AuthenticationManagementResource {
copy = realm.addAuthenticationFlow(copy); copy = realm.addAuthenticationFlow(copy);
copy(newName, flow, copy); copy(newName, flow, copy);
data.put("id", copy.getId());
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(data).success();
return Response.status(201).build(); return Response.status(201).build();
} }
@ -362,8 +372,10 @@ public class AuthenticationManagementResource {
execution.setAuthenticatorFlow(true); execution.setAuthenticatorFlow(true);
execution.setAuthenticator(provider); execution.setAuthenticator(provider);
execution.setPriority(getNextPriority(parentFlow)); execution.setPriority(getNextPriority(parentFlow));
execution = realm.addAuthenticatorExecution(execution);
realm.addAuthenticatorExecution(execution); data.put("id", execution.getId());
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(data).success();
} }
private int getNextPriority(AuthenticationFlowModel parentFlow) { private int getNextPriority(AuthenticationFlowModel parentFlow) {
@ -413,7 +425,10 @@ public class AuthenticationManagementResource {
execution.setAuthenticator(provider); execution.setAuthenticator(provider);
execution.setPriority(getNextPriority(parentFlow)); execution.setPriority(getNextPriority(parentFlow));
realm.addAuthenticatorExecution(execution); execution = realm.addAuthenticatorExecution(execution);
data.put("id", execution.getId());
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(data).success();
} }
/** /**
@ -519,6 +534,7 @@ public class AuthenticationManagementResource {
if (!model.getRequirement().name().equals(rep.getRequirement())) { if (!model.getRequirement().name().equals(rep.getRequirement())) {
model.setRequirement(AuthenticationExecutionModel.Requirement.valueOf(rep.getRequirement())); model.setRequirement(AuthenticationExecutionModel.Requirement.valueOf(rep.getRequirement()));
realm.updateAuthenticatorExecution(model); realm.updateAuthenticatorExecution(model);
adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
} }
} }
@ -541,6 +557,8 @@ public class AuthenticationManagementResource {
} }
model.setPriority(getNextPriority(parentFlow)); model.setPriority(getNextPriority(parentFlow));
model = realm.addAuthenticatorExecution(model); model = realm.addAuthenticatorExecution(model);
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, model.getId()).representation(execution).success();
return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build(); return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build();
} }
@ -592,6 +610,8 @@ public class AuthenticationManagementResource {
realm.updateAuthenticatorExecution(previous); realm.updateAuthenticatorExecution(previous);
model.setPriority(tmp); model.setPriority(tmp);
realm.updateAuthenticatorExecution(model); realm.updateAuthenticatorExecution(model);
adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).success();
} }
public List<AuthenticationExecutionModel> getSortedExecutions(AuthenticationFlowModel parentFlow) { public List<AuthenticationExecutionModel> getSortedExecutions(AuthenticationFlowModel parentFlow) {
@ -635,6 +655,8 @@ public class AuthenticationManagementResource {
realm.updateAuthenticatorExecution(model); realm.updateAuthenticatorExecution(model);
next.setPriority(tmp); next.setPriority(tmp);
realm.updateAuthenticatorExecution(next); realm.updateAuthenticatorExecution(next);
adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).success();
} }
@ -666,6 +688,8 @@ public class AuthenticationManagementResource {
} }
realm.removeAuthenticatorExecution(model); realm.removeAuthenticatorExecution(model);
adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
} }
@ -693,6 +717,9 @@ public class AuthenticationManagementResource {
config = realm.addAuthenticatorConfig(config); config = realm.addAuthenticatorConfig(config);
model.setAuthenticatorConfig(config.getId()); model.setAuthenticatorConfig(config.getId());
realm.updateAuthenticatorExecution(model); realm.updateAuthenticatorExecution(model);
json.setId(config.getId());
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(json).success();
return Response.created(uriInfo.getAbsolutePathBuilder().path(config.getId()).build()).build(); return Response.created(uriInfo.getAbsolutePathBuilder().path(config.getId()).build()).build();
} }
@ -772,7 +799,10 @@ public class AuthenticationManagementResource {
requiredAction.setProviderId(providerId); requiredAction.setProviderId(providerId);
requiredAction.setDefaultAction(false); requiredAction.setDefaultAction(false);
requiredAction.setEnabled(true); requiredAction.setEnabled(true);
realm.addRequiredActionProvider(requiredAction); requiredAction = realm.addRequiredActionProvider(requiredAction);
data.put("id", requiredAction.getId());
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(data).success();
} }
@ -850,6 +880,8 @@ public class AuthenticationManagementResource {
update.setEnabled(rep.isEnabled()); update.setEnabled(rep.isEnabled());
update.setConfig(rep.getConfig()); update.setConfig(rep.getConfig());
realm.updateRequiredActionProvider(update); realm.updateRequiredActionProvider(update);
adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
} }
/** /**
@ -866,6 +898,8 @@ public class AuthenticationManagementResource {
throw new NotFoundException("Failed to find required action."); throw new NotFoundException("Failed to find required action.");
} }
realm.removeRequiredActionProvider(model); realm.removeRequiredActionProvider(model);
adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
} }
/** /**
@ -947,6 +981,7 @@ public class AuthenticationManagementResource {
auth.requireManage(); auth.requireManage();
AuthenticatorConfigModel config = realm.addAuthenticatorConfig(RepresentationToModel.toModel(rep)); AuthenticatorConfigModel config = realm.addAuthenticatorConfig(RepresentationToModel.toModel(rep));
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, config.getId()).representation(rep).success();
return Response.created(uriInfo.getAbsolutePathBuilder().path(config.getId()).build()).build(); return Response.created(uriInfo.getAbsolutePathBuilder().path(config.getId()).build()).build();
} }
@ -995,6 +1030,8 @@ public class AuthenticationManagementResource {
} }
realm.removeAuthenticatorConfig(config); realm.removeAuthenticatorConfig(config);
adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
} }
/** /**
@ -1017,5 +1054,6 @@ public class AuthenticationManagementResource {
exists.setAlias(rep.getAlias()); exists.setAlias(rep.getAlias());
exists.setConfig(rep.getConfig()); exists.setConfig(rep.getConfig());
realm.updateAuthenticatorConfig(exists); realm.updateAuthenticatorConfig(exists);
adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
} }
} }

View file

@ -108,6 +108,7 @@ public class ClientInitialAccessResource {
auth.requireManage(); auth.requireManage();
session.sessions().removeClientInitialAccessModel(realm, id); session.sessions().removeClientInitialAccessModel(realm, id);
adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
} }
private ClientInitialAccessPresentation wrap(ClientInitialAccessModel model) { private ClientInitialAccessPresentation wrap(ClientInitialAccessModel model) {

View file

@ -485,7 +485,7 @@ public class ClientResource {
} }
if (logger.isDebugEnabled()) logger.debug("Register node: " + node); if (logger.isDebugEnabled()) logger.debug("Register node: " + node);
client.registerNode(node, Time.currentTime()); client.registerNode(node, Time.currentTime());
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success(); adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, node).success();
} }
/** /**
@ -532,9 +532,9 @@ public class ClientResource {
} }
logger.debug("Test availability of cluster nodes"); logger.debug("Test availability of cluster nodes");
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success(); GlobalRequestResult result = new ResourceAdminManager(session).testNodesAvailability(uriInfo.getRequestUri(), realm, client);
return new ResourceAdminManager(session).testNodesAvailability(uriInfo.getRequestUri(), realm, client); adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).representation(result).success();
return result;
} }
} }

View file

@ -43,6 +43,7 @@ import javax.ws.rs.core.UriInfo;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
@ -196,12 +197,15 @@ public class ClientRoleMappingsResource {
if (roles == null) { if (roles == null) {
Set<RoleModel> roleModels = user.getClientRoleMappings(client); Set<RoleModel> roleModels = user.getClientRoleMappings(client);
roles = new LinkedList<>();
for (RoleModel roleModel : roleModels) { for (RoleModel roleModel : roleModels) {
if (!(roleModel.getContainer() instanceof ClientModel)) { if (roleModel.getContainer() instanceof ClientModel) {
ClientModel client = (ClientModel) roleModel.getContainer(); ClientModel client = (ClientModel) roleModel.getContainer();
if (!client.getId().equals(this.client.getId())) continue; if (!client.getId().equals(this.client.getId())) continue;
} }
user.deleteRoleMapping(roleModel); user.deleteRoleMapping(roleModel);
roles.add(ModelToRepresentation.toRepresentation(roleModel));
} }
} else { } else {
@ -220,6 +224,7 @@ public class ClientRoleMappingsResource {
} }
} }
} }
adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).representation(roles).success(); adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).representation(roles).success();
} }
} }

View file

@ -144,7 +144,7 @@ public class GroupResource {
if (child == null) { if (child == null) {
throw new NotFoundException("Could not find child by id"); throw new NotFoundException("Could not find child by id");
} }
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(rep).success(); adminEvent.operation(OperationType.UPDATE);
} else { } else {
child = realm.createGroup(rep.getName()); child = realm.createGroup(rep.getName());
updateGroup(rep, child); updateGroup(rep, child);
@ -152,10 +152,13 @@ public class GroupResource {
.path(uriInfo.getMatchedURIs().get(2)) .path(uriInfo.getMatchedURIs().get(2))
.path(child.getId()).build(); .path(child.getId()).build();
builder.status(201).location(uri); builder.status(201).location(uri);
adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success(); rep.setId(child.getId());
adminEvent.operation(OperationType.CREATE);
} }
realm.moveGroup(child, group); realm.moveGroup(child, group);
adminEvent.resourcePath(uriInfo).representation(rep).success();
GroupRepresentation childRep = ModelToRepresentation.toGroupHierarchy(child, true); GroupRepresentation childRep = ModelToRepresentation.toGroupHierarchy(child, true);
return builder.type(MediaType.APPLICATION_JSON_TYPE).entity(childRep).build(); return builder.type(MediaType.APPLICATION_JSON_TYPE).entity(childRep).build();
} }

View file

@ -108,16 +108,20 @@ public class GroupsResource {
if (child == null) { if (child == null) {
throw new NotFoundException("Could not find child by id"); throw new NotFoundException("Could not find child by id");
} }
adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success(); adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo);
} else { } else {
child = realm.createGroup(rep.getName()); child = realm.createGroup(rep.getName());
GroupResource.updateGroup(rep, child); GroupResource.updateGroup(rep, child);
URI uri = uriInfo.getAbsolutePathBuilder() URI uri = uriInfo.getAbsolutePathBuilder()
.path(child.getId()).build(); .path(child.getId()).build();
builder.status(201).location(uri); builder.status(201).location(uri);
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(rep).success();
rep.setId(child.getId());
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, child.getId());
} }
realm.moveGroup(child, null); realm.moveGroup(child, null);
adminEvent.representation(rep).success();
return builder.build(); return builder.build();
} }
} }

View file

@ -189,7 +189,8 @@ public class IdentityProvidersResource {
IdentityProviderModel identityProvider = RepresentationToModel.toModel(realm, representation); IdentityProviderModel identityProvider = RepresentationToModel.toModel(realm, representation);
this.realm.addIdentityProvider(identityProvider); this.realm.addIdentityProvider(identityProvider);
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, identityProvider.getInternalId()) representation.setInternalId(identityProvider.getInternalId());
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, identityProvider.getAlias())
.representation(representation).success(); .representation(representation).success();
return Response.created(uriInfo.getAbsolutePathBuilder().path(representation.getAlias()).build()).build(); return Response.created(uriInfo.getAbsolutePathBuilder().path(representation.getAlias()).build()).build();

View file

@ -354,8 +354,9 @@ public class RealmAdminResource {
public GlobalRequestResult pushRevocation() { public GlobalRequestResult pushRevocation() {
auth.requireManage(); auth.requireManage();
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success(); GlobalRequestResult result = new ResourceAdminManager(session).pushRealmRevocationPolicy(uriInfo.getRequestUri(), realm);
return new ResourceAdminManager(session).pushRealmRevocationPolicy(uriInfo.getRequestUri(), realm); adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).representation(result).success();
return result;
} }
/** /**
@ -369,8 +370,9 @@ public class RealmAdminResource {
auth.init(RealmAuth.Resource.USER).requireManage(); auth.init(RealmAuth.Resource.USER).requireManage();
session.sessions().removeUserSessions(realm); session.sessions().removeUserSessions(realm);
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success(); GlobalRequestResult result = new ResourceAdminManager(session).logoutAll(uriInfo.getRequestUri(), realm);
return new ResourceAdminManager(session).logoutAll(uriInfo.getRequestUri(), realm); adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).representation(result).success();
return result;
} }
/** /**
@ -730,6 +732,8 @@ public class RealmAdminResource {
throw new NotFoundException("Group not found"); throw new NotFoundException("Group not found");
} }
realm.addDefaultGroup(group); realm.addDefaultGroup(group);
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).success();
} }
@DELETE @DELETE
@ -743,6 +747,8 @@ public class RealmAdminResource {
throw new NotFoundException("Group not found"); throw new NotFoundException("Group not found");
} }
realm.removeDefaultGroup(group); realm.removeDefaultGroup(group);
adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
} }
@ -794,11 +800,12 @@ public class RealmAdminResource {
public void clearRealmCache() { public void clearRealmCache() {
auth.requireManage(); auth.requireManage();
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
CacheRealmProvider cache = session.getProvider(CacheRealmProvider.class); CacheRealmProvider cache = session.getProvider(CacheRealmProvider.class);
if (cache != null) { if (cache != null) {
cache.clear(); cache.clear();
} }
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
} }
/** /**
@ -810,11 +817,12 @@ public class RealmAdminResource {
public void clearUserCache() { public void clearUserCache() {
auth.requireManage(); auth.requireManage();
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
CacheUserProvider cache = session.getProvider(CacheUserProvider.class); CacheUserProvider cache = session.getProvider(CacheUserProvider.class);
if (cache != null) { if (cache != null) {
cache.clear(); cache.clear();
} }
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
} }
} }

View file

@ -226,9 +226,7 @@ public class RoleByIdResource extends RoleResource {
auth.requireManage(); auth.requireManage();
RoleModel role = getRoleModel(id); RoleModel role = getRoleModel(id);
deleteComposites(roles, role); deleteComposites(adminEvent, uriInfo, roles, role);
adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).representation(roles).success();
} }
} }

View file

@ -115,7 +115,8 @@ public class RoleContainerResource extends RoleResource {
boolean scopeParamRequired = rep.isScopeParamRequired()==null ? false : rep.isScopeParamRequired(); boolean scopeParamRequired = rep.isScopeParamRequired()==null ? false : rep.isScopeParamRequired();
role.setScopeParamRequired(scopeParamRequired); 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(); return Response.created(uriInfo.getAbsolutePathBuilder().path(role.getName()).build()).build();
} catch (ModelDuplicateException e) { } catch (ModelDuplicateException e) {
@ -332,8 +333,7 @@ public class RoleContainerResource extends RoleResource {
if (role == null) { if (role == null) {
throw new NotFoundException("Could not find role"); throw new NotFoundException("Could not find role");
} }
deleteComposites(roles, role); deleteComposites(adminEvent, uriInfo, roles, role);
adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
} }
} }

View file

@ -50,6 +50,7 @@ import javax.ws.rs.core.UriInfo;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
@ -236,8 +237,9 @@ public class RoleMapperResource {
throw new NotFoundException("Role not found"); throw new NotFoundException("Role not found");
} }
roleMapper.grantRole(roleModel); 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"); logger.debug("deleteRealmRoleMappings");
if (roles == null) { if (roles == null) {
Set<RoleModel> roleModels = roleMapper.getRealmRoleMappings(); Set<RoleModel> roleModels = roleMapper.getRealmRoleMappings();
roles = new LinkedList<>();
for (RoleModel roleModel : roleModels) { for (RoleModel roleModel : roleModels) {
roleMapper.deleteRoleMapping(roleModel); roleMapper.deleteRoleMapping(roleModel);
roles.add(ModelToRepresentation.toRepresentation(roleModel));
} }
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(roles).success();
} else { } else {
for (RoleRepresentation role : roles) { for (RoleRepresentation role : roles) {
RoleModel roleModel = realm.getRole(role.getName()); 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()), throw new ErrorResponseException(me.getMessage(), MessageFormat.format(messages.getProperty(me.getMessage(), me.getMessage()), me.getParameters()),
Response.Status.BAD_REQUEST); 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}") @Path("clients/{client}")

View file

@ -65,9 +65,9 @@ public abstract class RoleResource {
throw new NotFoundException("Could not find composite role"); throw new NotFoundException("Could not find composite role");
} }
role.addCompositeRole(composite); 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) { protected Set<RoleRepresentation> getRoleComposites(RoleModel role) {
@ -102,7 +102,7 @@ public abstract class RoleResource {
return composites; 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) { for (RoleRepresentation rep : roles) {
RoleModel composite = realm.getRoleById(rep.getId()); RoleModel composite = realm.getRoleById(rep.getId());
if (composite == null) { if (composite == null) {
@ -110,5 +110,7 @@ public abstract class RoleResource {
} }
role.removeCompositeRole(composite); role.removeCompositeRole(composite);
} }
adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).representation(roles).success();
} }
} }

View file

@ -38,6 +38,7 @@ import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -151,8 +152,9 @@ public class ScopeMappedClientResource {
throw new NotFoundException("Role not found"); throw new NotFoundException("Role not found");
} }
scopeContainer.addScopeMapping(roleModel); 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) { if (roles == null) {
Set<RoleModel> roleModels = KeycloakModelUtils.getClientScopeMappings(scopedClient, scopeContainer);//scopedClient.getClientScopeMappings(client); Set<RoleModel> roleModels = KeycloakModelUtils.getClientScopeMappings(scopedClient, scopeContainer);//scopedClient.getClientScopeMappings(client);
roles = new LinkedList<>();
for (RoleModel roleModel : roleModels) { for (RoleModel roleModel : roleModels) {
scopeContainer.deleteScopeMapping(roleModel); scopeContainer.deleteScopeMapping(roleModel);
roles.add(ModelToRepresentation.toRepresentation(roleModel));
} }
adminEvent.operation(OperationType.DELETE).resourcePath(session.getContext().getUri()).representation(roles).success();
} else { } else {
for (RoleRepresentation role : roles) { for (RoleRepresentation role : roles) {
RoleModel roleModel = scopedClient.getRole(role.getName()); RoleModel roleModel = scopedClient.getRole(role.getName());
@ -182,8 +187,9 @@ public class ScopeMappedClientResource {
throw new NotFoundException("Role not found"); throw new NotFoundException("Role not found");
} }
scopeContainer.deleteScopeMapping(roleModel); 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();
} }
} }

View file

@ -42,6 +42,7 @@ import javax.ws.rs.core.MediaType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -220,8 +221,9 @@ public class ScopeMappedResource {
throw new NotFoundException("Role not found"); throw new NotFoundException("Role not found");
} }
scopeContainer.addScopeMapping(roleModel); 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) { if (roles == null) {
Set<RoleModel> roleModels = scopeContainer.getRealmScopeMappings(); Set<RoleModel> roleModels = scopeContainer.getRealmScopeMappings();
roles = new LinkedList<>();
for (RoleModel roleModel : roleModels) { for (RoleModel roleModel : roleModels) {
scopeContainer.deleteScopeMapping(roleModel); scopeContainer.deleteScopeMapping(roleModel);
roles.add(ModelToRepresentation.toRepresentation(roleModel));
} }
adminEvent.operation(OperationType.DELETE).resourcePath(session.getContext().getUri()).representation(roles).success();
} else { } else {
for (RoleRepresentation role : roles) { for (RoleRepresentation role : roles) {
RoleModel roleModel = realm.getRoleById(role.getId()); RoleModel roleModel = realm.getRoleById(role.getId());
@ -252,10 +257,11 @@ public class ScopeMappedResource {
throw new NotFoundException("Client not found"); throw new NotFoundException("Client not found");
} }
scopeContainer.deleteScopeMapping(roleModel); 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}") @Path("clients/{client}")

View file

@ -190,7 +190,11 @@ public class UserFederationProviderResource {
throw new NotFoundException("Unknown action: " + action); throw new NotFoundException("Unknown action: " + action);
} }
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success(); Map<String, Object> eventRep = new HashMap<>();
eventRep.put("action", action);
eventRep.put("result", syncResult);
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).representation(eventRep).success();
return syncResult; return syncResult;
} }
@ -422,7 +426,10 @@ public class UserFederationProviderResource {
throw new NotFoundException("Unknown direction: " + direction); throw new NotFoundException("Unknown direction: " + direction);
} }
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success(); Map<String, Object> eventRep = new HashMap<>();
eventRep.put("action", direction);
eventRep.put("result", syncResult);
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).representation(eventRep).success();
return syncResult; return syncResult;
} }

View file

@ -37,11 +37,9 @@ import org.keycloak.representations.idm.ConfigPropertyRepresentation;
import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.UserFederationProviderFactoryRepresentation; import org.keycloak.representations.idm.UserFederationProviderFactoryRepresentation;
import org.keycloak.representations.idm.UserFederationProviderRepresentation; import org.keycloak.representations.idm.UserFederationProviderRepresentation;
import org.keycloak.services.ErrorResponse;
import org.keycloak.services.ErrorResponseException; import org.keycloak.services.ErrorResponseException;
import org.keycloak.services.ServicesLogger; import org.keycloak.services.ServicesLogger;
import org.keycloak.services.managers.UsersSyncManager; import org.keycloak.services.managers.UsersSyncManager;
import org.keycloak.timer.TimerProvider;
import org.keycloak.utils.CredentialHelper; import org.keycloak.utils.CredentialHelper;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
@ -211,8 +209,8 @@ public class UserFederationProvidersResource {
logger.addedKerberosToRealmCredentials(); logger.addedKerberosToRealmCredentials();
} }
rep.setId(model.getId());
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(rep).success(); adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, model.getId()).representation(rep).success();
return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build(); return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build();
} }

View file

@ -959,7 +959,7 @@ public class UsersResource {
try { try {
if (user.isMemberOf(group)){ if (user.isMemberOf(group)){
user.leaveGroup(group); user.leaveGroup(group);
adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success(); adminEvent.operation(OperationType.DELETE).representation(ModelToRepresentation.toRepresentation(group, true)).resourcePath(uriInfo).success();
} }
} catch (ModelException me) { } catch (ModelException me) {
Properties messages = AdminRoot.getMessages(session, realm, auth.getAuth().getToken().getLocale()); Properties messages = AdminRoot.getMessages(session, realm, auth.getAuth().getToken().getLocale());
@ -984,9 +984,8 @@ public class UsersResource {
} }
if (!user.isMemberOf(group)){ if (!user.isMemberOf(group)){
user.joinGroup(group); user.joinGroup(group);
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).success(); adminEvent.operation(OperationType.CREATE).representation(ModelToRepresentation.toRepresentation(group, true)).resourcePath(uriInfo).success();
} }
} }
} }

View file

@ -17,13 +17,12 @@
package org.keycloak.testsuite.admin; package org.keycloak.testsuite.admin;
import org.jboss.arquillian.graphene.page.Page;
import org.jboss.arquillian.test.api.ArquillianResource; import org.jboss.arquillian.test.api.ArquillianResource;
import org.junit.Test; import org.junit.Test;
import org.keycloak.admin.client.resource.AttackDetectionResource; import org.keycloak.admin.client.resource.AttackDetectionResource;
import org.keycloak.common.util.Time; import org.keycloak.events.admin.OperationType;
import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.testsuite.pages.LoginPage; import org.keycloak.testsuite.util.AdminEventPaths;
import org.keycloak.testsuite.util.OAuthClient; import org.keycloak.testsuite.util.OAuthClient;
import org.keycloak.testsuite.util.UserBuilder; import org.keycloak.testsuite.util.UserBuilder;
@ -33,7 +32,6 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
/** /**
* TODO adminEvents: Add adminEvents once resourcePath is added in AttackDetectionResource (server-side) events
* *
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/ */
@ -69,11 +67,13 @@ public class AttackDetectionResourceTest extends AbstractAdminTest {
assertBruteForce(detection.bruteForceUserStatus("nosuchuser"), 0, false, false); assertBruteForce(detection.bruteForceUserStatus("nosuchuser"), 0, false, false);
detection.clearBruteForceForUser("test-user@localhost"); detection.clearBruteForceForUser("test-user@localhost");
assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.attackDetectionClearBruteForceForUserPath("test-user@localhost"));
assertBruteForce(detection.bruteForceUserStatus("test-user@localhost"), 0, false, false); assertBruteForce(detection.bruteForceUserStatus("test-user@localhost"), 0, false, false);
assertBruteForce(detection.bruteForceUserStatus("test-user2"), 2, true, true); assertBruteForce(detection.bruteForceUserStatus("test-user2"), 2, true, true);
detection.clearAllBruteForce(); detection.clearAllBruteForce();
assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.attackDetectionClearAllBruteForcePath());
assertBruteForce(detection.bruteForceUserStatus("test-user@localhost"), 0, false, false); assertBruteForce(detection.bruteForceUserStatus("test-user@localhost"), 0, false, false);
assertBruteForce(detection.bruteForceUserStatus("test-user2"), 0, false, false); assertBruteForce(detection.bruteForceUserStatus("test-user2"), 0, false, false);

View file

@ -17,7 +17,6 @@
package org.keycloak.testsuite.admin; package org.keycloak.testsuite.admin;
import org.hamcrest.Matchers;
import org.junit.Test; import org.junit.Test;
import org.keycloak.OAuth2Constants; import org.keycloak.OAuth2Constants;
import org.keycloak.admin.client.resource.ClientResource; import org.keycloak.admin.client.resource.ClientResource;
@ -43,10 +42,8 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.keycloak.services.resources.admin.ScopeMappedResource;
import org.keycloak.testsuite.Assert; import org.keycloak.testsuite.Assert;
import org.keycloak.testsuite.util.AdminEventPaths; import org.keycloak.testsuite.util.AdminEventPaths;
import org.keycloak.testsuite.util.AssertAdminEvents;
import org.keycloak.testsuite.util.ClientBuilder; import org.keycloak.testsuite.util.ClientBuilder;
import org.keycloak.testsuite.util.CredentialBuilder; import org.keycloak.testsuite.util.CredentialBuilder;
import org.keycloak.testsuite.util.OAuthClient; import org.keycloak.testsuite.util.OAuthClient;
@ -154,7 +151,7 @@ public class ClientTest extends AbstractAdminTest {
RoleRepresentation role = new RoleRepresentation("test", "test", false); RoleRepresentation role = new RoleRepresentation("test", "test", false);
realm.clients().get(id).roles().create(role); 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(); ClientRepresentation foundClientRep = realm.clients().get(id).toRepresentation();
foundClientRep.setDefaultRoles(new String[]{"test"}); foundClientRep.setDefaultRoles(new String[]{"test"});
@ -258,18 +255,18 @@ public class ClientTest extends AbstractAdminTest {
ClientRepresentation client = createAppClient(); ClientRepresentation client = createAppClient();
String id = client.getId(); String id = client.getId();
realm.clients().get(id).registerNode(Collections.singletonMap("node", suiteContext.getAuthServerInfo().getContextRoot().getHost())); String myhost = suiteContext.getAuthServerInfo().getContextRoot().getHost();
realm.clients().get(id).registerNode(Collections.singletonMap("node", myhost));
realm.clients().get(id).registerNode(Collections.singletonMap("node", "invalid")); realm.clients().get(id).registerNode(Collections.singletonMap("node", "invalid"));
// TODO adminEvents: should be rather CREATE and include nodePath like in DELETE event assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientNodePath(id, myhost));
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.clientNodesPath(id)); assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientNodePath(id, "invalid"));
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.clientNodesPath(id));
GlobalRequestResult result = realm.clients().get(id).testNodesAvailable(); GlobalRequestResult result = realm.clients().get(id).testNodesAvailable();
assertEquals(1, result.getSuccessRequests().size()); assertEquals(1, result.getSuccessRequests().size());
assertEquals(1, result.getFailedRequests().size()); assertEquals(1, result.getFailedRequests().size());
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.clientTestNodesAvailablePath(id)); assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.clientTestNodesAvailablePath(id), result);
TestAvailabilityAction testAvailable = testingClient.testApp().getTestAvailable(); TestAvailabilityAction testAvailable = testingClient.testApp().getTestAvailable();
assertEquals("test-app", testAvailable.getResource()); assertEquals("test-app", testAvailable.getResource());
@ -327,28 +324,24 @@ public class ClientTest extends AbstractAdminTest {
realm.roles().create(roleRep1); realm.roles().create(roleRep1);
realm.roles().create(roleRep2); realm.roles().create(roleRep2);
AssertAdminEvents.ExpectedAdminEvent adminEvent = assertAdminEvents.expect() assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.roleResourcePath("role1"), roleRep1);
.realmId(realmId) assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.roleResourcePath("role2"), roleRep2);
.operationType(OperationType.CREATE)
.resourcePath(Matchers.startsWith(AdminEventPaths.rolesResourcePath()));
adminEvent.representation(roleRep1).assertEvent();
adminEvent.representation(roleRep2).assertEvent();
roleRep1 = realm.roles().get("role1").toRepresentation(); roleRep1 = realm.roles().get("role1").toRepresentation();
roleRep2 = realm.roles().get("role2").toRepresentation(); roleRep2 = realm.roles().get("role2").toRepresentation();
realm.roles().get("role1").addComposites(Collections.singletonList(roleRep2)); 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(); 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(); RoleRepresentation viewAccountRoleRep = realm.clients().get(accountMgmtId).roles().get(AccountRoles.VIEW_PROFILE).toRepresentation();
scopesResource.realmLevel().add(Collections.singletonList(roleRep1)); 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)); 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().listAll(), "role1");
Assert.assertNames(scopesResource.realmLevel().listEffective(), "role1", "role2"); 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); Assert.assertNames(scopesResource.getAll().getClientMappings().get(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID).getMappings(), AccountRoles.VIEW_PROFILE);
scopesResource.realmLevel().remove(Collections.singletonList(roleRep1)); 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)); 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().listAll());
Assert.assertNames(scopesResource.realmLevel().listEffective()); Assert.assertNames(scopesResource.realmLevel().listEffective());

View file

@ -17,7 +17,6 @@
package org.keycloak.testsuite.admin; package org.keycloak.testsuite.admin;
import org.hamcrest.Matchers;
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput; import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput;
import org.junit.Test; import org.junit.Test;
import org.keycloak.admin.client.resource.IdentityProviderResource; import org.keycloak.admin.client.resource.IdentityProviderResource;
@ -166,8 +165,7 @@ public class IdentityProviderTest extends AbstractAdminTest {
Assert.assertNotNull(ApiUtil.getCreatedId(response)); Assert.assertNotNull(ApiUtil.getCreatedId(response));
response.close(); response.close();
// TODO adminEvents: should rather use alias instead of internalId (same issue like for roles) assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.identityProviderPath(idpRep.getAlias()), idpRep);
assertAdminEvents.assertEvent(realmId, OperationType.CREATE, Matchers.startsWith(AdminEventPaths.identityProviderCreatePath()), idpRep);
} }
private IdentityProviderRepresentation createRep(String id, String providerId) { private IdentityProviderRepresentation createRep(String id, String providerId) {

View file

@ -69,13 +69,22 @@ public class InitialAccessTokenResourceTest extends AbstractAdminTest {
rep.setCount(4); rep.setCount(4);
response = resource.create(rep); response = resource.create(rep);
assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientInitialAccessPath(response.getId()), rep); String lastId = response.getId();
assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientInitialAccessPath(lastId), rep);
List<ClientInitialAccessPresentation> list = resource.list(); List<ClientInitialAccessPresentation> list = resource.list();
assertEquals(3, list.size()); assertEquals(3, list.size());
assertEquals(9, list.get(0).getCount() + list.get(1).getCount() + list.get(2).getCount()); assertEquals(9, list.get(0).getCount() + list.get(1).getCount() + list.get(2).getCount());
assertNull(list.get(0).getToken()); assertNull(list.get(0).getToken());
// Delete last and assert it was deleted
resource.delete(lastId);
assertAdminEvents.assertEvent(realmId, OperationType.DELETE, AdminEventPaths.clientInitialAccessPath(lastId));
list = resource.list();
assertEquals(2, list.size());
assertEquals(5, list.get(0).getCount() + list.get(1).getCount());
} }
} }

View file

@ -17,7 +17,6 @@
package org.keycloak.testsuite.admin; package org.keycloak.testsuite.admin;
import org.hamcrest.Matchers;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.keycloak.admin.client.resource.RoleByIdResource; 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()); l.add(RoleBuilder.create().id(ids.get("role-c")).build());
resource.addComposites(ids.get("role-a"), l); resource.addComposites(ids.get("role-a"), l);
// TODO adminEvents: Fix once composite roles events will be fixed... assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.roleByIdResourceCompositesPath(ids.get("role-a")), l);
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"))));
Set<RoleRepresentation> composites = resource.getRoleComposites(ids.get("role-a")); Set<RoleRepresentation> composites = resource.getRoleComposites(ids.get("role-a"));
@ -136,7 +133,7 @@ public class RoleByIdResourceTest extends AbstractAdminTest {
Assert.assertNames(clientComposites, "role-c"); Assert.assertNames(clientComposites, "role-c");
resource.deleteComposites(ids.get("role-a"), l); 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()); assertFalse(resource.getRole(ids.get("role-a")).isComposite());
assertEquals(0, resource.getRoleComposites(ids.get("role-a")).size()); assertEquals(0, resource.getRoleComposites(ids.get("role-a")).size());

View file

@ -65,7 +65,7 @@ public class UserFederationMapperTest extends AbstractAdminTest {
Response resp = realm.userFederation().create(ldapRep); Response resp = realm.userFederation().create(ldapRep);
this.ldapProviderId = ApiUtil.getCreatedId(resp); this.ldapProviderId = ApiUtil.getCreatedId(resp);
resp.close(); resp.close();
assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.userFederationCreateResourcePath(), ldapRep); assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.userFederationResourcePath(this.ldapProviderId), ldapRep);
UserFederationProviderRepresentation dummyRep = UserFederationProviderBuilder.create() UserFederationProviderRepresentation dummyRep = UserFederationProviderBuilder.create()
.displayName("dummy-1") .displayName("dummy-1")
@ -75,7 +75,7 @@ public class UserFederationMapperTest extends AbstractAdminTest {
resp = realm.userFederation().create(dummyRep); resp = realm.userFederation().create(dummyRep);
this.dummyProviderId = ApiUtil.getCreatedId(resp); this.dummyProviderId = ApiUtil.getCreatedId(resp);
resp.close(); resp.close();
assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.userFederationCreateResourcePath(), dummyRep); assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.userFederationResourcePath(this.dummyProviderId), dummyRep);
} }
@After @After
@ -254,11 +254,16 @@ public class UserFederationMapperTest extends AbstractAdminTest {
// Try fed To Keycloak sync // Try fed To Keycloak sync
UserFederationSyncResultRepresentation result = ldapProviderResource().syncMapperData(mapperId, "fedToKeycloak"); UserFederationSyncResultRepresentation result = ldapProviderResource().syncMapperData(mapperId, "fedToKeycloak");
Assert.assertEquals("dummyFedToKeycloakSuccess mapper=some-dummy", result.getStatus()); Assert.assertEquals("dummyFedToKeycloakSuccess mapper=some-dummy", result.getStatus());
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.userFederationMapperResourcePath(ldapProviderId, mapperId) + "/sync");
Map<String, Object> eventRep = new HashMap<>();
eventRep.put("action", "fedToKeycloak");
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.userFederationMapperResourcePath(ldapProviderId, mapperId) + "/sync", eventRep);
// Try keycloak to fed // Try keycloak to fed
result = ldapProviderResource().syncMapperData(mapperId, "keycloakToFed"); result = ldapProviderResource().syncMapperData(mapperId, "keycloakToFed");
Assert.assertEquals("dummyKeycloakToFedSuccess mapper=some-dummy", result.getStatus()); Assert.assertEquals("dummyKeycloakToFedSuccess mapper=some-dummy", result.getStatus());
eventRep.put("action", "keycloakToFed");
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.userFederationMapperResourcePath(ldapProviderId, mapperId) + "/sync"); assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.userFederationMapperResourcePath(ldapProviderId, mapperId) + "/sync");
} }

View file

@ -17,8 +17,10 @@
package org.keycloak.testsuite.admin; package org.keycloak.testsuite.admin;
import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map;
import javax.ws.rs.BadRequestException; import javax.ws.rs.BadRequestException;
import javax.ws.rs.NotFoundException; import javax.ws.rs.NotFoundException;
@ -251,6 +253,7 @@ public class UserFederationTest extends AbstractAdminTest {
// Switch kerberos authenticator to DISABLED // Switch kerberos authenticator to DISABLED
kerberosExecution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED.toString()); kerberosExecution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED.toString());
realm.flows().updateExecutions("browser", kerberosExecution); realm.flows().updateExecutions("browser", kerberosExecution);
assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, AdminEventPaths.authUpdateExecutionPath("browser"), kerberosExecution);
// update LDAP provider with kerberos // update LDAP provider with kerberos
ldapRep = userFederation().get(id).toRepresentation(); ldapRep = userFederation().get(id).toRepresentation();
@ -264,6 +267,7 @@ public class UserFederationTest extends AbstractAdminTest {
// Cleanup // Cleanup
kerberosExecution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED.toString()); kerberosExecution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED.toString());
realm.flows().updateExecutions("browser", kerberosExecution); realm.flows().updateExecutions("browser", kerberosExecution);
assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, AdminEventPaths.authUpdateExecutionPath("browser"), kerberosExecution);
removeUserFederationProvider(id); removeUserFederationProvider(id);
} }
@ -297,7 +301,10 @@ public class UserFederationTest extends AbstractAdminTest {
// Sync and assert it happened // Sync and assert it happened
UserFederationSyncResultRepresentation syncResult = userFederation().get(id1).syncUsers("triggerFullSync"); UserFederationSyncResultRepresentation syncResult = userFederation().get(id1).syncUsers("triggerFullSync");
Assert.assertEquals("0 imported users, 0 updated users", syncResult.getStatus()); Assert.assertEquals("0 imported users, 0 updated users", syncResult.getStatus());
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.userFederationResourcePath(id1) + "/sync");
Map<String, Object> eventRep = new HashMap<>();
eventRep.put("action", "triggerFullSync");
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.userFederationResourcePath(id1) + "/sync", eventRep);
int fullSyncTime = userFederation().get(id1).toRepresentation().getLastSync(); int fullSyncTime = userFederation().get(id1).toRepresentation().getLastSync();
Assert.assertTrue(fullSyncTime > 0); Assert.assertTrue(fullSyncTime > 0);
@ -305,7 +312,9 @@ public class UserFederationTest extends AbstractAdminTest {
// Changed sync // Changed sync
setTimeOffset(50); setTimeOffset(50);
syncResult = userFederation().get(id1).syncUsers("triggerChangedUsersSync"); syncResult = userFederation().get(id1).syncUsers("triggerChangedUsersSync");
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.userFederationResourcePath(id1) + "/sync");
eventRep.put("action", "triggerChangedUsersSync");
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.userFederationResourcePath(id1) + "/sync", eventRep);
Assert.assertEquals("0 imported users, 0 updated users", syncResult.getStatus()); Assert.assertEquals("0 imported users, 0 updated users", syncResult.getStatus());
int changedSyncTime = userFederation().get(id1).toRepresentation().getLastSync(); int changedSyncTime = userFederation().get(id1).toRepresentation().getLastSync();
@ -323,8 +332,7 @@ public class UserFederationTest extends AbstractAdminTest {
resp.close(); resp.close();
String federationProviderId = ApiUtil.getCreatedId(resp); String federationProviderId = ApiUtil.getCreatedId(resp);
// TODO adminEvents: should be rather whole path include ID (consistency with UPDATE and DELETE) assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.userFederationResourcePath(federationProviderId), rep);
assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.userFederationCreateResourcePath(), rep);
return federationProviderId; return federationProviderId;
} }

View file

@ -353,7 +353,7 @@ public class UserTest extends AbstractAdminTest {
rep.setProviderId("social-provider-type"); rep.setProviderId("social-provider-type");
realm.identityProviders().create(rep); realm.identityProviders().create(rep);
assertAdminEvents.assertEvent(realmId, OperationType.CREATE, Matchers.startsWith(AdminEventPaths.identityProviderCreatePath()), rep); assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.identityProviderPath(rep.getAlias()), rep);
} }
private void removeSampleIdentityProvider() { private void removeSampleIdentityProvider() {
@ -742,6 +742,7 @@ public class UserTest extends AbstractAdminTest {
RequiredActionProviderRepresentation updatePasswordReqAction = realm.flows().getRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD.toString()); RequiredActionProviderRepresentation updatePasswordReqAction = realm.flows().getRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD.toString());
updatePasswordReqAction.setDefaultAction(true); updatePasswordReqAction.setDefaultAction(true);
realm.flows().updateRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD.toString(), updatePasswordReqAction); realm.flows().updateRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD.toString(), updatePasswordReqAction);
assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, AdminEventPaths.authRequiredActionPath(UserModel.RequiredAction.UPDATE_PASSWORD.toString()), updatePasswordReqAction);
// Create user // Create user
String userId = createUser("user1", "user1@localhost"); String userId = createUser("user1", "user1@localhost");
@ -754,6 +755,7 @@ public class UserTest extends AbstractAdminTest {
updatePasswordReqAction = realm.flows().getRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD.toString()); updatePasswordReqAction = realm.flows().getRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD.toString());
updatePasswordReqAction.setDefaultAction(true); updatePasswordReqAction.setDefaultAction(true);
realm.flows().updateRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD.toString(), updatePasswordReqAction); realm.flows().updateRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD.toString(), updatePasswordReqAction);
assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, AdminEventPaths.authRequiredActionPath(UserModel.RequiredAction.UPDATE_PASSWORD.toString()), updatePasswordReqAction);
} }
@Test @Test
@ -794,14 +796,16 @@ public class UserTest extends AbstractAdminTest {
l.add(realm.roles().get("realm-role").toRepresentation()); l.add(realm.roles().get("realm-role").toRepresentation());
l.add(realm.roles().get("realm-composite").toRepresentation()); l.add(realm.roles().get("realm-composite").toRepresentation());
roles.realmLevel().add(l); roles.realmLevel().add(l);
assertAdminEvents.assertEvent("test", OperationType.CREATE, Matchers.startsWith(AdminEventPaths.userRealmRoleMappingsPath(userId))); assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.userRealmRoleMappingsPath(userId), l);
assertAdminEvents.assertEvent("test", OperationType.CREATE, Matchers.startsWith(AdminEventPaths.userRealmRoleMappingsPath(userId)));
// Add client roles // Add client roles
roles.clientLevel(clientUuid).add(Collections.singletonList(realm.clients().get(clientUuid).roles().get("client-role").toRepresentation())); List<RoleRepresentation> list = 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())); roles.clientLevel(clientUuid).add(list);
assertAdminEvents.assertEvent("test", OperationType.CREATE, Matchers.startsWith(AdminEventPaths.userClientRoleMappingsPath(userId, clientUuid))); assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.userClientRoleMappingsPath(userId, clientUuid), list);
assertAdminEvents.assertEvent("test", OperationType.CREATE, Matchers.startsWith(AdminEventPaths.userClientRoleMappingsPath(userId, clientUuid)));
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 // List realm roles
assertNames(roles.realmLevel().listAll(), "realm-role", "realm-composite", "user", "offline_access"); assertNames(roles.realmLevel().listAll(), "realm-role", "realm-composite", "user", "offline_access");
@ -823,16 +827,14 @@ public class UserTest extends AbstractAdminTest {
// Remove realm role // Remove realm role
RoleRepresentation realmRoleRep = realm.roles().get("realm-role").toRepresentation(); RoleRepresentation realmRoleRep = realm.roles().get("realm-role").toRepresentation();
roles.realmLevel().remove(Collections.singletonList(realmRoleRep)); 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"); assertNames(roles.realmLevel().listAll(), "realm-composite", "user", "offline_access");
// Remove client role // Remove client role
RoleRepresentation clientRoleRep = realm.clients().get(clientUuid).roles().get("client-role").toRepresentation(); RoleRepresentation clientRoleRep = realm.clients().get(clientUuid).roles().get("client-role").toRepresentation();
roles.clientLevel(clientUuid).remove(Collections.singletonList(clientRoleRep)); roles.clientLevel(clientUuid).remove(Collections.singletonList(clientRoleRep));
assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.userClientRoleMappingsPath(userId, clientUuid), 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));
assertNames(roles.clientLevel(clientUuid).listAll(), "client-composite"); assertNames(roles.clientLevel(clientUuid).listAll(), "client-composite");
} }

View file

@ -19,19 +19,26 @@ package org.keycloak.testsuite.admin.authentication;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.keycloak.admin.client.resource.AuthenticationManagementResource; import org.keycloak.admin.client.resource.AuthenticationManagementResource;
import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.events.admin.OperationType;
import org.keycloak.representations.idm.AuthenticationExecutionExportRepresentation; import org.keycloak.representations.idm.AuthenticationExecutionExportRepresentation;
import org.keycloak.representations.idm.AuthenticationExecutionInfoRepresentation; import org.keycloak.representations.idm.AuthenticationExecutionInfoRepresentation;
import org.keycloak.representations.idm.AuthenticationFlowRepresentation; import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
import org.keycloak.representations.idm.AuthenticatorConfigRepresentation; import org.keycloak.representations.idm.AuthenticatorConfigRepresentation;
import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.testsuite.AbstractKeycloakTest; import org.keycloak.testsuite.AbstractKeycloakTest;
import org.keycloak.testsuite.util.AdminEventPaths;
import org.keycloak.testsuite.util.AssertAdminEvents;
import org.keycloak.testsuite.util.RealmBuilder;
import java.util.Arrays; import java.util.Arrays;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import javax.ws.rs.core.Response;
/** /**
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a> * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
@ -48,6 +55,9 @@ public abstract class AbstractAuthenticationTest extends AbstractKeycloakTest {
RealmResource realmResource; RealmResource realmResource;
AuthenticationManagementResource authMgmtResource; AuthenticationManagementResource authMgmtResource;
@Rule
public AssertAdminEvents assertAdminEvents = new AssertAdminEvents(this);
@Before @Before
public void before() { public void before() {
realmResource = adminClient.realms().realm(REALM_NAME); realmResource = adminClient.realms().realm(REALM_NAME);
@ -56,9 +66,8 @@ public abstract class AbstractAuthenticationTest extends AbstractKeycloakTest {
@Override @Override
public void addTestRealms(List<RealmRepresentation> testRealms) { public void addTestRealms(List<RealmRepresentation> testRealms) {
RealmRepresentation testRealmRep = new RealmRepresentation(); RealmRepresentation testRealmRep = RealmBuilder.create().name(REALM_NAME).testEventListener().build();
testRealmRep.setRealm(REALM_NAME); testRealmRep.setId(REALM_NAME);
testRealmRep.setEnabled(true);
testRealms.add(testRealmRep); testRealms.add(testRealmRep);
} }
@ -182,4 +191,11 @@ public abstract class AbstractAuthenticationTest extends AbstractKeycloakTest {
config.setConfig(params); config.setConfig(params);
return config; return config;
} }
void createFlow(AuthenticationFlowRepresentation flowRep) {
Response response = authMgmtResource.createFlow(flowRep);
org.keycloak.testsuite.Assert.assertEquals(201, response.getStatus());
response.close();
assertAdminEvents.assertEvent(REALM_NAME, OperationType.CREATE, AssertAdminEvents.isExpectedPrefixFollowedByUuid(AdminEventPaths.authFlowsPath()), flowRep);
}
} }

View file

@ -28,11 +28,14 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.keycloak.authentication.authenticators.broker.IdpCreateUserIfUniqueAuthenticator; import org.keycloak.authentication.authenticators.broker.IdpCreateUserIfUniqueAuthenticator;
import org.keycloak.authentication.authenticators.broker.IdpCreateUserIfUniqueAuthenticatorFactory; import org.keycloak.authentication.authenticators.broker.IdpCreateUserIfUniqueAuthenticatorFactory;
import org.keycloak.events.admin.OperationType;
import org.keycloak.representations.idm.AuthenticationExecutionInfoRepresentation; import org.keycloak.representations.idm.AuthenticationExecutionInfoRepresentation;
import org.keycloak.representations.idm.AuthenticationFlowRepresentation; import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
import org.keycloak.representations.idm.AuthenticatorConfigRepresentation; import org.keycloak.representations.idm.AuthenticatorConfigRepresentation;
import org.keycloak.testsuite.Assert; import org.keycloak.testsuite.Assert;
import org.keycloak.testsuite.admin.ApiUtil; import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.util.AdminEventPaths;
import org.keycloak.testsuite.util.AssertAdminEvents;
/** /**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a> * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@ -43,13 +46,13 @@ public class AuthenticatorConfigTest extends AbstractAuthenticationTest {
@Before @Before
public void beforeConfigTest() { public void beforeConfigTest() {
Response response = authMgmtResource.createFlow(newFlow("firstBrokerLogin2", "firstBrokerLogin2", "basic-flow", true, false)); AuthenticationFlowRepresentation flowRep = newFlow("firstBrokerLogin2", "firstBrokerLogin2", "basic-flow", true, false);
Assert.assertEquals(201, response.getStatus()); createFlow(flowRep);
response.close();
HashMap<String, String> params = new HashMap<>(); HashMap<String, String> params = new HashMap<>();
params.put("provider", IdpCreateUserIfUniqueAuthenticatorFactory.PROVIDER_ID); params.put("provider", IdpCreateUserIfUniqueAuthenticatorFactory.PROVIDER_ID);
authMgmtResource.addExecution("firstBrokerLogin2", params); authMgmtResource.addExecution("firstBrokerLogin2", params);
assertAdminEvents.assertEvent(REALM_NAME, OperationType.CREATE, AdminEventPaths.authAddExecutionPath("firstBrokerLogin2"), params);
List<AuthenticationExecutionInfoRepresentation> executionReps = authMgmtResource.getExecutions("firstBrokerLogin2"); List<AuthenticationExecutionInfoRepresentation> executionReps = authMgmtResource.getExecutions("firstBrokerLogin2");
AuthenticationExecutionInfoRepresentation exec = findExecutionByProvider(IdpCreateUserIfUniqueAuthenticatorFactory.PROVIDER_ID, executionReps); AuthenticationExecutionInfoRepresentation exec = findExecutionByProvider(IdpCreateUserIfUniqueAuthenticatorFactory.PROVIDER_ID, executionReps);
@ -57,12 +60,6 @@ public class AuthenticatorConfigTest extends AbstractAuthenticationTest {
executionId = exec.getId(); executionId = exec.getId();
} }
@Override
public void afterAbstractKeycloakTest() {
AuthenticationFlowRepresentation flowRep = findFlowByAlias("firstBrokerLogin2", authMgmtResource.getFlows());
authMgmtResource.deleteFlow(flowRep.getId());
}
@Test @Test
public void testCreateConfig() { public void testCreateConfig() {
@ -82,6 +79,7 @@ public class AuthenticatorConfigTest extends AbstractAuthenticationTest {
// Cleanup // Cleanup
authMgmtResource.removeAuthenticatorConfig(cfgId); authMgmtResource.removeAuthenticatorConfig(cfgId);
assertAdminEvents.assertEvent(REALM_NAME, OperationType.DELETE, AdminEventPaths.authExecutionConfigPath(cfgId));
} }
@ -107,6 +105,7 @@ public class AuthenticatorConfigTest extends AbstractAuthenticationTest {
cfgRep.setAlias("foo2"); cfgRep.setAlias("foo2");
cfgRep.getConfig().put("configKey2", "configValue2"); cfgRep.getConfig().put("configKey2", "configValue2");
authMgmtResource.updateAuthenticatorConfig(cfgRep.getId(), cfgRep); authMgmtResource.updateAuthenticatorConfig(cfgRep.getId(), cfgRep);
assertAdminEvents.assertEvent(REALM_NAME, OperationType.UPDATE, AdminEventPaths.authExecutionConfigPath(cfgId), cfgRep);
// Assert updated // Assert updated
cfgRep = authMgmtResource.getAuthenticatorConfig(cfgRep.getId()); cfgRep = authMgmtResource.getAuthenticatorConfig(cfgRep.getId());
@ -137,7 +136,8 @@ public class AuthenticatorConfigTest extends AbstractAuthenticationTest {
} }
// Test remove our config // Test remove our config
authMgmtResource.removeAuthenticatorConfig(cfgRep.getId()); authMgmtResource.removeAuthenticatorConfig(cfgId);
assertAdminEvents.assertEvent(REALM_NAME, OperationType.DELETE, AdminEventPaths.authExecutionConfigPath(cfgId));
// Assert config not found // Assert config not found
try { try {
@ -159,6 +159,7 @@ public class AuthenticatorConfigTest extends AbstractAuthenticationTest {
Assert.assertEquals(201, resp.getStatus()); Assert.assertEquals(201, resp.getStatus());
String cfgId = ApiUtil.getCreatedId(resp); String cfgId = ApiUtil.getCreatedId(resp);
Assert.assertNotNull(cfgId); Assert.assertNotNull(cfgId);
assertAdminEvents.assertEvent(REALM_NAME, OperationType.CREATE, AdminEventPaths.authAddExecutionConfigPath(executionId), cfg);
return cfgId; return cfgId;
} }

View file

@ -21,10 +21,12 @@ import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.keycloak.authentication.AuthenticationFlow; import org.keycloak.authentication.AuthenticationFlow;
import org.keycloak.authentication.authenticators.client.ClientIdAndSecretAuthenticator; import org.keycloak.authentication.authenticators.client.ClientIdAndSecretAuthenticator;
import org.keycloak.models.AuthenticationExecutionModel; import org.keycloak.events.admin.OperationType;
import org.keycloak.representations.idm.AuthenticationExecutionInfoRepresentation; import org.keycloak.representations.idm.AuthenticationExecutionInfoRepresentation;
import org.keycloak.representations.idm.AuthenticationExecutionRepresentation; import org.keycloak.representations.idm.AuthenticationExecutionRepresentation;
import org.keycloak.representations.idm.AuthenticationFlowRepresentation; import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
import org.keycloak.testsuite.util.AdminEventPaths;
import org.keycloak.testsuite.util.AssertAdminEvents;
import javax.ws.rs.BadRequestException; import javax.ws.rs.BadRequestException;
import javax.ws.rs.NotFoundException; import javax.ws.rs.NotFoundException;
@ -60,8 +62,9 @@ public class ExecutionTest extends AbstractAuthenticationTest {
} }
// copy built-in flow so we get a new editable flow // copy built-in flow so we get a new editable flow
params.put("newName", "Copy of browser"); params.put("newName", "Copy-of-browser");
Response response = authMgmtResource.copy("browser", params); Response response = authMgmtResource.copy("browser", params);
assertAdminEvents.assertEvent(REALM_NAME, OperationType.CREATE, AdminEventPaths.authCopyFlowPath("browser"), params);
try { try {
Assert.assertEquals("Copy flow", 201, response.getStatus()); Assert.assertEquals("Copy flow", 201, response.getStatus());
} finally { } finally {
@ -71,17 +74,19 @@ public class ExecutionTest extends AbstractAuthenticationTest {
// add execution using inexistent provider // add execution using inexistent provider
params.put("provider", "test-execution"); params.put("provider", "test-execution");
try { try {
authMgmtResource.addExecution("Copy of browser", params); authMgmtResource.addExecution("CopyOfBrowser", params);
Assert.fail("add execution with inexistent provider should fail"); Assert.fail("add execution with inexistent provider should fail");
} catch(BadRequestException expected) { } catch(BadRequestException expected) {
// Expected
} }
// add execution - should succeed // add execution - should succeed
params.put("provider", "idp-review-profile"); params.put("provider", "idp-review-profile");
authMgmtResource.addExecution("Copy of browser", params); authMgmtResource.addExecution("Copy-of-browser", params);
assertAdminEvents.assertEvent(REALM_NAME, OperationType.CREATE, AdminEventPaths.authAddExecutionPath("Copy-of-browser"), params);
// check execution was added // check execution was added
List<AuthenticationExecutionInfoRepresentation> executionReps = authMgmtResource.getExecutions("Copy of browser"); List<AuthenticationExecutionInfoRepresentation> executionReps = authMgmtResource.getExecutions("Copy-of-browser");
AuthenticationExecutionInfoRepresentation exec = findExecutionByProvider("idp-review-profile", executionReps); AuthenticationExecutionInfoRepresentation exec = findExecutionByProvider("idp-review-profile", executionReps);
Assert.assertNotNull("idp-review-profile added", exec); Assert.assertNotNull("idp-review-profile added", exec);
@ -92,9 +97,10 @@ public class ExecutionTest extends AbstractAuthenticationTest {
// remove execution // remove execution
authMgmtResource.removeExecution(exec.getId()); authMgmtResource.removeExecution(exec.getId());
assertAdminEvents.assertEvent(REALM_NAME, OperationType.DELETE, AdminEventPaths.authExecutionPath(exec.getId()));
// check execution was removed // check execution was removed
executionReps = authMgmtResource.getExecutions("Copy of browser"); executionReps = authMgmtResource.getExecutions("Copy-of-browser");
exec = findExecutionByProvider("idp-review-profile", executionReps); exec = findExecutionByProvider("idp-review-profile", executionReps);
Assert.assertNull("idp-review-profile removed", exec); Assert.assertNull("idp-review-profile removed", exec);
@ -102,6 +108,7 @@ public class ExecutionTest extends AbstractAuthenticationTest {
// delete auth-cookie // delete auth-cookie
authMgmtResource.removeExecution(authCookieExec.getId()); authMgmtResource.removeExecution(authCookieExec.getId());
assertAdminEvents.assertEvent(REALM_NAME, OperationType.DELETE, AdminEventPaths.authExecutionPath(authCookieExec.getId()));
AuthenticationExecutionRepresentation rep = new AuthenticationExecutionRepresentation(); AuthenticationExecutionRepresentation rep = new AuthenticationExecutionRepresentation();
rep.setPriority(10); rep.setPriority(10);
@ -135,13 +142,14 @@ public class ExecutionTest extends AbstractAuthenticationTest {
response.close(); response.close();
} }
// get Copy of browser flow id, and set it on execution // get Copy-of-browser flow id, and set it on execution
List<AuthenticationFlowRepresentation> flows = authMgmtResource.getFlows(); List<AuthenticationFlowRepresentation> flows = authMgmtResource.getFlows();
AuthenticationFlowRepresentation flow = findFlowByAlias("Copy of browser", flows); AuthenticationFlowRepresentation flow = findFlowByAlias("Copy-of-browser", flows);
rep.setParentFlow(flow.getId()); rep.setParentFlow(flow.getId());
// add execution - should succeed // add execution - should succeed
response = authMgmtResource.addExecution(rep); response = authMgmtResource.addExecution(rep);
assertAdminEvents.assertEvent(REALM_NAME, OperationType.CREATE, AssertAdminEvents.isExpectedPrefixFollowedByUuid(AdminEventPaths.authMgmtBasePath() + "/executions"), rep);
try { try {
Assert.assertEquals("added execution", 201, response.getStatus()); Assert.assertEquals("added execution", 201, response.getStatus());
} finally { } finally {
@ -149,7 +157,7 @@ public class ExecutionTest extends AbstractAuthenticationTest {
} }
// check execution was added // check execution was added
List<AuthenticationExecutionInfoRepresentation> executions = authMgmtResource.getExecutions("Copy of browser"); List<AuthenticationExecutionInfoRepresentation> executions = authMgmtResource.getExecutions("Copy-of-browser");
exec = findExecutionByProvider("auth-cookie", executions); exec = findExecutionByProvider("auth-cookie", executions);
Assert.assertNotNull("auth-cookie added", exec); Assert.assertNotNull("auth-cookie added", exec);
@ -170,6 +178,7 @@ public class ExecutionTest extends AbstractAuthenticationTest {
// switch from DISABLED to ALTERNATIVE // switch from DISABLED to ALTERNATIVE
exec.setRequirement(DISABLED); exec.setRequirement(DISABLED);
authMgmtResource.updateExecutions("browser", exec); authMgmtResource.updateExecutions("browser", exec);
assertAdminEvents.assertEvent(REALM_NAME, OperationType.UPDATE, AdminEventPaths.authUpdateExecutionPath("browser"), exec);
// make sure the change is visible // make sure the change is visible
executionReps = authMgmtResource.getExecutions("browser"); executionReps = authMgmtResource.getExecutions("browser");
@ -183,14 +192,13 @@ public class ExecutionTest extends AbstractAuthenticationTest {
public void testClientFlowExecutions() { public void testClientFlowExecutions() {
// Create client flow // Create client flow
AuthenticationFlowRepresentation clientFlow = newFlow("new-client-flow", "desc", AuthenticationFlow.CLIENT_FLOW, true, false); AuthenticationFlowRepresentation clientFlow = newFlow("new-client-flow", "desc", AuthenticationFlow.CLIENT_FLOW, true, false);
Response response = authMgmtResource.createFlow(clientFlow); createFlow(clientFlow);
Assert.assertEquals(201, response.getStatus());
response.close();
// Add execution to it // Add execution to it
Map<String, String> executionData = new HashMap<>(); Map<String, String> executionData = new HashMap<>();
executionData.put("provider", ClientIdAndSecretAuthenticator.PROVIDER_ID); executionData.put("provider", ClientIdAndSecretAuthenticator.PROVIDER_ID);
authMgmtResource.addExecution("new-client-flow", executionData); authMgmtResource.addExecution("new-client-flow", executionData);
assertAdminEvents.assertEvent(REALM_NAME, OperationType.CREATE, AdminEventPaths.authAddExecutionPath("new-client-flow"), executionData);
// Check executions of not-existent flow - SHOULD FAIL // Check executions of not-existent flow - SHOULD FAIL
try { try {
@ -226,6 +234,7 @@ public class ExecutionTest extends AbstractAuthenticationTest {
// Update success // Update success
executionRep.setRequirement(ALTERNATIVE); executionRep.setRequirement(ALTERNATIVE);
authMgmtResource.updateExecutions("new-client-flow", executionRep); authMgmtResource.updateExecutions("new-client-flow", executionRep);
assertAdminEvents.assertEvent(REALM_NAME, OperationType.UPDATE, AdminEventPaths.authUpdateExecutionPath("new-client-flow"), executionRep);
// Check updated // Check updated
executionRep = findExecutionByProvider(ClientIdAndSecretAuthenticator.PROVIDER_ID, authMgmtResource.getExecutions("new-client-flow")); executionRep = findExecutionByProvider(ClientIdAndSecretAuthenticator.PROVIDER_ID, authMgmtResource.getExecutions("new-client-flow"));
@ -241,7 +250,10 @@ public class ExecutionTest extends AbstractAuthenticationTest {
// Successfuly remove execution and flow // Successfuly remove execution and flow
authMgmtResource.removeExecution(executionRep.getId()); authMgmtResource.removeExecution(executionRep.getId());
assertAdminEvents.assertEvent(REALM_NAME, OperationType.DELETE, AdminEventPaths.authExecutionPath(executionRep.getId()));
AuthenticationFlowRepresentation rep = findFlowByAlias("new-client-flow", authMgmtResource.getFlows()); AuthenticationFlowRepresentation rep = findFlowByAlias("new-client-flow", authMgmtResource.getFlows());
authMgmtResource.deleteFlow(rep.getId()); authMgmtResource.deleteFlow(rep.getId());
assertAdminEvents.assertEvent(REALM_NAME, OperationType.DELETE, AdminEventPaths.authFlowPath(rep.getId()));
} }
} }

View file

@ -19,8 +19,10 @@ package org.keycloak.testsuite.admin.authentication;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.keycloak.events.admin.OperationType;
import org.keycloak.representations.idm.AuthenticationExecutionExportRepresentation; import org.keycloak.representations.idm.AuthenticationExecutionExportRepresentation;
import org.keycloak.representations.idm.AuthenticationFlowRepresentation; import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
import org.keycloak.testsuite.util.AdminEventPaths;
import javax.ws.rs.BadRequestException; import javax.ws.rs.BadRequestException;
import javax.ws.rs.NotFoundException; import javax.ws.rs.NotFoundException;
@ -67,12 +69,7 @@ public class FlowTest extends AbstractAuthenticationTest {
// create new flow that should succeed // create new flow that should succeed
AuthenticationFlowRepresentation newFlow = newFlow("browser-2", "Browser flow", "basic-flow", true, false); AuthenticationFlowRepresentation newFlow = newFlow("browser-2", "Browser flow", "basic-flow", true, false);
response = authMgmtResource.createFlow(newFlow); createFlow(newFlow);
try {
Assert.assertEquals("createFlow success", 201, response.getStatus());
} finally {
response.close();
}
// check that new flow is returned in a children list // check that new flow is returned in a children list
flows = authMgmtResource.getFlows(); flows = authMgmtResource.getFlows();
@ -122,6 +119,7 @@ public class FlowTest extends AbstractAuthenticationTest {
// Successfully add flow // Successfully add flow
data.put("alias", "SomeFlow"); data.put("alias", "SomeFlow");
authMgmtResource.addExecutionFlow("browser-2", data); authMgmtResource.addExecutionFlow("browser-2", data);
assertAdminEvents.assertEvent(REALM_NAME, OperationType.CREATE, AdminEventPaths.authAddExecutionFlowPath("browser-2"), data);
// check that new flow is returned in a children list // check that new flow is returned in a children list
flows = authMgmtResource.getFlows(); flows = authMgmtResource.getFlows();
@ -143,6 +141,7 @@ public class FlowTest extends AbstractAuthenticationTest {
// delete non-built-in flow // delete non-built-in flow
authMgmtResource.deleteFlow(found.getId()); authMgmtResource.deleteFlow(found.getId());
assertAdminEvents.assertEvent(REALM_NAME, OperationType.DELETE, AdminEventPaths.authFlowPath(found.getId()));
// check the deleted flow is no longer returned // check the deleted flow is no longer returned
flows = authMgmtResource.getFlows(); flows = authMgmtResource.getFlows();
@ -185,6 +184,7 @@ public class FlowTest extends AbstractAuthenticationTest {
// copy that should succeed // copy that should succeed
params.put("newName", "Copy of browser"); params.put("newName", "Copy of browser");
response = authMgmtResource.copy("browser", params); response = authMgmtResource.copy("browser", params);
assertAdminEvents.assertEvent(REALM_NAME, OperationType.CREATE, AdminEventPaths.authCopyFlowPath("browser"), params);
try { try {
Assert.assertEquals("Copy flow", 201, response.getStatus()); Assert.assertEquals("Copy flow", 201, response.getStatus());
} finally { } finally {
@ -219,6 +219,7 @@ public class FlowTest extends AbstractAuthenticationTest {
Response response = authMgmtResource.copy("browser", params); Response response = authMgmtResource.copy("browser", params);
Assert.assertEquals(201, response.getStatus()); Assert.assertEquals(201, response.getStatus());
response.close(); response.close();
assertAdminEvents.assertEvent(REALM_NAME, OperationType.CREATE, AdminEventPaths.authCopyFlowPath("browser"), params);
params = new HashMap<>(); params = new HashMap<>();
params.put("alias", "child"); params.put("alias", "child");
@ -227,6 +228,7 @@ public class FlowTest extends AbstractAuthenticationTest {
params.put("type", "basic-flow"); params.put("type", "basic-flow");
authMgmtResource.addExecutionFlow("parent", params); authMgmtResource.addExecutionFlow("parent", params);
assertAdminEvents.assertEvent(REALM_NAME, OperationType.CREATE, AdminEventPaths.authAddExecutionFlowPath("parent"), params);
} }
} }

View file

@ -25,6 +25,9 @@ import javax.ws.rs.core.Response;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.keycloak.events.admin.OperationType;
import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
import org.keycloak.testsuite.util.AdminEventPaths;
/** /**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a> * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@ -34,13 +37,8 @@ public class RegistrationFlowTest extends AbstractAuthenticationTest {
@Test @Test
public void testAddExecution() { public void testAddExecution() {
// Add registration flow 2 // Add registration flow 2
Response response = authMgmtResource.createFlow(newFlow("registration2", "RegistrationFlow2", "basic-flow", true, false)); AuthenticationFlowRepresentation flowRep = newFlow("registration2", "RegistrationFlow2", "basic-flow", true, false);
try { createFlow(flowRep);
Assert.assertEquals("createFlow success", 201, response.getStatus());
} finally {
response.close();
}
// add registration execution form flow // add registration execution form flow
Map<String, String> data = new HashMap<>(); Map<String, String> data = new HashMap<>();
@ -49,6 +47,7 @@ public class RegistrationFlowTest extends AbstractAuthenticationTest {
data.put("description", "registrationForm2 flow"); data.put("description", "registrationForm2 flow");
data.put("provider", "registration-page-form"); data.put("provider", "registration-page-form");
authMgmtResource.addExecutionFlow("registration2", data); authMgmtResource.addExecutionFlow("registration2", data);
assertAdminEvents.assertEvent(REALM_NAME, OperationType.CREATE, AdminEventPaths.authAddExecutionFlowPath("registration2"), data);
// Should fail to add execution under top level flow // Should fail to add execution under top level flow
Map<String, String> data2 = new HashMap<>(); Map<String, String> data2 = new HashMap<>();
@ -63,9 +62,9 @@ public class RegistrationFlowTest extends AbstractAuthenticationTest {
// Should success to add execution under form flow // Should success to add execution under form flow
authMgmtResource.addExecution("registrationForm2", data2); authMgmtResource.addExecution("registrationForm2", data2);
assertAdminEvents.assertEvent(REALM_NAME, OperationType.CREATE, AdminEventPaths.authAddExecutionPath("registrationForm2"), data2);
} }
// TODO: More coverage... And hopefully more type-safety instead of passing generic maps // TODO: More type-safety instead of passing generic maps
} }

View file

@ -19,9 +19,11 @@ package org.keycloak.testsuite.admin.authentication;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.keycloak.events.admin.OperationType;
import org.keycloak.representations.idm.RequiredActionProviderRepresentation; import org.keycloak.representations.idm.RequiredActionProviderRepresentation;
import org.keycloak.representations.idm.RequiredActionProviderSimpleRepresentation; import org.keycloak.representations.idm.RequiredActionProviderSimpleRepresentation;
import org.keycloak.testsuite.actions.DummyRequiredActionFactory; import org.keycloak.testsuite.actions.DummyRequiredActionFactory;
import org.keycloak.testsuite.util.AdminEventPaths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -59,6 +61,7 @@ public class RequiredActionsTest extends AbstractAuthenticationTest {
forUpdate.setConfig(Collections.<String, String>emptyMap()); forUpdate.setConfig(Collections.<String, String>emptyMap());
authMgmtResource.updateRequiredAction(forUpdate.getAlias(), forUpdate); authMgmtResource.updateRequiredAction(forUpdate.getAlias(), forUpdate);
assertAdminEvents.assertEvent(REALM_NAME, OperationType.UPDATE, AdminEventPaths.authRequiredActionPath(forUpdate.getAlias()));
result = authMgmtResource.getRequiredActions(); result = authMgmtResource.getRequiredActions();
RequiredActionProviderRepresentation updated = findRequiredActionByAlias(forUpdate.getAlias(), result); RequiredActionProviderRepresentation updated = findRequiredActionByAlias(forUpdate.getAlias(), result);
@ -78,6 +81,7 @@ public class RequiredActionsTest extends AbstractAuthenticationTest {
// Register it // Register it
authMgmtResource.registerRequiredAction(action); authMgmtResource.registerRequiredAction(action);
assertAdminEvents.assertEvent(REALM_NAME, OperationType.CREATE, AdminEventPaths.authMgmtBasePath() + "/register-required-action", action);
// Try to find not-existent action - should fail // Try to find not-existent action - should fail
try { try {
@ -103,6 +107,7 @@ public class RequiredActionsTest extends AbstractAuthenticationTest {
// Update (set it as defaultAction) // Update (set it as defaultAction)
rep.setDefaultAction(true); rep.setDefaultAction(true);
authMgmtResource.updateRequiredAction(DummyRequiredActionFactory.PROVIDER_ID, rep); authMgmtResource.updateRequiredAction(DummyRequiredActionFactory.PROVIDER_ID, rep);
assertAdminEvents.assertEvent(REALM_NAME, OperationType.UPDATE, AdminEventPaths.authRequiredActionPath(rep.getAlias()), rep);
compareRequiredAction(rep, newRequiredAction(DummyRequiredActionFactory.PROVIDER_ID, "Dummy Action", compareRequiredAction(rep, newRequiredAction(DummyRequiredActionFactory.PROVIDER_ID, "Dummy Action",
true, true, Collections.emptyMap())); true, true, Collections.emptyMap()));
@ -116,6 +121,7 @@ public class RequiredActionsTest extends AbstractAuthenticationTest {
// Remove success // Remove success
authMgmtResource.removeRequiredAction(DummyRequiredActionFactory.PROVIDER_ID); authMgmtResource.removeRequiredAction(DummyRequiredActionFactory.PROVIDER_ID);
assertAdminEvents.assertEvent(REALM_NAME, OperationType.DELETE, AdminEventPaths.authRequiredActionPath(rep.getAlias()));
} }

View file

@ -19,7 +19,9 @@ package org.keycloak.testsuite.admin.authentication;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.keycloak.events.admin.OperationType;
import org.keycloak.representations.idm.AuthenticationExecutionInfoRepresentation; import org.keycloak.representations.idm.AuthenticationExecutionInfoRepresentation;
import org.keycloak.testsuite.util.AdminEventPaths;
import javax.ws.rs.NotFoundException; import javax.ws.rs.NotFoundException;
import javax.ws.rs.BadRequestException; import javax.ws.rs.BadRequestException;
@ -39,6 +41,7 @@ public class ShiftExecutionTest extends AbstractAuthenticationTest {
HashMap<String, String> params = new HashMap<>(); HashMap<String, String> params = new HashMap<>();
params.put("newName", "Copy of browser"); params.put("newName", "Copy of browser");
Response response = authMgmtResource.copy("browser", params); Response response = authMgmtResource.copy("browser", params);
assertAdminEvents.assertEvent(REALM_NAME, OperationType.CREATE, AdminEventPaths.authCopyFlowPath("browser"), params);
try { try {
Assert.assertEquals("Copy flow", 201, response.getStatus()); Assert.assertEquals("Copy flow", 201, response.getStatus());
} finally { } finally {
@ -61,6 +64,7 @@ public class ShiftExecutionTest extends AbstractAuthenticationTest {
// shift last execution up // shift last execution up
authMgmtResource.raisePriority(last.getId()); authMgmtResource.raisePriority(last.getId());
assertAdminEvents.assertEvent(REALM_NAME, OperationType.UPDATE, AdminEventPaths.authRaiseExecutionPath(last.getId()));
List<AuthenticationExecutionInfoRepresentation> executions2 = authMgmtResource.getExecutions("Copy of browser"); List<AuthenticationExecutionInfoRepresentation> executions2 = authMgmtResource.getExecutions("Copy of browser");
@ -80,6 +84,7 @@ public class ShiftExecutionTest extends AbstractAuthenticationTest {
// shift one before last down // shift one before last down
authMgmtResource.lowerPriority(oneButLast2.getId()); authMgmtResource.lowerPriority(oneButLast2.getId());
assertAdminEvents.assertEvent(REALM_NAME, OperationType.UPDATE, AdminEventPaths.authLowerExecutionPath(oneButLast2.getId()));
executions2 = authMgmtResource.getExecutions("Copy of browser"); executions2 = authMgmtResource.getExecutions("Copy of browser");

View file

@ -17,7 +17,6 @@
package org.keycloak.testsuite.admin.client; package org.keycloak.testsuite.admin.client;
import org.hamcrest.Matchers;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -27,7 +26,6 @@ import org.keycloak.events.admin.OperationType;
import org.keycloak.representations.idm.RoleRepresentation; import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.testsuite.Assert; import org.keycloak.testsuite.Assert;
import org.keycloak.testsuite.util.AdminEventPaths; import org.keycloak.testsuite.util.AdminEventPaths;
import org.keycloak.testsuite.util.RoleBuilder;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -75,15 +73,17 @@ public class ClientRolesTest extends AbstractClientTest {
@Test @Test
public void testAddRole() { public void testAddRole() {
rolesRsc.create(makeRole("role1")); RoleRepresentation role1 = makeRole("role1");
assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, Matchers.startsWith(AdminEventPaths.clientRolesResourcePath(clientDbId))); rolesRsc.create(role1);
assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, AdminEventPaths.clientRoleResourcePath(clientDbId, "role1"), role1);
assertTrue(hasRole(rolesRsc, "role1")); assertTrue(hasRole(rolesRsc, "role1"));
} }
@Test @Test
public void testRemoveRole() { public void testRemoveRole() {
rolesRsc.create(makeRole("role2")); RoleRepresentation role2 = makeRole("role2");
assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, Matchers.startsWith(AdminEventPaths.clientRolesResourcePath(clientDbId))); rolesRsc.create(role2);
assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, AdminEventPaths.clientRoleResourcePath(clientDbId, "role2"), role2);
rolesRsc.deleteRole("role2"); rolesRsc.deleteRole("role2");
assertAdminEvents.assertEvent(getRealmId(), OperationType.DELETE, AdminEventPaths.clientRoleResourcePath(clientDbId, "role2")); assertAdminEvents.assertEvent(getRealmId(), OperationType.DELETE, AdminEventPaths.clientRoleResourcePath(clientDbId, "role2"));
@ -93,25 +93,26 @@ public class ClientRolesTest extends AbstractClientTest {
@Test @Test
public void testComposites() { public void testComposites() {
rolesRsc.create(makeRole("role-a")); RoleRepresentation roleA = makeRole("role-a");
assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, Matchers.startsWith(AdminEventPaths.clientRolesResourcePath(clientDbId))); rolesRsc.create(roleA);
assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, AdminEventPaths.clientRoleResourcePath(clientDbId, "role-a"), roleA);
assertFalse(rolesRsc.get("role-a").toRepresentation().isComposite()); assertFalse(rolesRsc.get("role-a").toRepresentation().isComposite());
assertEquals(0, rolesRsc.get("role-a").getRoleComposites().size()); assertEquals(0, rolesRsc.get("role-a").getRoleComposites().size());
rolesRsc.create(makeRole("role-b")); RoleRepresentation roleB = makeRole("role-b");
assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, Matchers.startsWith(AdminEventPaths.clientRolesResourcePath(clientDbId))); rolesRsc.create(roleB);
assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, AdminEventPaths.clientRoleResourcePath(clientDbId, "role-b"), roleB);
testRealmResource().roles().create(makeRole("role-c")); RoleRepresentation roleC = makeRole("role-c");
assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, Matchers.startsWith(AdminEventPaths.rolesResourcePath())); testRealmResource().roles().create(roleC);
assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, AdminEventPaths.roleResourcePath("role-c"), roleC);
List<RoleRepresentation> l = new LinkedList<>(); List<RoleRepresentation> l = new LinkedList<>();
l.add(rolesRsc.get("role-b").toRepresentation()); l.add(rolesRsc.get("role-b").toRepresentation());
l.add(testRealmResource().roles().get("role-c").toRepresentation()); l.add(testRealmResource().roles().get("role-c").toRepresentation());
rolesRsc.get("role-a").addComposites(l); rolesRsc.get("role-a").addComposites(l);
// TODO adminEvents: Fix once composite roles events will be fixed... assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, AdminEventPaths.clientRoleResourceCompositesPath(clientDbId, "role-a"), l);
assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, Matchers.startsWith(AdminEventPaths.clientRoleResourceCompositesPath(clientDbId, "role-a")));
assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, Matchers.startsWith(AdminEventPaths.clientRoleResourceCompositesPath(clientDbId, "role-a")));
Set<RoleRepresentation> composites = rolesRsc.get("role-a").getRoleComposites(); Set<RoleRepresentation> composites = rolesRsc.get("role-a").getRoleComposites();
@ -125,7 +126,7 @@ public class ClientRolesTest extends AbstractClientTest {
Assert.assertNames(clientComposites, "role-b"); Assert.assertNames(clientComposites, "role-b");
rolesRsc.get("role-a").deleteComposites(l); 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()); assertFalse(rolesRsc.get("role-a").toRepresentation().isComposite());
assertEquals(0, rolesRsc.get("role-a").getRoleComposites().size()); assertEquals(0, rolesRsc.get("role-a").getRoleComposites().size());

View file

@ -26,7 +26,6 @@ import org.junit.Before;
import org.junit.FixMethodOrder; import org.junit.FixMethodOrder;
import org.junit.Test; import org.junit.Test;
import org.junit.runners.MethodSorters; 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.ClientTemplatesResource;
import org.keycloak.admin.client.resource.ProtocolMappersResource; import org.keycloak.admin.client.resource.ProtocolMappersResource;
import org.keycloak.events.admin.OperationType; import org.keycloak.events.admin.OperationType;

View file

@ -27,7 +27,6 @@ import javax.ws.rs.BadRequestException;
import javax.ws.rs.NotFoundException; import javax.ws.rs.NotFoundException;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import org.hamcrest.Matchers;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.keycloak.admin.client.resource.ClientTemplatesResource; import org.keycloak.admin.client.resource.ClientTemplatesResource;
@ -162,7 +161,7 @@ public class ClientTemplateTest extends AbstractClientTest {
// Add role2 as composite to role1 // Add role2 as composite to role1
testRealmResource().roles().get("role1").addComposites(Collections.singletonList(roleRep2)); 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 // create client template
ClientTemplateRepresentation templateRep = new ClientTemplateRepresentation(); ClientTemplateRepresentation templateRep = new ClientTemplateRepresentation();
@ -176,10 +175,10 @@ public class ClientTemplateTest extends AbstractClientTest {
RoleMappingResource scopesResource = clientTemplates().get(templateId).getScopeMappings(); RoleMappingResource scopesResource = clientTemplates().get(templateId).getScopeMappings();
scopesResource.realmLevel().add(Collections.singletonList(roleRep1)); 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)); 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) // test that scopes are available (also through composite role)
List<RoleRepresentation> allRealm = scopesResource.realmLevel().listAll(); List<RoleRepresentation> allRealm = scopesResource.realmLevel().listAll();
@ -198,10 +197,10 @@ public class ClientTemplateTest extends AbstractClientTest {
// remove scopes // remove scopes
scopesResource.realmLevel().remove(Collections.singletonList(roleRep1)); 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)); 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 // assert scopes are removed
allRealm = scopesResource.realmLevel().listAll(); allRealm = scopesResource.realmLevel().listAll();
@ -256,7 +255,7 @@ public class ClientTemplateTest extends AbstractClientTest {
// Add realm role to scopes of clientTemplate // Add realm role to scopes of clientTemplate
clientTemplates().get(templateId).getScopeMappings().realmLevel().add(Collections.singletonList(roleRep)); 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(); List<RoleRepresentation> roleReps = clientTemplates().get(templateId).getScopeMappings().realmLevel().listAll();
Assert.assertEquals(1, roleReps.size()); Assert.assertEquals(1, roleReps.size());
@ -279,7 +278,7 @@ public class ClientTemplateTest extends AbstractClientTest {
roleRep.setName(roleName); roleRep.setName(roleName);
testRealmResource().roles().create(roleRep); 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(); return testRealmResource().roles().get(roleName).toRepresentation();
} }

View file

@ -23,6 +23,7 @@ import org.junit.Test;
import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.admin.client.resource.RoleMappingResource; import org.keycloak.admin.client.resource.RoleMappingResource;
import org.keycloak.events.admin.OperationType; import org.keycloak.events.admin.OperationType;
import org.keycloak.models.RoleModel;
import org.keycloak.representations.AccessToken; import org.keycloak.representations.AccessToken;
import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.CredentialRepresentation;
@ -109,7 +110,7 @@ public class GroupTest extends AbstractGroupTest {
RoleRepresentation role = new RoleRepresentation(); RoleRepresentation role = new RoleRepresentation();
role.setName("foo-role"); role.setName("foo-role");
realm.clients().get(client.getId()).roles().create(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(); role = realm.clients().get(client.getId()).roles().get("foo-role").toRepresentation();
GroupRepresentation group = new GroupRepresentation(); GroupRepresentation group = new GroupRepresentation();
@ -119,7 +120,7 @@ public class GroupTest extends AbstractGroupTest {
List<RoleRepresentation> list = new LinkedList<>(); List<RoleRepresentation> list = new LinkedList<>();
list.add(role); list.add(role);
realm.groups().group(group.getId()).roles().clientLevel(client.getId()).add(list); 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(); realm.clients().get(client.getId()).remove();
assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.clientResourcePath(clientUuid)); assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.clientResourcePath(clientUuid));
@ -130,8 +131,7 @@ public class GroupTest extends AbstractGroupTest {
String groupId = ApiUtil.getCreatedId(response); String groupId = ApiUtil.getCreatedId(response);
response.close(); response.close();
// TODO adminEvents: ID of group is missing in create event assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.groupPath(groupId), group);
assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.groupsPath(), group);
// Set ID to the original rep // Set ID to the original rep
group.setId(groupId); group.setId(groupId);
@ -170,14 +170,13 @@ public class GroupTest extends AbstractGroupTest {
List<RoleRepresentation> roles = new LinkedList<>(); List<RoleRepresentation> roles = new LinkedList<>();
roles.add(topRole); roles.add(topRole);
realm.groups().group(topGroup.getId()).roles().realmLevel().add(roles); 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(); GroupRepresentation level2Group = new GroupRepresentation();
level2Group.setName("level2"); level2Group.setName("level2");
Response response = realm.groups().group(topGroup.getId()).subGroup(level2Group); Response response = realm.groups().group(topGroup.getId()).subGroup(level2Group);
response.close(); response.close();
// TODO adminEvents: Should be CREATE assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.groupSubgroupsPath(topGroup.getId()), level2Group);
assertAdminEvents.assertEvent("test", OperationType.UPDATE, AdminEventPaths.groupSubgroupsPath(topGroup.getId()), level2Group);
URI location = response.getLocation(); URI location = response.getLocation();
final String level2Id = ApiUtil.getCreatedId(response); final String level2Id = ApiUtil.getCreatedId(response);
@ -198,21 +197,20 @@ public class GroupTest extends AbstractGroupTest {
roles.clear(); roles.clear();
roles.add(level2Role); roles.add(level2Role);
realm.groups().group(level2Group.getId()).roles().realmLevel().add(roles); 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(); GroupRepresentation level3Group = new GroupRepresentation();
level3Group.setName("level3"); level3Group.setName("level3");
response = realm.groups().group(level2Group.getId()).subGroup(level3Group); response = realm.groups().group(level2Group.getId()).subGroup(level3Group);
response.close(); response.close();
// TODO adminEvents: Should be CREATE assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.groupSubgroupsPath(level2Group.getId()), level3Group);
assertAdminEvents.assertEvent("test", OperationType.UPDATE, AdminEventPaths.groupSubgroupsPath(level2Group.getId()), level3Group);
level3Group = realm.getGroupByPath("/top/level2/level3"); level3Group = realm.getGroupByPath("/top/level2/level3");
Assert.assertNotNull(level3Group); Assert.assertNotNull(level3Group);
roles.clear(); roles.clear();
roles.add(level3Role); roles.add(level3Role);
realm.groups().group(level3Group.getId()).roles().realmLevel().add(roles); 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"); topGroup = realm.getGroupByPath("/top");
assertEquals(1, topGroup.getRealmRoles().size()); assertEquals(1, topGroup.getRealmRoles().size());
@ -232,7 +230,7 @@ public class GroupTest extends AbstractGroupTest {
UserRepresentation user = realm.users().search("direct-login", -1, -1).get(0); UserRepresentation user = realm.users().search("direct-login", -1, -1).get(0);
realm.users().get(user.getId()).joinGroup(level3Group.getId()); realm.users().get(user.getId()).joinGroup(level3Group.getId());
assertAdminEvents.assertEvent("test", OperationType.CREATE, Matchers.startsWith(AdminEventPaths.userGroupPath(user.getId(), level3Group.getId()))); assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.userGroupPath(user.getId(), level3Group.getId()));
List<GroupRepresentation> membership = realm.users().get(user.getId()).groups(); List<GroupRepresentation> membership = realm.users().get(user.getId()).groups();
assertEquals(1, membership.size()); assertEquals(1, membership.size());
@ -244,6 +242,7 @@ public class GroupTest extends AbstractGroupTest {
assertTrue(token.getRealmAccess().getRoles().contains("level3Role")); assertTrue(token.getRealmAccess().getRoles().contains("level3Role"));
realm.addDefaultGroup(level3Group.getId()); realm.addDefaultGroup(level3Group.getId());
assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.defaultGroupPath(level3Group.getId()));
List<GroupRepresentation> defaultGroups = realm.getDefaultGroups(); List<GroupRepresentation> defaultGroups = realm.getDefaultGroups();
assertEquals(1, defaultGroups.size()); assertEquals(1, defaultGroups.size());
@ -262,6 +261,8 @@ public class GroupTest extends AbstractGroupTest {
assertEquals("level3", membership.get(0).getName()); assertEquals("level3", membership.get(0).getName());
realm.removeDefaultGroup(level3Group.getId()); realm.removeDefaultGroup(level3Group.getId());
assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.defaultGroupPath(level3Group.getId()));
defaultGroups = realm.getDefaultGroups(); defaultGroups = realm.getDefaultGroups();
assertEquals(0, defaultGroups.size()); assertEquals(0, defaultGroups.size());
@ -347,19 +348,19 @@ public class GroupTest extends AbstractGroupTest {
assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.userResourcePath(userBId)); assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.userResourcePath(userBId));
realm.users().get(userAId).joinGroup(groupId); realm.users().get(userAId).joinGroup(groupId);
assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.userGroupPath(userAId, groupId)); assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.userGroupPath(userAId, groupId), group);
List<UserRepresentation> members = realm.groups().group(groupId).members(0, 10); List<UserRepresentation> members = realm.groups().group(groupId).members(0, 10);
assertNames(members, "user-a"); assertNames(members, "user-a");
realm.users().get(userBId).joinGroup(groupId); realm.users().get(userBId).joinGroup(groupId);
assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.userGroupPath(userBId, groupId)); assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.userGroupPath(userBId, groupId), group);
members = realm.groups().group(groupId).members(0, 10); members = realm.groups().group(groupId).members(0, 10);
assertNames(members, "user-a", "user-b"); assertNames(members, "user-a", "user-b");
realm.users().get(userAId).leaveGroup(groupId); realm.users().get(userAId).leaveGroup(groupId);
assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.userGroupPath(userAId, groupId)); assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.userGroupPath(userAId, groupId), group);
members = realm.groups().group(groupId).members(0, 10); members = realm.groups().group(groupId).members(0, 10);
assertNames(members, "user-b"); assertNames(members, "user-b");
@ -417,14 +418,15 @@ public class GroupTest extends AbstractGroupTest {
l.add(realm.roles().get("realm-role").toRepresentation()); l.add(realm.roles().get("realm-role").toRepresentation());
l.add(realm.roles().get("realm-composite").toRepresentation()); l.add(realm.roles().get("realm-composite").toRepresentation());
roles.realmLevel().add(l); roles.realmLevel().add(l);
assertAdminEvents.assertEvent("test", OperationType.CREATE, Matchers.startsWith(AdminEventPaths.groupRolesRealmRolesPath(group.getId()))); assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.groupRolesRealmRolesPath(group.getId()), l);
assertAdminEvents.assertEvent("test", OperationType.CREATE, Matchers.startsWith(AdminEventPaths.groupRolesRealmRolesPath(group.getId())));
// Add client roles // Add client roles
roles.clientLevel(clientId).add(Collections.singletonList(realm.clients().get(clientId).roles().get("client-role").toRepresentation())); RoleRepresentation clientRole = realm.clients().get(clientId).roles().get("client-role").toRepresentation();
roles.clientLevel(clientId).add(Collections.singletonList(realm.clients().get(clientId).roles().get("client-composite").toRepresentation())); RoleRepresentation clientComposite = realm.clients().get(clientId).roles().get("client-composite").toRepresentation();
assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.groupRolesClientRolesPath(group.getId(), clientId)); roles.clientLevel(clientId).add(Collections.singletonList(clientRole));
assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.groupRolesClientRolesPath(group.getId(), clientId)); 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 // List realm roles
assertNames(roles.realmLevel().listAll(), "realm-role", "realm-composite"); assertNames(roles.realmLevel().listAll(), "realm-role", "realm-composite");
@ -443,16 +445,15 @@ public class GroupTest extends AbstractGroupTest {
assertNames(all.getClientMappings().get("myclient").getMappings(), "client-role", "client-composite"); assertNames(all.getClientMappings().get("myclient").getMappings(), "client-role", "client-composite");
// Remove realm role // 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(); RoleRepresentation realmRoleRep = realm.roles().get("realm-role").toRepresentation();
roles.realmLevel().remove(Collections.singletonList(realmRoleRep)); 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"); assertNames(roles.realmLevel().listAll(), "realm-composite");
// Remove client role // Remove client role
RoleRepresentation clientRoleRep = realm.clients().get(clientId).roles().get("client-role").toRepresentation(); RoleRepresentation clientRoleRep = realm.clients().get(clientId).roles().get("client-role").toRepresentation();
roles.clientLevel(clientId).remove(Collections.singletonList(clientRoleRep)); 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"); assertNames(roles.clientLevel(clientId).listAll(), "client-composite");
} }

View file

@ -17,10 +17,8 @@
package org.keycloak.testsuite.admin.realm; package org.keycloak.testsuite.admin.realm;
import org.hamcrest.Matchers;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.keycloak.admin.client.resource.RoleByIdResource;
import org.keycloak.admin.client.resource.RolesResource; import org.keycloak.admin.client.resource.RolesResource;
import org.keycloak.events.admin.OperationType; import org.keycloak.events.admin.OperationType;
import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.ClientRepresentation;
@ -80,12 +78,11 @@ public class RealmRolesTest extends AbstractAdminTest {
resource = adminClient.realm(REALM_NAME).roles(); 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("role-a"), roleA);
assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.roleResourcePath(ids.get("role-a")), roleA); assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.roleResourcePath("role-b"), roleB);
assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.roleResourcePath(ids.get("role-b")), roleB);
assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientResourcePath(clientUuid), clientRep); 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 @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-b")).build());
l.add(RoleBuilder.create().id(ids.get("role-c")).build()); l.add(RoleBuilder.create().id(ids.get("role-c")).build());
resource.get("role-a").addComposites(l); 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, AdminEventPaths.roleResourceCompositesPath("role-a"), l);
assertAdminEvents.assertEvent(realmId, OperationType.CREATE, Matchers.startsWith(AdminEventPaths.roleResourceCompositesPath("role-a")));
Set<RoleRepresentation> composites = resource.get("role-a").getRoleComposites(); Set<RoleRepresentation> composites = resource.get("role-a").getRoleComposites();
@ -154,7 +150,7 @@ public class RealmRolesTest extends AbstractAdminTest {
Assert.assertNames(clientComposites, "role-c"); Assert.assertNames(clientComposites, "role-c");
resource.get("role-a").deleteComposites(l); 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()); assertFalse(resource.get("role-a").toRepresentation().isComposite());
assertEquals(0, resource.get("role-a").getRoleComposites().size()); assertEquals(0, resource.get("role-a").getRoleComposites().size());

View file

@ -282,7 +282,7 @@ public class RealmTest extends AbstractAdminTest {
public void deleteDefaultRole() { public void deleteDefaultRole() {
RoleRepresentation role = new RoleRepresentation("test", "test", false); RoleRepresentation role = new RoleRepresentation("test", "test", false);
realm.roles().create(role); 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()); assertNotNull(realm.roles().get("test").toRepresentation());
@ -523,7 +523,7 @@ public class RealmTest extends AbstractAdminTest {
assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, Matchers.nullValue(String.class), rep); assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, Matchers.nullValue(String.class), rep);
GlobalRequestResult globalRequestResult = realm.pushRevocation(); GlobalRequestResult globalRequestResult = realm.pushRevocation();
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, "push-revocation"); assertAdminEvents.assertEvent(realmId, OperationType.ACTION, "push-revocation", globalRequestResult);
assertEquals(1, globalRequestResult.getSuccessRequests().size()); assertEquals(1, globalRequestResult.getSuccessRequests().size());
assertEquals("http://localhost:8180/auth/realms/master/app/admin", globalRequestResult.getSuccessRequests().get(0)); assertEquals("http://localhost:8180/auth/realms/master/app/admin", globalRequestResult.getSuccessRequests().get(0));
@ -548,7 +548,7 @@ public class RealmTest extends AbstractAdminTest {
oauth.doLogin("user", "password"); oauth.doLogin("user", "password");
GlobalRequestResult globalRequestResult = realm.logoutAll(); GlobalRequestResult globalRequestResult = realm.logoutAll();
assertAdminEvents.assertEvent(realmId, OperationType.ACTION, "logout-all"); assertAdminEvents.assertEvent(realmId, OperationType.ACTION, "logout-all", globalRequestResult);
assertEquals(1, globalRequestResult.getSuccessRequests().size()); assertEquals(1, globalRequestResult.getSuccessRequests().size());
assertEquals("http://localhost:8180/auth/realms/master/app/admin", globalRequestResult.getSuccessRequests().get(0)); assertEquals("http://localhost:8180/auth/realms/master/app/admin", globalRequestResult.getSuccessRequests().get(0));

View file

@ -21,6 +21,8 @@ import java.net.URI;
import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriBuilder;
import org.keycloak.admin.client.resource.AttackDetectionResource;
import org.keycloak.admin.client.resource.AuthenticationManagementResource;
import org.keycloak.admin.client.resource.ClientAttributeCertificateResource; import org.keycloak.admin.client.resource.ClientAttributeCertificateResource;
import org.keycloak.admin.client.resource.ClientInitialAccessResource; import org.keycloak.admin.client.resource.ClientInitialAccessResource;
import org.keycloak.admin.client.resource.ClientResource; import org.keycloak.admin.client.resource.ClientResource;
@ -54,6 +56,11 @@ public class AdminEventPaths {
return uri.toString(); return uri.toString();
} }
public static String defaultGroupPath(String groupId) {
URI uri = UriBuilder.fromUri("").path(RealmResource.class, "addDefaultGroup").build(groupId);
return uri.toString();
}
// CLIENT RESOURCE // CLIENT RESOURCE
@ -353,4 +360,99 @@ public class AdminEventPaths {
} }
// AUTHENTICATION FLOWS
public static String authMgmtBasePath() {
URI uri = UriBuilder.fromUri("").path(RealmResource.class, "flows")
.build();
return uri.toString();
}
public static String authFlowsPath() {
URI uri = UriBuilder.fromUri(authMgmtBasePath()).path(AuthenticationManagementResource.class, "getFlows")
.build();
return uri.toString();
}
public static String authFlowPath(String flowId) {
URI uri = UriBuilder.fromUri(authMgmtBasePath()).path(AuthenticationManagementResource.class, "getFlow")
.build(flowId);
return uri.toString();
}
public static String authCopyFlowPath(String flowAlias) {
URI uri = UriBuilder.fromUri(authMgmtBasePath()).path(AuthenticationManagementResource.class, "copy")
.build(flowAlias);
return uri.toString();
}
public static String authAddExecutionFlowPath(String flowAlias) {
URI uri = UriBuilder.fromUri(authMgmtBasePath()).path(AuthenticationManagementResource.class, "addExecutionFlow")
.build(flowAlias);
return uri.toString();
}
public static String authAddExecutionPath(String flowAlias) {
return authFlowPath(flowAlias) + "/executions/execution";
}
public static String authUpdateExecutionPath(String flowAlias) {
URI uri = UriBuilder.fromUri(authMgmtBasePath()).path(AuthenticationManagementResource.class, "updateExecutions")
.build(flowAlias);
return uri.toString();
}
public static String authExecutionPath(String executionId) {
URI uri = UriBuilder.fromUri(authMgmtBasePath()).path(AuthenticationManagementResource.class, "removeExecution")
.build(executionId);
return uri.toString();
}
public static String authAddExecutionConfigPath(String executionId) {
URI uri = UriBuilder.fromUri(authMgmtBasePath()).path(AuthenticationManagementResource.class, "newExecutionConfig")
.build(executionId);
return uri.toString();
}
public static String authExecutionConfigPath(String configId) {
URI uri = UriBuilder.fromUri(authMgmtBasePath()).path(AuthenticationManagementResource.class, "getAuthenticatorConfig")
.build(configId);
return uri.toString();
}
public static String authRaiseExecutionPath(String executionId) {
URI uri = UriBuilder.fromUri(authMgmtBasePath()).path(AuthenticationManagementResource.class, "raisePriority")
.build(executionId);
return uri.toString();
}
public static String authLowerExecutionPath(String executionId) {
URI uri = UriBuilder.fromUri(authMgmtBasePath()).path(AuthenticationManagementResource.class, "lowerPriority")
.build(executionId);
return uri.toString();
}
public static String authRequiredActionPath(String requiredActionAlias) {
URI uri = UriBuilder.fromUri(authMgmtBasePath()).path(AuthenticationManagementResource.class, "getRequiredAction")
.build(requiredActionAlias);
return uri.toString();
}
// ATTACK DETECTION
public static String attackDetectionClearBruteForceForUserPath(String username) {
URI uri = UriBuilder.fromUri("").path(RealmResource.class, "attackDetection")
.path(AttackDetectionResource.class, "clearBruteForceForUser")
.build(username);
return uri.toString();
}
public static String attackDetectionClearAllBruteForcePath() {
URI uri = UriBuilder.fromUri("").path(RealmResource.class, "attackDetection")
.path(AttackDetectionResource.class, "clearAllBruteForce")
.build();
return uri.toString();
}
} }

View file

@ -17,13 +17,22 @@
package org.keycloak.testsuite.util; package org.keycloak.testsuite.util;
import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Method; 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 javax.ws.rs.core.Response;
import com.fasterxml.jackson.core.type.TypeReference;
import org.hamcrest.Description;
import org.hamcrest.Matcher; import org.hamcrest.Matcher;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.hamcrest.TypeSafeMatcher;
import org.junit.rules.TestRule; import org.junit.rules.TestRule;
import org.junit.runners.model.Statement; import org.junit.runners.model.Statement;
import org.keycloak.common.util.ObjectUtil; import org.keycloak.common.util.ObjectUtil;
@ -34,7 +43,9 @@ import org.keycloak.jose.jws.JWSInputException;
import org.keycloak.representations.AccessToken; import org.keycloak.representations.AccessToken;
import org.keycloak.representations.idm.AdminEventRepresentation; import org.keycloak.representations.idm.AdminEventRepresentation;
import org.keycloak.representations.idm.AuthDetailsRepresentation; import org.keycloak.representations.idm.AuthDetailsRepresentation;
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.testsuite.AbstractKeycloakTest; import org.keycloak.testsuite.AbstractKeycloakTest;
import org.keycloak.testsuite.Assert; import org.keycloak.testsuite.Assert;
import org.keycloak.util.JsonSerialization; import org.keycloak.util.JsonSerialization;
@ -179,8 +190,8 @@ public class AssertAdminEvents implements TestRule {
public AdminEventRepresentation assertEvent(AdminEventRepresentation actual) { public AdminEventRepresentation assertEvent(AdminEventRepresentation actual) {
Assert.assertEquals(expected.getRealmId(), actual.getRealmId()); Assert.assertEquals(expected.getRealmId(), actual.getRealmId());
Assert.assertEquals(expected.getOperationType(), actual.getOperationType());
Assert.assertThat(actual.getResourcePath(), resourcePath); Assert.assertThat(actual.getResourcePath(), resourcePath);
Assert.assertEquals(expected.getOperationType(), actual.getOperationType());
Assert.assertTrue(ObjectUtil.isEqualOrBothNull(expected.getError(), actual.getError())); Assert.assertTrue(ObjectUtil.isEqualOrBothNull(expected.getError(), actual.getError()));
@ -197,20 +208,55 @@ public class AssertAdminEvents implements TestRule {
Assert.assertEquals(expectedAuth.getClientId(), actualAuth.getClientId()); 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 (expectedRep != null) {
if (actual.getRepresentation() == null) { if (actual.getRepresentation() == null) {
Assert.fail("Expected representation " + expectedRep + " but no representation was available on actual event"); Assert.fail("Expected representation " + expectedRep + " but no representation was available on actual event");
} else { } else {
try { try {
Object actualRep = JsonSerialization.readValue(actual.getRepresentation(), expectedRep.getClass());
for (Method method : Reflections.getAllDeclaredMethods(expectedRep.getClass())) { if (expectedRep instanceof List) {
if (method.getName().startsWith("get") || method.getName().startsWith("is")) { // List of roles. All must be available in actual representation
Object expectedValue = Reflections.invokeMethod(method, expectedRep); 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;
for (Map.Entry entry : expectedRepMap.entrySet()) {
Object expectedValue = entry.getValue();
if (expectedValue != null) { if (expectedValue != null) {
Object actualValue = Reflections.invokeMethod(method, actualRep); Object actualValue = actualRepMap.get(entry.getKey());
Assert.assertEquals("Property " + method.getName() + " of representation not equal.", expectedValue, actualValue); Assert.assertEquals("Map item with key '" + entry.getKey() + "' not equal.", expectedValue, actualValue);
}
}
} else {
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);
if (expectedValue != null) {
Object actualValue = Reflections.invokeMethod(method, actualRep);
Assert.assertEquals("Property method '" + method.getName() + "' of representation not equal.", expectedValue, actualValue);
}
} }
} }
} }
@ -241,5 +287,22 @@ public class AssertAdminEvents implements TestRule {
} }
} }
public static Matcher<String> isExpectedPrefixFollowedByUuid(final String prefix) {
return new TypeSafeMatcher<String>() {
@Override
protected boolean matchesSafely(String item) {
int expectedLength = prefix.length() + 1 + org.keycloak.models.utils.KeycloakModelUtils.generateId().length();
return item.startsWith(prefix) && expectedLength == item.length();
}
@Override
public void describeTo(Description description) {
description.appendText("resourcePath in the format like \"" + prefix + "/<UUID>\"");
}
};
}
} }