refactor(core,common,proprietary): Replace Date with Instant/modern Date API alternative for improved time handling (#4497)

This commit is contained in:
Balázs Szücs 2025-09-28 17:41:20 +02:00 committed by GitHub
parent 07392ed25e
commit 133e6d3de6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 244 additions and 125 deletions

View File

@ -1,6 +1,6 @@
package stirling.software.common.model;
import java.util.Calendar;
import java.time.ZonedDateTime;
import lombok.AllArgsConstructor;
import lombok.Builder;
@ -18,6 +18,6 @@ public class PdfMetadata {
private String creator;
private String subject;
private String keywords;
private Calendar creationDate;
private Calendar modificationDate;
private ZonedDateTime creationDate;
private ZonedDateTime modificationDate;
}

View File

@ -1,5 +1,9 @@
package stirling.software.common.service;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import org.apache.pdfbox.pdmodel.PDDocument;
@ -29,17 +33,19 @@ public class PdfMetadataService {
this.runningProOrHigher = runningProOrHigher;
}
public PdfMetadata extractMetadataFromPdf(PDDocument pdf) {
return PdfMetadata.builder()
.author(pdf.getDocumentInformation().getAuthor())
.producer(pdf.getDocumentInformation().getProducer())
.title(pdf.getDocumentInformation().getTitle())
.creator(pdf.getDocumentInformation().getCreator())
.subject(pdf.getDocumentInformation().getSubject())
.keywords(pdf.getDocumentInformation().getKeywords())
.creationDate(pdf.getDocumentInformation().getCreationDate())
.modificationDate(pdf.getDocumentInformation().getModificationDate())
.build();
/**
* Converts ZonedDateTime to Calendar for PDFBox compatibility.
*
* @param zonedDateTime the ZonedDateTime to convert
* @return Calendar instance or null if input is null
*/
public static Calendar toCalendar(ZonedDateTime zonedDateTime) {
if (zonedDateTime == null) {
return null;
}
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(zonedDateTime.toInstant().toEpochMilli());
return calendar;
}
public void setDefaultMetadata(PDDocument pdf) {
@ -58,6 +64,52 @@ public class PdfMetadataService {
setCommonMetadata(pdf, pdfMetadata);
}
/**
* Parses a date string and converts it to Calendar for PDFBox compatibility.
*
* @param dateString the date string in "yyyy/MM/dd HH:mm:ss" format
* @return Calendar instance or null if parsing fails or input is empty
*/
public static Calendar parseToCalendar(String dateString) {
if (dateString == null || dateString.trim().isEmpty()) {
return null;
}
try {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
ZonedDateTime zonedDateTime =
LocalDateTime.parse(dateString, formatter).atZone(ZoneId.systemDefault());
return toCalendar(zonedDateTime);
} catch (Exception e) {
return null;
}
}
public PdfMetadata extractMetadataFromPdf(PDDocument pdf) {
Calendar creationCal = pdf.getDocumentInformation().getCreationDate();
Calendar modificationCal = pdf.getDocumentInformation().getModificationDate();
ZonedDateTime creationDate =
creationCal != null
? ZonedDateTime.ofInstant(creationCal.toInstant(), ZoneId.systemDefault())
: null;
ZonedDateTime modificationDate =
modificationCal != null
? ZonedDateTime.ofInstant(
modificationCal.toInstant(), ZoneId.systemDefault())
: null;
return PdfMetadata.builder()
.author(pdf.getDocumentInformation().getAuthor())
.producer(pdf.getDocumentInformation().getProducer())
.title(pdf.getDocumentInformation().getTitle())
.creator(pdf.getDocumentInformation().getCreator())
.subject(pdf.getDocumentInformation().getSubject())
.keywords(pdf.getDocumentInformation().getKeywords())
.creationDate(creationDate)
.modificationDate(modificationDate)
.build();
}
private void setNewDocumentMetadata(PDDocument pdf, PdfMetadata pdfMetadata) {
String creator = stirlingPDFLabel;
@ -79,7 +131,13 @@ public class PdfMetadataService {
}
pdf.getDocumentInformation().setCreator(creator);
pdf.getDocumentInformation().setCreationDate(Calendar.getInstance());
// Use existing creation date if available, otherwise create new one
Calendar creationCal =
pdfMetadata.getCreationDate() != null
? toCalendar(pdfMetadata.getCreationDate())
: Calendar.getInstance();
pdf.getDocumentInformation().setCreationDate(creationCal);
}
private void setCommonMetadata(PDDocument pdf, PdfMetadata pdfMetadata) {
@ -88,7 +146,13 @@ public class PdfMetadataService {
pdf.getDocumentInformation().setProducer(stirlingPDFLabel);
pdf.getDocumentInformation().setSubject(pdfMetadata.getSubject());
pdf.getDocumentInformation().setKeywords(pdfMetadata.getKeywords());
pdf.getDocumentInformation().setModificationDate(Calendar.getInstance());
// Convert ZonedDateTime to Calendar for PDFBox compatibility
Calendar modificationCal =
pdfMetadata.getModificationDate() != null
? toCalendar(pdfMetadata.getModificationDate())
: Calendar.getInstance();
pdf.getDocumentInformation().setModificationDate(modificationCal);
String author = pdfMetadata.getAuthor();
if (applicationProperties

View File

@ -6,6 +6,8 @@ import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@ -145,7 +147,11 @@ public class EmlParser {
extractRecipients(message, messageClass, content);
Method getSentDate = messageClass.getMethod("getSentDate");
content.setDate((Date) getSentDate.invoke(message));
Date legacyDate = (Date) getSentDate.invoke(message);
if (legacyDate != null) {
content.setDate(
ZonedDateTime.ofInstant(legacyDate.toInstant(), ZoneId.systemDefault()));
}
Method getContent = messageClass.getMethod("getContent");
Object messageContent = getContent.invoke(message);
@ -616,7 +622,7 @@ public class EmlParser {
private String to;
private String cc;
private String bcc;
private Date date;
private ZonedDateTime date;
private String dateString; // For basic parsing fallback
private String htmlBody;
private String textBody;

View File

@ -8,7 +8,9 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
@ -18,7 +20,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -290,11 +291,15 @@ public class PdfAttachmentHandler {
public static String formatEmailDate(Date date) {
if (date == null) return "";
return formatEmailDate(ZonedDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()));
}
SimpleDateFormat formatter =
new SimpleDateFormat("EEE, MMM d, yyyy 'at' h:mm a z", Locale.ENGLISH);
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
return formatter.format(date);
public static String formatEmailDate(ZonedDateTime dateTime) {
if (dateTime == null) return "";
DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("EEE, MMM d, yyyy 'at' h:mm a z", Locale.ENGLISH);
return dateTime.withZoneSameInstant(ZoneId.of("UTC")).format(formatter);
}
@Data

View File

@ -7,16 +7,18 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TimeZone;
import org.apache.commons.io.FileUtils;
import org.apache.pdfbox.Loader;
@ -564,18 +566,31 @@ public class ConvertPDFToPDFA {
adobePdfSchema.setKeywords(keywords);
}
// Set creation and modification dates
Calendar now = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
Calendar originalCreationDate = docInfo.getCreationDate();
if (originalCreationDate == null) {
originalCreationDate = now;
}
docInfo.setCreationDate(originalCreationDate);
xmpBasicSchema.setCreateDate(originalCreationDate);
// Set creation and modification dates using java.time and convert to GregorianCalendar
Instant nowInstant = Instant.now();
ZonedDateTime nowZdt = ZonedDateTime.ofInstant(nowInstant, ZoneId.of("UTC"));
GregorianCalendar nowCal = GregorianCalendar.from(nowZdt);
docInfo.setModificationDate(now);
xmpBasicSchema.setModifyDate(now);
xmpBasicSchema.setMetadataDate(now);
java.util.Calendar originalCreationDate = docInfo.getCreationDate();
GregorianCalendar creationCal;
if (originalCreationDate == null) {
creationCal = nowCal;
} else if (originalCreationDate instanceof GregorianCalendar) {
creationCal = (GregorianCalendar) originalCreationDate;
} else {
// convert other Calendar implementations to GregorianCalendar preserving instant
creationCal =
GregorianCalendar.from(
ZonedDateTime.ofInstant(
originalCreationDate.toInstant(), ZoneId.of("UTC")));
}
docInfo.setCreationDate(creationCal);
xmpBasicSchema.setCreateDate(creationCal);
docInfo.setModificationDate(nowCal);
xmpBasicSchema.setModifyDate(nowCal);
xmpBasicSchema.setMetadataDate(nowCal);
// Serialize the created metadata so it can be attached to the existent metadata
ByteArrayOutputStream xmpOut = new ByteArrayOutputStream();

View File

@ -1,8 +1,6 @@
package stirling.software.SPDF.controller.api.misc;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Map;
import java.util.Map.Entry;
@ -25,6 +23,7 @@ import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.misc.MetadataRequest;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.service.PdfMetadataService;
import stirling.software.common.util.WebResponseUtils;
import stirling.software.common.util.propertyeditor.StringToMapPropertyEditor;
@ -144,30 +143,13 @@ public class MetadataController {
}
}
}
if (creationDate != null && creationDate.length() > 0) {
Calendar creationDateCal = Calendar.getInstance();
try {
creationDateCal.setTime(
new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(creationDate));
} catch (ParseException e) {
log.error("exception", e);
}
info.setCreationDate(creationDateCal);
} else {
info.setCreationDate(null);
}
if (modificationDate != null && modificationDate.length() > 0) {
Calendar modificationDateCal = Calendar.getInstance();
try {
modificationDateCal.setTime(
new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(modificationDate));
} catch (ParseException e) {
log.error("exception", e);
}
info.setModificationDate(modificationDateCal);
} else {
info.setModificationDate(null);
}
// Set creation date using utility method
Calendar creationDateCal = PdfMetadataService.parseToCalendar(creationDate);
info.setCreationDate(creationDateCal);
// Set modification date using utility method
Calendar modificationDateCal = PdfMetadataService.parseToCalendar(modificationDate);
info.setModificationDate(modificationDateCal);
info.setCreator(creator);
info.setKeywords(keywords);
info.setAuthor(author);

View File

@ -120,7 +120,7 @@ public class CertSignController {
signature.setName(name);
signature.setLocation(location);
signature.setReason(reason);
signature.setSignDate(Calendar.getInstance());
signature.setSignDate(Calendar.getInstance()); // PDFBox requires Calendar
if (Boolean.TRUE.equals(showSignature)) {
SignatureOptions signatureOptions = new SignatureOptions();
signatureOptions.setVisualSignature(

View File

@ -3,7 +3,9 @@ package stirling.software.SPDF.controller.api.security;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import org.apache.pdfbox.cos.COSInputStream;
@ -817,8 +819,10 @@ public class GetInfoOnPDF {
private String formatDate(Calendar calendar) {
if (calendar != null) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(calendar.getTime());
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
ZonedDateTime zonedDateTime =
ZonedDateTime.ofInstant(calendar.toInstant(), ZoneId.systemDefault());
return zonedDateTime.format(formatter);
} else {
return null;
}

View File

@ -7,8 +7,8 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.pdfbox.pdmodel.PDDocument;
@ -134,11 +134,12 @@ public class ValidateSignatureController {
: certValidationService.validateTrustStore(cert));
result.setNotRevoked(!certValidationService.isRevoked(cert));
result.setNotExpired(!cert.getNotAfter().before(new Date()));
result.setNotExpired(
Instant.now().isBefore(cert.getNotAfter().toInstant()));
// Set basic signature info
result.setSignerName(sig.getName());
result.setSignatureDate(sig.getSignDate().getTime().toString());
result.setSignatureDate(sig.getSignDate().toInstant().toString());
result.setReason(sig.getReason());
result.setLocation(sig.getLocation());

View File

@ -3,6 +3,9 @@ package stirling.software.SPDF.service;
import static stirling.software.common.util.AttachmentUtils.setCatalogViewerPreferences;
import java.io.IOException;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
@ -54,8 +57,13 @@ public class AttachmentService implements AttachmentServiceInterface {
PDEmbeddedFile embeddedFile =
new PDEmbeddedFile(document, attachment.getInputStream());
embeddedFile.setSize((int) attachment.getSize());
embeddedFile.setCreationDate(new GregorianCalendar());
embeddedFile.setModDate(new GregorianCalendar());
// use java.time.Instant and convert to GregorianCalendar for PDFBox
Instant now = Instant.now();
GregorianCalendar nowCal =
GregorianCalendar.from(
ZonedDateTime.ofInstant(now, ZoneId.systemDefault()));
embeddedFile.setCreationDate(nowCal);
embeddedFile.setModDate(nowCal);
String contentType = attachment.getContentType();
if (StringUtils.isNotBlank(contentType)) {
embeddedFile.setSubtype(contentType);

View File

@ -7,6 +7,8 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import org.apache.pdfbox.pdmodel.PDDocument;
@ -81,6 +83,12 @@ class PdfMetadataServiceBasicTest {
// Act
PdfMetadata metadata = pdfMetadataService.extractMetadataFromPdf(testDocument);
// Convert Calendar to ZonedDateTime for comparison
ZonedDateTime expectedCreationDate =
ZonedDateTime.ofInstant(creationDate.toInstant(), ZoneId.systemDefault());
ZonedDateTime expectedModificationDate =
ZonedDateTime.ofInstant(modificationDate.toInstant(), ZoneId.systemDefault());
// Assert
assertEquals(testAuthor, metadata.getAuthor(), "Author should match");
assertEquals(testProducer, metadata.getProducer(), "Producer should match");
@ -88,9 +96,12 @@ class PdfMetadataServiceBasicTest {
assertEquals(testCreator, metadata.getCreator(), "Creator should match");
assertEquals(testSubject, metadata.getSubject(), "Subject should match");
assertEquals(testKeywords, metadata.getKeywords(), "Keywords should match");
assertEquals(creationDate, metadata.getCreationDate(), "Creation date should match");
assertEquals(
modificationDate, metadata.getModificationDate(), "Modification date should match");
expectedCreationDate, metadata.getCreationDate(), "Creation date should match");
assertEquals(
expectedModificationDate,
metadata.getModificationDate(),
"Modification date should match");
}
@Test

View File

@ -7,6 +7,8 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import org.apache.pdfbox.pdmodel.PDDocument;
@ -84,6 +86,12 @@ class PdfMetadataServiceTest {
// Act
PdfMetadata metadata = pdfMetadataService.extractMetadataFromPdf(testDocument);
// Convert Calendar to ZonedDateTime for comparison
ZonedDateTime expectedCreationDate =
ZonedDateTime.ofInstant(creationDate.toInstant(), ZoneId.systemDefault());
ZonedDateTime expectedModificationDate =
ZonedDateTime.ofInstant(modificationDate.toInstant(), ZoneId.systemDefault());
// Assert
assertEquals(testAuthor, metadata.getAuthor(), "Author should match");
assertEquals(testProducer, metadata.getProducer(), "Producer should match");
@ -91,9 +99,12 @@ class PdfMetadataServiceTest {
assertEquals(testCreator, metadata.getCreator(), "Creator should match");
assertEquals(testSubject, metadata.getSubject(), "Subject should match");
assertEquals(testKeywords, metadata.getKeywords(), "Keywords should match");
assertEquals(creationDate, metadata.getCreationDate(), "Creation date should match");
assertEquals(
modificationDate, metadata.getModificationDate(), "Modification date should match");
expectedCreationDate, metadata.getCreationDate(), "Creation date should match");
assertEquals(
expectedModificationDate,
metadata.getModificationDate(),
"Modification date should match");
}
@Test
@ -190,6 +201,8 @@ class PdfMetadataServiceTest {
// Prepare test metadata with existing creation date
Calendar existingCreationDate = Calendar.getInstance();
existingCreationDate.add(Calendar.DAY_OF_MONTH, -1); // Yesterday
ZonedDateTime existingCreationDateZdt =
ZonedDateTime.ofInstant(existingCreationDate.toInstant(), ZoneId.systemDefault());
PdfMetadata testMetadata =
PdfMetadata.builder()
@ -197,7 +210,7 @@ class PdfMetadataServiceTest {
.title("Test Title")
.subject("Test Subject")
.keywords("Test Keywords")
.creationDate(existingCreationDate)
.creationDate(existingCreationDateZdt)
.build();
// Act

View File

@ -4,7 +4,6 @@ import static stirling.software.common.util.ProviderUtils.validateProvider;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@ -218,7 +217,7 @@ public class AccountWebController {
Map<String, String> roleDetails = Role.getAllRoleDetails();
// Map to store session information and user activity status
Map<String, Boolean> userSessions = new HashMap<>();
Map<String, Date> userLastRequest = new HashMap<>();
Map<String, Instant> userLastRequest = new HashMap<>();
int activeUsers = 0;
int disabledUsers = 0;
while (iterator.hasNext()) {
@ -249,27 +248,29 @@ public class AccountWebController {
// Determine the user's session status and last request time
int maxInactiveInterval = sessionPersistentRegistry.getMaxInactiveInterval();
boolean hasActiveSession = false;
Date lastRequest = null;
Instant lastRequest = null;
Optional<SessionEntity> latestSession =
sessionPersistentRegistry.findLatestSession(user.getUsername());
if (latestSession.isPresent()) {
SessionEntity sessionEntity = latestSession.get();
Date lastAccessedTime = sessionEntity.getLastRequest();
// sessionEntity stores Instant directly
Instant lastAccessedTime =
Optional.ofNullable(sessionEntity.getLastRequest())
.orElse(Instant.EPOCH);
Instant now = Instant.now();
// Calculate session expiration and update session status accordingly
Instant expirationTime =
lastAccessedTime
.toInstant()
.plus(maxInactiveInterval, ChronoUnit.SECONDS);
lastAccessedTime.plus(maxInactiveInterval, ChronoUnit.SECONDS);
if (now.isAfter(expirationTime)) {
sessionPersistentRegistry.expireSession(sessionEntity.getSessionId());
} else {
hasActiveSession = !sessionEntity.isExpired();
}
lastRequest = sessionEntity.getLastRequest();
lastRequest = lastAccessedTime;
} else {
// No session, set default last request time
lastRequest = new Date(0);
lastRequest = Instant.EPOCH;
}
userSessions.put(user.getUsername(), hasActiveSession);
userLastRequest.put(user.getUsername(), lastRequest);
@ -286,19 +287,21 @@ public class AccountWebController {
allUsers.stream()
.sorted(
(u1, u2) -> {
boolean u1Active = userSessions.get(u1.getUsername());
boolean u2Active = userSessions.get(u2.getUsername());
boolean u1Active =
userSessions.getOrDefault(u1.getUsername(), false);
boolean u2Active =
userSessions.getOrDefault(u2.getUsername(), false);
if (u1Active && !u2Active) {
return -1;
} else if (!u1Active && u2Active) {
return 1;
} else {
Date u1LastRequest =
Instant u1LastRequest =
userLastRequest.getOrDefault(
u1.getUsername(), new Date(0));
Date u2LastRequest =
u1.getUsername(), Instant.EPOCH);
Instant u2LastRequest =
userLastRequest.getOrDefault(
u2.getUsername(), new Date(0));
u2.getUsername(), Instant.EPOCH);
return u2LastRequest.compareTo(u1LastRequest);
}
})

View File

@ -1,6 +1,6 @@
package stirling.software.proprietary.security.controller.web;
import java.util.Date;
import java.time.Instant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -44,17 +44,17 @@ public class TeamWebController {
// Filter out the Internal team
List<TeamWithUserCountDTO> teamsWithCounts =
allTeamsWithCounts.stream()
.filter(team -> !team.getName().equals(TeamService.INTERNAL_TEAM_NAME))
.filter(team -> !TeamService.INTERNAL_TEAM_NAME.equals(team.getName()))
.toList();
// Get the latest activity for each team
List<Object[]> teamActivities = sessionRepository.findLatestActivityByTeam();
// Convert the query results to a map for easy access in the view
Map<Long, Date> teamLastRequest = new HashMap<>();
Map<Long, Instant> teamLastRequest = new HashMap<>();
for (Object[] result : teamActivities) {
Long teamId = (Long) result[0]; // teamId alias
Date lastActivity = (Date) result[1]; // lastActivity alias
Instant lastActivity = (Instant) result[1]; // lastActivity alias
teamLastRequest.put(teamId, lastActivity);
}
@ -97,7 +97,7 @@ public class TeamWebController {
.orElseThrow(() -> new RuntimeException("Team not found"));
// Prevent access to Internal team
if (team.getName().equals(TeamService.INTERNAL_TEAM_NAME)) {
if (TeamService.INTERNAL_TEAM_NAME.equals(team.getName())) {
return "redirect:/teams?error=internalTeamNotAccessible";
}
@ -114,21 +114,18 @@ public class TeamWebController {
(user.getTeam() == null
|| !user.getTeam().getId().equals(id))
&& (user.getTeam() == null
|| !user.getTeam()
.getName()
.equals(
TeamService
.INTERNAL_TEAM_NAME)))
|| !TeamService.INTERNAL_TEAM_NAME.equals(
user.getTeam().getName())))
.toList();
// Get the latest session for each user in the team
List<Object[]> userSessions = sessionRepository.findLatestSessionByTeamId(id);
// Create a map of username to last request date
Map<String, Date> userLastRequest = new HashMap<>();
Map<String, Instant> userLastRequest = new HashMap<>();
for (Object[] result : userSessions) {
String username = (String) result[0]; // username alias
Date lastRequest = (Date) result[1]; // lastRequest alias
Instant lastRequest = (Instant) result[1]; // lastRequest alias
userLastRequest.put(username, lastRequest);
}

View File

@ -23,7 +23,7 @@ public class JPATokenRepositoryImpl implements PersistentTokenRepository {
newToken.setSeries(token.getSeries());
newToken.setUsername(token.getUsername());
newToken.setToken(token.getTokenValue());
newToken.setLastUsed(token.getDate());
newToken.setLastUsed(token.getDate().toInstant());
persistentLoginRepository.save(newToken);
}
@ -33,7 +33,7 @@ public class JPATokenRepositoryImpl implements PersistentTokenRepository {
PersistentLogin existingToken = persistentLoginRepository.findById(series).orElse(null);
if (existingToken != null) {
existingToken.setToken(tokenValue);
existingToken.setLastUsed(lastUsed);
existingToken.setLastUsed(lastUsed.toInstant());
persistentLoginRepository.save(existingToken);
}
}
@ -43,7 +43,10 @@ public class JPATokenRepositoryImpl implements PersistentTokenRepository {
PersistentLogin token = persistentLoginRepository.findById(seriesId).orElse(null);
if (token != null) {
return new PersistentRememberMeToken(
token.getUsername(), token.getSeries(), token.getToken(), token.getLastUsed());
token.getUsername(),
token.getSeries(),
token.getToken(),
Date.from(token.getLastUsed()));
}
return null;
}

View File

@ -1,6 +1,6 @@
package stirling.software.proprietary.security.database.repository;
import java.util.Date;
import java.time.Instant;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
@ -27,7 +27,7 @@ public interface SessionRepository extends JpaRepository<SessionEntity, String>
"UPDATE SessionEntity s SET s.expired = :expired, s.lastRequest = :lastRequest WHERE s.principalName = :principalName")
void saveByPrincipalName(
@Param("expired") boolean expired,
@Param("lastRequest") Date lastRequest,
@Param("lastRequest") Instant lastRequest,
@Param("principalName") String principalName);
@Query(

View File

@ -1,8 +1,9 @@
package stirling.software.proprietary.security.filter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Optional;
import org.springframework.context.annotation.Lazy;
@ -60,8 +61,12 @@ public class FirstLoginFilter extends OncePerRequestFilter {
}
if (log.isDebugEnabled()) {
HttpSession session = request.getSession(true);
SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
String creationTime = timeFormat.format(new Date(session.getCreationTime()));
DateTimeFormatter timeFormat = DateTimeFormatter.ofPattern("HH:mm:ss");
String creationTime =
timeFormat.format(
Instant.ofEpochMilli(session.getCreationTime())
.atZone(ZoneId.systemDefault())
.toLocalTime());
log.debug(
"Request Info - New: {}, creationTimeSession {}, ID: {}, IP: {}, User-Agent: {}, Referer: {}, Request URL: {}",
session.isNew(),

View File

@ -1,6 +1,6 @@
package stirling.software.proprietary.security.model;
import java.util.Date;
import java.time.Instant;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
@ -25,5 +25,5 @@ public class PersistentLogin {
private String token;
@Column(name = "last_used", nullable = false)
private Date lastUsed;
private Instant lastUsed;
}

View File

@ -1,7 +1,7 @@
package stirling.software.proprietary.security.model;
import java.io.Serializable;
import java.util.Date;
import java.time.Instant;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
@ -17,7 +17,7 @@ public class SessionEntity implements Serializable {
private String principalName;
private Date lastRequest;
private Instant lastRequest;
private boolean expired;
}

View File

@ -4,6 +4,7 @@ import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
@ -92,8 +93,8 @@ public class JwtService implements JwtServiceInterface {
.claims(claims)
.subject(username)
.issuer(ISSUER)
.issuedAt(new Date())
.expiration(new Date(System.currentTimeMillis() + EXPIRATION))
.issuedAt(Date.from(Instant.now()))
.expiration(Date.from(Instant.now().plusMillis(EXPIRATION)))
.signWith(keyPair.getPrivate(), Jwts.SIG.RS256);
String keyId = activeKey.getKeyId();
@ -129,7 +130,7 @@ public class JwtService implements JwtServiceInterface {
@Override
public boolean isTokenExpired(String token) {
return extractExpiration(token).before(new Date());
return extractExpiration(token).before(Date.from(Instant.now()));
}
private Date extractExpiration(String token) {

View File

@ -1,6 +1,7 @@
package stirling.software.proprietary.security.session;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@ -67,7 +68,7 @@ public class SessionPersistentRegistry implements SessionRegistry {
new SessionInformation(
sessionEntity.getPrincipalName(),
sessionEntity.getSessionId(),
sessionEntity.getLastRequest()));
Date.from(sessionEntity.getLastRequest())));
}
}
}
@ -101,7 +102,7 @@ public class SessionPersistentRegistry implements SessionRegistry {
SessionEntity sessionEntity = new SessionEntity();
sessionEntity.setSessionId(sessionId);
sessionEntity.setPrincipalName(principalName);
sessionEntity.setLastRequest(new Date()); // Set lastRequest to the current date
sessionEntity.setLastRequest(Instant.now()); // Set lastRequest to the current date
sessionEntity.setExpired(false);
sessionRepository.save(sessionEntity);
}
@ -119,7 +120,7 @@ public class SessionPersistentRegistry implements SessionRegistry {
Optional<SessionEntity> sessionEntityOpt = sessionRepository.findById(sessionId);
if (sessionEntityOpt.isPresent()) {
SessionEntity sessionEntity = sessionEntityOpt.get();
sessionEntity.setLastRequest(new Date()); // Update lastRequest to the current date
sessionEntity.setLastRequest(Instant.now()); // Update lastRequest to the current date
sessionRepository.save(sessionEntity);
}
}
@ -132,7 +133,7 @@ public class SessionPersistentRegistry implements SessionRegistry {
return new SessionInformation(
sessionEntity.getPrincipalName(),
sessionEntity.getSessionId(),
sessionEntity.getLastRequest());
Date.from(sessionEntity.getLastRequest()));
}
return null;
}
@ -170,7 +171,7 @@ public class SessionPersistentRegistry implements SessionRegistry {
// Update session details by principal name
public void updateSessionByPrincipalName(
String principalName, boolean expired, Date lastRequest) {
sessionRepository.saveByPrincipalName(expired, lastRequest, principalName);
sessionRepository.saveByPrincipalName(expired, lastRequest.toInstant(), principalName);
}
// Find the latest session for a given principal name