Auditing support (#3739)

# Description of Changes

This pull request introduces a comprehensive auditing system to the
application, along with minor updates to existing utilities and
dependencies. The most significant changes include the addition of
audit-related classes and enums, updates to the `ApplicationProperties`
model to support auditing configuration, and enhancements to utility
methods for handling static and trackable resources.

### Audit System Implementation:

* **Audit Aspect for Method Annotations**: Added `AuditAspect` to
process the new `@Audited` annotation, enabling detailed logging of
method execution, HTTP requests, and operation results based on
configurable audit levels.
(`proprietary/src/main/java/stirling/software/proprietary/audit/AuditAspect.java`)
* **Audit Event Types**: Introduced `AuditEventType` enum to define
standardized event types for auditing, such as authentication events,
file operations, and HTTP requests.
(`proprietary/src/main/java/stirling/software/proprietary/audit/AuditEventType.java`)
* **Audit Levels**: Added `AuditLevel` enum to define different levels
of audit logging (OFF, BASIC, STANDARD, VERBOSE), providing granular
control over the amount of data logged.
(`proprietary/src/main/java/stirling/software/proprietary/audit/AuditLevel.java`)

### Application Properties Update:

* **Audit Configuration in `ProFeatures`**: Updated the `ProFeatures`
class in `ApplicationProperties` to include support for auditing with
configurable retention days, levels, and enablement flags.
(`common/src/main/java/stirling/software/common/model/ApplicationProperties.java`)

### Utility Enhancements:

* **Static and Trackable Resource Handling**: Extended `RequestUriUtils`
methods (`isStaticResource` and `isTrackableResource`) to recognize
`.txt` files as valid static and trackable resources.
(`common/src/main/java/stirling/software/common/util/RequestUriUtils.java`)
[[1]](diffhunk://#diff-de3599037908683f2cd8f170939547612c6fc2203e9207eb4d7966508f92bbcbR22)
[[2]](diffhunk://#diff-de3599037908683f2cd8f170939547612c6fc2203e9207eb4d7966508f92bbcbR39)

### Dependency Update:

* **Spring Validation Starter**: Added `spring-boot-starter-validation`
to project dependencies to support validation mechanisms required for
auditing features. (`proprietary/build.gradle`)


Dashboard WIP

![image](https://github.com/user-attachments/assets/20d86809-63b0-44d6-82d3-bdce2ac77aa3)


![image](https://github.com/user-attachments/assets/53a5ba69-71ab-4247-9a66-7ef86e462b13)

![image](https://github.com/user-attachments/assets/9a53eaed-ebc7-463c-81da-8b1c140f8a8c)


---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.

---------

Co-authored-by: a <a>
Co-authored-by: pixeebot[bot] <104101892+pixeebot[bot]@users.noreply.github.com>
This commit is contained in:
Anthony Stirling
2025-06-18 13:11:36 +01:00
committed by GitHub
parent ee41dc11c2
commit 552f2ced4d
38 changed files with 4168 additions and 17 deletions

View File

@@ -175,7 +175,6 @@ public class SPDFApplication {
}
}
}
log.info("Running configs {}", applicationProperties.toString());
}
public static void setServerPortStatic(String port) {
@@ -208,20 +207,19 @@ public class SPDFApplication {
if (arg.startsWith("--spring.profiles.active=")) {
String[] provided = arg.substring(arg.indexOf('=') + 1).split(",");
if (provided.length > 0) {
log.info("#######0000000000000###############################");
return provided;
}
}
}
}
log.info("######################################");
// 2. Detect if SecurityConfiguration is present on classpath
if (isClassPresent(
"stirling.software.proprietary.security.configuration.SecurityConfiguration")) {
log.info("security");
log.info("Additional features in jar");
return new String[] {"security"};
} else {
log.info("default");
log.info("Without additional features in jar");
return new String[] {"default"};
}
}

View File

@@ -13,17 +13,11 @@ import jakarta.servlet.http.HttpServletResponse;
public class CleanUrlInterceptor implements HandlerInterceptor {
private static final List<String> ALLOWED_PARAMS =
Arrays.asList(
"lang",
"endpoint",
"endpoints",
"logout",
"error",
"errorOAuth",
"file",
"messageType",
"infoMessage");
private static final List<String> ALLOWED_PARAMS = Arrays.asList(
"lang", "endpoint", "endpoints", "logout", "error", "errorOAuth", "file", "messageType", "infoMessage",
"page", "size", "type", "principal", "startDate", "endDate"
);
@Override
public boolean preHandle(

View File

@@ -1637,6 +1637,84 @@ validateSignature.cert.keyUsage=Key Usage
validateSignature.cert.selfSigned=Self-Signed
validateSignature.cert.bits=bits
# Audit Dashboard
audit.dashboard.title=Audit Dashboard
audit.dashboard.systemStatus=Audit System Status
audit.dashboard.status=Status
audit.dashboard.enabled=Enabled
audit.dashboard.disabled=Disabled
audit.dashboard.currentLevel=Current Level
audit.dashboard.retentionPeriod=Retention Period
audit.dashboard.days=days
audit.dashboard.totalEvents=Total Events
# Audit Dashboard Tabs
audit.dashboard.tab.dashboard=Dashboard
audit.dashboard.tab.events=Audit Events
audit.dashboard.tab.export=Export
# Dashboard Charts
audit.dashboard.eventsByType=Events by Type
audit.dashboard.eventsByUser=Events by User
audit.dashboard.eventsOverTime=Events Over Time
audit.dashboard.period.7days=7 Days
audit.dashboard.period.30days=30 Days
audit.dashboard.period.90days=90 Days
# Events Tab
audit.dashboard.auditEvents=Audit Events
audit.dashboard.filter.eventType=Event Type
audit.dashboard.filter.allEventTypes=All event types
audit.dashboard.filter.user=User
audit.dashboard.filter.userPlaceholder=Filter by user
audit.dashboard.filter.startDate=Start Date
audit.dashboard.filter.endDate=End Date
audit.dashboard.filter.apply=Apply Filters
audit.dashboard.filter.reset=Reset Filters
# Table Headers
audit.dashboard.table.id=ID
audit.dashboard.table.time=Time
audit.dashboard.table.user=User
audit.dashboard.table.type=Type
audit.dashboard.table.details=Details
audit.dashboard.table.viewDetails=View Details
# Pagination
audit.dashboard.pagination.show=Show
audit.dashboard.pagination.entries=entries
audit.dashboard.pagination.pageInfo1=Page
audit.dashboard.pagination.pageInfo2=of
audit.dashboard.pagination.totalRecords=Total records:
# Modal
audit.dashboard.modal.eventDetails=Event Details
audit.dashboard.modal.id=ID
audit.dashboard.modal.user=User
audit.dashboard.modal.type=Type
audit.dashboard.modal.time=Time
audit.dashboard.modal.data=Data
# Export Tab
audit.dashboard.export.title=Export Audit Data
audit.dashboard.export.format=Export Format
audit.dashboard.export.csv=CSV (Comma Separated Values)
audit.dashboard.export.json=JSON (JavaScript Object Notation)
audit.dashboard.export.button=Export Data
audit.dashboard.export.infoTitle=Export Information
audit.dashboard.export.infoDesc1=The export will include all audit events matching the selected filters. For large datasets, the export may take a few moments to generate.
audit.dashboard.export.infoDesc2=Exported data will include:
audit.dashboard.export.infoItem1=Event ID
audit.dashboard.export.infoItem2=User
audit.dashboard.export.infoItem3=Event Type
audit.dashboard.export.infoItem4=Timestamp
audit.dashboard.export.infoItem5=Event Data
# JavaScript i18n keys
audit.dashboard.js.noEventsFound=No audit events found matching the current filters
audit.dashboard.js.errorLoading=Error loading data:
audit.dashboard.js.errorRendering=Error rendering table:
audit.dashboard.js.loadingPage=Loading page
####################
# Cookie banner #
####################

View File

@@ -76,6 +76,11 @@ premium:
clientId: ''
apiKey: ''
appId: ''
enterpriseFeatures:
audit:
enabled: true # Enable audit logging
level: 2 # Audit logging level: 0=OFF, 1=BASIC, 2=STANDARD, 3=VERBOSE
retentionDays: 90 # Number of days to retain audit logs
mail:
enabled: false # set to 'true' to enable sending emails

View File

@@ -112,6 +112,11 @@
<span class="material-symbols-rounded">analytics</span>
<span th:text="#{adminUserSettings.usage}">Usage Statistics</span>
</a>
<a href="/audit" th:if="${@runningEE}" class="data-btn data-btn-secondary" title="Audit Dashboard">
<span class="material-symbols-rounded">security</span>
<span>Audit Dashboard</span>
</a>
</div>
<!-- Users Table -->