Make DateUtil convert the local dates into epoch in milliseconds

Closes #38911

Signed-off-by: rmartinc <rmartinc@redhat.com>
This commit is contained in:
rmartinc 2025-04-25 10:51:55 +02:00 committed by Marek Posolda
parent 54e1c8af1e
commit 08704df651
4 changed files with 44 additions and 13 deletions

View File

@ -857,6 +857,7 @@ public class RealmAdminResource {
* @param dateFrom From date
* @param firstResult Paging offset
* @param maxResults Maximum results size (defaults to 100)
* @param direction The direction to sort events by (asc or desc)
* @return
*/
@Path("events")
@ -873,8 +874,8 @@ public class RealmAdminResource {
public Stream<EventRepresentation> getEvents(@Parameter(description = "The types of events to return") @QueryParam("type") List<String> types,
@Parameter(description = "App or oauth client name") @QueryParam("client") String client,
@Parameter(description = "User id") @QueryParam("user") String user,
@Parameter(description = "From (inclusive) date (yyyy-MM-dd) or time in Epoch timestamp") @QueryParam("dateFrom") String dateFrom,
@Parameter(description = "To (inclusive) date (yyyy-MM-dd) or time in Epoch timestamp") @QueryParam("dateTo") String dateTo,
@Parameter(description = "From (inclusive) date (yyyy-MM-dd) or time in Epoch timestamp millis (number of milliseconds since January 1, 1970, 00:00:00 GMT)") @QueryParam("dateFrom") String dateFrom,
@Parameter(description = "To (inclusive) date (yyyy-MM-dd) or time in Epoch timestamp millis (number of milliseconds since January 1, 1970, 00:00:00 GMT)") @QueryParam("dateTo") String dateTo,
@Parameter(description = "IP Address") @QueryParam("ipAddress") String ipAddress,
@Parameter(description = "Paging offset") @QueryParam("first") Integer firstResult,
@Parameter(description = "Maximum results size (defaults to 100)") @QueryParam("max") Integer maxResults,
@ -957,6 +958,8 @@ public class RealmAdminResource {
* @param dateFrom
* @param firstResult
* @param maxResults Maximum results size (defaults to 100)
* @param resourceTypes
* @param direction The direction to sort events by (asc or desc)
* @return
*/
@Path("admin-events")
@ -973,8 +976,8 @@ public class RealmAdminResource {
public Stream<AdminEventRepresentation> getEvents(@QueryParam("operationTypes") List<String> operationTypes, @QueryParam("authRealm") String authRealm, @QueryParam("authClient") String authClient,
@Parameter(description = "user id") @QueryParam("authUser") String authUser, @QueryParam("authIpAddress") String authIpAddress,
@QueryParam("resourcePath") String resourcePath,
@Parameter(description = "From (inclusive) date (yyyy-MM-dd) or time in Epoch timestamp") @QueryParam("dateFrom") String dateFrom,
@Parameter(description = "To (inclusive) date (yyyy-MM-dd) or time in Epoch timestamp") @QueryParam("dateTo") String dateTo,
@Parameter(description = "From (inclusive) date (yyyy-MM-dd) or time in Epoch timestamp millis (number of milliseconds since January 1, 1970, 00:00:00 GMT)") @QueryParam("dateFrom") String dateFrom,
@Parameter(description = "To (inclusive) date (yyyy-MM-dd) or time in Epoch timestamp millis (number of milliseconds since January 1, 1970, 00:00:00 GMT)") @QueryParam("dateTo") String dateTo,
@QueryParam("first") Integer firstResult,
@Parameter(description = "Maximum results size (defaults to 100)") @QueryParam("max") Integer maxResults,
@QueryParam("resourceTypes") List<String> resourceTypes,

View File

@ -7,30 +7,30 @@ import java.time.ZoneOffset;
public class DateUtil {
/**
* Parses a string timestamp or date to an Epoc timestamp; if the date is a ISO-8601 extended local date format,
* the time at the beginning of the day is returned.
* Parses a string timestamp or date to an Epoch timestamp in milliseconds (number of milliseconds since January 1, 1970, 00:00:00 GMT);
* if the date is a ISO-8601 extended local date format, the time at the beginning of the day is returned.
*
* @param date the date in ISO-8601 extended local date format
* @return Epoch time for the start of the day
*/
public static long toStartOfDay(String date) {
if (date.indexOf('-') != -1) {
return LocalDate.parse(date).atStartOfDay().toEpochSecond(ZoneOffset.UTC);
return LocalDate.parse(date).atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli();
} else {
return Long.parseLong(date);
}
}
/**
* Parses a string timestamp or date to an Epoc timestamp; if the date is a ISO-8601 extended local date format,
* the time at the end of the day is returned.
* Parses a string timestamp or date to an Epoch timestamp in milliseconds (number of milliseconds since January 1, 1970, 00:00:00 GMT);
* if the date is a ISO-8601 extended local date format, the time at the end of the day is returned.
*
* @param date the date in ISO-8601 extended local date format
* @return Epoch time for the start of the day
* @return Epoch time for the end of the day
*/
public static long toEndOfDay(String date) {
if (date.indexOf('-') != -1) {
return LocalDate.parse(date).atTime(LocalTime.MAX).toEpochSecond(ZoneOffset.UTC);
return LocalDate.parse(date).atTime(LocalTime.MAX).toInstant(ZoneOffset.UTC).toEpochMilli();
} else {
return Long.parseLong(date);
}

View File

@ -51,6 +51,9 @@ import org.keycloak.tests.utils.admin.ApiUtil;
import org.keycloak.util.JsonSerialization;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@ -297,18 +300,29 @@ public class AdminEventTest {
event.setAuthDetails(new AuthDetails());
event.setRealmId(realmId);
event.setTime(currentTime - 2*24*3600*1000);
provider.onEvent(event, false);
event.setTime(currentTime - 1000);
provider.onEvent(event, false);
event.setTime(currentTime);
provider.onEvent(event, false);
event.setTime(currentTime + 1000);
provider.onEvent(event, false);
event.setTime(currentTime + 2*24*3600*1000);
provider.onEvent(event, false);
});
List<AdminEventRepresentation> events = realm.getAdminEvents(null, null, null, null, null, null, null, currentTime, currentTime, null, null, null);
List<AdminEventRepresentation> events = realm.getAdminEvents();
Assertions.assertEquals(5, events.size());
events = realm.getAdminEvents(null, null, null, null, null, null, null, currentTime, currentTime, null, null, null);
Assertions.assertEquals(1, events.size());
events = realm.getAdminEvents(null, null, null, null, null, null, null, currentTime - 1000, currentTime + 1000, null, null, null);
Assertions.assertEquals(3, events.size());
LocalDate dateFrom = Instant.ofEpochMilli(currentTime - 1000).atZone(ZoneOffset.UTC).toLocalDate();
LocalDate dateTo = Instant.ofEpochMilli(currentTime + 1000).atZone(ZoneOffset.UTC).toLocalDate();
events = realm.getAdminEvents(null, null, null, null, null, null, null, dateFrom.toString(), dateTo.toString(), null, null, null);
Assertions.assertEquals(3, events.size());
}
private void checkUpdateRealmEventsConfigEvent(int size) {

View File

@ -35,6 +35,9 @@ import org.keycloak.testframework.realm.RealmConfigBuilder;
import org.keycloak.testframework.remote.runonserver.InjectRunOnServer;
import org.keycloak.testframework.remote.runonserver.RunOnServerClient;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.util.List;
import java.util.Map;
@ -202,18 +205,29 @@ public class LoginEventsTest {
event.setType(EventType.LOGIN);
event.setRealmId(realmId);
event.setTime(currentTime - 2*24*3600*1000);
provider.onEvent(event);
event.setTime(currentTime - 1000);
provider.onEvent(event);
event.setTime(currentTime);
provider.onEvent(event);
event.setTime(currentTime + 1000);
provider.onEvent(event);
event.setTime(currentTime + 2*24*3600*1000);
provider.onEvent(event);
});
List<EventRepresentation> events = managedRealm.admin().getEvents(null, null, null, currentTime, currentTime, null, null, null, null);
List<EventRepresentation> events = managedRealm.admin().getEvents();
Assertions.assertEquals(5, events.size());
events = managedRealm.admin().getEvents(null, null, null, currentTime, currentTime, null, null, null, null);
Assertions.assertEquals(1, events.size());
events = managedRealm.admin().getEvents(null, null, null, currentTime - 1000, currentTime + 1000, null, null, null, null);
Assertions.assertEquals(3, events.size());
LocalDate dateFrom = Instant.ofEpochMilli(currentTime - 1000).atZone(ZoneOffset.UTC).toLocalDate();
LocalDate dateTo = Instant.ofEpochMilli(currentTime + 1000).atZone(ZoneOffset.UTC).toLocalDate();
events = managedRealm.admin().getEvents(null, null, null, dateFrom.toString(), dateTo.toString(), null, null, null, null);
Assertions.assertEquals(3, events.size());
}
@Test