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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -50,8 +50,10 @@
".vscode/", ".vscode/",
"bin/", "bin/",
"common/bin/", "common/bin/",
"proprietary/bin/",
"build/", "build/",
"common/build/", "common/build/",
"proprietary/build/",
"configs/", "configs/",
"customFiles/", "customFiles/",
"docs/", "docs/",
@ -66,6 +68,7 @@
".gitattributes", ".gitattributes",
".gitignore", ".gitignore",
"common/.gitignore", "common/.gitignore",
"proprietary/.gitignore",
".pre-commit-config.yaml", ".pre-commit-config.yaml",
], ],
// Enables signature help in Java. // 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. Visit the [Lombok website](https://projectlombok.org/setup/) for installation instructions specific to your IDE.
5. Add environment variable 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 ## 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: 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.yml`: Latest version without login and security features
- `docker-compose-latest-security.yml`: Latest version with security features enabled - `docker-compose-latest-security.yml`: Latest version with login and security features enabled
- `docker-compose-latest-fat-security.yml`: Fat version with 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`: 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/config:/configs:rw
- /stirling/latest/logs:/logs:rw - /stirling/latest/logs:/logs:rw
environment: environment:
DOCKER_ENABLE_SECURITY: "true" DISABLE_ADDITIONAL_FEATURES: "false"
SECURITY_ENABLELOGIN: "true" SECURITY_ENABLELOGIN: "true"
PUID: 1002 PUID: 1002
PGID: 1002 PGID: 1002
@ -170,7 +170,7 @@ Stirling-PDF uses different Docker images for various configurations. The build
1. Set the security environment variable: 1. Set the security environment variable:
```bash ```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: 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 . 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 ```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 . 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" LABEL org.opencontainers.image.keywords="PDF, manipulation, merge, split, convert, OCR, watermark"
# Set Environment Variables # Set Environment Variables
ENV DOCKER_ENABLE_SECURITY=false \ ENV DISABLE_ADDITIONAL_FEATURES=true \
VERSION_TAG=$VERSION_TAG \ 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_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \
JAVA_CUSTOM_OPTS="" \ JAVA_CUSTOM_OPTS="" \

View File

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

View File

@ -4,7 +4,7 @@ FROM alpine:3.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be02
ARG VERSION_TAG ARG VERSION_TAG
# Set Environment Variables # Set Environment Variables
ENV DOCKER_ENABLE_SECURITY=false \ ENV DISABLE_ADDITIONAL_FEATURES=true \
HOME=/home/stirlingpdfuser \ HOME=/home/stirlingpdfuser \
VERSION_TAG=$VERSION_TAG \ 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_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 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 Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal 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.diffplug.spotless" version "7.0.4"
id "com.github.jk1.dependency-license-report" version "2.9" id "com.github.jk1.dependency-license-report" version "2.9"
//id "nebula.lint" version "19.0.3" //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" id "org.sonarqube" version "6.2.0.5505"
} }
@ -51,29 +51,14 @@ licenseReport {
sourceSets { sourceSets {
main { main {
java { java {
if (System.getenv("DOCKER_ENABLE_SECURITY") == "false") { if (System.getenv('DOCKER_ENABLE_SECURITY') == 'false' || System.getenv('DISABLE_ADDITIONAL_FEATURES') == 'true'
exclude "stirling/software/SPDF/config/interfaces/DatabaseInterface.java" || (project.hasProperty('DISABLE_ADDITIONAL_FEATURES')
exclude "stirling/software/SPDF/config/security/**" && System.getProperty('DISABLE_ADDITIONAL_FEATURES') == 'true')) {
exclude "stirling/software/SPDF/controller/api/DatabaseController.java" exclude 'stirling/software/proprietary/security/**'
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("STIRLING_PDF_DESKTOP_UI") == "false") { if (System.getenv('STIRLING_PDF_DESKTOP_UI') == 'false') {
exclude "stirling/software/SPDF/UI/impl/**" exclude 'stirling/software/SPDF/UI/impl/**'
} }
} }
@ -81,15 +66,14 @@ sourceSets {
test { test {
java { java {
if (System.getenv("DOCKER_ENABLE_SECURITY") == "false") { if (System.getenv('DOCKER_ENABLE_SECURITY') == 'false' || System.getenv('DISABLE_ADDITIONAL_FEATURES') == 'true'
exclude "stirling/software/SPDF/config/security/**" || (project.hasProperty('DISABLE_ADDITIONAL_FEATURES')
exclude "stirling/software/SPDF/model/ApiKeyAuthenticationTokenTest.java" && System.getProperty('DISABLE_ADDITIONAL_FEATURES') == 'true')) {
exclude "stirling/software/SPDF/controller/api/EmailControllerTest.java" exclude 'stirling/software/proprietary/security/**'
exclude "stirling/software/SPDF/repository/**"
} }
if (System.getenv("STIRLING_PDF_DESKTOP_UI") == "false") { if (System.getenv('STIRLING_PDF_DESKTOP_UI') == 'false') {
exclude "stirling/software/SPDF/UI/impl/**" exclude 'stirling/software/SPDF/UI/impl/**'
} }
} }
} }
@ -126,6 +110,7 @@ jpackage {
javaOptions = [ javaOptions = [
"-DBROWSER_OPEN=true", "-DBROWSER_OPEN=true",
"-DSTIRLING_PDF_DESKTOP_UI=true", "-DSTIRLING_PDF_DESKTOP_UI=true",
"-DDISABLE_ADDITIONAL_FEATURES=false",
"-Djava.awt.headless=false", "-Djava.awt.headless=false",
"-Dapple.awt.UIElement=true", "-Dapple.awt.UIElement=true",
"--add-opens=java.base/java.lang=ALL-UNNAMED", "--add-opens=java.base/java.lang=ALL-UNNAMED",
@ -262,6 +247,7 @@ tasks.register('jpackageMacX64') {
// Java options // Java options
'--java-options', '-DBROWSER_OPEN=true', '--java-options', '-DBROWSER_OPEN=true',
'--java-options', '-DSTIRLING_PDF_DESKTOP_UI=true', '--java-options', '-DSTIRLING_PDF_DESKTOP_UI=true',
'--java-options', '-DDISABLE_ADDITIONAL_FEATURES=false',
'--java-options', '-Djava.awt.headless=false', '--java-options', '-Djava.awt.headless=false',
'--java-options', '-Dapple.awt.UIElement=true', '--java-options', '-Dapple.awt.UIElement=true',
'--java-options', '--add-opens=java.base/java.lang=ALL-UNNAMED', '--java-options', '--add-opens=java.base/java.lang=ALL-UNNAMED',
@ -290,8 +276,6 @@ tasks.register('jpackageMacX64') {
} }
} }
//jpackage.finalizedBy(jpackageMacX64)
tasks.register('downloadTempJre') { tasks.register('downloadTempJre') {
group = 'distribution' group = 'distribution'
description = 'Downloads and extracts a temporary JRE' description = 'Downloads and extracts a temporary JRE'
@ -303,18 +287,18 @@ tasks.register('downloadTempJre') {
def jreArchive = new File(tmpDir, 'jre.tar.gz') def jreArchive = new File(tmpDir, 'jre.tar.gz')
def jreDir = new File(tmpDir, 'jre') def jreDir = new File(tmpDir, 'jre')
println "🔽 Downloading JRE to $jreArchive..." println "Downloading JRE to $jreArchive..."
jreArchive.withOutputStream { out -> jreArchive.withOutputStream { out ->
new URI(jreUrl).toURL().withInputStream { from -> out << from } new URI(jreUrl).toURL().withInputStream { from -> out << from }
} }
println "📦 Extracting JRE to $jreDir..." println "Extracting JRE to $jreDir..."
jreDir.mkdirs() jreDir.mkdirs()
providers.exec { providers.exec {
commandLine 'tar', '-xzf', jreArchive.absolutePath, '-C', jreDir.absolutePath, '--strip-components=1' commandLine 'tar', '-xzf', jreArchive.absolutePath, '-C', jreDir.absolutePath, '--strip-components=1'
}.result.get() }.result.get()
println "JRE ready at: $jreDir" println "JRE ready at: $jreDir"
ext.tempJrePath = jreDir.absolutePath ext.tempJrePath = jreDir.absolutePath
project.ext.tempJrePath = jreDir.absolutePath project.ext.tempJrePath = jreDir.absolutePath
} catch (Exception e) { } catch (Exception e) {
@ -376,6 +360,7 @@ spotless {
java { java {
target sourceSets.main.allJava target sourceSets.main.allJava
target project(':common').sourceSets.main.allJava target project(':common').sourceSets.main.allJava
target project(':proprietary').sourceSets.main.allJava
googleJavaFormat("1.27.0").aosp().reorderImports(false) googleJavaFormat("1.27.0").aosp().reorderImports(false)
@ -441,43 +426,18 @@ dependencies {
implementation("io.github.pixee:java-security-toolkit:1.2.1") implementation("io.github.pixee:java-security-toolkit:1.2.1")
// Exclude Tomcat and include Jetty // 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-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.posthog.java:posthog:1.2.0'
implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1' 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' 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 // Batik
implementation "org.apache.xmlgraphics:batik-all:1.19" implementation "org.apache.xmlgraphics:batik-all:1.19"
@ -485,10 +445,12 @@ dependencies {
// TwelveMonkeys // TwelveMonkeys
runtimeOnly "com.twelvemonkeys.imageio:imageio-batik:$imageioVersion" runtimeOnly "com.twelvemonkeys.imageio:imageio-batik:$imageioVersion"
runtimeOnly "com.twelvemonkeys.imageio:imageio-bmp:$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-hdr:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-icns:$imageioVersion" // runtimeOnly "com.twelvemonkeys.imageio:imageio-icns:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-iff:$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-pcx:$imageioVersion@
// runtimeOnly "com.twelvemonkeys.imageio:imageio-pict:$imageioVersion" // runtimeOnly "com.twelvemonkeys.imageio:imageio-pict:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-pnm:$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-sgi:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-tga:$imageioVersion" // runtimeOnly "com.twelvemonkeys.imageio:imageio-tga:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-thumbsdb:$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" // runtimeOnly "com.twelvemonkeys.imageio:imageio-xwd:$imageioVersion"
// Image metadata extractor // Image metadata extractor
implementation "com.drewnoakes:metadata-extractor:2.19.0" implementation "com.drewnoakes:metadata-extractor:2.19.0"
implementation "commons-io:commons-io:2.19.0" implementation "commons-io:commons-io:2.19.0"
implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8" // implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8"
//general PDF
// General PDF
// https://mvnrepository.com/artifact/com.opencsv/opencsv // https://mvnrepository.com/artifact/com.opencsv/opencsv
implementation ("com.opencsv:opencsv:5.11") 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:preflight:$pdfboxVersion"
implementation ("org.apache.pdfbox:xmpbox:$pdfboxVersion") implementation ("org.apache.pdfbox:xmpbox:$pdfboxVersion")
// https://mvnrepository.com/artifact/technology.tabula/tabula // https://mvnrepository.com/artifact/technology.tabula/tabula
@ -537,7 +493,6 @@ dependencies {
// https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17 // https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17
implementation "com.bucket4j:bucket4j_jdk17-core:8.14.0" implementation "com.bucket4j:bucket4j_jdk17-core:8.14.0"
implementation "com.fathzer:javaluator:3.0.6" implementation "com.fathzer:javaluator:3.0.6"
implementation 'com.vladsch.flexmark:flexmark-html2md-converter:0.64.8' implementation 'com.vladsch.flexmark:flexmark-html2md-converter:0.64.8'
developmentOnly("org.springframework.boot:spring-boot-devtools:$springBootVersion") developmentOnly("org.springframework.boot:spring-boot-devtools:$springBootVersion")
@ -547,6 +502,7 @@ dependencies {
// Mockito (core) // Mockito (core)
testImplementation 'org.mockito:mockito-core:5.18.0' testImplementation 'org.mockito:mockito-core:5.18.0'
testRuntimeOnly 'org.mockito:mockito-inline:5.2.0' testRuntimeOnly 'org.mockito:mockito-inline:5.2.0'
testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
} }
tasks.withType(JavaCompile).configureEach { tasks.withType(JavaCompile).configureEach {

View File

@ -30,19 +30,19 @@ dependencyManagement {
} }
dependencies { dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web' api 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' api 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1' api 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1'
implementation 'com.fathzer:javaluator:3.0.6' api 'com.fathzer:javaluator:3.0.6'
implementation 'com.posthog.java:posthog:1.2.0' api 'com.posthog.java:posthog:1.2.0'
implementation 'io.github.pixee:java-security-toolkit:1.2.1' api 'io.github.pixee:java-security-toolkit:1.2.1'
implementation 'org.apache.commons:commons-lang3:3.17.0' api 'org.apache.commons:commons-lang3:3.17.0'
implementation 'com.drewnoakes:metadata-extractor:2.19.0' // Image metadata extractor api 'com.drewnoakes:metadata-extractor:2.19.0' // Image metadata extractor
implementation 'com.vladsch.flexmark:flexmark-html2md-converter:0.64.8' api 'com.vladsch.flexmark:flexmark-html2md-converter:0.64.8'
implementation "org.apache.pdfbox:pdfbox:$pdfboxVersion" api "org.apache.pdfbox:pdfbox:$pdfboxVersion"
implementation 'jakarta.servlet:jakarta.servlet-api:6.1.0' api 'jakarta.servlet:jakarta.servlet-api:6.1.0'
implementation 'org.snakeyaml:snakeyaml-engine:2.9' api 'org.snakeyaml:snakeyaml-engine:2.9'
implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8" api "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8"
compileOnly "org.projectlombok:lombok:$lombokVersion" compileOnly "org.projectlombok:lombok:$lombokVersion"
annotationProcessor "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 java.util.function.Predicate;
import org.springframework.beans.factory.annotation.Value; 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.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -146,8 +147,22 @@ public class AppConfig {
} }
} }
@ConditionalOnMissingClass("stirling.software.SPDF.config.security.SecurityConfiguration")
@Bean(name = "activeSecurity") @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() { public boolean missingActiveSecurity() {
return false; return false;
} }

View File

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

View File

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

View File

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

View File

@ -18,7 +18,7 @@ services:
- /stirling/latest/config:/configs:rw - /stirling/latest/config:/configs:rw
- /stirling/latest/logs:/logs:rw - /stirling/latest/logs:/logs:rw
environment: environment:
DOCKER_ENABLE_SECURITY: "true" DISABLE_ADDITIONAL_FEATURES: "false"
SECURITY_ENABLELOGIN: "true" SECURITY_ENABLELOGIN: "true"
SECURITY_OAUTH2_ENABLED: "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 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/config:/configs:rw
- ./stirling/latest/logs:/logs:rw - ./stirling/latest/logs:/logs:rw
environment: environment:
DOCKER_ENABLE_SECURITY: "true" DISABLE_ADDITIONAL_FEATURES: "false"
SECURITY_ENABLELOGIN: "true" SECURITY_ENABLELOGIN: "true"
PUID: 1002 PUID: 1002
PGID: 1002 PGID: 1002

View File

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

View File

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

View File

@ -18,7 +18,7 @@ services:
- /stirling/latest/config:/configs:rw - /stirling/latest/config:/configs:rw
- /stirling/latest/logs:/logs:rw - /stirling/latest/logs:/logs:rw
environment: environment:
DOCKER_ENABLE_SECURITY: "false" DISABLE_ADDITIONAL_FEATURES: "true"
SECURITY_ENABLELOGIN: "false" 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" 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 SYSTEM_DEFAULTLOCALE: en-US

View File

@ -18,7 +18,7 @@ services:
- /stirling/latest/config:/configs:rw - /stirling/latest/config:/configs:rw
- /stirling/latest/logs:/logs:rw - /stirling/latest/logs:/logs:rw
environment: environment:
DOCKER_ENABLE_SECURITY: "true" DISABLE_ADDITIONAL_FEATURES: "false"
SECURITY_ENABLELOGIN: "true" SECURITY_ENABLELOGIN: "true"
PUID: 1002 PUID: 1002
PGID: 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.io.IOException;
import java.util.Optional; import java.util.Optional;
@ -17,7 +17,9 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j; 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 @Slf4j
public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { 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; import java.io.IOException;
@ -14,6 +14,8 @@ import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.common.util.RequestUriUtils; import stirling.software.common.util.RequestUriUtils;
import stirling.software.proprietary.security.service.LoginAttemptService;
import stirling.software.proprietary.security.service.UserService;
@Slf4j @Slf4j
public class CustomAuthenticationSuccessHandler 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.io.IOException;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
@ -22,14 +22,14 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.SPDFApplication; import stirling.software.common.configuration.AppConfig;
import stirling.software.SPDF.config.security.saml2.CertificateUtils;
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.common.model.ApplicationProperties.Security.SAML2; import stirling.software.common.model.ApplicationProperties.Security.SAML2;
import stirling.software.common.model.oauth2.KeycloakProvider; import stirling.software.common.model.oauth2.KeycloakProvider;
import stirling.software.common.util.UrlUtils; import stirling.software.common.util.UrlUtils;
import stirling.software.proprietary.security.saml2.CertificateUtils;
import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal;
@Slf4j @Slf4j
@RequiredArgsConstructor @RequiredArgsConstructor
@ -38,6 +38,7 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
public static final String LOGOUT_PATH = "/login?logout=true"; public static final String LOGOUT_PATH = "/login?logout=true";
private final ApplicationProperties applicationProperties; private final ApplicationProperties applicationProperties;
private final AppConfig appConfig;
@Override @Override
public void onLogoutSuccess( public void onLogoutSuccess(
@ -102,7 +103,7 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
// Set service provider keys for the SamlClient // Set service provider keys for the SamlClient
samlClient.setSPKeys(certificate, privateKey); 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); samlClient.redirectToIdentityProvider(response, null, nameIdValue);
} catch (Exception e) { } catch (Exception e) {
log.error( 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) String registrationId, SAML2 samlConf, List<X509Certificate> certificates)
throws SamlException { throws SamlException {
String serverUrl = String serverUrl = appConfig.getBaseUrl() + ":" + appConfig.getServerPort();
SPDFApplication.getStaticBaseUrl() + ":" + SPDFApplication.getStaticPort();
String relyingPartyIdentifier = String relyingPartyIdentifier =
serverUrl + "/saml2/service-provider-metadata/" + registrationId; 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.sql.SQLException;
import java.util.UUID; import java.util.UUID;
@ -10,10 +10,11 @@ import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; 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.ApplicationProperties;
import stirling.software.common.model.enumeration.Role;
import stirling.software.common.model.exception.UnsupportedProviderException; import stirling.software.common.model.exception.UnsupportedProviderException;
import stirling.software.proprietary.security.service.DatabaseServiceInterface;
import stirling.software.proprietary.security.service.UserService;
@Slf4j @Slf4j
@Component @Component
@ -24,7 +25,7 @@ public class InitialSecuritySetup {
private final ApplicationProperties applicationProperties; private final ApplicationProperties applicationProperties;
private final DatabaseInterface databaseService; private final DatabaseServiceInterface databaseService;
@PostConstruct @PostConstruct
public void init() { 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.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.proprietary.security.filter.IPRateLimitingFilter;
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
public class RateLimitResetScheduler { 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 javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier; 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.DataSourceBuilder;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -17,14 +21,14 @@ import stirling.software.common.model.exception.UnsupportedProviderException;
@Slf4j @Slf4j
@Getter @Getter
@Configuration @Configuration
@EnableJpaRepositories(basePackages = "stirling.software.proprietary.security.database.repository")
@EntityScan({"stirling.software.proprietary.security.model"})
public class DatabaseConfig { public class DatabaseConfig {
public final String DATASOURCE_DEFAULT_URL; public final String DATASOURCE_DEFAULT_URL;
public static final String DATASOURCE_URL_TEMPLATE = "jdbc:%s://%s:%4d/%s"; 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 DEFAULT_USERNAME = "sa";
public static final String POSTGRES_DRIVER = "org.postgresql.Driver";
private final ApplicationProperties.Datasource datasource; private final ApplicationProperties.Datasource datasource;
private final boolean runningProOrHigher; private final boolean runningProOrHigher;
@ -54,19 +58,32 @@ public class DatabaseConfig {
public DataSource dataSource() throws UnsupportedProviderException { public DataSource dataSource() throws UnsupportedProviderException {
DataSourceBuilder<?> dataSourceBuilder = DataSourceBuilder.create(); DataSourceBuilder<?> dataSourceBuilder = DataSourceBuilder.create();
if (!runningProOrHigher) { if (!runningProOrHigher || !datasource.isEnableCustomDatabase()) {
return useDefaultDataSource(dataSourceBuilder); return useDefaultDataSource(dataSourceBuilder);
} }
if (!datasource.isEnableCustomDatabase()) { return useCustomDataSource(dataSourceBuilder);
return useDefaultDataSource(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"); log.info("Using custom database configuration");
if (!datasource.getCustomDatabaseUrl().isBlank()) { if (!datasource.getCustomDatabaseUrl().isBlank()) {
if (datasource.getCustomDatabaseUrl().contains("postgresql")) { if (datasource.getCustomDatabaseUrl().contains("postgresql")) {
dataSourceBuilder.driverClassName(POSTGRES_DRIVER); dataSourceBuilder.driverClassName(DatabaseDriver.POSTGRESQL.getDriverClassName());
} }
dataSourceBuilder.url(datasource.getCustomDatabaseUrl()); dataSourceBuilder.url(datasource.getCustomDatabaseUrl());
@ -85,15 +102,6 @@ public class DatabaseConfig {
return dataSourceBuilder.build(); 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 * Generate the URL the <code>DataSource</code> will use to connect to the database
* *
@ -123,11 +131,11 @@ public class DatabaseConfig {
switch (driver) { switch (driver) {
case H2 -> { case H2 -> {
log.debug("H2 driver selected"); log.debug("H2 driver selected");
return DEFAULT_DRIVER; return DatabaseDriver.H2.getDriverClassName();
} }
case POSTGRESQL -> { case POSTGRESQL -> {
log.debug("Postgres driver selected"); log.debug("Postgres driver selected");
return POSTGRES_DRIVER; return DatabaseDriver.POSTGRESQL.getDriverClassName();
} }
default -> { default -> {
log.warn("{} driver selected", driverName); 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; 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; 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.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.ProviderManager; import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider; 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 lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2AuthenticationFailureHandler; import stirling.software.common.configuration.AppConfig;
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.model.ApplicationProperties; 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 @Configuration
@EnableWebSecurity @EnableWebSecurity
@EnableMethodSecurity @EnableMethodSecurity
@Slf4j
@DependsOn("runningProOrHigher")
public class SecurityConfiguration { public class SecurityConfiguration {
private final CustomUserDetailsService userDetailsService; private final CustomUserDetailsService userDetailsService;
@ -55,6 +63,7 @@ public class SecurityConfiguration {
private final boolean runningProOrHigher; private final boolean runningProOrHigher;
private final ApplicationProperties applicationProperties; private final ApplicationProperties applicationProperties;
private final AppConfig appConfig;
private final UserAuthenticationFilter userAuthenticationFilter; private final UserAuthenticationFilter userAuthenticationFilter;
private final LoginAttemptService loginAttemptService; private final LoginAttemptService loginAttemptService;
private final FirstLoginFilter firstLoginFilter; private final FirstLoginFilter firstLoginFilter;
@ -70,6 +79,7 @@ public class SecurityConfiguration {
@Lazy UserService userService, @Lazy UserService userService,
@Qualifier("loginEnabled") boolean loginEnabledValue, @Qualifier("loginEnabled") boolean loginEnabledValue,
@Qualifier("runningProOrHigher") boolean runningProOrHigher, @Qualifier("runningProOrHigher") boolean runningProOrHigher,
AppConfig appConfig,
ApplicationProperties applicationProperties, ApplicationProperties applicationProperties,
UserAuthenticationFilter userAuthenticationFilter, UserAuthenticationFilter userAuthenticationFilter,
LoginAttemptService loginAttemptService, LoginAttemptService loginAttemptService,
@ -84,6 +94,7 @@ public class SecurityConfiguration {
this.userService = userService; this.userService = userService;
this.loginEnabledValue = loginEnabledValue; this.loginEnabledValue = loginEnabledValue;
this.runningProOrHigher = runningProOrHigher; this.runningProOrHigher = runningProOrHigher;
this.appConfig = appConfig;
this.applicationProperties = applicationProperties; this.applicationProperties = applicationProperties;
this.userAuthenticationFilter = userAuthenticationFilter; this.userAuthenticationFilter = userAuthenticationFilter;
this.loginAttemptService = loginAttemptService; this.loginAttemptService = loginAttemptService;
@ -161,7 +172,8 @@ public class SecurityConfiguration {
PathPatternRequestMatcher.withDefaults() PathPatternRequestMatcher.withDefaults()
.matcher("/logout")) .matcher("/logout"))
.logoutSuccessHandler( .logoutSuccessHandler(
new CustomLogoutSuccessHandler(applicationProperties)) new CustomLogoutSuccessHandler(
applicationProperties, appConfig))
.clearAuthentication(true) .clearAuthentication(true)
.invalidateHttpSession(true) .invalidateHttpSession(true)
.deleteCookies("JSESSIONID", "remember-me")); .deleteCookies("JSESSIONID", "remember-me"));
@ -229,13 +241,12 @@ public class SecurityConfiguration {
http.oauth2Login( http.oauth2Login(
oauth2 -> oauth2 ->
oauth2.loginPage("/oauth2") oauth2.loginPage("/oauth2")
.
/* /*
This Custom handler is used to check if the OAUTH2 user trying to log in, already exists in the database. 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' 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. is set as true, else login fails with an error message advising the same.
*/ */
successHandler( .successHandler(
new CustomOAuth2AuthenticationSuccessHandler( new CustomOAuth2AuthenticationSuccessHandler(
loginAttemptService, loginAttemptService,
applicationProperties, applicationProperties,
@ -287,15 +298,14 @@ public class SecurityConfiguration {
}); });
} }
} else { } else {
log.debug("SAML 2 login is not enabled. Using default."); log.debug("Login is not enabled.");
http.authorizeHttpRequests(authz -> authz.anyRequest().permitAll()); http.authorizeHttpRequests(authz -> authz.anyRequest().permitAll());
} }
return http.build(); return http.build();
} }
public DaoAuthenticationProvider daoAuthenticationProvider() { public DaoAuthenticationProvider daoAuthenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(userDetailsService);
provider.setUserDetailsService(userDetailsService);
provider.setPasswordEncoder(passwordEncoder()); provider.setPasswordEncoder(passwordEncoder());
return provider; return provider;
} }
@ -311,9 +321,4 @@ public class SecurityConfiguration {
public PersistentTokenRepository persistentTokenRepository() { public PersistentTokenRepository persistentTokenRepository() {
return new JPATokenRepositoryImpl(persistentLoginRepository); 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.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -27,7 +27,8 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; 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 @Slf4j
@Controller @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.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
@ -18,8 +18,8 @@ import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.mail.EmailService; import stirling.software.proprietary.security.model.api.Email;
import stirling.software.SPDF.model.api.Email; import stirling.software.proprietary.security.service.EmailService;
/** /**
* Controller for handling email-related API requests. This controller exposes an endpoint for * 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.io.IOException;
import java.security.Principal; import java.security.Principal;
@ -29,15 +29,15 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; 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.ApplicationProperties;
import stirling.software.common.model.enumeration.Role;
import stirling.software.common.model.exception.UnsupportedProviderException; 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 @Controller
@Tag(name = "User", description = "User APIs") @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; import static stirling.software.common.util.ProviderUtils.validateProvider;
@ -29,21 +29,21 @@ import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j; 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;
import stirling.software.common.model.ApplicationProperties.Security; import stirling.software.common.model.ApplicationProperties.Security;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2.Client; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2.Client;
import stirling.software.common.model.ApplicationProperties.Security.SAML2; 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.GitHubProvider;
import stirling.software.common.model.oauth2.GoogleProvider; import stirling.software.common.model.oauth2.GoogleProvider;
import stirling.software.common.model.oauth2.KeycloakProvider; 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 @Controller
@Slf4j @Slf4j

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.controller.web; package stirling.software.proprietary.security.controller.web;
import java.util.List; import java.util.List;
@ -14,8 +14,8 @@ import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.security.database.DatabaseService;
import stirling.software.common.model.FileInfo; import stirling.software.common.model.FileInfo;
import stirling.software.proprietary.security.service.DatabaseService;
@Controller @Controller
@Tag(name = "Database Management", description = "Database management and security APIs") @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.Condition;
import org.springframework.context.annotation.ConditionContext; import org.springframework.context.annotation.ConditionContext;
@ -12,8 +12,12 @@ public class H2SQLCondition implements Condition {
Boolean.parseBoolean( Boolean.parseBoolean(
context.getEnvironment() context.getEnvironment()
.getProperty("system.datasource.enableCustomDatabase")); .getProperty("system.datasource.enableCustomDatabase"));
if (!enableCustomDatabase) {
return false;
}
String dataSourceType = context.getEnvironment().getProperty("system.datasource.type"); String dataSourceType = context.getEnvironment().getProperty("system.datasource.type");
return !enableCustomDatabase return "h2".equalsIgnoreCase(dataSourceType);
|| (enableCustomDatabase && "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; import java.sql.SQLException;
@ -8,16 +8,15 @@ import org.springframework.stereotype.Component;
import lombok.RequiredArgsConstructor; 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.common.model.exception.UnsupportedProviderException;
import stirling.software.proprietary.security.service.DatabaseServiceInterface;
@Component @Component
@Conditional(H2SQLCondition.class) @Conditional(H2SQLCondition.class)
@RequiredArgsConstructor @RequiredArgsConstructor
public class ScheduledTasks { public class ScheduledTasks {
private final DatabaseInterface databaseService; private final DatabaseServiceInterface databaseService;
@Scheduled(cron = "0 0 0 * * ?") @Scheduled(cron = "0 0 0 * * ?")
public void performBackup() throws SQLException, UnsupportedProviderException { 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 java.util.Set;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import stirling.software.SPDF.model.Authority; import stirling.software.proprietary.security.model.Authority;
@Repository @Repository
public interface AuthorityRepository extends JpaRepository<Authority, Long> { 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; 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.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import stirling.software.SPDF.model.PersistentLogin; import stirling.software.proprietary.security.model.PersistentLogin;
public class JPATokenRepositoryImpl implements PersistentTokenRepository { 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.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import stirling.software.SPDF.model.PersistentLogin; import stirling.software.proprietary.security.model.PersistentLogin;
@Repository @Repository
public interface PersistentLoginRepository extends JpaRepository<PersistentLogin, String> { 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.Date;
import java.util.List; import java.util.List;
@ -11,7 +11,7 @@ import org.springframework.stereotype.Repository;
import jakarta.transaction.Transactional; import jakarta.transaction.Transactional;
import stirling.software.SPDF.model.SessionEntity; import stirling.software.proprietary.security.model.SessionEntity;
@Repository @Repository
public interface SessionRepository extends JpaRepository<SessionEntity, String> { 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.List;
import java.util.Optional; 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.data.repository.query.Param;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import stirling.software.SPDF.model.User; import stirling.software.proprietary.security.model.User;
@Repository @Repository
public interface UserRepository extends JpaRepository<User, Long> { 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; 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.io.IOException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
@ -19,8 +19,9 @@ import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.User;
import stirling.software.common.util.RequestUriUtils; import stirling.software.common.util.RequestUriUtils;
import stirling.software.proprietary.security.model.User;
import stirling.software.proprietary.security.service.UserService;
@Slf4j @Slf4j
@Component @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.io.IOException;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger; 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 jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor; 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.io.IOException;
import java.util.List; import java.util.List;
@ -24,13 +24,14 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j; 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;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.common.model.ApplicationProperties.Security.SAML2; 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 @Slf4j
@Component @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.io.IOException;
import java.time.Duration; import java.time.Duration;
@ -24,7 +24,7 @@ import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import stirling.software.SPDF.model.Role; import stirling.software.common.model.enumeration.Role;
@Component @Component
public class UserBasedRateLimitingFilter extends OncePerRequestFilter { 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; import java.util.Collection;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model; package stirling.software.proprietary.security.model;
public class AttemptCounter { public class AttemptCounter {
private int attemptCount; 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; 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; 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.io.Serializable;
import java.util.Date; 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.io.Serializable;
import java.util.HashMap; import java.util.HashMap;
@ -15,6 +15,8 @@ import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
import stirling.software.common.model.enumeration.Role;
@Entity @Entity
@Table(name = "users") @Table(name = "users")
@NoArgsConstructor @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 class BackupNotFoundException extends RuntimeException {
public BackupNotFoundException(String message) { 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 class NoProviderFoundException extends Exception {
public NoProviderFoundException(String message) { 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; 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.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
@ -17,13 +17,13 @@ import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor; 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;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.common.model.exception.UnsupportedProviderException; import stirling.software.common.model.exception.UnsupportedProviderException;
import stirling.software.common.util.RequestUriUtils; 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 @RequiredArgsConstructor
public class CustomOAuth2AuthenticationSuccessHandler 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 org.springframework.security.oauth2.core.AuthorizationGrantType.AUTHORIZATION_CODE;
import static stirling.software.common.util.ProviderUtils.validateProvider; import static stirling.software.common.util.ProviderUtils.validateProvider;
@ -10,6 +10,7 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -25,9 +26,6 @@ import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
import lombok.extern.slf4j.Slf4j; 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;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2.Client; 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.GoogleProvider;
import stirling.software.common.model.oauth2.KeycloakProvider; import stirling.software.common.model.oauth2.KeycloakProvider;
import stirling.software.common.model.oauth2.Provider; 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 @Slf4j
@Configuration @Configuration
@ConditionalOnProperty(value = "security.oauth2.enabled", havingValue = "true") @ConditionalOnBooleanProperty("security.oauth2.enabled")
public class OAuth2Configuration { public class OAuth2Configuration {
public static final String REDIRECT_URI_PATH = "{baseUrl}/login/oauth2/code/"; public static final String REDIRECT_URI_PATH = "{baseUrl}/login/oauth2/code/";
@ -54,7 +55,6 @@ public class OAuth2Configuration {
} }
@Bean @Bean
@ConditionalOnProperty(value = "security.oauth2.enabled", havingValue = "true")
public ClientRegistrationRepository clientRegistrationRepository() public ClientRegistrationRepository clientRegistrationRepository()
throws NoProviderFoundException { throws NoProviderFoundException {
List<ClientRegistration> registrations = new ArrayList<>(); 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.ByteArrayInputStream;
import java.io.InputStreamReader; 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.io.Serializable;
import java.util.List; 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; 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.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
@ -16,13 +16,13 @@ import jakarta.servlet.http.HttpSession;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; 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;
import stirling.software.common.model.ApplicationProperties.Security.SAML2; import stirling.software.common.model.ApplicationProperties.Security.SAML2;
import stirling.software.common.model.exception.UnsupportedProviderException; import stirling.software.common.model.exception.UnsupportedProviderException;
import stirling.software.common.util.RequestUriUtils; 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 @AllArgsConstructor
@Slf4j @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.core.xml.XMLObject;
import org.opensaml.saml.saml2.core.Assertion; 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.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.UserService; import stirling.software.proprietary.security.model.User;
import stirling.software.SPDF.model.User; import stirling.software.proprietary.security.service.UserService;
@Slf4j @Slf4j
@ConditionalOnProperty(name = "security.saml2.enabled", havingValue = "true") @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.security.cert.X509Certificate;
import java.util.Collections; import java.util.Collections;
import java.util.UUID; import java.util.UUID;
import org.opensaml.saml.saml2.core.AuthnRequest; import org.opensaml.saml.saml2.core.AuthnRequest;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -29,8 +30,8 @@ import stirling.software.common.model.ApplicationProperties.Security.SAML2;
@Configuration @Configuration
@Slf4j @Slf4j
@ConditionalOnProperty(value = "security.saml2.enabled", havingValue = "true")
@RequiredArgsConstructor @RequiredArgsConstructor
@ConditionalOnBooleanProperty("security.saml2.enabled")
public class SAML2Configuration { public class SAML2Configuration {
private final ApplicationProperties applicationProperties; 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; import java.util.Optional;
@ -8,10 +8,10 @@ import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.interfaces.ShowAdminInterface; import stirling.software.common.configuration.interfaces.ShowAdminInterface;
import stirling.software.SPDF.model.User;
import stirling.software.SPDF.repository.UserRepository;
import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties;
import stirling.software.proprietary.security.database.repository.UserRepository;
import stirling.software.proprietary.security.model.User;
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.oauth2; package stirling.software.proprietary.security.service;
import java.util.Optional; import java.util.Optional;
@ -13,12 +13,10 @@ import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import lombok.extern.slf4j.Slf4j; 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;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2; import stirling.software.common.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.common.model.enumeration.UsernameAttribute; import stirling.software.common.model.enumeration.UsernameAttribute;
import stirling.software.proprietary.security.model.User;
@Slf4j @Slf4j
public class CustomOAuth2UserService implements OAuth2UserService<OidcUserRequest, OidcUser> { 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.Collection;
import java.util.Set; import java.util.Set;
@ -13,9 +13,9 @@ import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.model.Authority; import stirling.software.proprietary.security.database.repository.UserRepository;
import stirling.software.SPDF.model.User; import stirling.software.proprietary.security.model.Authority;
import stirling.software.SPDF.repository.UserRepository; import stirling.software.proprietary.security.model.User;
@Service @Service
@RequiredArgsConstructor @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.io.IOException;
import java.nio.file.DirectoryStream; import java.nio.file.DirectoryStream;
@ -27,15 +27,14 @@ import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j; 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.configuration.InstallationPathConfig;
import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.FileInfo; import stirling.software.common.model.FileInfo;
import stirling.software.proprietary.security.model.exception.BackupNotFoundException;
@Slf4j @Slf4j
@Service @Service
public class DatabaseService implements DatabaseInterface { public class DatabaseService implements DatabaseServiceInterface {
public static final String BACKUP_PREFIX = "backup_"; public static final String BACKUP_PREFIX = "backup_";
public static final String SQL_SUFFIX = ".sql"; 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.sql.SQLException;
import java.util.List; import java.util.List;
@ -6,7 +6,7 @@ import java.util.List;
import stirling.software.common.model.FileInfo; import stirling.software.common.model.FileInfo;
import stirling.software.common.model.exception.UnsupportedProviderException; import stirling.software.common.model.exception.UnsupportedProviderException;
public interface DatabaseInterface { public interface DatabaseServiceInterface {
void exportDatabase() throws SQLException, UnsupportedProviderException; void exportDatabase() throws SQLException, UnsupportedProviderException;
void importDatabase(); 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.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.JavaMailSender;
@ -12,8 +12,8 @@ import jakarta.mail.internet.MimeMessage;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.model.api.Email;
import stirling.software.common.model.ApplicationProperties; 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 * 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.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -10,8 +10,8 @@ import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.AttemptCounter;
import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties;
import stirling.software.proprietary.security.model.AttemptCounter;
@Service @Service
@Slf4j @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.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -28,18 +27,17 @@ import org.springframework.transaction.annotation.Transactional;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; 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.ApplicationProperties;
import stirling.software.common.model.enumeration.Role;
import stirling.software.common.model.exception.UnsupportedProviderException; import stirling.software.common.model.exception.UnsupportedProviderException;
import stirling.software.common.service.UserServiceInterface; 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 @Service
@Slf4j @Slf4j
@ -56,7 +54,7 @@ public class UserService implements UserServiceInterface {
private final SessionPersistentRegistry sessionRegistry; private final SessionPersistentRegistry sessionRegistry;
private final DatabaseInterface databaseService; private final DatabaseServiceInterface databaseService;
private final ApplicationProperties.Security.OAUTH2 oAuth2; private final ApplicationProperties.Security.OAUTH2 oAuth2;
@ -88,7 +86,7 @@ public class UserService implements UserServiceInterface {
public Authentication getAuthentication(String apiKey) { public Authentication getAuthentication(String apiKey) {
Optional<User> user = getUserByApiKey(apiKey); Optional<User> user = getUserByApiKey(apiKey);
if (!user.isPresent()) { if (user.isEmpty()) {
throw new UsernameNotFoundException("API key is not valid"); throw new UsernameNotFoundException("API key is not valid");
} }
// Convert the user into an Authentication object // Convert the user into an Authentication object
@ -305,10 +303,7 @@ public class UserService implements UserServiceInterface {
} }
public void changeUsername(User user, String newUsername) public void changeUsername(User user, String newUsername)
throws IllegalArgumentException, throws IllegalArgumentException, SQLException, UnsupportedProviderException {
IOException,
SQLException,
UnsupportedProviderException {
if (!isUsernameValid(newUsername)) { if (!isUsernameValid(newUsername)) {
throw new IllegalArgumentException(getInvalidUsernameMessage()); throw new IllegalArgumentException(getInvalidUsernameMessage());
} }
@ -418,7 +413,7 @@ public class UserService implements UserServiceInterface {
if (principal instanceof UserDetails detailsUser) { if (principal instanceof UserDetails detailsUser) {
return detailsUser.getUsername(); return detailsUser.getUsername();
} else if (principal instanceof stirling.software.SPDF.model.User domainUser) { } else if (principal instanceof User domainUser) {
return domainUser.getUsername(); return domainUser.getUsername();
} else if (principal instanceof OAuth2User oAuth2User) { } else if (principal instanceof OAuth2User oAuth2User) {
return oAuth2User.getAttribute(oAuth2.getUseAsUsername()); 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; import org.springframework.stereotype.Component;
@ -11,7 +11,7 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j @Slf4j
public class CustomHttpSessionListener implements HttpSessionListener { public class CustomHttpSessionListener implements HttpSessionListener {
private SessionPersistentRegistry sessionPersistentRegistry; private final SessionPersistentRegistry sessionPersistentRegistry;
public CustomHttpSessionListener(SessionPersistentRegistry sessionPersistentRegistry) { public CustomHttpSessionListener(SessionPersistentRegistry sessionPersistentRegistry) {
super(); 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.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.beans.factory.annotation.Value;
import org.springframework.security.core.session.SessionInformation; import org.springframework.security.core.session.SessionInformation;
@ -14,8 +19,9 @@ import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal; import stirling.software.proprietary.security.database.repository.SessionRepository;
import stirling.software.SPDF.model.SessionEntity; import stirling.software.proprietary.security.model.SessionEntity;
import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal;
@Component @Component
@RequiredArgsConstructor @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.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.session.SessionRegistryImpl; import org.springframework.security.core.session.SessionRegistryImpl;
import stirling.software.proprietary.security.database.repository.SessionRepository;
@Configuration @Configuration
public class SessionRegistryConfig { 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.Instant;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;

View File

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

View File

@ -1,11 +1,6 @@
package stirling.software.SPDF.config.security.database; package stirling.software.proprietary.security.configuration;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.when;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; 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.junit.jupiter.params.provider.ValueSource;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.exception.UnsupportedProviderException; import stirling.software.common.model.exception.UnsupportedProviderException;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
class DatabaseConfigTest { 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.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doNothing;
@ -23,8 +23,8 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import jakarta.mail.MessagingException; import jakarta.mail.MessagingException;
import stirling.software.SPDF.config.security.mail.EmailService; import stirling.software.proprietary.security.model.api.Email;
import stirling.software.SPDF.model.api.Email; import stirling.software.proprietary.security.service.EmailService;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
class EmailControllerTest { 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.assertEquals;
import static org.junit.jupiter.api.Assertions.fail; 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.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks; import org.mockito.InjectMocks;
@ -15,8 +15,11 @@ import org.springframework.web.multipart.MultipartFile;
import jakarta.mail.MessagingException; import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage; import jakarta.mail.internet.MimeMessage;
import stirling.software.SPDF.model.api.Email;
import stirling.software.common.model.ApplicationProperties; 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) @ExtendWith(MockitoExtension.class)
public class EmailServiceTest { 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.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals; 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 org.springframework.mail.javamail.JavaMailSenderImpl;
import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties;
import stirling.software.proprietary.security.configuration.MailConfig;
class MailConfigTest { class MailConfigTest {

View File

@ -1,6 +1,6 @@
echo "Running Stirling PDF with DOCKER_ENABLE_SECURITY=${DOCKER_ENABLE_SECURITY} and VERSION_TAG=${VERSION_TAG}" echo "Running Stirling PDF with DISABLE_ADDITIONAL_FEATURES=${DISABLE_ADDITIONAL_FEATURES} and VERSION_TAG=${VERSION_TAG}"
# Check for DOCKER_ENABLE_SECURITY and download the appropriate JAR if required # Check for $DISABLE_ADDITIONAL_FEATURES and download the appropriate JAR if required
if [ "$DOCKER_ENABLE_SECURITY" = "true" ] && [ "$VERSION_TAG" != "alpha" ]; then if [ "$DISABLE_ADDITIONAL_FEATURES" = "false" ] && [ "$VERSION_TAG" != "alpha" ]; then
if [ ! -f app-security.jar ]; then if [ ! -f app-security.jar ]; then
echo "Trying to download from: https://files.stirlingpdf.com/v$VERSION_TAG/Stirling-PDF-with-login.jar" 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 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' rootProject.name = 'Stirling-PDF'
include 'common' include 'common', 'proprietary'

View File

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

View File

@ -35,7 +35,11 @@ import stirling.software.common.util.UrlUtils;
@Slf4j @Slf4j
@EnableScheduling @EnableScheduling
@SpringBootApplication( @SpringBootApplication(
scanBasePackages = {"stirling.software.common", "stirling.software.SPDF"}, scanBasePackages = {
"stirling.software.common",
"stirling.software.SPDF",
"stirling.software.proprietary.security"
},
exclude = { exclude = {
DataSourceAutoConfiguration.class, DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.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.Configuration;
import org.springframework.context.annotation.Scope; 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; import stirling.software.common.model.ApplicationProperties;
@Configuration @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 lombok.RequiredArgsConstructor;
import stirling.software.SPDF.model.api.GeneralFile;
import stirling.software.common.configuration.RuntimePathConfig; import stirling.software.common.configuration.RuntimePathConfig;
import stirling.software.common.model.api.GeneralFile;
import stirling.software.common.service.CustomPDFDocumentFactory; import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.ProcessExecutor; import stirling.software.common.util.ProcessExecutor;
import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult; import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult;

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