[KEYCLOAK-1050] - Improve filtering in Event viewer in admin app.
This commit is contained in:
parent
6874933724
commit
ce33ce2485
8 changed files with 249 additions and 17 deletions
|
@ -18,6 +18,10 @@ public class Event {
|
||||||
|
|
||||||
private String userId;
|
private String userId;
|
||||||
|
|
||||||
|
private long fromDate;
|
||||||
|
|
||||||
|
private long toDate;
|
||||||
|
|
||||||
private String sessionId;
|
private String sessionId;
|
||||||
|
|
||||||
private String ipAddress;
|
private String ipAddress;
|
||||||
|
@ -58,6 +62,22 @@ public class Event {
|
||||||
this.clientId = clientId;
|
this.clientId = clientId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getFromDate() {
|
||||||
|
return fromDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFromDate(long fromDate) {
|
||||||
|
this.fromDate = fromDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getToDate() {
|
||||||
|
return toDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToDate(long toDate) {
|
||||||
|
this.toDate = toDate;
|
||||||
|
}
|
||||||
|
|
||||||
public String getUserId() {
|
public String getUserId() {
|
||||||
return userId;
|
return userId;
|
||||||
}
|
}
|
||||||
|
@ -105,6 +125,8 @@ public class Event {
|
||||||
clone.realmId = realmId;
|
clone.realmId = realmId;
|
||||||
clone.clientId = clientId;
|
clone.clientId = clientId;
|
||||||
clone.userId = userId;
|
clone.userId = userId;
|
||||||
|
clone.fromDate = fromDate;
|
||||||
|
clone.toDate = toDate;
|
||||||
clone.sessionId = sessionId;
|
clone.sessionId = sessionId;
|
||||||
clone.ipAddress = ipAddress;
|
clone.ipAddress = ipAddress;
|
||||||
clone.error = error;
|
clone.error = error;
|
||||||
|
|
|
@ -15,6 +15,12 @@ public interface EventQuery {
|
||||||
|
|
||||||
public EventQuery user(String userId);
|
public EventQuery user(String userId);
|
||||||
|
|
||||||
|
public EventQuery dateRange(String fromDate, String toDate);
|
||||||
|
|
||||||
|
public EventQuery fromDate(String fromDate);
|
||||||
|
|
||||||
|
public EventQuery toDate(String toDate);
|
||||||
|
|
||||||
public EventQuery ipAddress(String ipAddress);
|
public EventQuery ipAddress(String ipAddress);
|
||||||
|
|
||||||
public EventQuery firstResult(int result);
|
public EventQuery firstResult(int result);
|
||||||
|
|
|
@ -10,6 +10,9 @@ import javax.persistence.criteria.CriteriaBuilder;
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
import javax.persistence.criteria.Predicate;
|
import javax.persistence.criteria.Predicate;
|
||||||
import javax.persistence.criteria.Root;
|
import javax.persistence.criteria.Root;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -64,6 +67,47 @@ public class JpaEventQuery implements EventQuery {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventQuery dateRange(String fromDate, String toDate) {
|
||||||
|
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
Long from = null, to = null;
|
||||||
|
try {
|
||||||
|
from = df.parse(fromDate).getTime();
|
||||||
|
to = df.parse(toDate).getTime();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
predicates.add(cb.greaterThanOrEqualTo(root.<Long>get("time"), from));
|
||||||
|
predicates.add(cb.lessThanOrEqualTo(root.<Long>get("time"), to));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventQuery fromDate(String fromDate) {
|
||||||
|
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
Long from = null;
|
||||||
|
try {
|
||||||
|
from = df.parse(fromDate).getTime();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
predicates.add(cb.greaterThanOrEqualTo(root.<Long>get("time"), from));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventQuery toDate(String toDate) {
|
||||||
|
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
Long to = null;
|
||||||
|
try {
|
||||||
|
to = df.parse(toDate).getTime();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
predicates.add(cb.lessThanOrEqualTo(root.<Long>get("time"), to));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EventQuery ipAddress(String ipAddress) {
|
public EventQuery ipAddress(String ipAddress) {
|
||||||
predicates.add(cb.equal(root.get("ipAddress"), ipAddress));
|
predicates.add(cb.equal(root.get("ipAddress"), ipAddress));
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
package org.keycloak.events.mongo;
|
package org.keycloak.events.mongo;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
import com.mongodb.BasicDBObject;
|
||||||
|
import com.mongodb.BasicDBObjectBuilder;
|
||||||
import com.mongodb.DBCollection;
|
import com.mongodb.DBCollection;
|
||||||
import com.mongodb.DBCursor;
|
import com.mongodb.DBCursor;
|
||||||
|
|
||||||
import org.keycloak.events.Event;
|
import org.keycloak.events.Event;
|
||||||
import org.keycloak.events.EventQuery;
|
import org.keycloak.events.EventQuery;
|
||||||
import org.keycloak.events.EventType;
|
import org.keycloak.events.EventType;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -53,6 +57,47 @@ public class MongoEventQuery implements EventQuery {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventQuery dateRange(String fromDate, String toDate) {
|
||||||
|
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
Long from = null, to = null;
|
||||||
|
try {
|
||||||
|
from = df.parse(fromDate).getTime();
|
||||||
|
to = df.parse(toDate).getTime();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
query.put("time", BasicDBObjectBuilder.start("$gte", from).add("$lte", to).get());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventQuery fromDate(String fromDate) {
|
||||||
|
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
Long from = null;
|
||||||
|
try {
|
||||||
|
from = df.parse(fromDate).getTime();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
query.put("time", BasicDBObjectBuilder.start("$gte", from).get());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventQuery toDate(String toDate) {
|
||||||
|
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
Long to = null;
|
||||||
|
try {
|
||||||
|
to = df.parse(toDate).getTime();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
query.put("time", BasicDBObjectBuilder.start("$lte", to).get());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EventQuery ipAddress(String ipAddress) {
|
public EventQuery ipAddress(String ipAddress) {
|
||||||
query.put("ipAddress", ipAddress);
|
query.put("ipAddress", ipAddress);
|
||||||
|
|
|
@ -4,6 +4,8 @@ import org.keycloak.events.Event;
|
||||||
import org.keycloak.events.EventQuery;
|
import org.keycloak.events.EventQuery;
|
||||||
import org.keycloak.events.EventType;
|
import org.keycloak.events.EventType;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -74,6 +76,64 @@ public class MemEventQuery implements EventQuery {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventQuery dateRange(String fromDate, String toDate) {
|
||||||
|
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
Long from = null, to = null;
|
||||||
|
try {
|
||||||
|
from = df.parse(fromDate).getTime();
|
||||||
|
to = df.parse(toDate).getTime();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator<Event> itr = this.events.iterator();
|
||||||
|
while (itr.hasNext()) {
|
||||||
|
if (!(itr.next().getFromDate() >= from && itr.next().getToDate() <= to)) {
|
||||||
|
itr.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventQuery fromDate(String fromDate) {
|
||||||
|
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
Long from = null;
|
||||||
|
try {
|
||||||
|
from = df.parse(fromDate).getTime();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator<Event> itr = this.events.iterator();
|
||||||
|
while (itr.hasNext()) {
|
||||||
|
if (!(itr.next().getFromDate() >= from)) {
|
||||||
|
itr.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventQuery toDate(String toDate) {
|
||||||
|
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
Long to = null;
|
||||||
|
try {
|
||||||
|
to = df.parse(toDate).getTime();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator<Event> itr = this.events.iterator();
|
||||||
|
while (itr.hasNext()) {
|
||||||
|
if (!(itr.next().getToDate() <= to)) {
|
||||||
|
itr.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EventQuery ipAddress(String ipAddress) {
|
public EventQuery ipAddress(String ipAddress) {
|
||||||
Iterator<Event> itr = this.events.iterator();
|
Iterator<Event> itr = this.events.iterator();
|
||||||
|
|
|
@ -1155,13 +1155,40 @@ module.controller('RealmEventsCtrl', function($scope, RealmEvents, realm) {
|
||||||
$scope.realm = realm;
|
$scope.realm = realm;
|
||||||
$scope.page = 0;
|
$scope.page = 0;
|
||||||
|
|
||||||
|
$scope.eventTypes = [{tag:'LOGIN'}, {tag:'REGISTER'}, {tag:'LOGOUT'}, {tag:'CODE_TO_TOKEN'}, {tag:'REFRESH_TOKEN'},
|
||||||
|
{tag:'LOGIN_ERROR'}, {tag:'REGISTER_ERROR'}, {tag:'LOGOUT_ERROR'}, {tag:'CODE_TO_TOKEN_ERROR'}, {tag:'REFRESH_TOKEN_ERROR'},
|
||||||
|
{tag:'VALIDATE_ACCESS_TOKEN'}, {tag:'VALIDATE_ACCESS_TOKEN_ERROR'}, {tag:'SOCIAL_LINK'}, {tag:'SOCIAL_LINK_ERROR'}, {tag:'REMOVE_FEDERATED_IDENTITY'},
|
||||||
|
{tag:'REMOVE_SOCIAL_LINK_ERROR'}, {tag:'UPDATE_EMAIL'}, {tag:'UPDATE_PROFILE'}, {tag:'UPDATE_PASSWORD'}, {tag:'UPDATE_TOTP'}];
|
||||||
|
|
||||||
$scope.query = {
|
$scope.query = {
|
||||||
id : realm.realm,
|
id : realm.realm,
|
||||||
max : 5,
|
max : 10,
|
||||||
first : 0
|
first : 0
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.update = function() {
|
$scope.update = function() {
|
||||||
|
$scope.query.first = 0;
|
||||||
|
for (var i in $scope.query) {
|
||||||
|
if ($scope.query[i] === '') {
|
||||||
|
delete $scope.query[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$scope.events = RealmEvents.query($scope.query);
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.reset = function() {
|
||||||
|
$scope.query.first = 0;
|
||||||
|
$scope.query.max = 10;
|
||||||
|
$scope.query.type = '';
|
||||||
|
$scope.query.client = '';
|
||||||
|
$scope.query.user = '';
|
||||||
|
$scope.query.dateFrom = '';
|
||||||
|
$scope.query.dateTo = '';
|
||||||
|
|
||||||
|
$scope.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.queryUpdate = function() {
|
||||||
for (var i in $scope.query) {
|
for (var i in $scope.query) {
|
||||||
if ($scope.query[i] === '') {
|
if ($scope.query[i] === '') {
|
||||||
delete $scope.query[i];
|
delete $scope.query[i];
|
||||||
|
@ -1172,10 +1199,7 @@ module.controller('RealmEventsCtrl', function($scope, RealmEvents, realm) {
|
||||||
|
|
||||||
$scope.firstPage = function() {
|
$scope.firstPage = function() {
|
||||||
$scope.query.first = 0;
|
$scope.query.first = 0;
|
||||||
if ($scope.query.first < 0) {
|
$scope.queryUpdate();
|
||||||
$scope.query.first = 0;
|
|
||||||
}
|
|
||||||
$scope.update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.previousPage = function() {
|
$scope.previousPage = function() {
|
||||||
|
@ -1183,12 +1207,12 @@ module.controller('RealmEventsCtrl', function($scope, RealmEvents, realm) {
|
||||||
if ($scope.query.first < 0) {
|
if ($scope.query.first < 0) {
|
||||||
$scope.query.first = 0;
|
$scope.query.first = 0;
|
||||||
}
|
}
|
||||||
$scope.update();
|
$scope.queryUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.nextPage = function() {
|
$scope.nextPage = function() {
|
||||||
$scope.query.first += parseInt($scope.query.max);
|
$scope.query.first += parseInt($scope.query.max);
|
||||||
$scope.update();
|
$scope.queryUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.update();
|
$scope.update();
|
||||||
|
|
|
@ -27,12 +27,18 @@
|
||||||
Filter
|
Filter
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-default btn-primary" data-ng-click="update()">Update</button>
|
<button class="btn btn-default btn-primary" data-ng-click="update()">Update</button>
|
||||||
|
<button class="btn btn-default btn-primary" data-ng-click="reset()">Reset</button>
|
||||||
</div>
|
</div>
|
||||||
<form class="form-horizontal">
|
<form class="form-horizontal">
|
||||||
<div class="form-group" data-ng-show="filter">
|
<div class="form-group" data-ng-show="filter">
|
||||||
<label class="col-sm-2 control-label" for="type">Event Type</label>
|
<label class="col-sm-2 control-label" for="eventType">Event Type</label>
|
||||||
<div class="col-sm-4">
|
<div class="col-sm-5">
|
||||||
<input class="form-control" type="text" id="type" name="event" data-ng-model="query.type">
|
<select style="width:230px" data-ui-select2 data-ng-model="query.type" data-placeholder="Select Event Type">
|
||||||
|
<!-- empty option gets placeholder working -->
|
||||||
|
<option value=""></option>
|
||||||
|
<!-- ng-repeat to populate dynamic options -->
|
||||||
|
<option data-ng-repeat="event in eventTypes">{{event.tag}}</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group" data-ng-show="filter">
|
<div class="form-group" data-ng-show="filter">
|
||||||
|
@ -47,6 +53,20 @@
|
||||||
<input class="form-control" type="text" id="user" name="user" data-ng-model="query.user">
|
<input class="form-control" type="text" id="user" name="user" data-ng-model="query.user">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group" data-ng-show="filter">
|
||||||
|
<label class="col-sm-2 control-label" for="dateFrom">Date (From)</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<input class="form-control" type="date" id="dateFrom" name="dateFrom" data-ng-model="query.dateFrom">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group" data-ng-show="filter">
|
||||||
|
<label class="col-sm-2 control-label" for="toDate">Date (To)</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<input class="form-control" type="date" id="dateTo" name="dateTo" data-ng-model="query.dateTo">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -397,8 +397,10 @@ public class RealmAdminResource {
|
||||||
@GET
|
@GET
|
||||||
@NoCache
|
@NoCache
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public List<Event> getEvents(@QueryParam("client") String client, @QueryParam("type") String type, @QueryParam("user") String user,
|
public List<Event> getEvents(@QueryParam("client") String client, @QueryParam("type") String type,
|
||||||
@QueryParam("ipAddress") String ipAddress, @QueryParam("first") Integer firstResult, @QueryParam("max") Integer maxResults) {
|
@QueryParam("user") String user, @QueryParam("dateFrom") String dateFrom, @QueryParam("dateTo") String dateTo,
|
||||||
|
@QueryParam("ipAddress") String ipAddress, @QueryParam("first") Integer firstResult,
|
||||||
|
@QueryParam("max") Integer maxResults) {
|
||||||
auth.init(RealmAuth.Resource.EVENTS).requireView();
|
auth.init(RealmAuth.Resource.EVENTS).requireView();
|
||||||
|
|
||||||
EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class);
|
EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class);
|
||||||
|
@ -413,6 +415,15 @@ public class RealmAdminResource {
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
query.user(user);
|
query.user(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dateFrom != null && dateTo != null) {
|
||||||
|
query.dateRange(dateFrom, dateTo);
|
||||||
|
} else if(dateFrom != null) {
|
||||||
|
query.fromDate(dateFrom);
|
||||||
|
} else if(dateTo != null) {
|
||||||
|
query.toDate(dateTo);
|
||||||
|
}
|
||||||
|
|
||||||
if (ipAddress != null) {
|
if (ipAddress != null) {
|
||||||
query.ipAddress(ipAddress);
|
query.ipAddress(ipAddress);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue