Merge pull request #3619 from Stirling-Tools/proprietary_module

Proprietary module
This commit is contained in:
Anthony Stirling 2025-06-05 12:29:02 +01:00 committed by GitHub
commit 4272dfa240
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
108 changed files with 861 additions and 513 deletions

View File

@ -37,7 +37,7 @@ jobs:
pr_repository: ${{ steps.get-pr-info.outputs.repository }}
pr_ref: ${{ steps.get-pr-info.outputs.ref }}
comment_id: ${{ github.event.comment.id }}
enable_security: ${{ steps.check-security-flag.outputs.enable_security }}
disable_security: ${{ steps.check-security-flag.outputs.disable_security }}
steps:
- name: Harden Runner
@ -92,10 +92,10 @@ jobs:
run: |
if [[ "$COMMENT_BODY" == *"security"* ]] || [[ "$COMMENT_BODY" == *"login"* ]]; then
echo "Security flags detected in comment"
echo "enable_security=true" >> $GITHUB_OUTPUT
echo "disable_security=false" >> $GITHUB_OUTPUT
else
echo "No security flags detected in comment"
echo "enable_security=false" >> $GITHUB_OUTPUT
echo "disable_security=true" >> $GITHUB_OUTPUT
fi
- name: Add 'in_progress' reaction to comment
@ -155,10 +155,10 @@ jobs:
- name: Run Gradle Command
run: |
if [ "${{ needs.check-comment.outputs.enable_security }}" == "true" ]; then
export DOCKER_ENABLE_SECURITY=true
if [ "${{ needs.check-comment.outputs.disable_security }}" == "true" ]; then
export DISABLE_ADDITIONAL_FEATURES=true
else
export DOCKER_ENABLE_SECURITY=false
export DISABLE_ADDITIONAL_FEATURES=false
fi
./gradlew clean build
env:
@ -199,7 +199,7 @@ jobs:
id: deploy
run: |
# Set security settings based on flags
if [ "${{ needs.check-comment.outputs.enable_security }}" == "true" ]; then
if [ "${{ needs.check-comment.outputs.disable_security }}" == "false" ]; then
DOCKER_SECURITY="true"
LOGIN_SECURITY="true"
SECURITY_STATUS="🔒 Security Enabled"
@ -223,7 +223,7 @@ jobs:
- /stirling/PR-${{ needs.check-comment.outputs.pr_number }}/config:/configs:rw
- /stirling/PR-${{ needs.check-comment.outputs.pr_number }}/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "${DOCKER_SECURITY}"
DISABLE_ADDITIONAL_FEATURES: "${DOCKER_SECURITY}"
SECURITY_ENABLELOGIN: "${LOGIN_SECURITY}"
SYSTEM_DEFAULTLOCALE: en-GB
UI_APPNAME: "Stirling-PDF PR#${{ needs.check-comment.outputs.pr_number }}"

View File

@ -40,12 +40,12 @@ jobs:
- name: Build with Gradle and no spring security
run: ./gradlew clean build
env:
DOCKER_ENABLE_SECURITY: false
DISABLE_ADDITIONAL_FEATURES: true
- name: Build with Gradle and with spring security
run: ./gradlew clean build
env:
DOCKER_ENABLE_SECURITY: true
DISABLE_ADDITIONAL_FEATURES: false
- name: Upload Test Reports
if: always()

View File

@ -48,11 +48,11 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
enable_security: [true, false]
disable_security: [true, false]
include:
- enable_security: true
- disable_security: false
file_suffix: "-with-login"
- enable_security: false
- disable_security: true
file_suffix: ""
steps:
- name: Harden Runner
@ -72,10 +72,10 @@ jobs:
with:
gradle-version: 8.14
- name: Generate jar (With Security=${{ matrix.enable_security }})
- name: Generate jar (Disable Security=${{ matrix.disable_security }})
run: ./gradlew clean createExe
env:
DOCKER_ENABLE_SECURITY: ${{ matrix.enable_security }}
DISABLE_ADDITIONAL_FEATURES: ${{ matrix.disable_security }}
STIRLING_PDF_DESKTOP_UI: false
- name: Rename binaries
@ -98,11 +98,11 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
enable_security: [true, false]
disable_security: [true, false]
include:
- enable_security: true
- disable_security: false
file_suffix: "with-login-"
- enable_security: false
- disable_security: true
file_suffix: ""
steps:
- name: Harden Runner
@ -171,7 +171,7 @@ jobs:
- name: Build Installer
run: ./gradlew build jpackage -x test --info
env:
DOCKER_ENABLE_SECURITY: false
DISABLE_ADDITIONAL_FEATURES: true
STIRLING_PDF_DESKTOP_UI: true
BROWSER_OPEN: true

View File

@ -37,7 +37,7 @@ jobs:
- name: Run Gradle Command
run: ./gradlew clean build
env:
DOCKER_ENABLE_SECURITY: false
DISABLE_ADDITIONAL_FEATURES: true
STIRLING_PDF_DESKTOP_UI: false
- name: Install cosign

View File

@ -13,11 +13,11 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
enable_security: [true, false]
disable_security: [true, false]
include:
- enable_security: true
- disable_security: false
file_suffix: "-with-login"
- enable_security: false
- disable_security: true
file_suffix: ""
outputs:
version: ${{ steps.versionNumber.outputs.versionNumber }}
@ -39,10 +39,10 @@ jobs:
with:
gradle-version: 8.14
- name: Generate jar (With Security=${{ matrix.enable_security }})
- name: Generate jar (Disable Security=${{ matrix.disable_security }})
run: ./gradlew clean createExe
env:
DOCKER_ENABLE_SECURITY: ${{ matrix.enable_security }}
DISABLE_ADDITIONAL_FEATURES: ${{ matrix.disable_security }}
STIRLING_PDF_DESKTOP_UI: false
- name: Get version number
@ -75,11 +75,11 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
enable_security: [true, false]
disable_security: [true, false]
include:
- enable_security: true
- disable_security: false
file_suffix: "-with-login"
- enable_security: false
- disable_security: true
file_suffix: ""
steps:
- name: Harden Runner
@ -153,11 +153,11 @@ jobs:
contents: write
strategy:
matrix:
enable_security: [true, false]
disable_security: [true, false]
include:
- enable_security: true
- disable_security: false
file_suffix: "-with-login"
- enable_security: false
- disable_security: true
file_suffix: ""
steps:
- name: Harden Runner

View File

@ -33,7 +33,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
DOCKER_ENABLE_SECURITY: true
DISABLE_ADDITIONAL_FEATURES: false
STIRLING_PDF_DESKTOP_UI: true
run: |
./gradlew clean build sonar \

View File

@ -28,7 +28,7 @@ jobs:
- name: Build with Gradle
run: ./gradlew clean build
env:
DOCKER_ENABLE_SECURITY: false
DISABLE_ADDITIONAL_FEATURES: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
@ -76,7 +76,7 @@ jobs:
- /stirling/test-${{ github.sha }}/config:/configs:rw
- /stirling/test-${{ github.sha }}/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "false"
DISABLE_ADDITIONAL_FEATURES: "true"
SECURITY_ENABLELOGIN: "false"
SYSTEM_DEFAULTLOCALE: en-GB
UI_APPNAME: "Stirling-PDF Test"

View File

@ -50,8 +50,10 @@
".vscode/",
"bin/",
"common/bin/",
"proprietary/bin/",
"build/",
"common/build/",
"proprietary/build/",
"configs/",
"customFiles/",
"docs/",
@ -66,6 +68,7 @@
".gitattributes",
".gitignore",
"common/.gitignore",
"proprietary/.gitignore",
".pre-commit-config.yaml",
],
// Enables signature help in Java.

View File

@ -55,7 +55,7 @@ Stirling-PDF uses Lombok to reduce boilerplate code. Some IDEs, like Eclipse, do
Visit the [Lombok website](https://projectlombok.org/setup/) for installation instructions specific to your IDE.
5. Add environment variable
For local testing, you should generally be testing the full 'Security' version of Stirling-PDF. To do this, you must add the environment flag DOCKER_ENABLE_SECURITY=true to your system and/or IDE build/run step.
For local testing, you should generally be testing the full 'Security' version of Stirling PDF. To do this, you must add the environment flag DISABLE_ADDITIONAL_FEATURES=false to your system and/or IDE build/run step.
## 4. Project Structure
@ -114,9 +114,9 @@ Stirling-PDF offers several Docker versions:
Stirling-PDF provides several example Docker Compose files in the `exampleYmlFiles` directory, such as:
- `docker-compose-latest.yml`: Latest version without security features
- `docker-compose-latest-security.yml`: Latest version with security features enabled
- `docker-compose-latest-fat-security.yml`: Fat version with security features enabled
- `docker-compose-latest.yml`: Latest version without login and security features
- `docker-compose-latest-security.yml`: Latest version with login and security features enabled
- `docker-compose-latest-fat-security.yml`: Fat version with login and security features enabled
These files provide pre-configured setups for different scenarios. For example, here's a snippet from `docker-compose-latest-security.yml`:
@ -141,7 +141,7 @@ services:
- /stirling/latest/config:/configs:rw
- /stirling/latest/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "true"
DISABLE_ADDITIONAL_FEATURES: "false"
SECURITY_ENABLELOGIN: "true"
PUID: 1002
PGID: 1002
@ -170,7 +170,7 @@ Stirling-PDF uses different Docker images for various configurations. The build
1. Set the security environment variable:
```bash
export DOCKER_ENABLE_SECURITY=false # or true for security-enabled builds
export DISABLE_ADDITIONAL_FEATURES=true # or false for to enable login and security features for builds
```
2. Build the project with Gradle:
@ -193,10 +193,10 @@ Stirling-PDF uses different Docker images for various configurations. The build
docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-ultra-lite -f ./Dockerfile.ultra-lite .
```
For the fat version (with security enabled):
For the fat version (with login and security features enabled):
```bash
export DOCKER_ENABLE_SECURITY=true
export DISABLE_ADDITIONAL_FEATURES=false
docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-fat -f ./Dockerfile.fat .
```

View File

@ -23,7 +23,7 @@ LABEL org.opencontainers.image.version="${VERSION_TAG}"
LABEL org.opencontainers.image.keywords="PDF, manipulation, merge, split, convert, OCR, watermark"
# Set Environment Variables
ENV DOCKER_ENABLE_SECURITY=false \
ENV DISABLE_ADDITIONAL_FEATURES=true \
VERSION_TAG=$VERSION_TAG \
JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \
JAVA_CUSTOM_OPTS="" \

View File

@ -5,6 +5,8 @@ COPY build.gradle .
COPY settings.gradle .
COPY gradlew .
COPY gradle gradle/
COPY common/build.gradle common/.
COPY proprietary/build.gradle proprietary/.
RUN ./gradlew build -x spotlessApply -x spotlessCheck -x test -x sonarqube || return 0
# Set the working directory
@ -13,8 +15,8 @@ WORKDIR /app
# Copy the entire project to the working directory
COPY . .
# Build the application with DOCKER_ENABLE_SECURITY=false
RUN DOCKER_ENABLE_SECURITY=true \
# Build the application with DISABLE_ADDITIONAL_FEATURES=false
RUN DISABLE_ADDITIONAL_FEATURES=false \
STIRLING_PDF_DESKTOP_UI=false \
./gradlew clean build -x spotlessApply -x spotlessCheck -x test -x sonarqube
@ -30,7 +32,7 @@ COPY --from=build /app/build/libs/*.jar app.jar
ARG VERSION_TAG
# Set Environment Variables
ENV DOCKER_ENABLE_SECURITY=false \
ENV DISABLE_ADDITIONAL_FEATURES=true \
VERSION_TAG=$VERSION_TAG \
JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \
JAVA_CUSTOM_OPTS="" \

View File

@ -4,7 +4,7 @@ FROM alpine:3.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be02
ARG VERSION_TAG
# Set Environment Variables
ENV DOCKER_ENABLE_SECURITY=false \
ENV DISABLE_ADDITIONAL_FEATURES=true \
HOME=/home/stirlingpdfuser \
VERSION_TAG=$VERSION_TAG \
JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \

View File

@ -1,6 +1,13 @@
MIT License
Copyright (c) 2024 Stirling Tools
Copyright (c) 2025 Stirling PDF Inc.
Portions of this software are licensed as follows:
* All content that resides under the "proprietary/" directory of this repository,
if that directory exists, is licensed under the license defined in "proprietary/LICENSE".
* Content outside of the above mentioned directories or restrictions above is
available under the MIT License as defined below.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -9,7 +9,7 @@ plugins {
id "com.diffplug.spotless" version "7.0.4"
id "com.github.jk1.dependency-license-report" version "2.9"
//id "nebula.lint" version "19.0.3"
id("org.panteleyev.jpackageplugin") version "1.6.1"
id "org.panteleyev.jpackageplugin" version "1.6.1"
id "org.sonarqube" version "6.2.0.5505"
}
@ -51,29 +51,14 @@ licenseReport {
sourceSets {
main {
java {
if (System.getenv("DOCKER_ENABLE_SECURITY") == "false") {
exclude "stirling/software/SPDF/config/interfaces/DatabaseInterface.java"
exclude "stirling/software/SPDF/config/security/**"
exclude "stirling/software/SPDF/controller/api/DatabaseController.java"
exclude "stirling/software/SPDF/controller/api/EmailController.java"
exclude "stirling/software/SPDF/controller/api/H2SQLCondition.java"
exclude "stirling/software/SPDF/controller/api/UserController.java"
exclude "stirling/software/SPDF/controller/web/AccountWebController.java"
exclude "stirling/software/SPDF/controller/web/DatabaseWebController.java"
exclude "stirling/software/SPDF/model/api/Email.java"
exclude "stirling/software/SPDF/model/ApiKeyAuthenticationToken.java"
exclude "stirling/software/SPDF/model/AttemptCounter.java"
exclude "stirling/software/SPDF/model/Authority.java"
exclude "stirling/software/SPDF/model/exception/BackupNotFoundException.java"
exclude "stirling/software/SPDF/model/exception/NoProviderFoundException.java"
exclude "stirling/software/SPDF/model/PersistentLogin.java"
exclude "stirling/software/SPDF/model/SessionEntity.java"
exclude "stirling/software/SPDF/model/User.java"
exclude "stirling/software/SPDF/repository/**"
if (System.getenv('DOCKER_ENABLE_SECURITY') == 'false' || System.getenv('DISABLE_ADDITIONAL_FEATURES') == 'true'
|| (project.hasProperty('DISABLE_ADDITIONAL_FEATURES')
&& System.getProperty('DISABLE_ADDITIONAL_FEATURES') == 'true')) {
exclude 'stirling/software/proprietary/security/**'
}
if (System.getenv("STIRLING_PDF_DESKTOP_UI") == "false") {
exclude "stirling/software/SPDF/UI/impl/**"
if (System.getenv('STIRLING_PDF_DESKTOP_UI') == 'false') {
exclude 'stirling/software/SPDF/UI/impl/**'
}
}
@ -81,15 +66,14 @@ sourceSets {
test {
java {
if (System.getenv("DOCKER_ENABLE_SECURITY") == "false") {
exclude "stirling/software/SPDF/config/security/**"
exclude "stirling/software/SPDF/model/ApiKeyAuthenticationTokenTest.java"
exclude "stirling/software/SPDF/controller/api/EmailControllerTest.java"
exclude "stirling/software/SPDF/repository/**"
if (System.getenv('DOCKER_ENABLE_SECURITY') == 'false' || System.getenv('DISABLE_ADDITIONAL_FEATURES') == 'true'
|| (project.hasProperty('DISABLE_ADDITIONAL_FEATURES')
&& System.getProperty('DISABLE_ADDITIONAL_FEATURES') == 'true')) {
exclude 'stirling/software/proprietary/security/**'
}
if (System.getenv("STIRLING_PDF_DESKTOP_UI") == "false") {
exclude "stirling/software/SPDF/UI/impl/**"
if (System.getenv('STIRLING_PDF_DESKTOP_UI') == 'false') {
exclude 'stirling/software/SPDF/UI/impl/**'
}
}
}
@ -126,6 +110,7 @@ jpackage {
javaOptions = [
"-DBROWSER_OPEN=true",
"-DSTIRLING_PDF_DESKTOP_UI=true",
"-DDISABLE_ADDITIONAL_FEATURES=false",
"-Djava.awt.headless=false",
"-Dapple.awt.UIElement=true",
"--add-opens=java.base/java.lang=ALL-UNNAMED",
@ -262,6 +247,7 @@ tasks.register('jpackageMacX64') {
// Java options
'--java-options', '-DBROWSER_OPEN=true',
'--java-options', '-DSTIRLING_PDF_DESKTOP_UI=true',
'--java-options', '-DDISABLE_ADDITIONAL_FEATURES=false',
'--java-options', '-Djava.awt.headless=false',
'--java-options', '-Dapple.awt.UIElement=true',
'--java-options', '--add-opens=java.base/java.lang=ALL-UNNAMED',
@ -290,8 +276,6 @@ tasks.register('jpackageMacX64') {
}
}
//jpackage.finalizedBy(jpackageMacX64)
tasks.register('downloadTempJre') {
group = 'distribution'
description = 'Downloads and extracts a temporary JRE'
@ -303,18 +287,18 @@ tasks.register('downloadTempJre') {
def jreArchive = new File(tmpDir, 'jre.tar.gz')
def jreDir = new File(tmpDir, 'jre')
println "🔽 Downloading JRE to $jreArchive..."
println "Downloading JRE to $jreArchive..."
jreArchive.withOutputStream { out ->
new URI(jreUrl).toURL().withInputStream { from -> out << from }
}
println "📦 Extracting JRE to $jreDir..."
println "Extracting JRE to $jreDir..."
jreDir.mkdirs()
providers.exec {
commandLine 'tar', '-xzf', jreArchive.absolutePath, '-C', jreDir.absolutePath, '--strip-components=1'
}.result.get()
println "JRE ready at: $jreDir"
println "JRE ready at: $jreDir"
ext.tempJrePath = jreDir.absolutePath
project.ext.tempJrePath = jreDir.absolutePath
} catch (Exception e) {
@ -376,6 +360,7 @@ spotless {
java {
target sourceSets.main.allJava
target project(':common').sourceSets.main.allJava
target project(':proprietary').sourceSets.main.allJava
googleJavaFormat("1.27.0").aosp().reorderImports(false)
@ -441,43 +426,18 @@ dependencies {
implementation("io.github.pixee:java-security-toolkit:1.2.1")
// Exclude Tomcat and include Jetty
implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
// implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
implementation "org.springframework.boot:spring-boot-starter-jetty:$springBootVersion"
implementation "org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVersion"
// implementation "org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVersion"
implementation 'com.posthog.java:posthog:1.2.0'
implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1'
if (System.getenv("DOCKER_ENABLE_SECURITY") != "false") {
implementation 'io.micrometer:micrometer-registry-prometheus'
implementation "org.springframework.boot:spring-boot-starter-security:$springBootVersion"
implementation "org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.3.RELEASE"
implementation "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
implementation "org.springframework.boot:spring-boot-starter-oauth2-client:$springBootVersion"
implementation "org.springframework.boot:spring-boot-starter-mail:$springBootVersion"
implementation "org.springframework.session:spring-session-core:3.5.0"
implementation "org.springframework:spring-jdbc:6.2.7"
implementation 'com.unboundid.product.scim2:scim2-sdk-client:2.3.5'
// Don't upgrade h2database
runtimeOnly "com.h2database:h2:2.3.232"
runtimeOnly "org.postgresql:postgresql:42.7.6"
constraints {
implementation "org.opensaml:opensaml-core:$openSamlVersion"
implementation "org.opensaml:opensaml-saml-api:$openSamlVersion"
implementation "org.opensaml:opensaml-saml-impl:$openSamlVersion"
}
implementation "org.springframework.security:spring-security-saml2-service-provider:$springSecuritySamlVersion"
// implementation 'org.springframework.security:spring-security-core:$springSecuritySamlVersion'
implementation 'com.coveo:saml-client:5.0.0'
}
implementation 'org.snakeyaml:snakeyaml-engine:2.9'
testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
if (System.getenv("DOCKER_ENABLE_SECURITY") != "false" || System.getenv('DISABLE_ADDITIONAL_FEATURES') != 'true'
|| (project.hasProperty('DISABLE_ADDITIONAL_FEATURES')
&& System.getProperty('DISABLE_ADDITIONAL_FEATURES') != 'true')) {
implementation project(':proprietary')
}
// Batik
implementation "org.apache.xmlgraphics:batik-all:1.19"
@ -485,10 +445,12 @@ dependencies {
// TwelveMonkeys
runtimeOnly "com.twelvemonkeys.imageio:imageio-batik:$imageioVersion"
runtimeOnly "com.twelvemonkeys.imageio:imageio-bmp:$imageioVersion"
runtimeOnly "com.twelvemonkeys.imageio:imageio-jpeg:$imageioVersion"
runtimeOnly "com.twelvemonkeys.imageio:imageio-tiff:$imageioVersion"
runtimeOnly "com.twelvemonkeys.imageio:imageio-webp:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-hdr:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-icns:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-iff:$imageioVersion"
runtimeOnly "com.twelvemonkeys.imageio:imageio-jpeg:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-pcx:$imageioVersion@
// runtimeOnly "com.twelvemonkeys.imageio:imageio-pict:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-pnm:$imageioVersion"
@ -496,24 +458,18 @@ dependencies {
// runtimeOnly "com.twelvemonkeys.imageio:imageio-sgi:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-tga:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-thumbsdb:$imageioVersion"
runtimeOnly "com.twelvemonkeys.imageio:imageio-tiff:$imageioVersion"
runtimeOnly "com.twelvemonkeys.imageio:imageio-webp:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-xwd:$imageioVersion"
// Image metadata extractor
implementation "com.drewnoakes:metadata-extractor:2.19.0"
implementation "commons-io:commons-io:2.19.0"
implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8"
//general PDF
// implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8"
// General PDF
// https://mvnrepository.com/artifact/com.opencsv/opencsv
implementation ("com.opencsv:opencsv:5.11")
implementation ("org.apache.pdfbox:pdfbox:$pdfboxVersion")
// implementation ("org.apache.pdfbox:pdfbox:$pdfboxVersion")
implementation "org.apache.pdfbox:preflight:$pdfboxVersion"
implementation ("org.apache.pdfbox:xmpbox:$pdfboxVersion")
// https://mvnrepository.com/artifact/technology.tabula/tabula
@ -537,7 +493,6 @@ dependencies {
// https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17
implementation "com.bucket4j:bucket4j_jdk17-core:8.14.0"
implementation "com.fathzer:javaluator:3.0.6"
implementation 'com.vladsch.flexmark:flexmark-html2md-converter:0.64.8'
developmentOnly("org.springframework.boot:spring-boot-devtools:$springBootVersion")
@ -547,6 +502,7 @@ dependencies {
// Mockito (core)
testImplementation 'org.mockito:mockito-core:5.18.0'
testRuntimeOnly 'org.mockito:mockito-inline:5.2.0'
testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
}
tasks.withType(JavaCompile).configureEach {

View File

@ -30,19 +30,19 @@ dependencyManagement {
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1'
implementation 'com.fathzer:javaluator:3.0.6'
implementation 'com.posthog.java:posthog:1.2.0'
implementation 'io.github.pixee:java-security-toolkit:1.2.1'
implementation 'org.apache.commons:commons-lang3:3.17.0'
implementation 'com.drewnoakes:metadata-extractor:2.19.0' // Image metadata extractor
implementation 'com.vladsch.flexmark:flexmark-html2md-converter:0.64.8'
implementation "org.apache.pdfbox:pdfbox:$pdfboxVersion"
implementation 'jakarta.servlet:jakarta.servlet-api:6.1.0'
implementation 'org.snakeyaml:snakeyaml-engine:2.9'
implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8"
api 'org.springframework.boot:spring-boot-starter-web'
api 'org.springframework.boot:spring-boot-starter-thymeleaf'
api 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1'
api 'com.fathzer:javaluator:3.0.6'
api 'com.posthog.java:posthog:1.2.0'
api 'io.github.pixee:java-security-toolkit:1.2.1'
api 'org.apache.commons:commons-lang3:3.17.0'
api 'com.drewnoakes:metadata-extractor:2.19.0' // Image metadata extractor
api 'com.vladsch.flexmark:flexmark-html2md-converter:0.64.8'
api "org.apache.pdfbox:pdfbox:$pdfboxVersion"
api 'jakarta.servlet:jakarta.servlet-api:6.1.0'
api 'org.snakeyaml:snakeyaml-engine:2.9'
api "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8"
compileOnly "org.projectlombok:lombok:$lombokVersion"
annotationProcessor "org.projectlombok:lombok:$lombokVersion"

View File

@ -10,6 +10,7 @@ import java.util.Properties;
import java.util.function.Predicate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
@ -146,8 +147,22 @@ public class AppConfig {
}
}
@ConditionalOnMissingClass("stirling.software.SPDF.config.security.SecurityConfiguration")
@Bean(name = "activeSecurity")
public boolean activeSecurity() {
String additionalFeaturesOff = env.getProperty("DISABLE_ADDITIONAL_FEATURES");
if (additionalFeaturesOff != null) {
// DISABLE_ADDITIONAL_FEATURES=true means security OFF, so return false
// DISABLE_ADDITIONAL_FEATURES=false means security ON, so return true
return !Boolean.parseBoolean(additionalFeaturesOff);
}
return env.getProperty("DOCKER_ENABLE_SECURITY", Boolean.class, true);
}
@Bean(name = "missingActiveSecurity")
@ConditionalOnMissingClass(
"stirling.software.proprietary.security.configuration.SecurityConfiguration")
public boolean missingActiveSecurity() {
return false;
}

View File

@ -20,7 +20,7 @@ services:
- ./stirling/latest/logs:/logs:rw
- ../testing/allEndpointsRemovedSettings.yml:/configs/settings.yml:rw
environment:
DOCKER_ENABLE_SECURITY: "true"
DISABLE_ADDITIONAL_FEATURES: "false"
SECURITY_ENABLELOGIN: "false"
PUID: 1002
PGID: 1002

View File

@ -20,7 +20,7 @@ services:
- ./stirling/latest/config:/configs:rw
- ./stirling/latest/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "true"
DISABLE_ADDITIONAL_FEATURES: "false"
SECURITY_ENABLELOGIN: "false"
PUID: 1002
PGID: 1002

View File

@ -18,7 +18,7 @@ services:
- ./stirling/latest/config:/configs:rw
- ./stirling/latest/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "true"
DISABLE_ADDITIONAL_FEATURES: "false"
SECURITY_ENABLELOGIN: "false"
PUID: 1002
PGID: 1002

View File

@ -18,7 +18,7 @@ services:
- /stirling/latest/config:/configs:rw
- /stirling/latest/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "true"
DISABLE_ADDITIONAL_FEATURES: "false"
SECURITY_ENABLELOGIN: "true"
SECURITY_OAUTH2_ENABLED: "true"
SECURITY_OAUTH2_AUTOCREATEUSER: "true" # This is set to true to allow auto-creation of non-existing users in Stirling-PDF

View File

@ -18,7 +18,7 @@ services:
- ./stirling/latest/config:/configs:rw
- ./stirling/latest/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "true"
DISABLE_ADDITIONAL_FEATURES: "false"
SECURITY_ENABLELOGIN: "true"
PUID: 1002
PGID: 1002

View File

@ -18,7 +18,7 @@ services:
- /stirling/latest/config:/configs:rw
- /stirling/latest/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "true"
DISABLE_ADDITIONAL_FEATURES: "false"
SECURITY_ENABLELOGIN: "true"
SYSTEM_DEFAULTLOCALE: en-US
UI_APPNAME: Stirling-PDF-Lite

View File

@ -17,7 +17,7 @@ services:
- /stirling/latest/config:/configs:rw
- /stirling/latest/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "false"
DISABLE_ADDITIONAL_FEATURES: "true"
SECURITY_ENABLELOGIN: "false"
SYSTEM_DEFAULTLOCALE: en-US
UI_APPNAME: Stirling-PDF-Ultra-lite

View File

@ -18,7 +18,7 @@ services:
- /stirling/latest/config:/configs:rw
- /stirling/latest/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "false"
DISABLE_ADDITIONAL_FEATURES: "true"
SECURITY_ENABLELOGIN: "false"
LANGS: "en_GB,en_US,ar_AR,de_DE,fr_FR,es_ES,zh_CN,zh_TW,ca_CA,it_IT,sv_SE,pl_PL,ro_RO,ko_KR,pt_BR,ru_RU,el_GR,hi_IN,hu_HU,tr_TR,id_ID"
SYSTEM_DEFAULTLOCALE: en-US

View File

@ -18,7 +18,7 @@ services:
- /stirling/latest/config:/configs:rw
- /stirling/latest/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "true"
DISABLE_ADDITIONAL_FEATURES: "false"
SECURITY_ENABLELOGIN: "true"
PUID: 1002
PGID: 1002

196
proprietary/.gitignore vendored Normal file
View File

@ -0,0 +1,196 @@
### Eclipse ###
.metadata
bin/
tmp/
*.tmp
*.bak
*.exe
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders
.classpath
.project
version.properties
#### Stirling-PDF Files ###
pipeline/watchedFolders/
pipeline/finishedFolders/
customFiles/
configs/
watchedFolders/
clientWebUI/
!cucumber/
!cucumber/exampleFiles/
!cucumber/exampleFiles/example_html.zip
exampleYmlFiles/stirling/
/testing/file_snapshots
SwaggerDoc.json
# Gradle
.gradle
.lock
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# PyDev specific (Python IDE for Eclipse)
*.pydevproject
# CDT-specific (C/C++ Development Tooling)
.cproject
# CDT- autotools
.autotools
# Java annotation processor (APT)
.factorypath
# PDT-specific (PHP Development Tools)
.buildpath
# sbteclipse plugin
.target
# Tern plugin
.tern-project
# TeXlipse plugin
.texlipse
# STS (Spring Tool Suite)
.springBeans
# Code Recommenders
.recommenders/
# Annotation Processing
.apt_generated/
.apt_generated_test/
# Scala IDE specific (Scala & Java development for Eclipse)
.cache-main
.scala_dependencies
.worksheet
# Uncomment this line if you wish to ignore the project description file.
# Typically, this file would be tracked if it contains build/dependency configurations:
#.project
### Eclipse Patch ###
# Spring Boot Tooling
.sts4-cache/
### Git ###
# Created by git for backups. To disable backups in Git:
# $ git config --global mergetool.keepBackup false
*.orig
# Created by git when using merge tools for conflicts
*.BACKUP.*
*.BASE.*
*.LOCAL.*
*.REMOTE.*
*_BACKUP_*.txt
*_BASE_*.txt
*_LOCAL_*.txt
*_REMOTE_*.txt
### Java ###
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
*.db
/build
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*.pyo
# Virtual environments
.env*
.venv*
env*/
venv*/
ENV/
env.bak/
venv.bak/
# VS Code
/.vscode/**/*
!/.vscode/settings.json
!/.vscode/extensions.json
# IntelliJ IDEA
.idea/
*.iml
out/
# Ignore Mac DS_Store files
.DS_Store
**/.DS_Store
# cucumber
/cucumber/reports/**
# Certs and Security Files
*.p12
*.pk8
*.pem
*.crt
*.cer
*.cert
*.der
*.key
*.csr
*.kdbx
*.jks
*.asc
# SSH Keys
*.pub
*.priv
id_rsa
id_rsa.pub
id_ecdsa
id_ecdsa.pub
id_ed25519
id_ed25519.pub
.ssh/
*ssh
# cache
.cache
.ruff_cache
.mypy_cache
.pytest_cache
.ipynb_checkpoints
**/jcef-bundle/
# node_modules
node_modules/
*.mjs

51
proprietary/LICENSE Normal file
View File

@ -0,0 +1,51 @@
Stirling PDF User License
Copyright (c) 2025 Stirling PDF Inc.
License Scope & Usage Rights
Production use of the Stirling PDF Software is only permitted with a valid Stirling PDF User License.
For purposes of this license, “the Software” refers to the Stirling PDF application and any associated documentation files
provided by Stirling PDF Inc. You or your organization may not use the Software in production, at scale, or for business-critical
processes unless you have agreed to, and remain in compliance with, the Stirling PDF Subscription Terms of Service
(https://www.stirlingpdf.com/terms) or another valid agreement with Stirling PDF, and hold an active User License subscription
covering the appropriate number of licensed users.
Trial and Minimal Use
You may use the Software without a paid subscription for the sole purposes of internal trial, evaluation, or minimal use, provided that:
* Use is limited to the capabilities and restrictions defined by the Software itself;
* You do not copy, distribute, sublicense, reverse-engineer, or use the Software in client-facing or commercial contexts.
Continued use beyond this scope requires a valid Stirling PDF User License.
Modifications and Derivative Works
You may modify the Software only for development or internal testing purposes. Any such modifications or derivative works:
* May not be deployed in production environments without a valid User License;
* May not be distributed or sublicensed;
* Remain the intellectual property of Stirling PDF and/or its licensors;
* May only be used, copied, or exploited in accordance with the terms of a valid Stirling PDF User License subscription.
Prohibited Actions
Unless explicitly permitted by a paid license or separate agreement, you may not:
* Use the Software in production environments;
* Copy, merge, distribute, sublicense, or sell the Software;
* Remove or alter any licensing or copyright notices;
* Circumvent access restrictions or licensing requirements.
Third-Party Components
The Stirling PDF Software may include components subject to separate open source licenses. Such components remain governed by
their original license terms as provided by their respective owners.
Disclaimer
THE SOFTWARE IS PROVIDED “AS IS,” WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

67
proprietary/build.gradle Normal file
View File

@ -0,0 +1,67 @@
plugins {
id 'java-library'
id 'io.spring.dependency-management' version '1.1.7'
}
repositories {
mavenCentral()
maven { url = "https://build.shibboleth.net/maven/releases" }
}
java {
sourceCompatibility = JavaVersion.VERSION_17
}
configurations.all {
exclude group: 'commons-logging', module: 'commons-logging'
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
}
dependencyManagement {
imports {
mavenBom 'org.springframework.boot:spring-boot-dependencies:3.5.0'
}
}
dependencies {
implementation project(':common')
api 'org.springframework:spring-jdbc'
api 'org.springframework:spring-webmvc'
api 'org.springframework.session:spring-session-core'
api "org.springframework.security:spring-security-core:$springSecuritySamlVersion"
api "org.springframework.security:spring-security-saml2-service-provider:$springSecuritySamlVersion"
api 'org.springframework.boot:spring-boot-starter-jetty'
api 'org.springframework.boot:spring-boot-starter-security'
api 'org.springframework.boot:spring-boot-starter-data-jpa'
api 'org.springframework.boot:spring-boot-starter-oauth2-client'
api 'org.springframework.boot:spring-boot-starter-mail'
api 'io.swagger.core.v3:swagger-core-jakarta:2.2.30'
implementation 'com.bucket4j:bucket4j_jdk17-core:8.14.0'
// https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17
implementation 'org.bouncycastle:bcprov-jdk18on:1.80'
implementation 'io.github.pixee:java-security-toolkit:1.2.1'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.3.RELEASE'
api 'io.micrometer:micrometer-registry-prometheus'
implementation 'com.unboundid.product.scim2:scim2-sdk-client:2.3.5'
runtimeOnly 'com.h2database:h2:2.3.232' // Don't upgrade h2database
runtimeOnly 'org.postgresql:postgresql:42.7.5'
constraints {
implementation "org.opensaml:opensaml-core:$openSamlVersion"
implementation "org.opensaml:opensaml-saml-api:$openSamlVersion"
implementation "org.opensaml:opensaml-saml-impl:$openSamlVersion"
}
implementation 'com.coveo:saml-client:5.0.0'
compileOnly "org.projectlombok:lombok:$lombokVersion"
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
testImplementation platform('org.junit:junit-bom:5.10.0')
testImplementation 'org.junit.jupiter:junit-jupiter'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.mockito:mockito-inline:5.2.0'
}
tasks.register('prepareKotlinBuildScriptModel') {}

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security;
import java.io.IOException;
import java.util.Optional;
@ -17,7 +17,9 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.User;
import stirling.software.proprietary.security.model.User;
import stirling.software.proprietary.security.service.LoginAttemptService;
import stirling.software.proprietary.security.service.UserService;
@Slf4j
public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security;
import java.io.IOException;
@ -14,6 +14,8 @@ import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import stirling.software.common.util.RequestUriUtils;
import stirling.software.proprietary.security.service.LoginAttemptService;
import stirling.software.proprietary.security.service.UserService;
@Slf4j
public class CustomAuthenticationSuccessHandler

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security;
import java.io.IOException;
import java.security.cert.X509Certificate;
@ -22,14 +22,14 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.SPDFApplication;
import stirling.software.SPDF.config.security.saml2.CertificateUtils;
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
import stirling.software.common.configuration.AppConfig;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.common.model.ApplicationProperties.Security.SAML2;
import stirling.software.common.model.oauth2.KeycloakProvider;
import stirling.software.common.util.UrlUtils;
import stirling.software.proprietary.security.saml2.CertificateUtils;
import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal;
@Slf4j
@RequiredArgsConstructor
@ -38,6 +38,7 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
public static final String LOGOUT_PATH = "/login?logout=true";
private final ApplicationProperties applicationProperties;
private final AppConfig appConfig;
@Override
public void onLogoutSuccess(
@ -102,7 +103,7 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
// Set service provider keys for the SamlClient
samlClient.setSPKeys(certificate, privateKey);
// Redirect to identity provider for logout
// Redirect to identity provider for logout. todo: add relay state
samlClient.redirectToIdentityProvider(response, null, nameIdValue);
} catch (Exception e) {
log.error(
@ -172,11 +173,10 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
}
}
private static SamlClient getSamlClient(
private SamlClient getSamlClient(
String registrationId, SAML2 samlConf, List<X509Certificate> certificates)
throws SamlException {
String serverUrl =
SPDFApplication.getStaticBaseUrl() + ":" + SPDFApplication.getStaticPort();
String serverUrl = appConfig.getBaseUrl() + ":" + appConfig.getServerPort();
String relyingPartyIdentifier =
serverUrl + "/saml2/service-provider-metadata/" + registrationId;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security;
import java.sql.SQLException;
import java.util.UUID;
@ -10,10 +10,11 @@ import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.interfaces.DatabaseInterface;
import stirling.software.SPDF.model.Role;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.enumeration.Role;
import stirling.software.common.model.exception.UnsupportedProviderException;
import stirling.software.proprietary.security.service.DatabaseServiceInterface;
import stirling.software.proprietary.security.service.UserService;
@Slf4j
@Component
@ -24,7 +25,7 @@ public class InitialSecuritySetup {
private final ApplicationProperties applicationProperties;
private final DatabaseInterface databaseService;
private final DatabaseServiceInterface databaseService;
@PostConstruct
public void init() {

View File

@ -1,10 +1,12 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import lombok.RequiredArgsConstructor;
import stirling.software.proprietary.security.filter.IPRateLimitingFilter;
@Component
@RequiredArgsConstructor
public class RateLimitResetScheduler {

View File

@ -1,11 +1,15 @@
package stirling.software.SPDF.config.security.database;
package stirling.software.proprietary.security.configuration;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
@ -17,14 +21,14 @@ import stirling.software.common.model.exception.UnsupportedProviderException;
@Slf4j
@Getter
@Configuration
@EnableJpaRepositories(basePackages = "stirling.software.proprietary.security.database.repository")
@EntityScan({"stirling.software.proprietary.security.model"})
public class DatabaseConfig {
public final String DATASOURCE_DEFAULT_URL;
public static final String DATASOURCE_URL_TEMPLATE = "jdbc:%s://%s:%4d/%s";
public static final String DEFAULT_DRIVER = "org.h2.Driver";
public static final String DEFAULT_USERNAME = "sa";
public static final String POSTGRES_DRIVER = "org.postgresql.Driver";
private final ApplicationProperties.Datasource datasource;
private final boolean runningProOrHigher;
@ -54,19 +58,32 @@ public class DatabaseConfig {
public DataSource dataSource() throws UnsupportedProviderException {
DataSourceBuilder<?> dataSourceBuilder = DataSourceBuilder.create();
if (!runningProOrHigher) {
if (!runningProOrHigher || !datasource.isEnableCustomDatabase()) {
return useDefaultDataSource(dataSourceBuilder);
}
if (!datasource.isEnableCustomDatabase()) {
return useDefaultDataSource(dataSourceBuilder);
return useCustomDataSource(dataSourceBuilder);
}
private DataSource useDefaultDataSource(DataSourceBuilder<?> dataSourceBuilder) {
log.info("Using default H2 database");
dataSourceBuilder
.url(DATASOURCE_DEFAULT_URL)
.driverClassName(DatabaseDriver.H2.getDriverClassName())
.username(DEFAULT_USERNAME);
return dataSourceBuilder.build();
}
@ConditionalOnBooleanProperty(name = "premium.enabled")
private DataSource useCustomDataSource(DataSourceBuilder<?> dataSourceBuilder)
throws UnsupportedProviderException {
log.info("Using custom database configuration");
if (!datasource.getCustomDatabaseUrl().isBlank()) {
if (datasource.getCustomDatabaseUrl().contains("postgresql")) {
dataSourceBuilder.driverClassName(POSTGRES_DRIVER);
dataSourceBuilder.driverClassName(DatabaseDriver.POSTGRESQL.getDriverClassName());
}
dataSourceBuilder.url(datasource.getCustomDatabaseUrl());
@ -85,15 +102,6 @@ public class DatabaseConfig {
return dataSourceBuilder.build();
}
private DataSource useDefaultDataSource(DataSourceBuilder<?> dataSourceBuilder) {
log.info("Using default H2 database");
dataSourceBuilder.url(DATASOURCE_DEFAULT_URL);
dataSourceBuilder.username(DEFAULT_USERNAME);
return dataSourceBuilder.build();
}
/**
* Generate the URL the <code>DataSource</code> will use to connect to the database
*
@ -123,11 +131,11 @@ public class DatabaseConfig {
switch (driver) {
case H2 -> {
log.debug("H2 driver selected");
return DEFAULT_DRIVER;
return DatabaseDriver.H2.getDriverClassName();
}
case POSTGRESQL -> {
log.debug("Postgres driver selected");
return POSTGRES_DRIVER;
return DatabaseDriver.POSTGRESQL.getDriverClassName();
}
default -> {
log.warn("{} driver selected", driverName);

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.mail;
package stirling.software.proprietary.security.configuration;
import java.util.Properties;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security.configuration;
import java.util.Optional;
@ -6,7 +6,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
@ -30,23 +29,32 @@ import org.springframework.security.web.servlet.util.matcher.PathPatternRequestM
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2AuthenticationFailureHandler;
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2AuthenticationSuccessHandler;
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2UserService;
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticationFailureHandler;
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticationSuccessHandler;
import stirling.software.SPDF.config.security.saml2.CustomSaml2ResponseAuthenticationConverter;
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
import stirling.software.SPDF.model.User;
import stirling.software.SPDF.repository.JPATokenRepositoryImpl;
import stirling.software.SPDF.repository.PersistentLoginRepository;
import stirling.software.common.configuration.AppConfig;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.proprietary.security.CustomAuthenticationFailureHandler;
import stirling.software.proprietary.security.CustomAuthenticationSuccessHandler;
import stirling.software.proprietary.security.CustomLogoutSuccessHandler;
import stirling.software.proprietary.security.database.repository.JPATokenRepositoryImpl;
import stirling.software.proprietary.security.database.repository.PersistentLoginRepository;
import stirling.software.proprietary.security.filter.FirstLoginFilter;
import stirling.software.proprietary.security.filter.IPRateLimitingFilter;
import stirling.software.proprietary.security.filter.UserAuthenticationFilter;
import stirling.software.proprietary.security.model.User;
import stirling.software.proprietary.security.oauth2.CustomOAuth2AuthenticationFailureHandler;
import stirling.software.proprietary.security.oauth2.CustomOAuth2AuthenticationSuccessHandler;
import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticationFailureHandler;
import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticationSuccessHandler;
import stirling.software.proprietary.security.saml2.CustomSaml2ResponseAuthenticationConverter;
import stirling.software.proprietary.security.service.CustomOAuth2UserService;
import stirling.software.proprietary.security.service.CustomUserDetailsService;
import stirling.software.proprietary.security.service.LoginAttemptService;
import stirling.software.proprietary.security.service.UserService;
import stirling.software.proprietary.security.session.SessionPersistentRegistry;
@Slf4j
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@Slf4j
@DependsOn("runningProOrHigher")
public class SecurityConfiguration {
private final CustomUserDetailsService userDetailsService;
@ -55,6 +63,7 @@ public class SecurityConfiguration {
private final boolean runningProOrHigher;
private final ApplicationProperties applicationProperties;
private final AppConfig appConfig;
private final UserAuthenticationFilter userAuthenticationFilter;
private final LoginAttemptService loginAttemptService;
private final FirstLoginFilter firstLoginFilter;
@ -70,6 +79,7 @@ public class SecurityConfiguration {
@Lazy UserService userService,
@Qualifier("loginEnabled") boolean loginEnabledValue,
@Qualifier("runningProOrHigher") boolean runningProOrHigher,
AppConfig appConfig,
ApplicationProperties applicationProperties,
UserAuthenticationFilter userAuthenticationFilter,
LoginAttemptService loginAttemptService,
@ -84,6 +94,7 @@ public class SecurityConfiguration {
this.userService = userService;
this.loginEnabledValue = loginEnabledValue;
this.runningProOrHigher = runningProOrHigher;
this.appConfig = appConfig;
this.applicationProperties = applicationProperties;
this.userAuthenticationFilter = userAuthenticationFilter;
this.loginAttemptService = loginAttemptService;
@ -161,7 +172,8 @@ public class SecurityConfiguration {
PathPatternRequestMatcher.withDefaults()
.matcher("/logout"))
.logoutSuccessHandler(
new CustomLogoutSuccessHandler(applicationProperties))
new CustomLogoutSuccessHandler(
applicationProperties, appConfig))
.clearAuthentication(true)
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID", "remember-me"));
@ -229,13 +241,12 @@ public class SecurityConfiguration {
http.oauth2Login(
oauth2 ->
oauth2.loginPage("/oauth2")
.
/*
This Custom handler is used to check if the OAUTH2 user trying to log in, already exists in the database.
If user exists, login proceeds as usual. If user does not exist, then it is auto-created but only if 'OAUTH2AutoCreateUser'
is set as true, else login fails with an error message advising the same.
*/
successHandler(
.successHandler(
new CustomOAuth2AuthenticationSuccessHandler(
loginAttemptService,
applicationProperties,
@ -287,15 +298,14 @@ public class SecurityConfiguration {
});
}
} else {
log.debug("SAML 2 login is not enabled. Using default.");
log.debug("Login is not enabled.");
http.authorizeHttpRequests(authz -> authz.anyRequest().permitAll());
}
return http.build();
}
public DaoAuthenticationProvider daoAuthenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService);
DaoAuthenticationProvider provider = new DaoAuthenticationProvider(userDetailsService);
provider.setPasswordEncoder(passwordEncoder());
return provider;
}
@ -311,9 +321,4 @@ public class SecurityConfiguration {
public PersistentTokenRepository persistentTokenRepository() {
return new JPATokenRepositoryImpl(persistentLoginRepository);
}
@Bean
public boolean activeSecurity() {
return true;
}
}

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.controller.api;
package stirling.software.proprietary.security.controller.api;
import java.io.IOException;
import java.io.InputStream;
@ -27,7 +27,8 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.database.DatabaseService;
import stirling.software.proprietary.security.database.H2SQLCondition;
import stirling.software.proprietary.security.service.DatabaseService;
@Slf4j
@Controller

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.controller.api;
package stirling.software.proprietary.security.controller.api;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpStatus;
@ -18,8 +18,8 @@ import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.mail.EmailService;
import stirling.software.SPDF.model.api.Email;
import stirling.software.proprietary.security.model.api.Email;
import stirling.software.proprietary.security.service.EmailService;
/**
* Controller for handling email-related API requests. This controller exposes an endpoint for

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.controller.api;
package stirling.software.proprietary.security.controller.api;
import java.io.IOException;
import java.security.Principal;
@ -29,15 +29,15 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.UserService;
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
import stirling.software.SPDF.model.AuthenticationType;
import stirling.software.SPDF.model.Role;
import stirling.software.SPDF.model.User;
import stirling.software.SPDF.model.api.user.UsernameAndPass;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.enumeration.Role;
import stirling.software.common.model.exception.UnsupportedProviderException;
import stirling.software.proprietary.security.model.AuthenticationType;
import stirling.software.proprietary.security.model.User;
import stirling.software.proprietary.security.model.api.user.UsernameAndPass;
import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal;
import stirling.software.proprietary.security.service.UserService;
import stirling.software.proprietary.security.session.SessionPersistentRegistry;
@Controller
@Tag(name = "User", description = "User APIs")

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.controller.web;
package stirling.software.proprietary.security.controller.web;
import static stirling.software.common.util.ProviderUtils.validateProvider;
@ -29,21 +29,21 @@ import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
import stirling.software.SPDF.model.Authority;
import stirling.software.SPDF.model.Role;
import stirling.software.SPDF.model.SessionEntity;
import stirling.software.SPDF.model.User;
import stirling.software.SPDF.repository.UserRepository;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.ApplicationProperties.Security;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2.Client;
import stirling.software.common.model.ApplicationProperties.Security.SAML2;
import stirling.software.common.model.enumeration.Role;
import stirling.software.common.model.oauth2.GitHubProvider;
import stirling.software.common.model.oauth2.GoogleProvider;
import stirling.software.common.model.oauth2.KeycloakProvider;
import stirling.software.proprietary.security.database.repository.UserRepository;
import stirling.software.proprietary.security.model.Authority;
import stirling.software.proprietary.security.model.SessionEntity;
import stirling.software.proprietary.security.model.User;
import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal;
import stirling.software.proprietary.security.session.SessionPersistentRegistry;
@Controller
@Slf4j

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.controller.web;
package stirling.software.proprietary.security.controller.web;
import java.util.List;
@ -14,8 +14,8 @@ import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.security.database.DatabaseService;
import stirling.software.common.model.FileInfo;
import stirling.software.proprietary.security.service.DatabaseService;
@Controller
@Tag(name = "Database Management", description = "Database management and security APIs")

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.controller.api;
package stirling.software.proprietary.security.database;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
@ -12,8 +12,12 @@ public class H2SQLCondition implements Condition {
Boolean.parseBoolean(
context.getEnvironment()
.getProperty("system.datasource.enableCustomDatabase"));
if (!enableCustomDatabase) {
return false;
}
String dataSourceType = context.getEnvironment().getProperty("system.datasource.type");
return !enableCustomDatabase
|| (enableCustomDatabase && "h2".equalsIgnoreCase(dataSourceType));
return "h2".equalsIgnoreCase(dataSourceType);
}
}

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.database;
package stirling.software.proprietary.security.database;
import java.sql.SQLException;
@ -8,16 +8,15 @@ import org.springframework.stereotype.Component;
import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.interfaces.DatabaseInterface;
import stirling.software.SPDF.controller.api.H2SQLCondition;
import stirling.software.common.model.exception.UnsupportedProviderException;
import stirling.software.proprietary.security.service.DatabaseServiceInterface;
@Component
@Conditional(H2SQLCondition.class)
@RequiredArgsConstructor
public class ScheduledTasks {
private final DatabaseInterface databaseService;
private final DatabaseServiceInterface databaseService;
@Scheduled(cron = "0 0 0 * * ?")
public void performBackup() throws SQLException, UnsupportedProviderException {

View File

@ -1,11 +1,11 @@
package stirling.software.SPDF.repository;
package stirling.software.proprietary.security.database.repository;
import java.util.Set;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import stirling.software.SPDF.model.Authority;
import stirling.software.proprietary.security.model.Authority;
@Repository
public interface AuthorityRepository extends JpaRepository<Authority, Long> {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.repository;
package stirling.software.proprietary.security.database.repository;
import java.util.Date;
@ -6,7 +6,7 @@ import org.springframework.security.web.authentication.rememberme.PersistentReme
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.transaction.annotation.Transactional;
import stirling.software.SPDF.model.PersistentLogin;
import stirling.software.proprietary.security.model.PersistentLogin;
public class JPATokenRepositoryImpl implements PersistentTokenRepository {

View File

@ -1,9 +1,9 @@
package stirling.software.SPDF.repository;
package stirling.software.proprietary.security.database.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import stirling.software.SPDF.model.PersistentLogin;
import stirling.software.proprietary.security.model.PersistentLogin;
@Repository
public interface PersistentLoginRepository extends JpaRepository<PersistentLogin, String> {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.session;
package stirling.software.proprietary.security.database.repository;
import java.util.Date;
import java.util.List;
@ -11,7 +11,7 @@ import org.springframework.stereotype.Repository;
import jakarta.transaction.Transactional;
import stirling.software.SPDF.model.SessionEntity;
import stirling.software.proprietary.security.model.SessionEntity;
@Repository
public interface SessionRepository extends JpaRepository<SessionEntity, String> {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.repository;
package stirling.software.proprietary.security.database.repository;
import java.util.List;
import java.util.Optional;
@ -8,7 +8,7 @@ import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import stirling.software.SPDF.model.User;
import stirling.software.proprietary.security.model.User;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config;
package stirling.software.proprietary.security.filter;
import java.io.IOException;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security.filter;
import java.io.IOException;
import java.text.SimpleDateFormat;
@ -19,8 +19,9 @@ import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.User;
import stirling.software.common.util.RequestUriUtils;
import stirling.software.proprietary.security.model.User;
import stirling.software.proprietary.security.service.UserService;
@Slf4j
@Component

View File

@ -1,10 +1,14 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security.filter;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import jakarta.servlet.*;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security.filter;
import java.io.IOException;
import java.util.List;
@ -24,13 +24,14 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
import stirling.software.SPDF.model.ApiKeyAuthenticationToken;
import stirling.software.SPDF.model.User;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.common.model.ApplicationProperties.Security.SAML2;
import stirling.software.proprietary.security.model.ApiKeyAuthenticationToken;
import stirling.software.proprietary.security.model.User;
import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal;
import stirling.software.proprietary.security.service.UserService;
import stirling.software.proprietary.security.session.SessionPersistentRegistry;
@Slf4j
@Component

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security.filter;
import java.io.IOException;
import java.time.Duration;
@ -24,7 +24,7 @@ import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import stirling.software.SPDF.model.Role;
import stirling.software.common.model.enumeration.Role;
@Component
public class UserBasedRateLimitingFilter extends OncePerRequestFilter {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model;
package stirling.software.proprietary.security.model;
import java.util.Collection;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model;
package stirling.software.proprietary.security.model;
public class AttemptCounter {
private int attemptCount;

View File

@ -0,0 +1,6 @@
package stirling.software.proprietary.security.model;
public enum AuthenticationType {
WEB,
SSO
}

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model;
package stirling.software.proprietary.security.model;
import java.io.Serializable;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model;
package stirling.software.proprietary.security.model;
import java.util.Date;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model;
package stirling.software.proprietary.security.model;
import java.io.Serializable;
import java.util.Date;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model;
package stirling.software.proprietary.security.model;
import java.io.Serializable;
import java.util.HashMap;
@ -15,6 +15,8 @@ import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import stirling.software.common.model.enumeration.Role;
@Entity
@Table(name = "users")
@NoArgsConstructor

View File

@ -0,0 +1,40 @@
package stirling.software.proprietary.security.model.api;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import stirling.software.common.model.api.GeneralFile;
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@ConditionalOnProperty(value = "mail.enabled", havingValue = "true", matchIfMissing = false)
public class Email extends GeneralFile {
@Schema(
description = "The recipient's email address",
requiredMode = Schema.RequiredMode.REQUIRED,
format = "email")
private String to;
@Schema(
description = "The subject of the email",
defaultValue = "Stirling Software PDF Notification",
requiredMode = Schema.RequiredMode.NOT_REQUIRED)
private String subject;
@Schema(
description = "The body of the email",
requiredMode = Schema.RequiredMode.NOT_REQUIRED,
defaultValue =
"This message was automatically generated by Stirling-PDF, an innovative"
+ " solution from Stirling Software. For more information, visit our <a"
+ " href=\"https://stirling-software.com\">website</a>.<br><br>Please do"
+ " not reply directly to this email.")
private String body;
}

View File

@ -0,0 +1,17 @@
package stirling.software.proprietary.security.model.api.user;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
public class UpdateUserDetails extends UpdateUserUsername {
@Schema(
description = "new password for user",
format = "password",
requiredMode = Schema.RequiredMode.REQUIRED)
private String newPassword;
}

View File

@ -0,0 +1,14 @@
package stirling.software.proprietary.security.model.api.user;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
public class UpdateUserUsername extends UsernameAndPass {
@Schema(description = "new username for user")
private String newUsername;
}

View File

@ -0,0 +1,14 @@
package stirling.software.proprietary.security.model.api.user;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode
public class Username {
@Schema(description = "username of user", requiredMode = Schema.RequiredMode.REQUIRED)
private String username;
}

View File

@ -0,0 +1,14 @@
package stirling.software.proprietary.security.model.api.user;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
public class UsernameAndPass extends Username {
@Schema(description = "password of user", format = "password")
private String password;
}

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model.exception;
package stirling.software.proprietary.security.model.exception;
public class BackupNotFoundException extends RuntimeException {
public BackupNotFoundException(String message) {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model.exception;
package stirling.software.proprietary.security.model.exception;
public class NoProviderFoundException extends Exception {
public NoProviderFoundException(String message) {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.oauth2;
package stirling.software.proprietary.security.oauth2;
import java.io.IOException;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.oauth2;
package stirling.software.proprietary.security.oauth2;
import java.io.IOException;
import java.sql.SQLException;
@ -17,13 +17,13 @@ import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.security.LoginAttemptService;
import stirling.software.SPDF.config.security.UserService;
import stirling.software.SPDF.model.AuthenticationType;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.common.model.exception.UnsupportedProviderException;
import stirling.software.common.util.RequestUriUtils;
import stirling.software.proprietary.security.model.AuthenticationType;
import stirling.software.proprietary.security.service.LoginAttemptService;
import stirling.software.proprietary.security.service.UserService;
@RequiredArgsConstructor
public class CustomOAuth2AuthenticationSuccessHandler

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.oauth2;
package stirling.software.proprietary.security.oauth2;
import static org.springframework.security.oauth2.core.AuthorizationGrantType.AUTHORIZATION_CODE;
import static stirling.software.common.util.ProviderUtils.validateProvider;
@ -10,6 +10,7 @@ import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -25,9 +26,6 @@ import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.UserService;
import stirling.software.SPDF.model.User;
import stirling.software.SPDF.model.exception.NoProviderFoundException;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2.Client;
@ -36,10 +34,13 @@ import stirling.software.common.model.oauth2.GitHubProvider;
import stirling.software.common.model.oauth2.GoogleProvider;
import stirling.software.common.model.oauth2.KeycloakProvider;
import stirling.software.common.model.oauth2.Provider;
import stirling.software.proprietary.security.model.User;
import stirling.software.proprietary.security.model.exception.NoProviderFoundException;
import stirling.software.proprietary.security.service.UserService;
@Slf4j
@Configuration
@ConditionalOnProperty(value = "security.oauth2.enabled", havingValue = "true")
@ConditionalOnBooleanProperty("security.oauth2.enabled")
public class OAuth2Configuration {
public static final String REDIRECT_URI_PATH = "{baseUrl}/login/oauth2/code/";
@ -54,7 +55,6 @@ public class OAuth2Configuration {
}
@Bean
@ConditionalOnProperty(value = "security.oauth2.enabled", havingValue = "true")
public ClientRegistrationRepository clientRegistrationRepository()
throws NoProviderFoundException {
List<ClientRegistration> registrations = new ArrayList<>();

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.saml2;
package stirling.software.proprietary.security.saml2;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.saml2;
package stirling.software.proprietary.security.saml2;
import java.io.Serializable;
import java.util.List;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.saml2;
package stirling.software.proprietary.security.saml2;
import java.io.IOException;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.saml2;
package stirling.software.proprietary.security.saml2;
import java.io.IOException;
import java.sql.SQLException;
@ -16,13 +16,13 @@ import jakarta.servlet.http.HttpSession;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.LoginAttemptService;
import stirling.software.SPDF.config.security.UserService;
import stirling.software.SPDF.model.AuthenticationType;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.ApplicationProperties.Security.SAML2;
import stirling.software.common.model.exception.UnsupportedProviderException;
import stirling.software.common.util.RequestUriUtils;
import stirling.software.proprietary.security.model.AuthenticationType;
import stirling.software.proprietary.security.service.LoginAttemptService;
import stirling.software.proprietary.security.service.UserService;
@AllArgsConstructor
@Slf4j

View File

@ -1,6 +1,10 @@
package stirling.software.SPDF.config.security.saml2;
package stirling.software.proprietary.security.saml2;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.opensaml.core.xml.XMLObject;
import org.opensaml.saml.saml2.core.Assertion;
@ -16,8 +20,8 @@ import org.springframework.security.saml2.provider.service.authentication.Saml2A
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.UserService;
import stirling.software.SPDF.model.User;
import stirling.software.proprietary.security.model.User;
import stirling.software.proprietary.security.service.UserService;
@Slf4j
@ConditionalOnProperty(name = "security.saml2.enabled", havingValue = "true")

View File

@ -1,10 +1,11 @@
package stirling.software.SPDF.config.security.saml2;
package stirling.software.proprietary.security.saml2;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.UUID;
import org.opensaml.saml.saml2.core.AuthnRequest;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -29,8 +30,8 @@ import stirling.software.common.model.ApplicationProperties.Security.SAML2;
@Configuration
@Slf4j
@ConditionalOnProperty(value = "security.saml2.enabled", havingValue = "true")
@RequiredArgsConstructor
@ConditionalOnBooleanProperty("security.saml2.enabled")
public class SAML2Configuration {
private final ApplicationProperties applicationProperties;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security.service;
import java.util.Optional;
@ -8,10 +8,10 @@ import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.interfaces.ShowAdminInterface;
import stirling.software.SPDF.model.User;
import stirling.software.SPDF.repository.UserRepository;
import stirling.software.common.configuration.interfaces.ShowAdminInterface;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.proprietary.security.database.repository.UserRepository;
import stirling.software.proprietary.security.model.User;
@Service
@RequiredArgsConstructor

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.oauth2;
package stirling.software.proprietary.security.service;
import java.util.Optional;
@ -13,12 +13,10 @@ import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.LoginAttemptService;
import stirling.software.SPDF.config.security.UserService;
import stirling.software.SPDF.model.User;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.common.model.enumeration.UsernameAttribute;
import stirling.software.proprietary.security.model.User;
@Slf4j
public class CustomOAuth2UserService implements OAuth2UserService<OidcUserRequest, OidcUser> {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security.service;
import java.util.Collection;
import java.util.Set;
@ -13,9 +13,9 @@ import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.model.Authority;
import stirling.software.SPDF.model.User;
import stirling.software.SPDF.repository.UserRepository;
import stirling.software.proprietary.security.database.repository.UserRepository;
import stirling.software.proprietary.security.model.Authority;
import stirling.software.proprietary.security.model.User;
@Service
@RequiredArgsConstructor

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.database;
package stirling.software.proprietary.security.service;
import java.io.IOException;
import java.nio.file.DirectoryStream;
@ -27,15 +27,14 @@ import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.interfaces.DatabaseInterface;
import stirling.software.SPDF.model.exception.BackupNotFoundException;
import stirling.software.common.configuration.InstallationPathConfig;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.FileInfo;
import stirling.software.proprietary.security.model.exception.BackupNotFoundException;
@Slf4j
@Service
public class DatabaseService implements DatabaseInterface {
public class DatabaseService implements DatabaseServiceInterface {
public static final String BACKUP_PREFIX = "backup_";
public static final String SQL_SUFFIX = ".sql";

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.interfaces;
package stirling.software.proprietary.security.service;
import java.sql.SQLException;
import java.util.List;
@ -6,7 +6,7 @@ import java.util.List;
import stirling.software.common.model.FileInfo;
import stirling.software.common.model.exception.UnsupportedProviderException;
public interface DatabaseInterface {
public interface DatabaseServiceInterface {
void exportDatabase() throws SQLException, UnsupportedProviderException;
void importDatabase();

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.mail;
package stirling.software.proprietary.security.service;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.mail.javamail.JavaMailSender;
@ -12,8 +12,8 @@ import jakarta.mail.internet.MimeMessage;
import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.model.api.Email;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.proprietary.security.model.api.Email;
/**
* Service class responsible for sending emails, including those with attachments. It uses

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security.service;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
@ -10,8 +10,8 @@ import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.AttemptCounter;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.proprietary.security.model.AttemptCounter;
@Service
@Slf4j

View File

@ -1,6 +1,5 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security.service;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
@ -28,18 +27,17 @@ import org.springframework.transaction.annotation.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.interfaces.DatabaseInterface;
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
import stirling.software.SPDF.model.AuthenticationType;
import stirling.software.SPDF.model.Authority;
import stirling.software.SPDF.model.Role;
import stirling.software.SPDF.model.User;
import stirling.software.SPDF.repository.AuthorityRepository;
import stirling.software.SPDF.repository.UserRepository;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.enumeration.Role;
import stirling.software.common.model.exception.UnsupportedProviderException;
import stirling.software.common.service.UserServiceInterface;
import stirling.software.proprietary.security.database.repository.AuthorityRepository;
import stirling.software.proprietary.security.database.repository.UserRepository;
import stirling.software.proprietary.security.model.AuthenticationType;
import stirling.software.proprietary.security.model.Authority;
import stirling.software.proprietary.security.model.User;
import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal;
import stirling.software.proprietary.security.session.SessionPersistentRegistry;
@Service
@Slf4j
@ -56,7 +54,7 @@ public class UserService implements UserServiceInterface {
private final SessionPersistentRegistry sessionRegistry;
private final DatabaseInterface databaseService;
private final DatabaseServiceInterface databaseService;
private final ApplicationProperties.Security.OAUTH2 oAuth2;
@ -88,7 +86,7 @@ public class UserService implements UserServiceInterface {
public Authentication getAuthentication(String apiKey) {
Optional<User> user = getUserByApiKey(apiKey);
if (!user.isPresent()) {
if (user.isEmpty()) {
throw new UsernameNotFoundException("API key is not valid");
}
// Convert the user into an Authentication object
@ -305,10 +303,7 @@ public class UserService implements UserServiceInterface {
}
public void changeUsername(User user, String newUsername)
throws IllegalArgumentException,
IOException,
SQLException,
UnsupportedProviderException {
throws IllegalArgumentException, SQLException, UnsupportedProviderException {
if (!isUsernameValid(newUsername)) {
throw new IllegalArgumentException(getInvalidUsernameMessage());
}
@ -418,7 +413,7 @@ public class UserService implements UserServiceInterface {
if (principal instanceof UserDetails detailsUser) {
return detailsUser.getUsername();
} else if (principal instanceof stirling.software.SPDF.model.User domainUser) {
} else if (principal instanceof User domainUser) {
return domainUser.getUsername();
} else if (principal instanceof OAuth2User oAuth2User) {
return oAuth2User.getAttribute(oAuth2.getUseAsUsername());

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.session;
package stirling.software.proprietary.security.session;
import org.springframework.stereotype.Component;
@ -11,7 +11,7 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
public class CustomHttpSessionListener implements HttpSessionListener {
private SessionPersistentRegistry sessionPersistentRegistry;
private final SessionPersistentRegistry sessionPersistentRegistry;
public CustomHttpSessionListener(SessionPersistentRegistry sessionPersistentRegistry) {
super();

View File

@ -1,7 +1,12 @@
package stirling.software.SPDF.config.security.session;
package stirling.software.proprietary.security.session;
import java.time.Duration;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.session.SessionInformation;
@ -14,8 +19,9 @@ import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
import stirling.software.SPDF.model.SessionEntity;
import stirling.software.proprietary.security.database.repository.SessionRepository;
import stirling.software.proprietary.security.model.SessionEntity;
import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal;
@Component
@RequiredArgsConstructor

View File

@ -1,9 +1,11 @@
package stirling.software.SPDF.config.security.session;
package stirling.software.proprietary.security.session;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.session.SessionRegistryImpl;
import stirling.software.proprietary.security.database.repository.SessionRepository;
@Configuration
public class SessionRegistryConfig {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.session;
package stirling.software.proprietary.security.session;
import java.time.Instant;
import java.time.temporal.ChronoUnit;

View File

@ -1,22 +1,17 @@
package stirling.software.SPDF.config.security;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
package stirling.software.proprietary.security;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import stirling.software.common.model.ApplicationProperties;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class CustomLogoutSuccessHandlerTest {

View File

@ -1,11 +1,6 @@
package stirling.software.SPDF.config.security.database;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.when;
package stirling.software.proprietary.security.configuration;
import javax.sql.DataSource;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ -13,9 +8,10 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.exception.UnsupportedProviderException;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class DatabaseConfigTest {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.controller.api;
package stirling.software.proprietary.security.controller.api;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
@ -23,8 +23,8 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import jakarta.mail.MessagingException;
import stirling.software.SPDF.config.security.mail.EmailService;
import stirling.software.SPDF.model.api.Email;
import stirling.software.proprietary.security.model.api.Email;
import stirling.software.proprietary.security.service.EmailService;
@ExtendWith(MockitoExtension.class)
class EmailControllerTest {

View File

@ -1,9 +1,9 @@
package stirling.software.SPDF.config.security.mail;
package stirling.software.proprietary.security.service;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.Mockito.*;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
@ -15,8 +15,11 @@ import org.springframework.web.multipart.MultipartFile;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import stirling.software.SPDF.model.api.Email;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.proprietary.security.model.api.Email;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
public class EmailServiceTest {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.mail;
package stirling.software.proprietary.security.service;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -14,6 +14,7 @@ import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.proprietary.security.configuration.MailConfig;
class MailConfigTest {

View File

@ -1,6 +1,6 @@
echo "Running Stirling PDF with DOCKER_ENABLE_SECURITY=${DOCKER_ENABLE_SECURITY} and VERSION_TAG=${VERSION_TAG}"
# Check for DOCKER_ENABLE_SECURITY and download the appropriate JAR if required
if [ "$DOCKER_ENABLE_SECURITY" = "true" ] && [ "$VERSION_TAG" != "alpha" ]; then
echo "Running Stirling PDF with DISABLE_ADDITIONAL_FEATURES=${DISABLE_ADDITIONAL_FEATURES} and VERSION_TAG=${VERSION_TAG}"
# Check for $DISABLE_ADDITIONAL_FEATURES and download the appropriate JAR if required
if [ "$DISABLE_ADDITIONAL_FEATURES" = "false" ] && [ "$VERSION_TAG" != "alpha" ]; then
if [ ! -f app-security.jar ]; then
echo "Trying to download from: https://files.stirlingpdf.com/v$VERSION_TAG/Stirling-PDF-with-login.jar"
curl -L -o app-security.jar https://files.stirlingpdf.com/v$VERSION_TAG/Stirling-PDF-with-login.jar

View File

@ -4,4 +4,4 @@ plugins {
}
rootProject.name = 'Stirling-PDF'
include 'common'
include 'common', 'proprietary'

View File

@ -520,7 +520,7 @@ public class KeygenLicenseVerifier {
HttpResponse<String> response =
httpClient.send(request, HttpResponse.BodyHandlers.ofString());
log.info("ValidateLicenseResponse body: {}", response.body());
log.debug("ValidateLicenseResponse body: {}", response.body());
JsonNode jsonResponse = objectMapper.readTree(response.body());
if (response.statusCode() == 200) {
JsonNode metaNode = jsonResponse.path("meta");
@ -529,9 +529,9 @@ public class KeygenLicenseVerifier {
String detail = metaNode.path("detail").asText();
String code = metaNode.path("code").asText();
log.info("License validity: " + isValid);
log.info("Validation detail: " + detail);
log.info("Validation code: " + code);
log.info("License validity: {}", isValid);
log.info("Validation detail: {}", detail);
log.info("Validation code: {}", code);
// Check if the license itself has floating attribute
JsonNode licenseAttrs = jsonResponse.path("data").path("attributes");
@ -595,7 +595,7 @@ public class KeygenLicenseVerifier {
.path("isEnterprise")
.asBoolean(false);
log.info(applicationProperties.toString());
log.debug(applicationProperties.toString());
} else {
log.error("Error validating license. Status code: {}", response.statusCode());

View File

@ -35,7 +35,11 @@ import stirling.software.common.util.UrlUtils;
@Slf4j
@EnableScheduling
@SpringBootApplication(
scanBasePackages = {"stirling.software.common", "stirling.software.SPDF"},
scanBasePackages = {
"stirling.software.common",
"stirling.software.SPDF",
"stirling.software.proprietary.security"
},
exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class

View File

@ -5,7 +5,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import stirling.software.SPDF.config.interfaces.ShowAdminInterface;
import stirling.software.common.configuration.interfaces.ShowAdminInterface;
import stirling.software.common.model.ApplicationProperties;
@Configuration

View File

@ -1,7 +0,0 @@
package stirling.software.SPDF.config.interfaces;
public interface ShowAdminInterface {
default boolean getShowUpdateOnlyAdmins() {
return true;
}
}

View File

@ -23,8 +23,8 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.model.api.GeneralFile;
import stirling.software.common.configuration.RuntimePathConfig;
import stirling.software.common.model.api.GeneralFile;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.ProcessExecutor;
import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult;

Some files were not shown because too many files have changed in this diff Show More