8000 Issue #8749: Add an option to control the order of the event query and admin event query by leischt · Pull Request #8822 · keycloak/keycloak · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Issue #8749: Add an option to control the order of the event query and admin event query #8822

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ public class JpaAdminEventQuery implements AdminEventQuery {
private final ArrayList<Predicate> predicates;
private Integer firstResult;
private Integer maxResults;

private boolean orderByDescTime = true;

public JpaAdminEventQuery(EntityManager em) {
this.em = em;

Expand Down Expand Up @@ -143,13 +144,29 @@ public AdminEventQuery maxResults(int maxResults) {
return this;
}

@Override
public AdminEventQuery orderByDescTime() {
orderByDescTime = true;
return this;
}

@Override
public AdminEventQuery orderByAscTime() {
orderByDescTime = false;
return this;
}

@Override
public Stream<AdminEvent> getResultStream() {
if (!predicates.isEmpty()) {
cq.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
}

cq.orderBy(cb.desc(root.get("time")));
if (orderByDescTime) {
cq.orderBy(cb.desc(root.get("time")));
} else {
cq.orderBy(cb.asc(root.get("time")));
}

TypedQuery<AdminEventEntity> query = em.createQuery(cq);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public class JpaEventQuery implements EventQuery {
private final ArrayList<Predicate> predicates;
private Integer firstResult;
private Integer maxResults;
private boolean orderByDescTime = true;

public JpaEventQuery(EntityManager em) {
this.em = em;
Expand Down Expand Up @@ -116,13 +117,29 @@ public EventQuery maxResults(int maxResults) {
return this;
}

@Override
public EventQuery orderByDescTime() {
orderByDescTime = true;
return this;
}

@Override
public EventQuery orderByAscTime() {
orderByDescTime = false;
return this;
}

@Override
public Stream<Event> getResultStream() {
if (!predicates.isEmpty()) {
cq.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
}

cq.orderBy(cb.desc(root.get("time")));
if(orderByDescTime) {
cq.orderBy(cb.desc(root.get("time")));
} else {
cq.orderBy(cb.asc(root.get("time")));
}

TypedQuery<EventEntity> query = em.createQuery(cq);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,15 @@
import static org.keycloak.models.map.storage.ModelCriteriaBuilder.Operator.IN;
import static org.keycloak.models.map.storage.ModelCriteriaBuilder.Operator.LE;
import static org.keycloak.models.map.storage.ModelCriteriaBuilder.Operator.LIKE;
import static org.keycloak.models.map.storage.QueryParameters.Order.ASCENDING;
import static org.keycloak.models.map.storage.QueryParameters.Order.DESCENDING;
import static org.keycloak.models.map.storage.criteria.DefaultModelCriteria.criteria;

public class MapAdminEventQuery implements AdminEventQuery {

private Integer firstResult;
private Integer maxResults;
private QueryParameters.Order order = DESCENDING;
private DefaultModelCriteria<AdminEvent> mcb = criteria();
private final Function<QueryParameters<AdminEvent>, Stream<AdminEvent>> resultProducer;

Expand Down Expand Up @@ -121,12 +123,24 @@ public AdminEventQuery maxResults(int max) {
return this;
}

@Override
public AdminEventQuery orderByDescTime() {
order = DESCENDING;
return this;
}

@Override
public AdminEventQuery orderByAscTime() {
order = ASCENDING;
return this;
}

@Override
public Stream<AdminEvent> getResultStream() {
return resultProducer.apply(QueryParameters.withCriteria(mcb)
.offset(firstResult)
.limit(maxResults)
.orderBy(SearchableFields.TIMESTAMP, DESCENDING)
.orderBy(SearchableFields.TIMESTAMP, order)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@
import static org.keycloak.models.map.storage.ModelCriteriaBuilder.Operator.GE;
import static org.keycloak.models.map.storage.ModelCriteriaBuilder.Operator.IN;
import static org.keycloak.models.map.storage.ModelCriteriaBuilder.Operator.LE;
import static org.keycloak.models.map.storage.QueryParameters.Order.ASCENDING;
import static org.keycloak.models.map.storage.QueryParameters.Order.DESCENDING;
import static org.keycloak.models.map.storage.criteria.DefaultModelCriteria.criteria;

public class MapAuthEventQuery implements EventQuery {

private Integer firstResult;
private Integer maxResults;
private QueryParameters.Order order = DESCENDING;
private DefaultModelCriteria<Event> mcb = criteria();
private final Function<QueryParameters<Event>, Stream<Event>> resultProducer;

Expand Down Expand Up @@ -101,11 +103,23 @@ public EventQuery maxResults(int max) {
return this;
}

@Override
public EventQuery orderByDescTime() {
order = DESCENDING;
return this;
}

@Override
public EventQuery orderByAscTime() {
order = ASCENDING;
return this;
}

@Override
public Stream<Event> getResultStream() {
return resultProducer.apply(QueryParameters.withCriteria(mcb)
.offset(firstResult)
.limit(maxResults)
.orderBy(SearchableFields.TIMESTAMP, DESCENDING));
.orderBy(SearchableFields.TIMESTAMP, order));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,20 @@ public interface EventQuery {
*/
EventQuery maxResults(int max);

/**
* Order the result by descending time
*
* @return <code>this</code> for method chaining
*/
EventQuery orderByDescTime();

/**
* Order the result by ascending time
*
* @return <code>this</code> for method chaining
*/
EventQuery orderByAscTime();

/**
* @deprecated Use {@link #getResultStream() getResultStream} instead.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,20 @@ public interface AdminEventQuery {
*/
AdminEventQuery maxResults(int max);

/**
* Order the result by descending time
*
* @return <code>this</code> for method chaining
*/
AdminEventQuery orderByDescTime();

/**
* Order the result by ascending time
*
* @return <code>this</code> for method chaining
*/
AdminEventQuery orderByAscTime();

/**
* Executes the query and returns the results
* @deprecated Use {@link #getResultStream() getResultStream} instead.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ private AdminEventBuilder createAdminEventBuilder(KeycloakIdentity identity, Res
KeycloakSession keycloakSession = authorization.getKeycloakSession();
UserModel serviceAccount = keycloakSession.users().getServiceAccount(client);
AdminEventBuilder adminEvent = new AdminEventBuilder(realm, new AdminAuth(realm, identity.getAccessToken(), serviceAccount, client), keycloakSession, clientConnection);
return adminEvent.realm(realm).authClient(client).authUser(serviceAccount);
return adminEvent;
}

@Path("/permission")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public AdminEventBuilder(RealmModel realm, AdminAuth auth, KeycloakSession sessi
this.listeners = new HashMap<>();
updateStore(session);
addListeners(session);

realm(realm);
authRealm(auth.getRealm());
authClient(auth.getClient());
authUser(auth.getUser());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public RealmAdminResource(AdminPermissionEvaluator auth, RealmModel realm, Token
this.auth = auth;
this.realm = realm;
this.tokenManager = tokenManager;
this.adminEvent = adminEvent.realm(realm).resource(ResourceType.REALM);
this.adminEvent = adminEvent.resource(ResourceType.REALM);
}

/**
Expand Down Expand Up @@ -699,7 +699,7 @@ public void updateRealmEventsConfig(final RealmEventsConfigRepresentation rep) {

logger.debug("updating realm events config: " + realm.getName());
new RealmManager(session).updateRealmEventsConfig(rep, realm);
adminEvent.operation(OperationType.UPDATE).resource(ResourceType.REALM).realm(realm)
adminEvent.operation(OperationType.UPDATE).resource(ResourceType.REALM)
.resourcePath(session.getContext().getUri()).representation(rep)
// refresh the builder to consider old and new config
.refreshRealmEventsConfig(session)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,31 @@ public void defaultMaxResults() {
assertThat(realm.getAdminEvents(null, null, null, null, null, null, null, null, 0, 1000).size(), is(greaterThanOrEqualTo(110)));
}

@Test
public void orderResultsTest() {
RealmResource realm = adminClient.realms().realm("test");
AdminEventRepresentation firstEvent = new AdminEventRepresentation();
firstEvent.setOperationType(OperationType.CREATE.toString());
firstEvent.setAuthDetails(new AuthDetailsRepresentation());
firstEvent.setRealmId(realm.toRepresentation().getId());
firstEvent.setTime(System.currentTimeMillis() - 1000);

AdminEventRepresentation secondEvent = new AdminEventRepresentation();
secondEvent.setOperationType(OperationType.DELETE.toString());
secondEvent.setAuthDetails(new AuthDetailsRepresentation());
secondEvent.setRealmId(realm.toRepresentation().getId());
secondEvent.setTime(System.currentTimeMillis());

testingClient.testing("test").onAdminEvent(firstEvent, false);
testingClient.testing("test").onAdminEvent(secondEvent, false);

List<AdminEventRepresentation> adminEvents = realm.getAdminEvents(null, null, null, null, null, null, null, null, null, null);
assertThat(adminEvents.size(), is(equalTo(2)));
assertThat(adminEvents.get(0).getOperationType(), is(equalTo(OperationType.DELETE.toString())));
assertThat(adminEvents.get(1).getOperationType(), is(equalTo(OperationType.CREATE.toString())));
}


private void checkUpdateRealmEventsConfigEvent(int size) {
List<AdminEventRepresentation> events = events();
assertThat(events.size(), is(equalTo(size)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,30 @@ public void defaultMaxResults() {
assertTrue(realm.getEvents(null, null, null, null, null, null, 0, 1000).size() >= 110);
}

@Test
public void orderResultsTest() {
RealmResource realm = adminClient.realms().realm("test");
EventRepresentation firstEvent = new EventRepresentation();
firstEvent.setRealmId(realm.toRepresentation().getId());
firstEvent.setType(EventType.LOGIN.toString());
firstEvent.setTime(System.currentTimeMillis() - 1000);

EventRepresentation secondEvent = new EventRepresentation();
secondEvent.setRealmId(realm.toRepresentation().getId());
secondEvent.setType(EventType.LOGOUT.toString());
secondEvent.setTime(System.currentTimeMillis());

528C
testingClient.testing("test").onEvent(firstEvent);
testingClient.testing("test").onEvent(secondEvent);

List<EventRepresentation> events = realm.getEvents(null, null, null, null, null, null, null, null);
assertEquals(2, events.size());
assertEquals(EventType.LOGOUT.toString(), events.get(0).getType());
assertEquals(EventType.LOGIN.toString(), events.get(1).getType());

}

/*
Removed this test because it takes too long. The default interval for
event cleanup is 15 minutes (900 seconds). I don't have time to figure out
Expand Down
Loading
0