mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-11-16 01:21:16 +01:00
refactor(core,common,proprietary): Replace Date with Instant/modern Date API alternative for improved time handling (#4497)
This commit is contained in:
parent
07392ed25e
commit
133e6d3de6
@ -1,6 +1,6 @@
|
|||||||
package stirling.software.common.model;
|
package stirling.software.common.model;
|
||||||
|
|
||||||
import java.util.Calendar;
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
@ -18,6 +18,6 @@ public class PdfMetadata {
|
|||||||
private String creator;
|
private String creator;
|
||||||
private String subject;
|
private String subject;
|
||||||
private String keywords;
|
private String keywords;
|
||||||
private Calendar creationDate;
|
private ZonedDateTime creationDate;
|
||||||
private Calendar modificationDate;
|
private ZonedDateTime modificationDate;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,9 @@
|
|||||||
package stirling.software.common.service;
|
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 java.util.Calendar;
|
||||||
|
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
@ -29,17 +33,19 @@ public class PdfMetadataService {
|
|||||||
this.runningProOrHigher = runningProOrHigher;
|
this.runningProOrHigher = runningProOrHigher;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PdfMetadata extractMetadataFromPdf(PDDocument pdf) {
|
/**
|
||||||
return PdfMetadata.builder()
|
* Converts ZonedDateTime to Calendar for PDFBox compatibility.
|
||||||
.author(pdf.getDocumentInformation().getAuthor())
|
*
|
||||||
.producer(pdf.getDocumentInformation().getProducer())
|
* @param zonedDateTime the ZonedDateTime to convert
|
||||||
.title(pdf.getDocumentInformation().getTitle())
|
* @return Calendar instance or null if input is null
|
||||||
.creator(pdf.getDocumentInformation().getCreator())
|
*/
|
||||||
.subject(pdf.getDocumentInformation().getSubject())
|
public static Calendar toCalendar(ZonedDateTime zonedDateTime) {
|
||||||
.keywords(pdf.getDocumentInformation().getKeywords())
|
if (zonedDateTime == null) {
|
||||||
.creationDate(pdf.getDocumentInformation().getCreationDate())
|
return null;
|
||||||
.modificationDate(pdf.getDocumentInformation().getModificationDate())
|
}
|
||||||
.build();
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
calendar.setTimeInMillis(zonedDateTime.toInstant().toEpochMilli());
|
||||||
|
return calendar;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDefaultMetadata(PDDocument pdf) {
|
public void setDefaultMetadata(PDDocument pdf) {
|
||||||
@ -58,6 +64,52 @@ public class PdfMetadataService {
|
|||||||
setCommonMetadata(pdf, pdfMetadata);
|
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) {
|
private void setNewDocumentMetadata(PDDocument pdf, PdfMetadata pdfMetadata) {
|
||||||
|
|
||||||
String creator = stirlingPDFLabel;
|
String creator = stirlingPDFLabel;
|
||||||
@ -79,7 +131,13 @@ public class PdfMetadataService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pdf.getDocumentInformation().setCreator(creator);
|
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) {
|
private void setCommonMetadata(PDDocument pdf, PdfMetadata pdfMetadata) {
|
||||||
@ -88,7 +146,13 @@ public class PdfMetadataService {
|
|||||||
pdf.getDocumentInformation().setProducer(stirlingPDFLabel);
|
pdf.getDocumentInformation().setProducer(stirlingPDFLabel);
|
||||||
pdf.getDocumentInformation().setSubject(pdfMetadata.getSubject());
|
pdf.getDocumentInformation().setSubject(pdfMetadata.getSubject());
|
||||||
pdf.getDocumentInformation().setKeywords(pdfMetadata.getKeywords());
|
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();
|
String author = pdfMetadata.getAuthor();
|
||||||
if (applicationProperties
|
if (applicationProperties
|
||||||
|
|||||||
@ -6,6 +6,8 @@ import java.io.InputStream;
|
|||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -145,7 +147,11 @@ public class EmlParser {
|
|||||||
extractRecipients(message, messageClass, content);
|
extractRecipients(message, messageClass, content);
|
||||||
|
|
||||||
Method getSentDate = messageClass.getMethod("getSentDate");
|
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");
|
Method getContent = messageClass.getMethod("getContent");
|
||||||
Object messageContent = getContent.invoke(message);
|
Object messageContent = getContent.invoke(message);
|
||||||
@ -616,7 +622,7 @@ public class EmlParser {
|
|||||||
private String to;
|
private String to;
|
||||||
private String cc;
|
private String cc;
|
||||||
private String bcc;
|
private String bcc;
|
||||||
private Date date;
|
private ZonedDateTime date;
|
||||||
private String dateString; // For basic parsing fallback
|
private String dateString; // For basic parsing fallback
|
||||||
private String htmlBody;
|
private String htmlBody;
|
||||||
private String textBody;
|
private String textBody;
|
||||||
|
|||||||
@ -8,7 +8,9 @@ import java.io.File;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
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.ArrayList;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@ -18,7 +20,6 @@ import java.util.List;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TimeZone;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@ -290,11 +291,15 @@ public class PdfAttachmentHandler {
|
|||||||
|
|
||||||
public static String formatEmailDate(Date date) {
|
public static String formatEmailDate(Date date) {
|
||||||
if (date == null) return "";
|
if (date == null) return "";
|
||||||
|
return formatEmailDate(ZonedDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()));
|
||||||
|
}
|
||||||
|
|
||||||
SimpleDateFormat formatter =
|
public static String formatEmailDate(ZonedDateTime dateTime) {
|
||||||
new SimpleDateFormat("EEE, MMM d, yyyy 'at' h:mm a z", Locale.ENGLISH);
|
if (dateTime == null) return "";
|
||||||
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
|
|
||||||
return formatter.format(date);
|
DateTimeFormatter formatter =
|
||||||
|
DateTimeFormatter.ofPattern("EEE, MMM d, yyyy 'at' h:mm a z", Locale.ENGLISH);
|
||||||
|
return dateTime.withZoneSameInstant(ZoneId.of("UTC")).format(formatter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
|||||||
@ -7,16 +7,18 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TimeZone;
|
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.pdfbox.Loader;
|
import org.apache.pdfbox.Loader;
|
||||||
@ -564,18 +566,31 @@ public class ConvertPDFToPDFA {
|
|||||||
adobePdfSchema.setKeywords(keywords);
|
adobePdfSchema.setKeywords(keywords);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set creation and modification dates
|
// Set creation and modification dates using java.time and convert to GregorianCalendar
|
||||||
Calendar now = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
|
Instant nowInstant = Instant.now();
|
||||||
Calendar originalCreationDate = docInfo.getCreationDate();
|
ZonedDateTime nowZdt = ZonedDateTime.ofInstant(nowInstant, ZoneId.of("UTC"));
|
||||||
if (originalCreationDate == null) {
|
GregorianCalendar nowCal = GregorianCalendar.from(nowZdt);
|
||||||
originalCreationDate = now;
|
|
||||||
}
|
|
||||||
docInfo.setCreationDate(originalCreationDate);
|
|
||||||
xmpBasicSchema.setCreateDate(originalCreationDate);
|
|
||||||
|
|
||||||
docInfo.setModificationDate(now);
|
java.util.Calendar originalCreationDate = docInfo.getCreationDate();
|
||||||
xmpBasicSchema.setModifyDate(now);
|
GregorianCalendar creationCal;
|
||||||
xmpBasicSchema.setMetadataDate(now);
|
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
|
// Serialize the created metadata so it can be attached to the existent metadata
|
||||||
ByteArrayOutputStream xmpOut = new ByteArrayOutputStream();
|
ByteArrayOutputStream xmpOut = new ByteArrayOutputStream();
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
package stirling.software.SPDF.controller.api.misc;
|
package stirling.software.SPDF.controller.api.misc;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.ParseException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
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.SPDF.model.api.misc.MetadataRequest;
|
||||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||||
|
import stirling.software.common.service.PdfMetadataService;
|
||||||
import stirling.software.common.util.WebResponseUtils;
|
import stirling.software.common.util.WebResponseUtils;
|
||||||
import stirling.software.common.util.propertyeditor.StringToMapPropertyEditor;
|
import stirling.software.common.util.propertyeditor.StringToMapPropertyEditor;
|
||||||
|
|
||||||
@ -144,30 +143,13 @@ public class MetadataController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (creationDate != null && creationDate.length() > 0) {
|
// Set creation date using utility method
|
||||||
Calendar creationDateCal = Calendar.getInstance();
|
Calendar creationDateCal = PdfMetadataService.parseToCalendar(creationDate);
|
||||||
try {
|
info.setCreationDate(creationDateCal);
|
||||||
creationDateCal.setTime(
|
|
||||||
new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(creationDate));
|
// Set modification date using utility method
|
||||||
} catch (ParseException e) {
|
Calendar modificationDateCal = PdfMetadataService.parseToCalendar(modificationDate);
|
||||||
log.error("exception", e);
|
info.setModificationDate(modificationDateCal);
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
info.setCreator(creator);
|
info.setCreator(creator);
|
||||||
info.setKeywords(keywords);
|
info.setKeywords(keywords);
|
||||||
info.setAuthor(author);
|
info.setAuthor(author);
|
||||||
|
|||||||
@ -120,7 +120,7 @@ public class CertSignController {
|
|||||||
signature.setName(name);
|
signature.setName(name);
|
||||||
signature.setLocation(location);
|
signature.setLocation(location);
|
||||||
signature.setReason(reason);
|
signature.setReason(reason);
|
||||||
signature.setSignDate(Calendar.getInstance());
|
signature.setSignDate(Calendar.getInstance()); // PDFBox requires Calendar
|
||||||
if (Boolean.TRUE.equals(showSignature)) {
|
if (Boolean.TRUE.equals(showSignature)) {
|
||||||
SignatureOptions signatureOptions = new SignatureOptions();
|
SignatureOptions signatureOptions = new SignatureOptions();
|
||||||
signatureOptions.setVisualSignature(
|
signatureOptions.setVisualSignature(
|
||||||
|
|||||||
@ -3,7 +3,9 @@ package stirling.software.SPDF.controller.api.security;
|
|||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
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 java.util.*;
|
||||||
|
|
||||||
import org.apache.pdfbox.cos.COSInputStream;
|
import org.apache.pdfbox.cos.COSInputStream;
|
||||||
@ -817,8 +819,10 @@ public class GetInfoOnPDF {
|
|||||||
|
|
||||||
private String formatDate(Calendar calendar) {
|
private String formatDate(Calendar calendar) {
|
||||||
if (calendar != null) {
|
if (calendar != null) {
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
return sdf.format(calendar.getTime());
|
ZonedDateTime zonedDateTime =
|
||||||
|
ZonedDateTime.ofInstant(calendar.toInstant(), ZoneId.systemDefault());
|
||||||
|
return zonedDateTime.format(formatter);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,8 +7,8 @@ import java.security.cert.CertificateException;
|
|||||||
import java.security.cert.CertificateFactory;
|
import java.security.cert.CertificateFactory;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.security.interfaces.RSAPublicKey;
|
import java.security.interfaces.RSAPublicKey;
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
@ -134,11 +134,12 @@ public class ValidateSignatureController {
|
|||||||
: certValidationService.validateTrustStore(cert));
|
: certValidationService.validateTrustStore(cert));
|
||||||
|
|
||||||
result.setNotRevoked(!certValidationService.isRevoked(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
|
// Set basic signature info
|
||||||
result.setSignerName(sig.getName());
|
result.setSignerName(sig.getName());
|
||||||
result.setSignatureDate(sig.getSignDate().getTime().toString());
|
result.setSignatureDate(sig.getSignDate().toInstant().toString());
|
||||||
result.setReason(sig.getReason());
|
result.setReason(sig.getReason());
|
||||||
result.setLocation(sig.getLocation());
|
result.setLocation(sig.getLocation());
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,9 @@ package stirling.software.SPDF.service;
|
|||||||
import static stirling.software.common.util.AttachmentUtils.setCatalogViewerPreferences;
|
import static stirling.software.common.util.AttachmentUtils.setCatalogViewerPreferences;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -54,8 +57,13 @@ public class AttachmentService implements AttachmentServiceInterface {
|
|||||||
PDEmbeddedFile embeddedFile =
|
PDEmbeddedFile embeddedFile =
|
||||||
new PDEmbeddedFile(document, attachment.getInputStream());
|
new PDEmbeddedFile(document, attachment.getInputStream());
|
||||||
embeddedFile.setSize((int) attachment.getSize());
|
embeddedFile.setSize((int) attachment.getSize());
|
||||||
embeddedFile.setCreationDate(new GregorianCalendar());
|
// use java.time.Instant and convert to GregorianCalendar for PDFBox
|
||||||
embeddedFile.setModDate(new GregorianCalendar());
|
Instant now = Instant.now();
|
||||||
|
GregorianCalendar nowCal =
|
||||||
|
GregorianCalendar.from(
|
||||||
|
ZonedDateTime.ofInstant(now, ZoneId.systemDefault()));
|
||||||
|
embeddedFile.setCreationDate(nowCal);
|
||||||
|
embeddedFile.setModDate(nowCal);
|
||||||
String contentType = attachment.getContentType();
|
String contentType = attachment.getContentType();
|
||||||
if (StringUtils.isNotBlank(contentType)) {
|
if (StringUtils.isNotBlank(contentType)) {
|
||||||
embeddedFile.setSubtype(contentType);
|
embeddedFile.setSubtype(contentType);
|
||||||
|
|||||||
@ -7,6 +7,8 @@ import static org.mockito.Mockito.times;
|
|||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
@ -81,6 +83,12 @@ class PdfMetadataServiceBasicTest {
|
|||||||
// Act
|
// Act
|
||||||
PdfMetadata metadata = pdfMetadataService.extractMetadataFromPdf(testDocument);
|
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
|
// Assert
|
||||||
assertEquals(testAuthor, metadata.getAuthor(), "Author should match");
|
assertEquals(testAuthor, metadata.getAuthor(), "Author should match");
|
||||||
assertEquals(testProducer, metadata.getProducer(), "Producer should match");
|
assertEquals(testProducer, metadata.getProducer(), "Producer should match");
|
||||||
@ -88,9 +96,12 @@ class PdfMetadataServiceBasicTest {
|
|||||||
assertEquals(testCreator, metadata.getCreator(), "Creator should match");
|
assertEquals(testCreator, metadata.getCreator(), "Creator should match");
|
||||||
assertEquals(testSubject, metadata.getSubject(), "Subject should match");
|
assertEquals(testSubject, metadata.getSubject(), "Subject should match");
|
||||||
assertEquals(testKeywords, metadata.getKeywords(), "Keywords should match");
|
assertEquals(testKeywords, metadata.getKeywords(), "Keywords should match");
|
||||||
assertEquals(creationDate, metadata.getCreationDate(), "Creation date should match");
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
modificationDate, metadata.getModificationDate(), "Modification date should match");
|
expectedCreationDate, metadata.getCreationDate(), "Creation date should match");
|
||||||
|
assertEquals(
|
||||||
|
expectedModificationDate,
|
||||||
|
metadata.getModificationDate(),
|
||||||
|
"Modification date should match");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@ -7,6 +7,8 @@ import static org.mockito.Mockito.mock;
|
|||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
@ -84,6 +86,12 @@ class PdfMetadataServiceTest {
|
|||||||
// Act
|
// Act
|
||||||
PdfMetadata metadata = pdfMetadataService.extractMetadataFromPdf(testDocument);
|
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
|
// Assert
|
||||||
assertEquals(testAuthor, metadata.getAuthor(), "Author should match");
|
assertEquals(testAuthor, metadata.getAuthor(), "Author should match");
|
||||||
assertEquals(testProducer, metadata.getProducer(), "Producer should match");
|
assertEquals(testProducer, metadata.getProducer(), "Producer should match");
|
||||||
@ -91,9 +99,12 @@ class PdfMetadataServiceTest {
|
|||||||
assertEquals(testCreator, metadata.getCreator(), "Creator should match");
|
assertEquals(testCreator, metadata.getCreator(), "Creator should match");
|
||||||
assertEquals(testSubject, metadata.getSubject(), "Subject should match");
|
assertEquals(testSubject, metadata.getSubject(), "Subject should match");
|
||||||
assertEquals(testKeywords, metadata.getKeywords(), "Keywords should match");
|
assertEquals(testKeywords, metadata.getKeywords(), "Keywords should match");
|
||||||
assertEquals(creationDate, metadata.getCreationDate(), "Creation date should match");
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
modificationDate, metadata.getModificationDate(), "Modification date should match");
|
expectedCreationDate, metadata.getCreationDate(), "Creation date should match");
|
||||||
|
assertEquals(
|
||||||
|
expectedModificationDate,
|
||||||
|
metadata.getModificationDate(),
|
||||||
|
"Modification date should match");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -190,6 +201,8 @@ class PdfMetadataServiceTest {
|
|||||||
// Prepare test metadata with existing creation date
|
// Prepare test metadata with existing creation date
|
||||||
Calendar existingCreationDate = Calendar.getInstance();
|
Calendar existingCreationDate = Calendar.getInstance();
|
||||||
existingCreationDate.add(Calendar.DAY_OF_MONTH, -1); // Yesterday
|
existingCreationDate.add(Calendar.DAY_OF_MONTH, -1); // Yesterday
|
||||||
|
ZonedDateTime existingCreationDateZdt =
|
||||||
|
ZonedDateTime.ofInstant(existingCreationDate.toInstant(), ZoneId.systemDefault());
|
||||||
|
|
||||||
PdfMetadata testMetadata =
|
PdfMetadata testMetadata =
|
||||||
PdfMetadata.builder()
|
PdfMetadata.builder()
|
||||||
@ -197,7 +210,7 @@ class PdfMetadataServiceTest {
|
|||||||
.title("Test Title")
|
.title("Test Title")
|
||||||
.subject("Test Subject")
|
.subject("Test Subject")
|
||||||
.keywords("Test Keywords")
|
.keywords("Test Keywords")
|
||||||
.creationDate(existingCreationDate)
|
.creationDate(existingCreationDateZdt)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import static stirling.software.common.util.ProviderUtils.validateProvider;
|
|||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -218,7 +217,7 @@ public class AccountWebController {
|
|||||||
Map<String, String> roleDetails = Role.getAllRoleDetails();
|
Map<String, String> roleDetails = Role.getAllRoleDetails();
|
||||||
// Map to store session information and user activity status
|
// Map to store session information and user activity status
|
||||||
Map<String, Boolean> userSessions = new HashMap<>();
|
Map<String, Boolean> userSessions = new HashMap<>();
|
||||||
Map<String, Date> userLastRequest = new HashMap<>();
|
Map<String, Instant> userLastRequest = new HashMap<>();
|
||||||
int activeUsers = 0;
|
int activeUsers = 0;
|
||||||
int disabledUsers = 0;
|
int disabledUsers = 0;
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
@ -249,27 +248,29 @@ public class AccountWebController {
|
|||||||
// Determine the user's session status and last request time
|
// Determine the user's session status and last request time
|
||||||
int maxInactiveInterval = sessionPersistentRegistry.getMaxInactiveInterval();
|
int maxInactiveInterval = sessionPersistentRegistry.getMaxInactiveInterval();
|
||||||
boolean hasActiveSession = false;
|
boolean hasActiveSession = false;
|
||||||
Date lastRequest = null;
|
Instant lastRequest = null;
|
||||||
Optional<SessionEntity> latestSession =
|
Optional<SessionEntity> latestSession =
|
||||||
sessionPersistentRegistry.findLatestSession(user.getUsername());
|
sessionPersistentRegistry.findLatestSession(user.getUsername());
|
||||||
if (latestSession.isPresent()) {
|
if (latestSession.isPresent()) {
|
||||||
SessionEntity sessionEntity = latestSession.get();
|
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();
|
Instant now = Instant.now();
|
||||||
// Calculate session expiration and update session status accordingly
|
// Calculate session expiration and update session status accordingly
|
||||||
Instant expirationTime =
|
Instant expirationTime =
|
||||||
lastAccessedTime
|
lastAccessedTime.plus(maxInactiveInterval, ChronoUnit.SECONDS);
|
||||||
.toInstant()
|
|
||||||
.plus(maxInactiveInterval, ChronoUnit.SECONDS);
|
|
||||||
if (now.isAfter(expirationTime)) {
|
if (now.isAfter(expirationTime)) {
|
||||||
sessionPersistentRegistry.expireSession(sessionEntity.getSessionId());
|
sessionPersistentRegistry.expireSession(sessionEntity.getSessionId());
|
||||||
} else {
|
} else {
|
||||||
hasActiveSession = !sessionEntity.isExpired();
|
hasActiveSession = !sessionEntity.isExpired();
|
||||||
}
|
}
|
||||||
lastRequest = sessionEntity.getLastRequest();
|
lastRequest = lastAccessedTime;
|
||||||
} else {
|
} else {
|
||||||
// No session, set default last request time
|
// No session, set default last request time
|
||||||
lastRequest = new Date(0);
|
lastRequest = Instant.EPOCH;
|
||||||
}
|
}
|
||||||
userSessions.put(user.getUsername(), hasActiveSession);
|
userSessions.put(user.getUsername(), hasActiveSession);
|
||||||
userLastRequest.put(user.getUsername(), lastRequest);
|
userLastRequest.put(user.getUsername(), lastRequest);
|
||||||
@ -286,19 +287,21 @@ public class AccountWebController {
|
|||||||
allUsers.stream()
|
allUsers.stream()
|
||||||
.sorted(
|
.sorted(
|
||||||
(u1, u2) -> {
|
(u1, u2) -> {
|
||||||
boolean u1Active = userSessions.get(u1.getUsername());
|
boolean u1Active =
|
||||||
boolean u2Active = userSessions.get(u2.getUsername());
|
userSessions.getOrDefault(u1.getUsername(), false);
|
||||||
|
boolean u2Active =
|
||||||
|
userSessions.getOrDefault(u2.getUsername(), false);
|
||||||
if (u1Active && !u2Active) {
|
if (u1Active && !u2Active) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if (!u1Active && u2Active) {
|
} else if (!u1Active && u2Active) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
Date u1LastRequest =
|
Instant u1LastRequest =
|
||||||
userLastRequest.getOrDefault(
|
userLastRequest.getOrDefault(
|
||||||
u1.getUsername(), new Date(0));
|
u1.getUsername(), Instant.EPOCH);
|
||||||
Date u2LastRequest =
|
Instant u2LastRequest =
|
||||||
userLastRequest.getOrDefault(
|
userLastRequest.getOrDefault(
|
||||||
u2.getUsername(), new Date(0));
|
u2.getUsername(), Instant.EPOCH);
|
||||||
return u2LastRequest.compareTo(u1LastRequest);
|
return u2LastRequest.compareTo(u1LastRequest);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
package stirling.software.proprietary.security.controller.web;
|
package stirling.software.proprietary.security.controller.web;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.time.Instant;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -44,17 +44,17 @@ public class TeamWebController {
|
|||||||
// Filter out the Internal team
|
// Filter out the Internal team
|
||||||
List<TeamWithUserCountDTO> teamsWithCounts =
|
List<TeamWithUserCountDTO> teamsWithCounts =
|
||||||
allTeamsWithCounts.stream()
|
allTeamsWithCounts.stream()
|
||||||
.filter(team -> !team.getName().equals(TeamService.INTERNAL_TEAM_NAME))
|
.filter(team -> !TeamService.INTERNAL_TEAM_NAME.equals(team.getName()))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
// Get the latest activity for each team
|
// Get the latest activity for each team
|
||||||
List<Object[]> teamActivities = sessionRepository.findLatestActivityByTeam();
|
List<Object[]> teamActivities = sessionRepository.findLatestActivityByTeam();
|
||||||
|
|
||||||
// Convert the query results to a map for easy access in the view
|
// 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) {
|
for (Object[] result : teamActivities) {
|
||||||
Long teamId = (Long) result[0]; // teamId alias
|
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);
|
teamLastRequest.put(teamId, lastActivity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ public class TeamWebController {
|
|||||||
.orElseThrow(() -> new RuntimeException("Team not found"));
|
.orElseThrow(() -> new RuntimeException("Team not found"));
|
||||||
|
|
||||||
// Prevent access to Internal team
|
// 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";
|
return "redirect:/teams?error=internalTeamNotAccessible";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,21 +114,18 @@ public class TeamWebController {
|
|||||||
(user.getTeam() == null
|
(user.getTeam() == null
|
||||||
|| !user.getTeam().getId().equals(id))
|
|| !user.getTeam().getId().equals(id))
|
||||||
&& (user.getTeam() == null
|
&& (user.getTeam() == null
|
||||||
|| !user.getTeam()
|
|| !TeamService.INTERNAL_TEAM_NAME.equals(
|
||||||
.getName()
|
user.getTeam().getName())))
|
||||||
.equals(
|
|
||||||
TeamService
|
|
||||||
.INTERNAL_TEAM_NAME)))
|
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
// Get the latest session for each user in the team
|
// Get the latest session for each user in the team
|
||||||
List<Object[]> userSessions = sessionRepository.findLatestSessionByTeamId(id);
|
List<Object[]> userSessions = sessionRepository.findLatestSessionByTeamId(id);
|
||||||
|
|
||||||
// Create a map of username to last request date
|
// 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) {
|
for (Object[] result : userSessions) {
|
||||||
String username = (String) result[0]; // username alias
|
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);
|
userLastRequest.put(username, lastRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,7 @@ public class JPATokenRepositoryImpl implements PersistentTokenRepository {
|
|||||||
newToken.setSeries(token.getSeries());
|
newToken.setSeries(token.getSeries());
|
||||||
newToken.setUsername(token.getUsername());
|
newToken.setUsername(token.getUsername());
|
||||||
newToken.setToken(token.getTokenValue());
|
newToken.setToken(token.getTokenValue());
|
||||||
newToken.setLastUsed(token.getDate());
|
newToken.setLastUsed(token.getDate().toInstant());
|
||||||
persistentLoginRepository.save(newToken);
|
persistentLoginRepository.save(newToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ public class JPATokenRepositoryImpl implements PersistentTokenRepository {
|
|||||||
PersistentLogin existingToken = persistentLoginRepository.findById(series).orElse(null);
|
PersistentLogin existingToken = persistentLoginRepository.findById(series).orElse(null);
|
||||||
if (existingToken != null) {
|
if (existingToken != null) {
|
||||||
existingToken.setToken(tokenValue);
|
existingToken.setToken(tokenValue);
|
||||||
existingToken.setLastUsed(lastUsed);
|
existingToken.setLastUsed(lastUsed.toInstant());
|
||||||
persistentLoginRepository.save(existingToken);
|
persistentLoginRepository.save(existingToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,7 +43,10 @@ public class JPATokenRepositoryImpl implements PersistentTokenRepository {
|
|||||||
PersistentLogin token = persistentLoginRepository.findById(seriesId).orElse(null);
|
PersistentLogin token = persistentLoginRepository.findById(seriesId).orElse(null);
|
||||||
if (token != null) {
|
if (token != null) {
|
||||||
return new PersistentRememberMeToken(
|
return new PersistentRememberMeToken(
|
||||||
token.getUsername(), token.getSeries(), token.getToken(), token.getLastUsed());
|
token.getUsername(),
|
||||||
|
token.getSeries(),
|
||||||
|
token.getToken(),
|
||||||
|
Date.from(token.getLastUsed()));
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
package stirling.software.proprietary.security.database.repository;
|
package stirling.software.proprietary.security.database.repository;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.time.Instant;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
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")
|
"UPDATE SessionEntity s SET s.expired = :expired, s.lastRequest = :lastRequest WHERE s.principalName = :principalName")
|
||||||
void saveByPrincipalName(
|
void saveByPrincipalName(
|
||||||
@Param("expired") boolean expired,
|
@Param("expired") boolean expired,
|
||||||
@Param("lastRequest") Date lastRequest,
|
@Param("lastRequest") Instant lastRequest,
|
||||||
@Param("principalName") String principalName);
|
@Param("principalName") String principalName);
|
||||||
|
|
||||||
@Query(
|
@Query(
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
package stirling.software.proprietary.security.filter;
|
package stirling.software.proprietary.security.filter;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.time.Instant;
|
||||||
import java.util.Date;
|
import java.time.ZoneId;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
@ -60,8 +61,12 @@ public class FirstLoginFilter extends OncePerRequestFilter {
|
|||||||
}
|
}
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
HttpSession session = request.getSession(true);
|
HttpSession session = request.getSession(true);
|
||||||
SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
|
DateTimeFormatter timeFormat = DateTimeFormatter.ofPattern("HH:mm:ss");
|
||||||
String creationTime = timeFormat.format(new Date(session.getCreationTime()));
|
String creationTime =
|
||||||
|
timeFormat.format(
|
||||||
|
Instant.ofEpochMilli(session.getCreationTime())
|
||||||
|
.atZone(ZoneId.systemDefault())
|
||||||
|
.toLocalTime());
|
||||||
log.debug(
|
log.debug(
|
||||||
"Request Info - New: {}, creationTimeSession {}, ID: {}, IP: {}, User-Agent: {}, Referer: {}, Request URL: {}",
|
"Request Info - New: {}, creationTimeSession {}, ID: {}, IP: {}, User-Agent: {}, Referer: {}, Request URL: {}",
|
||||||
session.isNew(),
|
session.isNew(),
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
package stirling.software.proprietary.security.model;
|
package stirling.software.proprietary.security.model;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.time.Instant;
|
||||||
|
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
@ -25,5 +25,5 @@ public class PersistentLogin {
|
|||||||
private String token;
|
private String token;
|
||||||
|
|
||||||
@Column(name = "last_used", nullable = false)
|
@Column(name = "last_used", nullable = false)
|
||||||
private Date lastUsed;
|
private Instant lastUsed;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
package stirling.software.proprietary.security.model;
|
package stirling.software.proprietary.security.model;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.time.Instant;
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
@ -17,7 +17,7 @@ public class SessionEntity implements Serializable {
|
|||||||
|
|
||||||
private String principalName;
|
private String principalName;
|
||||||
|
|
||||||
private Date lastRequest;
|
private Instant lastRequest;
|
||||||
|
|
||||||
private boolean expired;
|
private boolean expired;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import java.security.KeyPair;
|
|||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.time.Instant;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -92,8 +93,8 @@ public class JwtService implements JwtServiceInterface {
|
|||||||
.claims(claims)
|
.claims(claims)
|
||||||
.subject(username)
|
.subject(username)
|
||||||
.issuer(ISSUER)
|
.issuer(ISSUER)
|
||||||
.issuedAt(new Date())
|
.issuedAt(Date.from(Instant.now()))
|
||||||
.expiration(new Date(System.currentTimeMillis() + EXPIRATION))
|
.expiration(Date.from(Instant.now().plusMillis(EXPIRATION)))
|
||||||
.signWith(keyPair.getPrivate(), Jwts.SIG.RS256);
|
.signWith(keyPair.getPrivate(), Jwts.SIG.RS256);
|
||||||
|
|
||||||
String keyId = activeKey.getKeyId();
|
String keyId = activeKey.getKeyId();
|
||||||
@ -129,7 +130,7 @@ public class JwtService implements JwtServiceInterface {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isTokenExpired(String token) {
|
public boolean isTokenExpired(String token) {
|
||||||
return extractExpiration(token).before(new Date());
|
return extractExpiration(token).before(Date.from(Instant.now()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Date extractExpiration(String token) {
|
private Date extractExpiration(String token) {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package stirling.software.proprietary.security.session;
|
package stirling.software.proprietary.security.session;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
@ -67,7 +68,7 @@ public class SessionPersistentRegistry implements SessionRegistry {
|
|||||||
new SessionInformation(
|
new SessionInformation(
|
||||||
sessionEntity.getPrincipalName(),
|
sessionEntity.getPrincipalName(),
|
||||||
sessionEntity.getSessionId(),
|
sessionEntity.getSessionId(),
|
||||||
sessionEntity.getLastRequest()));
|
Date.from(sessionEntity.getLastRequest())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,7 +102,7 @@ public class SessionPersistentRegistry implements SessionRegistry {
|
|||||||
SessionEntity sessionEntity = new SessionEntity();
|
SessionEntity sessionEntity = new SessionEntity();
|
||||||
sessionEntity.setSessionId(sessionId);
|
sessionEntity.setSessionId(sessionId);
|
||||||
sessionEntity.setPrincipalName(principalName);
|
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);
|
sessionEntity.setExpired(false);
|
||||||
sessionRepository.save(sessionEntity);
|
sessionRepository.save(sessionEntity);
|
||||||
}
|
}
|
||||||
@ -119,7 +120,7 @@ public class SessionPersistentRegistry implements SessionRegistry {
|
|||||||
Optional<SessionEntity> sessionEntityOpt = sessionRepository.findById(sessionId);
|
Optional<SessionEntity> sessionEntityOpt = sessionRepository.findById(sessionId);
|
||||||
if (sessionEntityOpt.isPresent()) {
|
if (sessionEntityOpt.isPresent()) {
|
||||||
SessionEntity sessionEntity = sessionEntityOpt.get();
|
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);
|
sessionRepository.save(sessionEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,7 +133,7 @@ public class SessionPersistentRegistry implements SessionRegistry {
|
|||||||
return new SessionInformation(
|
return new SessionInformation(
|
||||||
sessionEntity.getPrincipalName(),
|
sessionEntity.getPrincipalName(),
|
||||||
sessionEntity.getSessionId(),
|
sessionEntity.getSessionId(),
|
||||||
sessionEntity.getLastRequest());
|
Date.from(sessionEntity.getLastRequest()));
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -170,7 +171,7 @@ public class SessionPersistentRegistry implements SessionRegistry {
|
|||||||
// Update session details by principal name
|
// Update session details by principal name
|
||||||
public void updateSessionByPrincipalName(
|
public void updateSessionByPrincipalName(
|
||||||
String principalName, boolean expired, Date lastRequest) {
|
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
|
// Find the latest session for a given principal name
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user