mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-06-23 16:05:09 +00:00
Compare commits
52 Commits
99886f9a70
...
a05bd7a57a
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a05bd7a57a | ||
![]() |
fa90725161 | ||
![]() |
3aac0b883b | ||
![]() |
34f738636f | ||
![]() |
be32bb4ce9 | ||
![]() |
1e0ebb2dab | ||
![]() |
98104d779d | ||
![]() |
da435570f5 | ||
![]() |
e39ab6779f | ||
![]() |
41d5f39536 | ||
![]() |
4883573e87 | ||
![]() |
63fdb958ef | ||
![]() |
55b9286958 | ||
![]() |
3cc3037408 | ||
![]() |
70a9b5f009 | ||
![]() |
92f5c5de7a | ||
![]() |
b08bc191fc | ||
![]() |
d12aca0ca6 | ||
![]() |
5ec78b5425 | ||
![]() |
3bec51f4e5 | ||
![]() |
d83d8b4748 | ||
![]() |
03d27013d6 | ||
![]() |
679ecdd50d | ||
![]() |
631c4fef0b | ||
![]() |
209c76d885 | ||
![]() |
3293d0d8a1 | ||
![]() |
45462dc5d4 | ||
![]() |
c0e93cd5e5 | ||
![]() |
2217cfb95d | ||
![]() |
214404b5c9 | ||
![]() |
ddc2daea52 | ||
![]() |
ff602a20a0 | ||
![]() |
85ac1259af | ||
![]() |
4acfc713e9 | ||
![]() |
e9f46aec53 | ||
![]() |
909c0aed7a | ||
![]() |
c9879c1d28 | ||
![]() |
38e472a631 | ||
![]() |
bedc3d02d7 | ||
![]() |
be1a9cc8da | ||
![]() |
055c642136 | ||
![]() |
61521b5bf3 | ||
![]() |
ccf1b23d67 | ||
![]() |
14f76b6146 | ||
![]() |
6780bb4a30 | ||
![]() |
feb84f001c | ||
![]() |
8c061ea644 | ||
![]() |
ea5515b614 | ||
![]() |
b1a6e1b481 | ||
![]() |
f2f11496a2 | ||
![]() |
75c325d15a | ||
![]() |
adcfe629f2 |
@ -102,8 +102,8 @@
|
|||||||
"java.eclipse.downloadSources": true,
|
"java.eclipse.downloadSources": true,
|
||||||
"java.import.gradle.wrapper.enabled": true,
|
"java.import.gradle.wrapper.enabled": true,
|
||||||
"spring.initializr.defaultLanguage": "Java",
|
"spring.initializr.defaultLanguage": "Java",
|
||||||
"spring.initializr.defaultGroupId": "stirling.software.spdf",
|
"spring.initializr.defaultGroupId": "stirling.software.SPDF",
|
||||||
"spring.initializr.defaultArtifactId": "spdf"
|
"spring.initializr.defaultArtifactId": "SPDF"
|
||||||
},
|
},
|
||||||
"extensions": [
|
"extensions": [
|
||||||
"elagil.pre-commit-helper", // Support for pre-commit hooks to enforce code quality
|
"elagil.pre-commit-helper", // Support for pre-commit hooks to enforce code quality
|
||||||
|
33
.github/actions/setup-bot/action.yml
vendored
Normal file
33
.github/actions/setup-bot/action.yml
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
name: 'Setup GitHub App Bot'
|
||||||
|
description: 'Generates a GitHub App Token and configures Git for a bot'
|
||||||
|
inputs:
|
||||||
|
app-id:
|
||||||
|
description: 'GitHub App ID'
|
||||||
|
required: True
|
||||||
|
private-key:
|
||||||
|
description: 'GitHub App Private Key'
|
||||||
|
required: True
|
||||||
|
outputs:
|
||||||
|
token:
|
||||||
|
description: 'Generated GitHub App Token'
|
||||||
|
value: ${{ steps.generate-token.outputs.token }}
|
||||||
|
committer:
|
||||||
|
description: 'Committer string for Git'
|
||||||
|
value: "${{ steps.generate-token.outputs.app-slug }}[bot] <${{ steps.generate-token.outputs.app-slug }}[bot]@users.noreply.github.com>"
|
||||||
|
app-slug:
|
||||||
|
description: 'GitHub App slug'
|
||||||
|
value: ${{ steps.generate-token.outputs.app-slug }}
|
||||||
|
runs:
|
||||||
|
using: 'composite'
|
||||||
|
steps:
|
||||||
|
- name: Generate a GitHub App Token
|
||||||
|
id: generate-token
|
||||||
|
uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
|
||||||
|
with:
|
||||||
|
app-id: ${{ inputs.app-id }}
|
||||||
|
private-key: ${{ inputs.private-key }}
|
||||||
|
- name: Configure Git
|
||||||
|
run: |
|
||||||
|
git config --global user.name "${{ steps.generate-token.outputs.app-slug }}[bot]"
|
||||||
|
git config --global user.email "${{ steps.generate-token.outputs.app-slug }}[bot]@users.noreply.github.com"
|
||||||
|
shell: bash
|
16
.github/labeler-config.yml
vendored
16
.github/labeler-config.yml
vendored
@ -8,8 +8,8 @@ Front End:
|
|||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/templates/**/*'
|
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/templates/**/*'
|
||||||
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/static/**/*'
|
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/static/**/*'
|
||||||
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/spdf/controller/web/**'
|
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/**'
|
||||||
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/spdf/UI/**/*'
|
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/SPDF/UI/**/*'
|
||||||
|
|
||||||
Java:
|
Java:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
@ -19,8 +19,8 @@ Java:
|
|||||||
|
|
||||||
Back End:
|
Back End:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/spdf/config/**/*'
|
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/SPDF/config/**/*'
|
||||||
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/spdf/controller/**/*'
|
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/SPDF/controller/**/*'
|
||||||
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/settings.yml.template'
|
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/settings.yml.template'
|
||||||
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/application.properties'
|
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/application.properties'
|
||||||
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/banner.txt'
|
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/banner.txt'
|
||||||
@ -36,10 +36,10 @@ Security:
|
|||||||
|
|
||||||
API:
|
API:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/spdf/config/OpenApiConfig.java'
|
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/SPDF/config/OpenApiConfig.java'
|
||||||
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/spdf/controller/web/MetricsController.java'
|
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/SPDF/controller/web/MetricsController.java'
|
||||||
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/spdf/controller/api/**/*'
|
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/SPDF/controller/api/**/*'
|
||||||
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/spdf/model/api/**/*'
|
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/SPDF/model/api/**/*'
|
||||||
- any-glob-to-any-file: 'scripts/png_to_webp.py'
|
- any-glob-to-any-file: 'scripts/png_to_webp.py'
|
||||||
- any-glob-to-any-file: 'split_photos.py'
|
- any-glob-to-any-file: 'split_photos.py'
|
||||||
- any-glob-to-any-file: '.github/workflows/swagger.yml'
|
- any-glob-to-any-file: '.github/workflows/swagger.yml'
|
||||||
|
12
.github/workflows/PR-Demo-Comment-with-react.yml
vendored
12
.github/workflows/PR-Demo-Comment-with-react.yml
vendored
@ -156,9 +156,9 @@ 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.enable_security }}" == "true" ]; then
|
||||||
export WITHOUT_ENHANCED_FEATURES=false
|
export ADDITIONAL_FEATURES_OFF=false
|
||||||
else
|
else
|
||||||
export WITHOUT_ENHANCED_FEATURES=true
|
export ADDITIONAL_FEATURES_OFF=true
|
||||||
fi
|
fi
|
||||||
./gradlew clean build
|
./gradlew clean build
|
||||||
env:
|
env:
|
||||||
@ -180,7 +180,7 @@ jobs:
|
|||||||
password: ${{ secrets.DOCKER_HUB_API }}
|
password: ${{ secrets.DOCKER_HUB_API }}
|
||||||
|
|
||||||
- name: Build and push PR-specific image
|
- name: Build and push PR-specific image
|
||||||
uses: docker/build-push-action@1dc73863535b631f98b2378be8619f83b136f4a0 # v6.17.0
|
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./Dockerfile
|
file: ./Dockerfile
|
||||||
@ -200,11 +200,11 @@ jobs:
|
|||||||
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.enable_security }}" == "true" ]; then
|
||||||
WITHOUT_ENHANCED_FEATURES="false"
|
DOCKER_SECURITY="true"
|
||||||
LOGIN_SECURITY="true"
|
LOGIN_SECURITY="true"
|
||||||
SECURITY_STATUS="🔒 Security Enabled"
|
SECURITY_STATUS="🔒 Security Enabled"
|
||||||
else
|
else
|
||||||
WITHOUT_ENHANCED_FEATURES="true"
|
DOCKER_SECURITY="false"
|
||||||
LOGIN_SECURITY="false"
|
LOGIN_SECURITY="false"
|
||||||
SECURITY_STATUS="Security Disabled"
|
SECURITY_STATUS="Security Disabled"
|
||||||
fi
|
fi
|
||||||
@ -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:
|
||||||
WITHOUT_ENHANCED_FEATURES: "${WITHOUT_ENHANCED_FEATURES}"
|
ADDITIONAL_FEATURES_OFF: "${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 }}"
|
||||||
|
7
.github/workflows/build.yml
vendored
7
.github/workflows/build.yml
vendored
@ -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:
|
||||||
WITHOUT_ENHANCED_FEATURES: true
|
ADDITIONAL_FEATURES_OFF: 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:
|
||||||
WITHOUT_ENHANCED_FEATURES: false
|
ADDITIONAL_FEATURES_OFF: false
|
||||||
|
|
||||||
- name: Upload Test Reports
|
- name: Upload Test Reports
|
||||||
if: always()
|
if: always()
|
||||||
@ -56,6 +56,9 @@ jobs:
|
|||||||
build/reports/tests/
|
build/reports/tests/
|
||||||
build/test-results/
|
build/test-results/
|
||||||
build/reports/problems/
|
build/reports/problems/
|
||||||
|
/common/build/reports/tests/
|
||||||
|
/common/build/test-results/
|
||||||
|
/common/build/reports/problems/
|
||||||
retention-days: 3
|
retention-days: 3
|
||||||
|
|
||||||
check-licence:
|
check-licence:
|
||||||
|
17
.github/workflows/check_properties.yml
vendored
17
.github/workflows/check_properties.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
issues: write # Allow posting comments on issues/PRs
|
issues: write # Allow posting comments on issues/PRs
|
||||||
pull-requests: write
|
pull-requests: write # Allow writing to pull requests
|
||||||
steps:
|
steps:
|
||||||
- name: Harden Runner
|
- name: Harden Runner
|
||||||
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
|
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
|
||||||
@ -25,15 +25,18 @@ jobs:
|
|||||||
- name: Checkout main branch first
|
- name: Checkout main branch first
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Setup GitHub App Bot
|
||||||
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
id: setup-bot
|
||||||
|
uses: ./.github/actions/setup-bot
|
||||||
with:
|
with:
|
||||||
python-version: "3.12"
|
app-id: ${{ secrets.GH_APP_ID }}
|
||||||
|
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
- name: Get PR data
|
- name: Get PR data
|
||||||
id: get-pr-data
|
id: get-pr-data
|
||||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||||
with:
|
with:
|
||||||
|
github-token: ${{ steps.setup-bot.outputs.token }}
|
||||||
script: |
|
script: |
|
||||||
const prNumber = context.payload.pull_request.number;
|
const prNumber = context.payload.pull_request.number;
|
||||||
const repoOwner = context.payload.repository.owner.login;
|
const repoOwner = context.payload.repository.owner.login;
|
||||||
@ -54,7 +57,7 @@ jobs:
|
|||||||
- name: Fetch PR changed files
|
- name: Fetch PR changed files
|
||||||
id: fetch-pr-changes
|
id: fetch-pr-changes
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ steps.setup-bot.outputs.token }}
|
||||||
run: |
|
run: |
|
||||||
echo "Fetching PR changed files..."
|
echo "Fetching PR changed files..."
|
||||||
echo "Getting list of changed files from PR..."
|
echo "Getting list of changed files from PR..."
|
||||||
@ -64,6 +67,7 @@ jobs:
|
|||||||
id: determine-file
|
id: determine-file
|
||||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||||
with:
|
with:
|
||||||
|
github-token: ${{ steps.setup-bot.outputs.token }}
|
||||||
script: |
|
script: |
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
@ -204,6 +208,7 @@ jobs:
|
|||||||
if: env.SCRIPT_OUTPUT != ''
|
if: env.SCRIPT_OUTPUT != ''
|
||||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||||
with:
|
with:
|
||||||
|
github-token: ${{ steps.setup-bot.outputs.token }}
|
||||||
script: |
|
script: |
|
||||||
const { GITHUB_REPOSITORY, SCRIPT_OUTPUT } = process.env;
|
const { GITHUB_REPOSITORY, SCRIPT_OUTPUT } = process.env;
|
||||||
const [repoOwner, repoName] = GITHUB_REPOSITORY.split('/');
|
const [repoOwner, repoName] = GITHUB_REPOSITORY.split('/');
|
||||||
@ -219,7 +224,7 @@ jobs:
|
|||||||
const comment = comments.data.find(c => c.body.includes("## 🚀 Translation Verification Summary"));
|
const comment = comments.data.find(c => c.body.includes("## 🚀 Translation Verification Summary"));
|
||||||
|
|
||||||
// Only update or create comments by the action user
|
// Only update or create comments by the action user
|
||||||
const expectedActor = "github-actions[bot]";
|
const expectedActor = "${{ steps.setup-bot.outputs.app-slug }}[bot]";
|
||||||
|
|
||||||
if (comment && comment.user.login === expectedActor) {
|
if (comment && comment.user.login === expectedActor) {
|
||||||
// Update existing comment
|
// Update existing comment
|
||||||
|
44
.github/workflows/licenses-update.yml
vendored
44
.github/workflows/licenses-update.yml
vendored
@ -16,52 +16,50 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
|
repository-projects: write # Required for enabling automerge
|
||||||
steps:
|
steps:
|
||||||
- name: Harden Runner
|
- name: Harden Runner
|
||||||
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
|
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
|
||||||
with:
|
with:
|
||||||
egress-policy: audit
|
egress-policy: audit
|
||||||
|
|
||||||
- name: Generate GitHub App Token
|
- name: Check out code
|
||||||
id: generate-token
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Setup GitHub App Bot
|
||||||
|
id: setup-bot
|
||||||
|
uses: ./.github/actions/setup-bot
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.GH_APP_ID }}
|
app-id: ${{ secrets.GH_APP_ID }}
|
||||||
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
|
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
- name: Check out code
|
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
||||||
|
|
||||||
- name: Set up JDK 17
|
- name: Set up JDK 17
|
||||||
uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
|
uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
|
||||||
with:
|
with:
|
||||||
java-version: "17"
|
java-version: "17"
|
||||||
distribution: "adopt"
|
distribution: "adopt"
|
||||||
|
|
||||||
- uses: gradle/actions/setup-gradle@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4.4.0
|
- name: Setup Gradle
|
||||||
|
uses: gradle/actions/setup-gradle@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4.4.0
|
||||||
|
|
||||||
- name: check the licenses for compatibility
|
- name: Check licenses for compatibility
|
||||||
run: ./gradlew clean checkLicense
|
run: ./gradlew clean checkLicense
|
||||||
|
|
||||||
- name: FAILED - check the licenses for compatibility
|
- name: Upload artifact on failure
|
||||||
if: failure()
|
if: failure()
|
||||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
with:
|
with:
|
||||||
name: dependencies-without-allowed-license.json
|
name: dependencies-without-allowed-license.json
|
||||||
path: |
|
path: build/reports/dependency-license/dependencies-without-allowed-license.json
|
||||||
build/reports/dependency-license/dependencies-without-allowed-license.json
|
|
||||||
retention-days: 3
|
retention-days: 3
|
||||||
|
|
||||||
- name: Move and Rename License File
|
- name: Move and rename license file
|
||||||
run: |
|
run: |
|
||||||
mv build/reports/dependency-license/index.json stirling-pdf/src/main/resources/static/3rdPartyLicenses.json
|
mv build/reports/dependency-license/index.json stirling-pdf/src/main/resources/static/3rdPartyLicenses.json
|
||||||
|
|
||||||
- name: Set up git config
|
- name: Commit changes
|
||||||
run: |
|
|
||||||
git config --global user.name "stirlingbot[bot]"
|
|
||||||
git config --global user.email "1113334+stirlingbot[bot]@users.noreply.github.com"
|
|
||||||
|
|
||||||
- name: Run git add
|
|
||||||
run: |
|
run: |
|
||||||
git add stirling-pdf/src/main/resources/static/3rdPartyLicenses.json
|
git add stirling-pdf/src/main/resources/static/3rdPartyLicenses.json
|
||||||
git diff --staged --quiet || echo "CHANGES_DETECTED=true" >> $GITHUB_ENV
|
git diff --staged --quiet || echo "CHANGES_DETECTED=true" >> $GITHUB_ENV
|
||||||
@ -71,15 +69,15 @@ jobs:
|
|||||||
if: env.CHANGES_DETECTED == 'true'
|
if: env.CHANGES_DETECTED == 'true'
|
||||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
|
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
|
||||||
with:
|
with:
|
||||||
token: ${{ steps.generate-token.outputs.token }}
|
token: ${{ steps.setup-bot.outputs.token }}
|
||||||
commit-message: "Update 3rd Party Licenses"
|
commit-message: "Update 3rd Party Licenses"
|
||||||
committer: "stirlingbot[bot] <1113334+stirlingbot[bot]@users.noreply.github.com>"
|
committer: ${{ steps.setup-bot.outputs.committer }}
|
||||||
author: "stirlingbot[bot] <1113334+stirlingbot[bot]@users.noreply.github.com>"
|
author: ${{ steps.setup-bot.outputs.committer }}
|
||||||
signoff: true
|
signoff: true
|
||||||
branch: update-3rd-party-licenses
|
branch: update-3rd-party-licenses
|
||||||
title: "Update 3rd Party Licenses"
|
title: "Update 3rd Party Licenses"
|
||||||
body: |
|
body: |
|
||||||
Auto-generated by StirlingBot
|
Auto-generated by ${{ steps.setup-bot.outputs.app-slug }}[bot]
|
||||||
labels: licenses,github-actions
|
labels: licenses,github-actions
|
||||||
draft: false
|
draft: false
|
||||||
delete-branch: true
|
delete-branch: true
|
||||||
@ -89,4 +87,4 @@ jobs:
|
|||||||
if: steps.cpr.outputs.pull-request-operation == 'created'
|
if: steps.cpr.outputs.pull-request-operation == 'created'
|
||||||
run: gh pr merge --squash --auto "${{ steps.cpr.outputs.pull-request-number }}"
|
run: gh pr merge --squash --auto "${{ steps.cpr.outputs.pull-request-number }}"
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
|
GH_TOKEN: ${{ steps.setup-bot.outputs.token }}
|
||||||
|
14
.github/workflows/multiOSReleases.yml
vendored
14
.github/workflows/multiOSReleases.yml
vendored
@ -50,10 +50,10 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
disable_security: [true, false]
|
disable_security: [true, false]
|
||||||
include:
|
include:
|
||||||
- disable_security: false
|
|
||||||
file_suffix: "-with-login"
|
|
||||||
- disable_security: true
|
- disable_security: true
|
||||||
file_suffix: ""
|
file_suffix: ""
|
||||||
|
- disable_security: false
|
||||||
|
file_suffix: "-with-login"
|
||||||
steps:
|
steps:
|
||||||
- name: Harden Runner
|
- name: Harden Runner
|
||||||
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
|
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
|
||||||
@ -72,10 +72,10 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
gradle-version: 8.14
|
gradle-version: 8.14
|
||||||
|
|
||||||
- name: Generate jar (With Security=${{ matrix.disable_security }})
|
- name: Generate jar (Without Security=${{ matrix.disable_security }})
|
||||||
run: ./gradlew clean createExe
|
run: ./gradlew clean createExe
|
||||||
env:
|
env:
|
||||||
WITHOUT_ENHANCED_FEATURES: ${{ matrix.disable_security }}
|
ADDITIONAL_FEATURES_OFF: ${{ matrix.disable_security }}
|
||||||
STIRLING_PDF_DESKTOP_UI: false
|
STIRLING_PDF_DESKTOP_UI: false
|
||||||
|
|
||||||
- name: Rename binaries
|
- name: Rename binaries
|
||||||
@ -100,10 +100,10 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
disable_security: [true, false]
|
disable_security: [true, false]
|
||||||
include:
|
include:
|
||||||
- disable_security: false
|
|
||||||
file_suffix: "with-login-"
|
|
||||||
- disable_security: true
|
- disable_security: true
|
||||||
file_suffix: ""
|
file_suffix: ""
|
||||||
|
- disable_security: false
|
||||||
|
file_suffix: "with-login-"
|
||||||
steps:
|
steps:
|
||||||
- name: Harden Runner
|
- name: Harden Runner
|
||||||
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
|
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
|
||||||
@ -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:
|
||||||
WITHOUT_ENHANCED_FEATURES: true
|
ADDITIONAL_FEATURES_OFF: true
|
||||||
STIRLING_PDF_DESKTOP_UI: true
|
STIRLING_PDF_DESKTOP_UI: true
|
||||||
BROWSER_OPEN: true
|
BROWSER_OPEN: true
|
||||||
|
|
||||||
|
43
.github/workflows/pre_commit.yml
vendored
43
.github/workflows/pre_commit.yml
vendored
@ -20,58 +20,49 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
egress-policy: audit
|
egress-policy: audit
|
||||||
|
|
||||||
- name: Generate GitHub App Token
|
|
||||||
id: generate-token
|
|
||||||
uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
|
|
||||||
with:
|
|
||||||
app-id: ${{ secrets.GH_APP_ID }}
|
|
||||||
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
|
|
||||||
|
|
||||||
- name: Get GitHub App User ID
|
|
||||||
id: get-user-id
|
|
||||||
run: echo "user-id=$(gh api "/users/${{ steps.generate-token.outputs.app-slug }}[bot]" --jq .id)" >> $GITHUB_OUTPUT
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
|
|
||||||
|
|
||||||
- id: committer
|
|
||||||
run: |
|
|
||||||
echo "string=${{ steps.generate-token.outputs.app-slug }}[bot] <${{ steps.get-user-id.outputs.user-id }}+${{ steps.generate-token.outputs.app-slug }}[bot]@users.noreply.github.com>" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Setup GitHub App Bot
|
||||||
|
id: setup-bot
|
||||||
|
uses: ./.github/actions/setup-bot
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.GH_APP_ID }}
|
||||||
|
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
||||||
with:
|
with:
|
||||||
python-version: 3.12
|
python-version: 3.12
|
||||||
cache: 'pip' # caching pip dependencies
|
cache: 'pip' # caching pip dependencies
|
||||||
|
|
||||||
- name: Run Pre-Commit Hooks
|
- name: Run Pre-Commit Hooks
|
||||||
run: |
|
run: |
|
||||||
pip install --require-hashes -r ./.github/scripts/requirements_pre_commit.txt
|
pip install --require-hashes -r ./.github/scripts/requirements_pre_commit.txt
|
||||||
|
|
||||||
- run: pre-commit run --all-files -c .pre-commit-config.yaml
|
- run: pre-commit run --all-files -c .pre-commit-config.yaml
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
- name: Set up git config
|
|
||||||
run: |
|
|
||||||
git config --global user.name ${{ steps.generate-token.outputs.app-slug }}[bot]
|
|
||||||
git config --global user.email "${{ steps.get-user-id.outputs.user-id }}+${{ steps.generate-token.outputs.app-slug }}[bot]@users.noreply.github.com"
|
|
||||||
- name: git add
|
- name: git add
|
||||||
run: |
|
run: |
|
||||||
git add .
|
git add .
|
||||||
git diff --staged --quiet || echo "CHANGES_DETECTED=true" >> $GITHUB_ENV
|
git diff --staged --quiet || echo "CHANGES_DETECTED=true" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Create Pull Request
|
- name: Create Pull Request
|
||||||
if: env.CHANGES_DETECTED == 'true'
|
if: env.CHANGES_DETECTED == 'true'
|
||||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
|
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
|
||||||
with:
|
with:
|
||||||
token: ${{ steps.generate-token.outputs.token }}
|
token: ${{ steps.setup-bot.outputs.token }}
|
||||||
commit-message: ":file_folder: pre-commit"
|
commit-message: ":file_folder: pre-commit"
|
||||||
committer: ${{ steps.committer.outputs.string }}
|
committer: ${{ steps.setup-bot.outputs.committer }}
|
||||||
author: ${{ steps.committer.outputs.string }}
|
author: ${{ steps.setup-bot.outputs.committer }}
|
||||||
signoff: true
|
signoff: true
|
||||||
branch: pre-commit
|
branch: pre-commit
|
||||||
title: "🤖 format everything with pre-commit by <${{ steps.generate-token.outputs.app-slug }}>"
|
title: "🤖 format everything with pre-commit by ${{ steps.setup-bot.outputs.app-slug }}"
|
||||||
body: |
|
body: |
|
||||||
Auto-generated by [create-pull-request][1] with **${{ steps.generate-token.outputs.app-slug }}**
|
Auto-generated by [create-pull-request][1] with **${{ steps.setup-bot.outputs.app-slug }}**
|
||||||
|
|
||||||
[1]: https://github.com/peter-evans/create-pull-request
|
[1]: https://github.com/peter-evans/create-pull-request
|
||||||
draft: false
|
draft: false
|
||||||
|
8
.github/workflows/push-docker.yml
vendored
8
.github/workflows/push-docker.yml
vendored
@ -37,7 +37,7 @@ jobs:
|
|||||||
- name: Run Gradle Command
|
- name: Run Gradle Command
|
||||||
run: ./gradlew clean build
|
run: ./gradlew clean build
|
||||||
env:
|
env:
|
||||||
WITHOUT_ENHANCED_FEATURES: true
|
ADDITIONAL_FEATURES_OFF: true
|
||||||
STIRLING_PDF_DESKTOP_UI: false
|
STIRLING_PDF_DESKTOP_UI: false
|
||||||
|
|
||||||
- name: Install cosign
|
- name: Install cosign
|
||||||
@ -90,7 +90,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Build and push main Dockerfile
|
- name: Build and push main Dockerfile
|
||||||
id: build-push-regular
|
id: build-push-regular
|
||||||
uses: docker/build-push-action@1dc73863535b631f98b2378be8619f83b136f4a0 # v6.17.0
|
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
|
||||||
with:
|
with:
|
||||||
builder: ${{ steps.buildx.outputs.name }}
|
builder: ${{ steps.buildx.outputs.name }}
|
||||||
context: .
|
context: .
|
||||||
@ -135,7 +135,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Build and push Dockerfile-ultra-lite
|
- name: Build and push Dockerfile-ultra-lite
|
||||||
id: build-push-lite
|
id: build-push-lite
|
||||||
uses: docker/build-push-action@1dc73863535b631f98b2378be8619f83b136f4a0 # v6.17.0
|
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
|
||||||
if: github.ref != 'refs/heads/main'
|
if: github.ref != 'refs/heads/main'
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
@ -166,7 +166,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Build and push main Dockerfile fat
|
- name: Build and push main Dockerfile fat
|
||||||
id: build-push-fat
|
id: build-push-fat
|
||||||
uses: docker/build-push-action@1dc73863535b631f98b2378be8619f83b136f4a0 # v6.17.0
|
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
|
||||||
if: github.ref != 'refs/heads/main'
|
if: github.ref != 'refs/heads/main'
|
||||||
with:
|
with:
|
||||||
builder: ${{ steps.buildx.outputs.name }}
|
builder: ${{ steps.buildx.outputs.name }}
|
||||||
|
23
.github/workflows/releaseArtifacts.yml
vendored
23
.github/workflows/releaseArtifacts.yml
vendored
@ -13,12 +13,17 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
|
enable_security: [true, false]
|
||||||
disable_security: [true, false]
|
disable_security: [true, false]
|
||||||
include:
|
include:
|
||||||
- disable_security: false
|
- enable_security: true
|
||||||
file_suffix: "-with-login"
|
file_suffix: "-with-login"
|
||||||
|
- enable_security: false
|
||||||
|
file_suffix: ""
|
||||||
- disable_security: true
|
- disable_security: true
|
||||||
file_suffix: ""
|
file_suffix: ""
|
||||||
|
- disable_security: false
|
||||||
|
file_suffix: "-with-login"
|
||||||
outputs:
|
outputs:
|
||||||
version: ${{ steps.versionNumber.outputs.versionNumber }}
|
version: ${{ steps.versionNumber.outputs.versionNumber }}
|
||||||
steps:
|
steps:
|
||||||
@ -39,10 +44,10 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
gradle-version: 8.14
|
gradle-version: 8.14
|
||||||
|
|
||||||
- name: Generate jar (With Security=${{ matrix.disable_security }})
|
- name: Generate jar (With Security=${{ matrix.enable_security }})
|
||||||
run: ./gradlew clean createExe
|
run: ./gradlew clean createExe
|
||||||
env:
|
env:
|
||||||
WITHOUT_ENHANCED_FEATURES: ${{ matrix.disable_security }}
|
ADDITIONAL_FEATURES_OFF: ${{ matrix.disable_security }}
|
||||||
STIRLING_PDF_DESKTOP_UI: false
|
STIRLING_PDF_DESKTOP_UI: false
|
||||||
|
|
||||||
- name: Get version number
|
- name: Get version number
|
||||||
@ -75,11 +80,11 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
disable_security: [true, false]
|
enable_security: [true, false]
|
||||||
include:
|
include:
|
||||||
- disable_security: false
|
- enable_security: true
|
||||||
file_suffix: "-with-login"
|
file_suffix: "-with-login"
|
||||||
- disable_security: true
|
- enable_security: false
|
||||||
file_suffix: ""
|
file_suffix: ""
|
||||||
steps:
|
steps:
|
||||||
- name: Harden Runner
|
- name: Harden Runner
|
||||||
@ -153,11 +158,11 @@ jobs:
|
|||||||
contents: write
|
contents: write
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
disable_security: [true, false]
|
enable_security: [true, false]
|
||||||
include:
|
include:
|
||||||
- disable_security: false
|
- enable_security: true
|
||||||
file_suffix: "-with-login"
|
file_suffix: "-with-login"
|
||||||
- disable_security: true
|
- enable_security: false
|
||||||
file_suffix: ""
|
file_suffix: ""
|
||||||
steps:
|
steps:
|
||||||
- name: Harden Runner
|
- name: Harden Runner
|
||||||
|
2
.github/workflows/scorecards.yml
vendored
2
.github/workflows/scorecards.yml
vendored
@ -44,7 +44,7 @@ jobs:
|
|||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: "Run analysis"
|
- name: "Run analysis"
|
||||||
uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1
|
uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2
|
||||||
with:
|
with:
|
||||||
results_file: results.sarif
|
results_file: results.sarif
|
||||||
results_format: sarif
|
results_format: sarif
|
||||||
|
2
.github/workflows/sonarqube.yml
vendored
2
.github/workflows/sonarqube.yml
vendored
@ -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 }}
|
||||||
WITHOUT_ENHANCED_FEATURES: false
|
ADDITIONAL_FEATURES_OFF: false
|
||||||
STIRLING_PDF_DESKTOP_UI: true
|
STIRLING_PDF_DESKTOP_UI: true
|
||||||
run: |
|
run: |
|
||||||
./gradlew clean build sonar \
|
./gradlew clean build sonar \
|
||||||
|
69
.github/workflows/sync_files.yml
vendored
69
.github/workflows/sync_files.yml
vendored
@ -16,79 +16,37 @@ permissions:
|
|||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
read_bot_entries:
|
sync-files:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
|
||||||
userName: ${{ steps.get-user-id.outputs.user_name }}
|
|
||||||
userEmail: ${{ steps.get-user-id.outputs.user_email }}
|
|
||||||
committer: ${{ steps.committer.outputs.committer }}
|
|
||||||
steps:
|
steps:
|
||||||
- name: Harden Runner
|
- name: Harden Runner
|
||||||
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
|
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
|
||||||
with:
|
with:
|
||||||
egress-policy: audit
|
egress-policy: audit
|
||||||
|
|
||||||
- name: Generate GitHub App Token
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
id: generate-token
|
|
||||||
uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
|
- name: Setup GitHub App Bot
|
||||||
|
id: setup-bot
|
||||||
|
uses: ./.github/actions/setup-bot
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.GH_APP_ID }}
|
app-id: ${{ secrets.GH_APP_ID }}
|
||||||
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
|
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
- name: Get GitHub App User ID
|
|
||||||
id: get-user-id
|
|
||||||
run: |
|
|
||||||
USER_NAME="${{ steps.generate-token.outputs.app-slug }}[bot]"
|
|
||||||
USER_ID=$(gh api "/users/$USER_NAME" --jq .id)
|
|
||||||
USER_EMAIL="$USER_ID+$USER_NAME@users.noreply.github.com"
|
|
||||||
echo "user_name=$USER_NAME" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "user_email=$USER_EMAIL" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "user-id=$USER_ID" >> "$GITHUB_OUTPUT"
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
|
|
||||||
|
|
||||||
- id: committer
|
|
||||||
run: |
|
|
||||||
COMMITTER="${{ steps.get-user-id.outputs.user_name }} <${{ steps.get-user-id.outputs.user_email }}>"
|
|
||||||
echo "committer=$COMMITTER" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
sync-files:
|
|
||||||
needs: ["read_bot_entries"]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Harden Runner
|
|
||||||
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
|
|
||||||
with:
|
|
||||||
egress-policy: audit
|
|
||||||
|
|
||||||
- name: Generate GitHub App Token
|
|
||||||
id: generate-token
|
|
||||||
uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
|
|
||||||
with:
|
|
||||||
app-id: ${{ vars.GH_APP_ID }}
|
|
||||||
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
|
|
||||||
|
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
||||||
with:
|
with:
|
||||||
python-version: "3.12"
|
python-version: "3.12"
|
||||||
cache: 'pip' # caching pip dependencies
|
cache: "pip" # caching pip dependencies
|
||||||
|
|
||||||
- name: Sync translation property files
|
- name: Sync translation property files
|
||||||
run: |
|
run: |
|
||||||
python .github/scripts/check_language_properties.py --reference-file "stirling-pdf/src/main/resources/messages_en_GB.properties" --branch main
|
python .github/scripts/check_language_properties.py --reference-file "stirling-pdf/src/main/resources/messages_en_GB.properties" --branch main
|
||||||
|
|
||||||
- name: Set up git config
|
- name: Commit translation files
|
||||||
run: |
|
|
||||||
git config --global user.name ${{ needs.read_bot_entries.outputs.userName }}
|
|
||||||
git config --global user.email ${{ needs.read_bot_entries.outputs.userEmail }}
|
|
||||||
|
|
||||||
- name: Run git add
|
|
||||||
run: |
|
run: |
|
||||||
git add stirling-pdf/src/main/resources/messages_*.properties
|
git add stirling-pdf/src/main/resources/messages_*.properties
|
||||||
git diff --staged --quiet || git commit -m ":memo: Sync translation files" || echo "no changes"
|
git diff --staged --quiet || git commit -m ":memo: Sync translation files" || echo "No changes detected"
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pip install --require-hashes -r ./.github/scripts/requirements_sync_readme.txt
|
run: pip install --require-hashes -r ./.github/scripts/requirements_sync_readme.txt
|
||||||
@ -100,15 +58,16 @@ jobs:
|
|||||||
- name: Run git add
|
- name: Run git add
|
||||||
run: |
|
run: |
|
||||||
git add README.md
|
git add README.md
|
||||||
git diff --staged --quiet || git commit -m ":memo: Sync README.md" || echo "no changes"
|
git diff --staged --quiet || git commit -m ":memo: Sync README.md" || echo "No changes detected"
|
||||||
|
|
||||||
- name: Create Pull Request
|
- name: Create Pull Request
|
||||||
|
if: always()
|
||||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
|
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
|
||||||
with:
|
with:
|
||||||
token: ${{ steps.generate-token.outputs.token }}
|
token: ${{ steps.setup-bot.outputs.token }}
|
||||||
commit-message: Update files
|
commit-message: Update files
|
||||||
committer: ${{ needs.read_bot_entries.outputs.committer }}
|
committer: ${{ steps.setup-bot.outputs.committer }}
|
||||||
author: ${{ needs.read_bot_entries.outputs.committer }}
|
author: ${{ steps.setup-bot.outputs.committer }}
|
||||||
signoff: true
|
signoff: true
|
||||||
branch: sync_readme
|
branch: sync_readme
|
||||||
title: ":globe_with_meridians: Sync Translations + Update README Progress Table"
|
title: ":globe_with_meridians: Sync Translations + Update README Progress Table"
|
||||||
|
6
.github/workflows/testdriver.yml
vendored
6
.github/workflows/testdriver.yml
vendored
@ -28,7 +28,7 @@ jobs:
|
|||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: ./gradlew clean build
|
run: ./gradlew clean build
|
||||||
env:
|
env:
|
||||||
WITHOUT_ENHANCED_FEATURES: false
|
ADDITIONAL_FEATURES_OFF: 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
|
||||||
@ -46,7 +46,7 @@ jobs:
|
|||||||
password: ${{ secrets.DOCKER_HUB_API }}
|
password: ${{ secrets.DOCKER_HUB_API }}
|
||||||
|
|
||||||
- name: Build and push test image
|
- name: Build and push test image
|
||||||
uses: docker/build-push-action@1dc73863535b631f98b2378be8619f83b136f4a0 # v6.17.0
|
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./Dockerfile
|
file: ./Dockerfile
|
||||||
@ -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:
|
||||||
WITHOUT_ENHANCED_FEATURES: "false"
|
ADDITIONAL_FEATURES_OFF: "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"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: v0.11.6
|
rev: v0.11.11
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff
|
- id: ruff
|
||||||
args:
|
args:
|
||||||
@ -22,7 +22,7 @@ repos:
|
|||||||
files: \.(html|css|js|py|md)$
|
files: \.(html|css|js|py|md)$
|
||||||
exclude: (.vscode|.devcontainer|stirling-pdf/src/main/resources|Dockerfile|.*/pdfjs.*|.*/thirdParty.*|bootstrap.*|.*\.min\..*|.*diff\.js)
|
exclude: (.vscode|.devcontainer|stirling-pdf/src/main/resources|Dockerfile|.*/pdfjs.*|.*/thirdParty.*|bootstrap.*|.*\.min\..*|.*diff\.js)
|
||||||
- repo: https://github.com/gitleaks/gitleaks
|
- repo: https://github.com/gitleaks/gitleaks
|
||||||
rev: v8.24.3
|
rev: v8.26.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: gitleaks
|
- id: gitleaks
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
12
.vscode/settings.json
vendored
12
.vscode/settings.json
vendored
@ -10,7 +10,7 @@
|
|||||||
"java.configuration.updateBuildConfiguration": "interactive",
|
"java.configuration.updateBuildConfiguration": "interactive",
|
||||||
"java.format.enabled": true,
|
"java.format.enabled": true,
|
||||||
"java.format.settings.profile": "GoogleStyle",
|
"java.format.settings.profile": "GoogleStyle",
|
||||||
"java.format.settings.google.version": "1.26.0",
|
"java.format.settings.google.version": "1.27.0",
|
||||||
"java.format.settings.google.extra": "--aosp --skip-sorting-imports --skip-javadoc-formatting",
|
"java.format.settings.google.extra": "--aosp --skip-sorting-imports --skip-javadoc-formatting",
|
||||||
// (DE) Aktiviert Kommentare im Java-Format.
|
// (DE) Aktiviert Kommentare im Java-Format.
|
||||||
// (EN) Enables comments in Java formatting.
|
// (EN) Enables comments in Java formatting.
|
||||||
@ -49,7 +49,11 @@
|
|||||||
".venv*/",
|
".venv*/",
|
||||||
".vscode/",
|
".vscode/",
|
||||||
"bin/",
|
"bin/",
|
||||||
|
"common/bin/",
|
||||||
|
"proprietary/bin/",
|
||||||
"build/",
|
"build/",
|
||||||
|
"common/build/",
|
||||||
|
"proprietary/build/",
|
||||||
"configs/",
|
"configs/",
|
||||||
"customFiles/",
|
"customFiles/",
|
||||||
"docs/",
|
"docs/",
|
||||||
@ -63,6 +67,8 @@
|
|||||||
".git-blame-ignore-revs",
|
".git-blame-ignore-revs",
|
||||||
".gitattributes",
|
".gitattributes",
|
||||||
".gitignore",
|
".gitignore",
|
||||||
|
"common/.gitignore",
|
||||||
|
"proprietary/.gitignore",
|
||||||
".pre-commit-config.yaml",
|
".pre-commit-config.yaml",
|
||||||
],
|
],
|
||||||
// Enables signature help in Java.
|
// Enables signature help in Java.
|
||||||
@ -78,6 +84,6 @@
|
|||||||
// Enables import of the Gradle wrapper.
|
// Enables import of the Gradle wrapper.
|
||||||
"java.import.gradle.wrapper.enabled": true,
|
"java.import.gradle.wrapper.enabled": true,
|
||||||
"spring.initializr.defaultLanguage": "Java",
|
"spring.initializr.defaultLanguage": "Java",
|
||||||
"spring.initializr.defaultGroupId": "stirling.software.spdf",
|
"spring.initializr.defaultGroupId": "stirling.software.SPDF",
|
||||||
"spring.initializr.defaultArtifactId": "spdf",
|
"spring.initializr.defaultArtifactId": "SPDF",
|
||||||
}
|
}
|
||||||
|
@ -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. Security is enabled by default. To disable it, you must add the environment flag WITHOUT_ENHANCED_FEATURES=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 ADDITIONAL_FEATURES_OFF=false to your system and/or IDE build/run step.
|
||||||
|
|
||||||
## 4. Project Structure
|
## 4. Project Structure
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ Stirling-PDF/
|
|||||||
│ │ ├── java/
|
│ │ ├── java/
|
||||||
│ │ │ └── stirling/
|
│ │ │ └── stirling/
|
||||||
│ │ │ └── software/
|
│ │ │ └── software/
|
||||||
│ │ │ └── spdf/
|
│ │ │ └── SPDF/
|
||||||
│ │ │ ├── config/
|
│ │ │ ├── config/
|
||||||
│ │ │ ├── controller/
|
│ │ │ ├── controller/
|
||||||
│ │ │ ├── model/
|
│ │ │ ├── model/
|
||||||
@ -93,7 +93,7 @@ Stirling-PDF/
|
|||||||
│ └── java/
|
│ └── java/
|
||||||
│ └── stirling/
|
│ └── stirling/
|
||||||
│ └── software/
|
│ └── software/
|
||||||
│ └── spdf/
|
│ └── SPDF/
|
||||||
├── build.gradle # Gradle build configuration
|
├── build.gradle # Gradle build configuration
|
||||||
├── Dockerfile # Main Dockerfile
|
├── Dockerfile # Main Dockerfile
|
||||||
├── Dockerfile.ultra-lite # Dockerfile for ultra-lite version
|
├── Dockerfile.ultra-lite # Dockerfile for ultra-lite version
|
||||||
@ -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:
|
||||||
WITHOUT_ENHANCED_FEATURES: "true"
|
ADDITIONAL_FEATURES_OFF: "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 WITHOUT_ENHANCED_FEATURES=false # or true for security-enabled builds
|
export ADDITIONAL_FEATURES_OFF=true # or false for security-enabled builds
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Build the project with Gradle:
|
2. Build the project with Gradle:
|
||||||
@ -196,7 +196,7 @@ Stirling-PDF uses different Docker images for various configurations. The build
|
|||||||
For the fat version (with security enabled):
|
For the fat version (with security enabled):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export WITHOUT_ENHANCED_FEATURES=true
|
export ADDITIONAL_FEATURES_OFF=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 .
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -384,12 +384,12 @@ This would generate n entries of tr for each person in exampleData
|
|||||||
### Adding a New Feature to the Backend (API)
|
### Adding a New Feature to the Backend (API)
|
||||||
|
|
||||||
1. **Create a New Controller:**
|
1. **Create a New Controller:**
|
||||||
- Create a new Java class in the `stirling-pdf/src/main/java/stirling/software/spdf/controller/api` directory.
|
- Create a new Java class in the `stirling-pdf/src/main/java/stirling/software/SPDF/controller/api` directory.
|
||||||
- Annotate the class with `@RestController` and `@RequestMapping` to define the API endpoint.
|
- Annotate the class with `@RestController` and `@RequestMapping` to define the API endpoint.
|
||||||
- Ensure to add API documentation annotations like `@Tag(name = "General", description = "General APIs")` and `@Operation(summary = "Crops a PDF document", description = "This operation takes an input PDF file and crops it according to the given coordinates. Input:PDF Output:PDF Type:SISO")`.
|
- Ensure to add API documentation annotations like `@Tag(name = "General", description = "General APIs")` and `@Operation(summary = "Crops a PDF document", description = "This operation takes an input PDF file and crops it according to the given coordinates. Input:PDF Output:PDF Type:SISO")`.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
package stirling.software.spdf.controller.api;
|
package stirling.software.SPDF.controller.api;
|
||||||
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
@ -411,11 +411,11 @@ This would generate n entries of tr for each person in exampleData
|
|||||||
```
|
```
|
||||||
|
|
||||||
2. **Define the Service Layer:** (Not required but often useful)
|
2. **Define the Service Layer:** (Not required but often useful)
|
||||||
- Create a new service class in the `stirling-pdf/src/main/java/stirling/software/spdf/service` directory.
|
- Create a new service class in the `stirling-pdf/src/main/java/stirling/software/SPDF/service` directory.
|
||||||
- Implement the business logic for the new feature.
|
- Implement the business logic for the new feature.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
package stirling.software.spdf.service;
|
package stirling.software.SPDF.service;
|
||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@ -434,13 +434,13 @@ This would generate n entries of tr for each person in exampleData
|
|||||||
- Autowire the service class in the controller and use it to handle the API request.
|
- Autowire the service class in the controller and use it to handle the API request.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
package stirling.software.spdf.controller.api;
|
package stirling.software.SPDF.controller.api;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import stirling.software.spdf.service.NewFeatureService;
|
import stirling.software.SPDF.service.NewFeatureService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
@ -507,18 +507,18 @@ This would generate n entries of tr for each person in exampleData
|
|||||||
```
|
```
|
||||||
|
|
||||||
2. **Create a New Controller for the UI:**
|
2. **Create a New Controller for the UI:**
|
||||||
- Create a new Java class in the `stirling-pdf/src/main/java/stirling/software/spdf/controller/ui` directory.
|
- Create a new Java class in the `stirling-pdf/src/main/java/stirling/software/SPDF/controller/ui` directory.
|
||||||
- Annotate the class with `@Controller` and `@RequestMapping` to define the UI endpoint.
|
- Annotate the class with `@Controller` and `@RequestMapping` to define the UI endpoint.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
package stirling.software.spdf.controller.ui;
|
package stirling.software.SPDF.controller.ui;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import stirling.software.spdf.service.NewFeatureService;
|
import stirling.software.SPDF.service.NewFeatureService;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
@RequestMapping("/new-feature")
|
@RequestMapping("/new-feature")
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Main stage
|
# Main stage
|
||||||
FROM alpine:3.21.3@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c
|
FROM alpine:3.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be023728e11715
|
||||||
|
|
||||||
# Copy necessary files
|
# Copy necessary files
|
||||||
COPY scripts /scripts
|
COPY scripts /scripts
|
||||||
@ -23,8 +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
|
||||||
# todo: keep security off?
|
ENV ADDITIONAL_FEATURES_OFF=true \
|
||||||
ENV WITHOUT_ENHANCED_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="" \
|
||||||
@ -74,7 +73,7 @@ RUN echo "@main https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/a
|
|||||||
py3-pillow@testing \
|
py3-pillow@testing \
|
||||||
py3-pdf2image@testing && \
|
py3-pdf2image@testing && \
|
||||||
python3 -m venv /opt/venv && \
|
python3 -m venv /opt/venv && \
|
||||||
/opt/venv/bin/pip install --upgrade pip && \
|
/opt/venv/bin/pip install --upgrade pip setuptools && \
|
||||||
/opt/venv/bin/pip install --no-cache-dir --upgrade unoserver weasyprint && \
|
/opt/venv/bin/pip install --no-cache-dir --upgrade unoserver weasyprint && \
|
||||||
ln -s /usr/lib/libreoffice/program/uno.py /opt/venv/lib/python3.12/site-packages/ && \
|
ln -s /usr/lib/libreoffice/program/uno.py /opt/venv/lib/python3.12/site-packages/ && \
|
||||||
ln -s /usr/lib/libreoffice/program/unohelper.py /opt/venv/lib/python3.12/site-packages/ && \
|
ln -s /usr/lib/libreoffice/program/unohelper.py /opt/venv/lib/python3.12/site-packages/ && \
|
||||||
|
@ -32,6 +32,7 @@ ENV SETUPTOOLS_USE_DISTUTILS=local
|
|||||||
# Installation der benötigten Python-Pakete
|
# Installation der benötigten Python-Pakete
|
||||||
RUN python3 -m venv --system-site-packages /opt/venv \
|
RUN python3 -m venv --system-site-packages /opt/venv \
|
||||||
&& . /opt/venv/bin/activate \
|
&& . /opt/venv/bin/activate \
|
||||||
|
&& pip install --upgrade pip setuptools \
|
||||||
&& pip install --no-cache-dir WeasyPrint pdf2image pillow unoserver opencv-python-headless pre-commit
|
&& pip install --no-cache-dir WeasyPrint pdf2image pillow unoserver opencv-python-headless pre-commit
|
||||||
|
|
||||||
# Füge den venv-Pfad zur globalen PATH-Variable hinzu, damit die Tools verfügbar sind
|
# Füge den venv-Pfad zur globalen PATH-Variable hinzu, damit die Tools verfügbar sind
|
||||||
|
@ -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,13 +15,13 @@ WORKDIR /app
|
|||||||
# Copy the entire project to the working directory
|
# Copy the entire project to the working directory
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Build the application with WITHOUT_ENHANCED_FEATURES=false
|
# Build the application with ADDITIONAL_FEATURES_OFF=false
|
||||||
RUN WITHOUT_ENHANCED_FEATURES=false \
|
RUN ADDITIONAL_FEATURES_OFF=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
|
||||||
|
|
||||||
# Main stage
|
# Main stage
|
||||||
FROM alpine:3.21.3@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c
|
FROM alpine:3.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be023728e11715
|
||||||
|
|
||||||
# Copy necessary files
|
# Copy necessary files
|
||||||
COPY scripts /scripts
|
COPY scripts /scripts
|
||||||
@ -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 WITHOUT_ENHANCED_FEATURES=false \
|
ENV ADDITIONAL_FEATURES_OFF=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="" \
|
||||||
@ -83,7 +85,7 @@ RUN echo "@main https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/a
|
|||||||
py3-pillow@testing \
|
py3-pillow@testing \
|
||||||
py3-pdf2image@testing && \
|
py3-pdf2image@testing && \
|
||||||
python3 -m venv /opt/venv && \
|
python3 -m venv /opt/venv && \
|
||||||
/opt/venv/bin/pip install --upgrade pip && \
|
/opt/venv/bin/pip install --upgrade pip setuptools && \
|
||||||
/opt/venv/bin/pip install --no-cache-dir --upgrade unoserver weasyprint && \
|
/opt/venv/bin/pip install --no-cache-dir --upgrade unoserver weasyprint && \
|
||||||
ln -s /usr/lib/libreoffice/program/uno.py /opt/venv/lib/python3.12/site-packages/ && \
|
ln -s /usr/lib/libreoffice/program/uno.py /opt/venv/lib/python3.12/site-packages/ && \
|
||||||
ln -s /usr/lib/libreoffice/program/unohelper.py /opt/venv/lib/python3.12/site-packages/ && \
|
ln -s /usr/lib/libreoffice/program/unohelper.py /opt/venv/lib/python3.12/site-packages/ && \
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
# use alpine
|
# use alpine
|
||||||
FROM alpine:3.21.3@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c
|
FROM alpine:3.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be023728e11715
|
||||||
|
|
||||||
ARG VERSION_TAG
|
ARG VERSION_TAG
|
||||||
|
|
||||||
# Set Environment Variables
|
# Set Environment Variables
|
||||||
ENV WITHOUT_ENHANCED_FEATURES=true \
|
ENV ADDITIONAL_FEATURES_OFF=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" \
|
||||||
|
22
LICENSE
22
LICENSE
@ -1,11 +1,27 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2024 Stirling Tools
|
Copyright (c) 2025 Stirling PDF Inc.
|
||||||
|
|
||||||
Portions of this software are licensed as follows:
|
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".
|
* All content that resides under the "proprietary/" directory of this repository,
|
||||||
* Content outside of the above mentioned directories or restrictions above is available under the MIT License as defined below.
|
if that directory exists, is licensed under the license defined in "proprietary/LICENSE-proprietary".
|
||||||
|
* Content outside of the above mentioned directories or restrictions above is
|
||||||
|
available under the MIT License as defined below.
|
||||||
|
|
||||||
|
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-proprietary".
|
||||||
|
* Content outside of the above mentioned directories or restrictions above is
|
||||||
|
available under the MIT License as defined below.
|
||||||
|
|
||||||
|
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-proprietary".
|
||||||
|
* 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
|
||||||
|
78
README.md
78
README.md
@ -116,47 +116,47 @@ Stirling-PDF currently supports 40 languages!
|
|||||||
|
|
||||||
| Language | Progress |
|
| Language | Progress |
|
||||||
| -------------------------------------------- | -------------------------------------- |
|
| -------------------------------------------- | -------------------------------------- |
|
||||||
| Arabic (العربية) (ar_AR) |  |
|
| Arabic (العربية) (ar_AR) |  |
|
||||||
| Azerbaijani (Azərbaycan Dili) (az_AZ) |  |
|
| Azerbaijani (Azərbaycan Dili) (az_AZ) |  |
|
||||||
| Basque (Euskara) (eu_ES) |  |
|
| Basque (Euskara) (eu_ES) |  |
|
||||||
| Bulgarian (Български) (bg_BG) |  |
|
| Bulgarian (Български) (bg_BG) |  |
|
||||||
| Catalan (Català) (ca_CA) |  |
|
| Catalan (Català) (ca_CA) |  |
|
||||||
| Croatian (Hrvatski) (hr_HR) |  |
|
| Croatian (Hrvatski) (hr_HR) |  |
|
||||||
| Czech (Česky) (cs_CZ) |  |
|
| Czech (Česky) (cs_CZ) |  |
|
||||||
| Danish (Dansk) (da_DK) |  |
|
| Danish (Dansk) (da_DK) |  |
|
||||||
| Dutch (Nederlands) (nl_NL) |  |
|
| Dutch (Nederlands) (nl_NL) |  |
|
||||||
| English (English) (en_GB) |  |
|
| English (English) (en_GB) |  |
|
||||||
| English (US) (en_US) |  |
|
| English (US) (en_US) |  |
|
||||||
| French (Français) (fr_FR) |  |
|
| French (Français) (fr_FR) |  |
|
||||||
| German (Deutsch) (de_DE) |  |
|
| German (Deutsch) (de_DE) |  |
|
||||||
| Greek (Ελληνικά) (el_GR) |  |
|
| Greek (Ελληνικά) (el_GR) |  |
|
||||||
| Hindi (हिंदी) (hi_IN) |  |
|
| Hindi (हिंदी) (hi_IN) |  |
|
||||||
| Hungarian (Magyar) (hu_HU) |  |
|
| Hungarian (Magyar) (hu_HU) |  |
|
||||||
| Indonesian (Bahasa Indonesia) (id_ID) |  |
|
| Indonesian (Bahasa Indonesia) (id_ID) |  |
|
||||||
| Irish (Gaeilge) (ga_IE) |  |
|
| Irish (Gaeilge) (ga_IE) |  |
|
||||||
| Italian (Italiano) (it_IT) |  |
|
| Italian (Italiano) (it_IT) |  |
|
||||||
| Japanese (日本語) (ja_JP) |  |
|
| Japanese (日本語) (ja_JP) |  |
|
||||||
| Korean (한국어) (ko_KR) |  |
|
| Korean (한국어) (ko_KR) |  |
|
||||||
| Norwegian (Norsk) (no_NB) |  |
|
| Norwegian (Norsk) (no_NB) |  |
|
||||||
| Persian (فارسی) (fa_IR) |  |
|
| Persian (فارسی) (fa_IR) |  |
|
||||||
| Polish (Polski) (pl_PL) |  |
|
| Polish (Polski) (pl_PL) |  |
|
||||||
| Portuguese (Português) (pt_PT) |  |
|
| Portuguese (Português) (pt_PT) |  |
|
||||||
| Portuguese Brazilian (Português) (pt_BR) |  |
|
| Portuguese Brazilian (Português) (pt_BR) |  |
|
||||||
| Romanian (Română) (ro_RO) |  |
|
| Romanian (Română) (ro_RO) |  |
|
||||||
| Russian (Русский) (ru_RU) |  |
|
| Russian (Русский) (ru_RU) |  |
|
||||||
| Serbian Latin alphabet (Srpski) (sr_LATN_RS) |  |
|
| Serbian Latin alphabet (Srpski) (sr_LATN_RS) |  |
|
||||||
| Simplified Chinese (简体中文) (zh_CN) |  |
|
| Simplified Chinese (简体中文) (zh_CN) |  |
|
||||||
| Slovakian (Slovensky) (sk_SK) |  |
|
| Slovakian (Slovensky) (sk_SK) |  |
|
||||||
| Slovenian (Slovenščina) (sl_SI) |  |
|
| Slovenian (Slovenščina) (sl_SI) |  |
|
||||||
| Spanish (Español) (es_ES) |  |
|
| Spanish (Español) (es_ES) |  |
|
||||||
| Swedish (Svenska) (sv_SE) |  |
|
| Swedish (Svenska) (sv_SE) |  |
|
||||||
| Thai (ไทย) (th_TH) |  |
|
| Thai (ไทย) (th_TH) |  |
|
||||||
| Tibetan (བོད་ཡིག་) (zh_BO) |  |
|
| Tibetan (བོད་ཡིག་) (bo_CN) |  |
|
||||||
| Traditional Chinese (繁體中文) (zh_TW) |  |
|
| Traditional Chinese (繁體中文) (zh_TW) |  |
|
||||||
| Turkish (Türkçe) (tr_TR) |  |
|
| Turkish (Türkçe) (tr_TR) |  |
|
||||||
| Ukrainian (Українська) (uk_UA) |  |
|
| Ukrainian (Українська) (uk_UA) |  |
|
||||||
| Vietnamese (Tiếng Việt) (vi_VN) |  |
|
| Vietnamese (Tiếng Việt) (vi_VN) |  |
|
||||||
| Malayalam (മലയാളം) (ml_ML) |  |
|
| Malayalam (മലയാളം) (ml_IN) |  |
|
||||||
|
|
||||||
## Stirling PDF Enterprise
|
## Stirling PDF Enterprise
|
||||||
|
|
||||||
|
73
build.gradle
73
build.gradle
@ -1,15 +1,15 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id "java"
|
id "java"
|
||||||
id 'jacoco'
|
id "jacoco"
|
||||||
id "org.springframework.boot" version "3.4.5"
|
id "org.springframework.boot" version "3.5.0"
|
||||||
id "io.spring.dependency-management" version "1.1.7"
|
id "io.spring.dependency-management" version "1.1.7"
|
||||||
id "org.springdoc.openapi-gradle-plugin" version "1.9.0"
|
id "org.springdoc.openapi-gradle-plugin" version "1.9.0"
|
||||||
id "io.swagger.swaggerhub" version "1.3.2"
|
id "io.swagger.swaggerhub" version "1.3.2"
|
||||||
id "edu.sc.seis.launch4j" version "3.0.6"
|
id "edu.sc.seis.launch4j" version "3.0.6"
|
||||||
id "com.diffplug.spotless" version "7.0.3"
|
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"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ import java.nio.file.Files
|
|||||||
import java.time.Year
|
import java.time.Year
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
springBootVersion = "3.4.5"
|
springBootVersion = "3.5.0"
|
||||||
pdfboxVersion = "3.0.5"
|
pdfboxVersion = "3.0.5"
|
||||||
imageioVersion = "3.12.0"
|
imageioVersion = "3.12.0"
|
||||||
lombokVersion = "1.18.38"
|
lombokVersion = "1.18.38"
|
||||||
@ -45,32 +45,32 @@ bootJar {
|
|||||||
sourceSets {
|
sourceSets {
|
||||||
main {
|
main {
|
||||||
java {
|
java {
|
||||||
if (System.getenv('WITHOUT_ENHANCED_FEATURES') == 'false'
|
if (System.getenv('DOCKER_ENABLE_SECURITY') == 'false' || System.getenv('ADDITIONAL_FEATURES_OFF') == 'true'
|
||||||
|| (project.hasProperty('WITHOUT_ENHANCED_FEATURES')
|
|| (project.hasProperty('ADDITIONAL_FEATURES_OFF')
|
||||||
&& System.getProperty('WITHOUT_ENHANCED_FEATURES') == 'false')) {
|
&& System.getProperty('ADDITIONAL_FEATURES_OFF') == 'true')) {
|
||||||
exclude 'stirling/software/proprietary/security/**'
|
exclude 'stirling/software/proprietary/security/**'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (System.getenv('STIRLING_PDF_DESKTOP_UI') != 'false'
|
if (System.getenv('STIRLING_PDF_DESKTOP_UI') != 'false'
|
||||||
|| (project.hasProperty('STIRLING_PDF_DESKTOP_UI')
|
|| (project.hasProperty('STIRLING_PDF_DESKTOP_UI')
|
||||||
&& project.getProperty('STIRLING_PDF_DESKTOP_UI') != 'false')) {
|
&& project.getProperty('STIRLING_PDF_DESKTOP_UI') != 'false')) {
|
||||||
exclude 'stirling/software/spdf/UI/impl/**'
|
exclude 'stirling/software/SPDF/UI/impl/**'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
java {
|
java {
|
||||||
if (System.getenv('WITHOUT_ENHANCED_FEATURES') == 'false'
|
if (System.getenv('DOCKER_ENABLE_SECURITY') == 'false' || System.getenv('ADDITIONAL_FEATURES_OFF') == 'true'
|
||||||
|| (project.hasProperty('WITHOUT_ENHANCED_FEATURES')
|
|| (project.hasProperty('ADDITIONAL_FEATURES_OFF')
|
||||||
&& System.getProperty('WITHOUT_ENHANCED_FEATURES') == 'false')) {
|
&& System.getProperty('ADDITIONAL_FEATURES_OFF') == 'true')) {
|
||||||
exclude 'stirling/software/proprietary/security/**'
|
exclude 'stirling/software/proprietary/security/**'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (System.getenv('STIRLING_PDF_DESKTOP_UI') != 'false'
|
if (System.getenv('STIRLING_PDF_DESKTOP_UI') != 'false'
|
||||||
|| (project.hasProperty('STIRLING_PDF_DESKTOP_UI')
|
|| (project.hasProperty('STIRLING_PDF_DESKTOP_UI')
|
||||||
&& project.getProperty('STIRLING_PDF_DESKTOP_UI') != 'false')) {
|
&& project.getProperty('STIRLING_PDF_DESKTOP_UI') != 'false')) {
|
||||||
exclude 'stirling/software/spdf/UI/impl/**'
|
exclude 'stirling/software/SPDF/UI/impl/**'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,10 +87,16 @@ allprojects {
|
|||||||
distributionType = Wrapper.DistributionType.ALL
|
distributionType = Wrapper.DistributionType.ALL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configurations.all {
|
||||||
|
exclude group: 'commons-logging', module: 'commons-logging'
|
||||||
|
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
apply plugin: 'java'
|
apply plugin: 'java'
|
||||||
|
apply plugin: 'java-library'
|
||||||
apply plugin: 'com.diffplug.spotless'
|
apply plugin: 'com.diffplug.spotless'
|
||||||
apply plugin: 'org.springframework.boot'
|
apply plugin: 'org.springframework.boot'
|
||||||
apply plugin: 'io.spring.dependency-management'
|
apply plugin: 'io.spring.dependency-management'
|
||||||
@ -100,6 +106,10 @@ subprojects {
|
|||||||
sourceCompatibility = JavaVersion.VERSION_17
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bootJar {
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
@ -153,6 +163,37 @@ licenseReport {
|
|||||||
allowedLicensesFile = new File("$projectDir/allowed-licenses.json")
|
allowedLicensesFile = new File("$projectDir/allowed-licenses.json")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
|
java {
|
||||||
|
if (System.getenv('DOCKER_ENABLE_SECURITY') == 'false' || System.getenv('ADDITIONAL_FEATURES_OFF') == 'true'
|
||||||
|
|| (project.hasProperty('ADDITIONAL_FEATURES_OFF')
|
||||||
|
&& System.getProperty('ADDITIONAL_FEATURES_OFF') == 'true')) {
|
||||||
|
exclude 'stirling/software/proprietary/security/**'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (System.getenv('STIRLING_PDF_DESKTOP_UI') == 'false') {
|
||||||
|
exclude 'stirling/software/SPDF/UI/impl/**'
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
java {
|
||||||
|
if (System.getenv('DOCKER_ENABLE_SECURITY') == 'false' || System.getenv('ADDITIONAL_FEATURES_OFF') == 'true'
|
||||||
|
|| (project.hasProperty('ADDITIONAL_FEATURES_OFF')
|
||||||
|
&& System.getProperty('ADDITIONAL_FEATURES_OFF') == 'true')) {
|
||||||
|
exclude 'stirling/software/proprietary/security/**'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (System.getenv('STIRLING_PDF_DESKTOP_UI') == 'false') {
|
||||||
|
exclude 'stirling/software/SPDF/UI/impl/**'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
openApi {
|
openApi {
|
||||||
apiDocsUrl = "http://localhost:8080/v1/api-docs"
|
apiDocsUrl = "http://localhost:8080/v1/api-docs"
|
||||||
outputDir = file("$projectDir")
|
outputDir = file("$projectDir")
|
||||||
@ -434,9 +475,11 @@ launch4j {
|
|||||||
|
|
||||||
spotless {
|
spotless {
|
||||||
java {
|
java {
|
||||||
target project.fileTree('src').include('**/*.java')
|
target sourceSets.main.allJava
|
||||||
|
target project(':common').sourceSets.main.allJava
|
||||||
|
target project(':proprietary').sourceSets.main.allJava
|
||||||
|
|
||||||
googleJavaFormat("1.26.0").aosp().reorderImports(false)
|
googleJavaFormat("1.27.0").aosp().reorderImports(false)
|
||||||
|
|
||||||
importOrder("java", "javax", "org", "com", "net", "io", "jakarta", "lombok", "me", "stirling")
|
importOrder("java", "javax", "org", "com", "net", "io", "jakarta", "lombok", "me", "stirling")
|
||||||
toggleOffOn()
|
toggleOffOn()
|
||||||
|
@ -1,30 +1,21 @@
|
|||||||
plugins {
|
|
||||||
id 'java-library'
|
|
||||||
}
|
|
||||||
|
|
||||||
bootJar {
|
|
||||||
enabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
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.0.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.6"
|
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"
|
||||||
|
|
||||||
testImplementation "org.springframework.boot:spring-boot-starter-test"
|
testImplementation "org.springframework.boot:spring-boot-starter-test"
|
||||||
testRuntimeOnly 'org.springframework.boot:spring-boot-starter-data-jpa'
|
|
||||||
testRuntimeOnly 'org.mockito:mockito-inline:5.2.0'
|
testRuntimeOnly 'org.mockito:mockito-inline:5.2.0'
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.common.configuration;
|
package stirling.software.common.configuration;
|
||||||
|
|
||||||
|
import io.github.pixee.security.SystemCommand;
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@ -8,10 +10,9 @@ import java.util.List;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
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;
|
||||||
@ -23,6 +24,11 @@ import org.springframework.core.io.ClassPathResource;
|
|||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
import org.thymeleaf.spring6.SpringTemplateEngine;
|
import org.thymeleaf.spring6.SpringTemplateEngine;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.common.model.ApplicationProperties;
|
import stirling.software.common.model.ApplicationProperties;
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
@ -60,11 +66,6 @@ public class AppConfig {
|
|||||||
return applicationProperties.getSecurity().getEnableLogin();
|
return applicationProperties.getSecurity().getEnableLogin();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
public boolean disableSecurity() {
|
|
||||||
return env.getProperty("WITHOUT_ENHANCED_FEATURES", Boolean.class, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean(name = "appName")
|
@Bean(name = "appName")
|
||||||
public String appName() {
|
public String appName() {
|
||||||
String homeTitle = applicationProperties.getUi().getAppName();
|
String homeTitle = applicationProperties.getUi().getAppName();
|
||||||
@ -148,8 +149,22 @@ public class AppConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean(name = "missingActiveSecurity") // todo: may not be needed anymore
|
@Bean(name = "activeSecurity")
|
||||||
@ConditionalOnMissingClass("stirling.software.proprietary.security.SecurityConfiguration")
|
public boolean activeSecurity() {
|
||||||
|
String additionalFeaturesOff = env.getProperty("ADDITIONAL_FEATURES_OFF");
|
||||||
|
|
||||||
|
if (additionalFeaturesOff != null) {
|
||||||
|
// ADDITIONAL_FEATURES_OFF=true means security OFF, so return false
|
||||||
|
// ADDITIONAL_FEATURES_OFF=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 true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import org.thymeleaf.IEngineConfiguration;
|
|||||||
import org.thymeleaf.templateresolver.AbstractConfigurableTemplateResolver;
|
import org.thymeleaf.templateresolver.AbstractConfigurableTemplateResolver;
|
||||||
import org.thymeleaf.templateresource.FileTemplateResource;
|
import org.thymeleaf.templateresource.FileTemplateResource;
|
||||||
import org.thymeleaf.templateresource.ITemplateResource;
|
import org.thymeleaf.templateresource.ITemplateResource;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.common.model.InputStreamTemplateResource;
|
import stirling.software.common.model.InputStreamTemplateResource;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package stirling.software.common.configuration;
|
package stirling.software.common.configuration;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
|
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
|
||||||
@ -12,8 +11,7 @@ import org.springframework.core.io.support.PropertySourceFactory;
|
|||||||
public class YamlPropertySourceFactory implements PropertySourceFactory {
|
public class YamlPropertySourceFactory implements PropertySourceFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PropertySource<?> createPropertySource(String name, EncodedResource encodedResource)
|
public PropertySource<?> createPropertySource(String name, EncodedResource encodedResource) {
|
||||||
throws IOException {
|
|
||||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||||
factory.setResources(encodedResource.getResource());
|
factory.setResources(encodedResource.getResource());
|
||||||
Properties properties = factory.getObject();
|
Properties properties = factory.getObject();
|
||||||
|
@ -12,14 +12,9 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import lombok.Data;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.core.env.ConfigurableEnvironment;
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
@ -29,29 +24,49 @@ import org.springframework.core.io.FileSystemResource;
|
|||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.support.EncodedResource;
|
import org.springframework.core.io.support.EncodedResource;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.common.configuration.InstallationPathConfig;
|
import stirling.software.common.configuration.InstallationPathConfig;
|
||||||
import stirling.software.common.configuration.YamlPropertySourceFactory;
|
import stirling.software.common.configuration.YamlPropertySourceFactory;
|
||||||
import stirling.software.common.model.exception.UnsupportedProviderException;
|
import stirling.software.common.model.exception.UnsupportedProviderException;
|
||||||
import stirling.software.common.util.ValidationUtil;
|
import stirling.software.common.model.oauth2.GitHubProvider;
|
||||||
import stirling.software.common.model.oauth2.provider.GitHubProvider;
|
import stirling.software.common.model.oauth2.GoogleProvider;
|
||||||
import stirling.software.common.model.oauth2.provider.GoogleProvider;
|
import stirling.software.common.model.oauth2.KeycloakProvider;
|
||||||
import stirling.software.common.model.oauth2.provider.KeycloakProvider;
|
import stirling.software.common.model.oauth2.Provider;
|
||||||
import stirling.software.common.model.oauth2.provider.Provider;
|
import stirling.software.common.util.ValidationUtils;
|
||||||
import static stirling.software.common.util.ValidationUtil.isCollectionEmpty;
|
|
||||||
import static stirling.software.common.util.ValidationUtil.isStringEmpty;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@ConfigurationProperties(prefix = "")
|
|
||||||
@Data
|
@Data
|
||||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||||
|
@ConfigurationProperties(prefix = "")
|
||||||
public class ApplicationProperties {
|
public class ApplicationProperties {
|
||||||
|
|
||||||
|
private Legal legal = new Legal();
|
||||||
|
private Security security = new Security();
|
||||||
|
private System system = new System();
|
||||||
|
private Ui ui = new Ui();
|
||||||
|
private Endpoints endpoints = new Endpoints();
|
||||||
|
private Metrics metrics = new Metrics();
|
||||||
|
private AutomaticallyGenerated automaticallyGenerated = new AutomaticallyGenerated();
|
||||||
|
|
||||||
|
private Mail mail = new Mail();
|
||||||
|
|
||||||
|
private Premium premium = new Premium();
|
||||||
|
private EnterpriseEdition enterpriseEdition = new EnterpriseEdition();
|
||||||
|
private AutoPipeline autoPipeline = new AutoPipeline();
|
||||||
|
private ProcessExecutor processExecutor = new ProcessExecutor();
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public PropertySource<?> dynamicYamlPropertySource(ConfigurableEnvironment environment)
|
public PropertySource<?> dynamicYamlPropertySource(ConfigurableEnvironment environment)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
String configPath = InstallationPathConfig.getSettingsPath();
|
String configPath = InstallationPathConfig.getSettingsPath();
|
||||||
log.info("Attempting to load settings from: " + configPath);
|
log.debug("Attempting to load settings from: " + configPath);
|
||||||
|
|
||||||
File file = new File(configPath);
|
File file = new File(configPath);
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
@ -68,26 +83,11 @@ public class ApplicationProperties {
|
|||||||
new YamlPropertySourceFactory().createPropertySource(null, encodedResource);
|
new YamlPropertySourceFactory().createPropertySource(null, encodedResource);
|
||||||
environment.getPropertySources().addFirst(propertySource);
|
environment.getPropertySources().addFirst(propertySource);
|
||||||
|
|
||||||
log.info("Loaded properties: " + propertySource.getSource());
|
log.debug("Loaded properties: " + propertySource.getSource());
|
||||||
|
|
||||||
return propertySource;
|
return propertySource;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Legal legal = new Legal();
|
|
||||||
private Security security = new Security();
|
|
||||||
private System system = new System();
|
|
||||||
private Ui ui = new Ui();
|
|
||||||
private Endpoints endpoints = new Endpoints();
|
|
||||||
private Metrics metrics = new Metrics();
|
|
||||||
private AutomaticallyGenerated automaticallyGenerated = new AutomaticallyGenerated();
|
|
||||||
|
|
||||||
private Mail mail = new Mail();
|
|
||||||
|
|
||||||
private Premium premium = new Premium();
|
|
||||||
private EnterpriseEdition enterpriseEdition = new EnterpriseEdition();
|
|
||||||
private AutoPipeline autoPipeline = new AutoPipeline();
|
|
||||||
private ProcessExecutor processExecutor = new ProcessExecutor();
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class AutoPipeline {
|
public static class AutoPipeline {
|
||||||
private String outputFolder;
|
private String outputFolder;
|
||||||
@ -247,11 +247,11 @@ public class ApplicationProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSettingsValid() {
|
public boolean isSettingsValid() {
|
||||||
return !isStringEmpty(this.getIssuer())
|
return !ValidationUtils.isStringEmpty(this.getIssuer())
|
||||||
&& !isStringEmpty(this.getClientId())
|
&& !ValidationUtils.isStringEmpty(this.getClientId())
|
||||||
&& !isStringEmpty(this.getClientSecret())
|
&& !ValidationUtils.isStringEmpty(this.getClientSecret())
|
||||||
&& !isCollectionEmpty(this.getScopes())
|
&& !ValidationUtils.isCollectionEmpty(this.getScopes())
|
||||||
&& !isStringEmpty(this.getUseAsUsername());
|
&& !ValidationUtils.isStringEmpty(this.getUseAsUsername());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
import stirling.software.common.model.api.PDFFile;
|
import stirling.software.common.model.api.PDFFile;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package stirling.software.common.model.oauth2.provider;
|
package stirling.software.common.model.oauth2;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import stirling.software.common.model.enumeration.UsernameAttribute;
|
import stirling.software.common.model.enumeration.UsernameAttribute;
|
||||||
|
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
@ -1,8 +1,10 @@
|
|||||||
package stirling.software.common.model.oauth2.provider;
|
package stirling.software.common.model.oauth2;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import stirling.software.common.model.enumeration.UsernameAttribute;
|
import stirling.software.common.model.enumeration.UsernameAttribute;
|
||||||
|
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
@ -1,8 +1,10 @@
|
|||||||
package stirling.software.common.model.oauth2.provider;
|
package stirling.software.common.model.oauth2;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import stirling.software.common.model.enumeration.UsernameAttribute;
|
import stirling.software.common.model.enumeration.UsernameAttribute;
|
||||||
|
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
@ -1,13 +1,16 @@
|
|||||||
package stirling.software.common.model.oauth2.provider;
|
package stirling.software.common.model.oauth2;
|
||||||
|
|
||||||
|
import static stirling.software.common.model.enumeration.UsernameAttribute.EMAIL;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import stirling.software.common.model.enumeration.UsernameAttribute;
|
import stirling.software.common.model.enumeration.UsernameAttribute;
|
||||||
import stirling.software.common.model.exception.UnsupportedClaimException;
|
import stirling.software.common.model.exception.UnsupportedClaimException;
|
||||||
import static stirling.software.common.model.enumeration.UsernameAttribute.EMAIL;
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
@ -208,7 +208,7 @@ public class PostHogService {
|
|||||||
|
|
||||||
// New environment variables
|
// New environment variables
|
||||||
dockerMetrics.put("version_tag", System.getenv("VERSION_TAG"));
|
dockerMetrics.put("version_tag", System.getenv("VERSION_TAG"));
|
||||||
dockerMetrics.put("without_enhanced_features", System.getenv("WITHOUT_ENHANCED_FEATURES"));
|
dockerMetrics.put("additional_features_off", System.getenv("ADDITIONAL_FEATURES_OFF"));
|
||||||
dockerMetrics.put("fat_docker", System.getenv("FAT_DOCKER"));
|
dockerMetrics.put("fat_docker", System.getenv("FAT_DOCKER"));
|
||||||
|
|
||||||
return dockerMetrics;
|
return dockerMetrics;
|
||||||
|
@ -17,6 +17,7 @@ import org.springframework.scheduling.annotation.Scheduled;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.common.configuration.RuntimePathConfig;
|
import stirling.software.common.configuration.RuntimePathConfig;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
|
@ -30,7 +30,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import stirling.software.common.configuration.InstallationPathConfig;
|
import stirling.software.common.configuration.InstallationPathConfig;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class GeneralUtil {
|
public class GeneralUtils {
|
||||||
|
|
||||||
public static File convertMultipartFileToFile(MultipartFile multipartFile) throws IOException {
|
public static File convertMultipartFileToFile(MultipartFile multipartFile) throws IOException {
|
||||||
File tempFile = Files.createTempFile("temp", null).toFile();
|
File tempFile = Files.createTempFile("temp", null).toFile();
|
@ -34,6 +34,7 @@ import org.springframework.web.multipart.MultipartFile;
|
|||||||
import io.github.pixee.security.Filenames;
|
import io.github.pixee.security.Filenames;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -84,7 +85,7 @@ public class PdfUtils {
|
|||||||
public static boolean hasImages(PDDocument document, String pagesToCheck) throws IOException {
|
public static boolean hasImages(PDDocument document, String pagesToCheck) throws IOException {
|
||||||
String[] pageOrderArr = pagesToCheck.split(",");
|
String[] pageOrderArr = pagesToCheck.split(",");
|
||||||
List<Integer> pageList =
|
List<Integer> pageList =
|
||||||
GeneralUtil.parsePageList(pageOrderArr, document.getNumberOfPages());
|
GeneralUtils.parsePageList(pageOrderArr, document.getNumberOfPages());
|
||||||
|
|
||||||
for (int pageNumber : pageList) {
|
for (int pageNumber : pageList) {
|
||||||
PDPage page = document.getPage(pageNumber);
|
PDPage page = document.getPage(pageNumber);
|
||||||
@ -100,7 +101,7 @@ public class PdfUtils {
|
|||||||
throws IOException {
|
throws IOException {
|
||||||
String[] pageOrderArr = pageNumbersToCheck.split(",");
|
String[] pageOrderArr = pageNumbersToCheck.split(",");
|
||||||
List<Integer> pageList =
|
List<Integer> pageList =
|
||||||
GeneralUtil.parsePageList(pageOrderArr, document.getNumberOfPages());
|
GeneralUtils.parsePageList(pageOrderArr, document.getNumberOfPages());
|
||||||
|
|
||||||
for (int pageNumber : pageList) {
|
for (int pageNumber : pageList) {
|
||||||
PDPage page = document.getPage(pageNumber);
|
PDPage page = document.getPage(pageNumber);
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
package stirling.software.common.util;
|
package stirling.software.common.util;
|
||||||
|
|
||||||
import stirling.software.common.model.oauth2.provider.Provider;
|
import static stirling.software.common.util.ValidationUtils.isCollectionEmpty;
|
||||||
import static stirling.software.common.util.ValidationUtil.isCollectionEmpty;
|
import static stirling.software.common.util.ValidationUtils.isStringEmpty;
|
||||||
import static stirling.software.common.util.ValidationUtil.isStringEmpty;
|
|
||||||
|
|
||||||
public class ProviderUtil {
|
import stirling.software.common.model.oauth2.Provider;
|
||||||
|
|
||||||
|
public class ProviderUtils {
|
||||||
|
|
||||||
public static boolean validateProvider(Provider provider) {
|
public static boolean validateProvider(Provider provider) {
|
||||||
if (provider == null) {
|
if (provider == null) {
|
@ -1,6 +1,6 @@
|
|||||||
package stirling.software.common.util;
|
package stirling.software.common.util;
|
||||||
|
|
||||||
public class RequestUriUtil {
|
public class RequestUriUtils {
|
||||||
|
|
||||||
public static boolean isStaticResource(String requestURI) {
|
public static boolean isStaticResource(String requestURI) {
|
||||||
return isStaticResource("", requestURI);
|
return isStaticResource("", requestURI);
|
@ -0,0 +1,14 @@
|
|||||||
|
package stirling.software.common.util;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
public class ValidationUtils {
|
||||||
|
|
||||||
|
public static boolean isStringEmpty(String input) {
|
||||||
|
return input == null || input.isBlank();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isCollectionEmpty(Collection<String> input) {
|
||||||
|
return input == null || input.isEmpty();
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,7 @@ import org.springframework.core.io.InputStreamResource;
|
|||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.common.model.api.misc.HighContrastColorCombination;
|
import stirling.software.common.model.api.misc.HighContrastColorCombination;
|
||||||
import stirling.software.common.model.api.misc.ReplaceAndInvert;
|
import stirling.software.common.model.api.misc.ReplaceAndInvert;
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
|||||||
import org.apache.pdfbox.rendering.PDFRenderer;
|
import org.apache.pdfbox.rendering.PDFRenderer;
|
||||||
import org.springframework.core.io.InputStreamResource;
|
import org.springframework.core.io.InputStreamResource;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import stirling.software.common.model.api.misc.ReplaceAndInvert;
|
import stirling.software.common.model.api.misc.ReplaceAndInvert;
|
||||||
|
|
||||||
public class InvertFullColorStrategy extends ReplaceAndInvertColorStrategy {
|
public class InvertFullColorStrategy extends ReplaceAndInvertColorStrategy {
|
||||||
|
@ -9,6 +9,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature;
|
|||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.common.model.api.security.RedactionArea;
|
import stirling.software.common.model.api.security.RedactionArea;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -24,9 +25,7 @@ public class StringToArrayListPropertyEditor extends PropertyEditorSupport {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
|
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
|
||||||
TypeReference<ArrayList<RedactionArea>> typeRef =
|
TypeReference<ArrayList<RedactionArea>> typeRef = new TypeReference<>() {};
|
||||||
new TypeReference<>() {
|
|
||||||
};
|
|
||||||
List<RedactionArea> list = objectMapper.readValue(text, typeRef);
|
List<RedactionArea> list = objectMapper.readValue(text, typeRef);
|
||||||
setValue(list);
|
setValue(list);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -14,8 +14,7 @@ public class StringToMapPropertyEditor extends PropertyEditorSupport {
|
|||||||
@Override
|
@Override
|
||||||
public void setAsText(String text) throws IllegalArgumentException {
|
public void setAsText(String text) throws IllegalArgumentException {
|
||||||
try {
|
try {
|
||||||
TypeReference<HashMap<String, String>> typeRef =
|
TypeReference<HashMap<String, String>> typeRef = new TypeReference<>() {};
|
||||||
new TypeReference<>() {};
|
|
||||||
Map<String, String> map = objectMapper.readValue(text, typeRef);
|
Map<String, String> map = objectMapper.readValue(text, typeRef);
|
||||||
setValue(map);
|
setValue(map);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -3,7 +3,6 @@ package stirling.software.common.util;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@ -14,7 +13,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.anyList;
|
||||||
import static org.mockito.Mockito.mockStatic;
|
import static org.mockito.Mockito.mockStatic;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
@ -140,7 +139,7 @@ class CheckProgramInstallTest {
|
|||||||
void testGetAvailablePythonCommand_WhenNoPythonIsAvailable()
|
void testGetAvailablePythonCommand_WhenNoPythonIsAvailable()
|
||||||
throws IOException, InterruptedException {
|
throws IOException, InterruptedException {
|
||||||
// Arrange
|
// Arrange
|
||||||
when(mockExecutor.runCommandWithOutputHandling(any(List.class)))
|
when(mockExecutor.runCommandWithOutputHandling(anyList()))
|
||||||
.thenThrow(new IOException("Command not found"));
|
.thenThrow(new IOException("Command not found"));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
@ -168,7 +167,7 @@ class CheckProgramInstallTest {
|
|||||||
String firstCall = CheckProgramInstall.getAvailablePythonCommand();
|
String firstCall = CheckProgramInstall.getAvailablePythonCommand();
|
||||||
|
|
||||||
// Change the mock to simulate a change in the environment
|
// Change the mock to simulate a change in the environment
|
||||||
when(mockExecutor.runCommandWithOutputHandling(any(List.class)))
|
when(mockExecutor.runCommandWithOutputHandling(anyList()))
|
||||||
.thenThrow(new IOException("Command not found"));
|
.thenThrow(new IOException("Command not found"));
|
||||||
|
|
||||||
String secondCall = CheckProgramInstall.getAvailablePythonCommand();
|
String secondCall = CheckProgramInstall.getAvailablePythonCommand();
|
||||||
|
@ -4,38 +4,38 @@ import static org.junit.jupiter.api.Assertions.*;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
class GeneralUtilAdditionalTest {
|
class GeneralUtilsAdditionalTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testConvertSizeToBytes() {
|
void testConvertSizeToBytes() {
|
||||||
assertEquals(1024L, GeneralUtil.convertSizeToBytes("1KB"));
|
assertEquals(1024L, GeneralUtils.convertSizeToBytes("1KB"));
|
||||||
assertEquals(1024L * 1024, GeneralUtil.convertSizeToBytes("1MB"));
|
assertEquals(1024L * 1024, GeneralUtils.convertSizeToBytes("1MB"));
|
||||||
assertEquals(1024L * 1024 * 1024, GeneralUtil.convertSizeToBytes("1GB"));
|
assertEquals(1024L * 1024 * 1024, GeneralUtils.convertSizeToBytes("1GB"));
|
||||||
assertEquals(100L * 1024 * 1024, GeneralUtil.convertSizeToBytes("100"));
|
assertEquals(100L * 1024 * 1024, GeneralUtils.convertSizeToBytes("100"));
|
||||||
assertNull(GeneralUtil.convertSizeToBytes("invalid"));
|
assertNull(GeneralUtils.convertSizeToBytes("invalid"));
|
||||||
assertNull(GeneralUtil.convertSizeToBytes(null));
|
assertNull(GeneralUtils.convertSizeToBytes(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testFormatBytes() {
|
void testFormatBytes() {
|
||||||
assertEquals("512 B", GeneralUtil.formatBytes(512));
|
assertEquals("512 B", GeneralUtils.formatBytes(512));
|
||||||
assertEquals("1.00 KB", GeneralUtil.formatBytes(1024));
|
assertEquals("1.00 KB", GeneralUtils.formatBytes(1024));
|
||||||
assertEquals("1.00 MB", GeneralUtil.formatBytes(1024L * 1024));
|
assertEquals("1.00 MB", GeneralUtils.formatBytes(1024L * 1024));
|
||||||
assertEquals("1.00 GB", GeneralUtil.formatBytes(1024L * 1024 * 1024));
|
assertEquals("1.00 GB", GeneralUtils.formatBytes(1024L * 1024 * 1024));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testURLHelpersAndUUID() {
|
void testURLHelpersAndUUID() {
|
||||||
assertTrue(GeneralUtil.isValidURL("https://example.com"));
|
assertTrue(GeneralUtils.isValidURL("https://example.com"));
|
||||||
assertFalse(GeneralUtil.isValidURL("htp:/bad"));
|
assertFalse(GeneralUtils.isValidURL("htp:/bad"));
|
||||||
assertFalse(GeneralUtil.isURLReachable("http://localhost"));
|
assertFalse(GeneralUtils.isURLReachable("http://localhost"));
|
||||||
assertFalse(GeneralUtil.isURLReachable("ftp://example.com"));
|
assertFalse(GeneralUtils.isURLReachable("ftp://example.com"));
|
||||||
|
|
||||||
assertTrue(GeneralUtil.isValidUUID("123e4567-e89b-12d3-a456-426614174000"));
|
assertTrue(GeneralUtils.isValidUUID("123e4567-e89b-12d3-a456-426614174000"));
|
||||||
assertFalse(GeneralUtil.isValidUUID("not-a-uuid"));
|
assertFalse(GeneralUtils.isValidUUID("not-a-uuid"));
|
||||||
|
|
||||||
assertFalse(GeneralUtil.isVersionHigher(null, "1.0"));
|
assertFalse(GeneralUtils.isVersionHigher(null, "1.0"));
|
||||||
assertTrue(GeneralUtil.isVersionHigher("2.0", "1.9"));
|
assertTrue(GeneralUtils.isVersionHigher("2.0", "1.9"));
|
||||||
assertFalse(GeneralUtil.isVersionHigher("1.0", "1.0.1"));
|
assertFalse(GeneralUtils.isVersionHigher("1.0", "1.0.1"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,152 +6,152 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class GeneralUtilTest {
|
public class GeneralUtilsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testParsePageListWithAll() {
|
void testParsePageListWithAll() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"all"}, 5, false);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"all"}, 5, false);
|
||||||
assertEquals(List.of(0, 1, 2, 3, 4), result, "'All' keyword should return all pages.");
|
assertEquals(List.of(0, 1, 2, 3, 4), result, "'All' keyword should return all pages.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testParsePageListWithAllOneBased() {
|
void testParsePageListWithAllOneBased() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"all"}, 5, true);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"all"}, 5, true);
|
||||||
assertEquals(List.of(1, 2, 3, 4, 5), result, "'All' keyword should return all pages.");
|
assertEquals(List.of(1, 2, 3, 4, 5), result, "'All' keyword should return all pages.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nFunc() {
|
void nFunc() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"n"}, 5, true);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"n"}, 5, true);
|
||||||
assertEquals(List.of(1, 2, 3, 4, 5), result, "'n' keyword should return all pages.");
|
assertEquals(List.of(1, 2, 3, 4, 5), result, "'n' keyword should return all pages.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nFuncAdvanced() {
|
void nFuncAdvanced() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"4n"}, 9, true);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"4n"}, 9, true);
|
||||||
// skip 0 as not valid
|
// skip 0 as not valid
|
||||||
assertEquals(List.of(4, 8), result, "'All' keyword should return all pages.");
|
assertEquals(List.of(4, 8), result, "'All' keyword should return all pages.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nFuncAdvancedZero() {
|
void nFuncAdvancedZero() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"4n"}, 9, false);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"4n"}, 9, false);
|
||||||
// skip 0 as not valid
|
// skip 0 as not valid
|
||||||
assertEquals(List.of(3, 7), result, "'All' keyword should return all pages.");
|
assertEquals(List.of(3, 7), result, "'All' keyword should return all pages.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nFuncAdvanced2() {
|
void nFuncAdvanced2() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"4n-1"}, 9, true);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"4n-1"}, 9, true);
|
||||||
// skip -1 as not valid
|
// skip -1 as not valid
|
||||||
assertEquals(List.of(3, 7), result, "4n-1 should do (0-1), (4-1), (8-1)");
|
assertEquals(List.of(3, 7), result, "4n-1 should do (0-1), (4-1), (8-1)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nFuncAdvanced3() {
|
void nFuncAdvanced3() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"4n+1"}, 9, true);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"4n+1"}, 9, true);
|
||||||
assertEquals(List.of(5, 9), result, "'All' keyword should return all pages.");
|
assertEquals(List.of(5, 9), result, "'All' keyword should return all pages.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nFunc_spaces() {
|
void nFunc_spaces() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"n + 1"}, 9, true);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"n + 1"}, 9, true);
|
||||||
assertEquals(List.of(2, 3, 4, 5, 6, 7, 8, 9), result);
|
assertEquals(List.of(2, 3, 4, 5, 6, 7, 8, 9), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nFunc_consecutive_Ns_nnn() {
|
void nFunc_consecutive_Ns_nnn() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"nnn"}, 9, true);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"nnn"}, 9, true);
|
||||||
assertEquals(List.of(1, 8), result);
|
assertEquals(List.of(1, 8), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nFunc_consecutive_Ns_nn() {
|
void nFunc_consecutive_Ns_nn() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"nn"}, 9, true);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"nn"}, 9, true);
|
||||||
assertEquals(List.of(1, 4, 9), result);
|
assertEquals(List.of(1, 4, 9), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nFunc_opening_closing_round_brackets() {
|
void nFunc_opening_closing_round_brackets() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"(n-1)(n-2)"}, 9, true);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"(n-1)(n-2)"}, 9, true);
|
||||||
assertEquals(List.of(2, 6), result);
|
assertEquals(List.of(2, 6), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nFunc_opening_round_brackets() {
|
void nFunc_opening_round_brackets() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"2(n-1)"}, 9, true);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"2(n-1)"}, 9, true);
|
||||||
assertEquals(List.of(2, 4, 6, 8), result);
|
assertEquals(List.of(2, 4, 6, 8), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nFunc_opening_round_brackets_n() {
|
void nFunc_opening_round_brackets_n() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"n(n-1)"}, 9, true);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"n(n-1)"}, 9, true);
|
||||||
assertEquals(List.of(2, 6), result);
|
assertEquals(List.of(2, 6), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nFunc_closing_round_brackets() {
|
void nFunc_closing_round_brackets() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"(n-1)2"}, 9, true);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"(n-1)2"}, 9, true);
|
||||||
assertEquals(List.of(2, 4, 6, 8), result);
|
assertEquals(List.of(2, 4, 6, 8), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nFunc_closing_round_brackets_n() {
|
void nFunc_closing_round_brackets_n() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"(n-1)n"}, 9, true);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"(n-1)n"}, 9, true);
|
||||||
assertEquals(List.of(2, 6), result);
|
assertEquals(List.of(2, 6), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nFunc_function_surrounded_with_brackets() {
|
void nFunc_function_surrounded_with_brackets() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"(n-1)"}, 9, true);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"(n-1)"}, 9, true);
|
||||||
assertEquals(List.of(1, 2, 3, 4, 5, 6, 7, 8), result);
|
assertEquals(List.of(1, 2, 3, 4, 5, 6, 7, 8), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nFuncAdvanced4() {
|
void nFuncAdvanced4() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"3+2n"}, 9, true);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"3+2n"}, 9, true);
|
||||||
assertEquals(List.of(5, 7, 9), result, "'All' keyword should return all pages.");
|
assertEquals(List.of(5, 7, 9), result, "'All' keyword should return all pages.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nFuncAdvancedZerobased() {
|
void nFuncAdvancedZerobased() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"4n"}, 9, false);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"4n"}, 9, false);
|
||||||
assertEquals(List.of(3, 7), result, "'All' keyword should return all pages.");
|
assertEquals(List.of(3, 7), result, "'All' keyword should return all pages.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nFuncAdvanced2Zerobased() {
|
void nFuncAdvanced2Zerobased() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"4n-1"}, 9, false);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"4n-1"}, 9, false);
|
||||||
assertEquals(List.of(2, 6), result, "'All' keyword should return all pages.");
|
assertEquals(List.of(2, 6), result, "'All' keyword should return all pages.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testParsePageListWithRangeOneBasedOutput() {
|
void testParsePageListWithRangeOneBasedOutput() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"1-3"}, 5, true);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"1-3"}, 5, true);
|
||||||
assertEquals(List.of(1, 2, 3), result, "Range should be parsed correctly.");
|
assertEquals(List.of(1, 2, 3), result, "Range should be parsed correctly.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testParsePageListWithRangeZeroBaseOutput() {
|
void testParsePageListWithRangeZeroBaseOutput() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"1-3"}, 5, false);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"1-3"}, 5, false);
|
||||||
assertEquals(List.of(0, 1, 2), result, "Range should be parsed correctly.");
|
assertEquals(List.of(0, 1, 2), result, "Range should be parsed correctly.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testParsePageListWithRangeOneBasedOutputFull() {
|
void testParsePageListWithRangeOneBasedOutputFull() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"1,3,7-8"}, 8, true);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"1,3,7-8"}, 8, true);
|
||||||
assertEquals(List.of(1, 3, 7, 8), result, "Range should be parsed correctly.");
|
assertEquals(List.of(1, 3, 7, 8), result, "Range should be parsed correctly.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testParsePageListWithRangeOneBasedOutputFullOutOfRange() {
|
void testParsePageListWithRangeOneBasedOutputFullOutOfRange() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"1,3,7-8"}, 5, true);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"1,3,7-8"}, 5, true);
|
||||||
assertEquals(List.of(1, 3), result, "Range should be parsed correctly.");
|
assertEquals(List.of(1, 3), result, "Range should be parsed correctly.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testParsePageListWithRangeZeroBaseOutputFull() {
|
void testParsePageListWithRangeZeroBaseOutputFull() {
|
||||||
List<Integer> result = GeneralUtil.parsePageList(new String[] {"1,3,7-8"}, 8, false);
|
List<Integer> result = GeneralUtils.parsePageList(new String[] {"1,3,7-8"}, 8, false);
|
||||||
assertEquals(List.of(0, 2, 6, 7), result, "Range should be parsed correctly.");
|
assertEquals(List.of(0, 2, 6, 7), result, "Range should be parsed correctly.");
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyList;
|
||||||
import static org.mockito.ArgumentMatchers.argThat;
|
import static org.mockito.ArgumentMatchers.argThat;
|
||||||
import static org.mockito.Mockito.mockStatic;
|
import static org.mockito.Mockito.mockStatic;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
@ -132,7 +133,7 @@ class PDFToFileTest {
|
|||||||
.when(() -> ProcessExecutor.getInstance(ProcessExecutor.Processes.PDFTOHTML))
|
.when(() -> ProcessExecutor.getInstance(ProcessExecutor.Processes.PDFTOHTML))
|
||||||
.thenReturn(mockProcessExecutor);
|
.thenReturn(mockProcessExecutor);
|
||||||
|
|
||||||
when(mockProcessExecutor.runCommandWithOutputHandling(any(List.class), any(File.class)))
|
when(mockProcessExecutor.runCommandWithOutputHandling(anyList(), any(File.class)))
|
||||||
.thenAnswer(
|
.thenAnswer(
|
||||||
invocation -> {
|
invocation -> {
|
||||||
// When command is executed, simulate creation of output files
|
// When command is executed, simulate creation of output files
|
||||||
@ -175,7 +176,7 @@ class PDFToFileTest {
|
|||||||
.when(() -> ProcessExecutor.getInstance(ProcessExecutor.Processes.PDFTOHTML))
|
.when(() -> ProcessExecutor.getInstance(ProcessExecutor.Processes.PDFTOHTML))
|
||||||
.thenReturn(mockProcessExecutor);
|
.thenReturn(mockProcessExecutor);
|
||||||
|
|
||||||
when(mockProcessExecutor.runCommandWithOutputHandling(any(List.class), any(File.class)))
|
when(mockProcessExecutor.runCommandWithOutputHandling(anyList(), any(File.class)))
|
||||||
.thenAnswer(
|
.thenAnswer(
|
||||||
invocation -> {
|
invocation -> {
|
||||||
// When command is executed, simulate creation of output files
|
// When command is executed, simulate creation of output files
|
||||||
@ -251,7 +252,7 @@ class PDFToFileTest {
|
|||||||
.when(() -> ProcessExecutor.getInstance(ProcessExecutor.Processes.PDFTOHTML))
|
.when(() -> ProcessExecutor.getInstance(ProcessExecutor.Processes.PDFTOHTML))
|
||||||
.thenReturn(mockProcessExecutor);
|
.thenReturn(mockProcessExecutor);
|
||||||
|
|
||||||
when(mockProcessExecutor.runCommandWithOutputHandling(any(List.class), any(File.class)))
|
when(mockProcessExecutor.runCommandWithOutputHandling(anyList(), any(File.class)))
|
||||||
.thenAnswer(
|
.thenAnswer(
|
||||||
invocation -> {
|
invocation -> {
|
||||||
// When command is executed, simulate creation of output files
|
// When command is executed, simulate creation of output files
|
||||||
@ -537,7 +538,7 @@ class PDFToFileTest {
|
|||||||
.when(() -> ProcessExecutor.getInstance(ProcessExecutor.Processes.LIBRE_OFFICE))
|
.when(() -> ProcessExecutor.getInstance(ProcessExecutor.Processes.LIBRE_OFFICE))
|
||||||
.thenReturn(mockProcessExecutor);
|
.thenReturn(mockProcessExecutor);
|
||||||
|
|
||||||
when(mockProcessExecutor.runCommandWithOutputHandling(any(List.class)))
|
when(mockProcessExecutor.runCommandWithOutputHandling(anyList()))
|
||||||
.thenAnswer(
|
.thenAnswer(
|
||||||
invocation -> {
|
invocation -> {
|
||||||
// When command is executed, find the output directory argument
|
// When command is executed, find the output directory argument
|
||||||
|
@ -10,13 +10,15 @@ import org.junit.jupiter.params.provider.Arguments;
|
|||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
import stirling.software.common.model.enumeration.UsernameAttribute;
|
import stirling.software.common.model.enumeration.UsernameAttribute;
|
||||||
import stirling.software.common.model.oauth2.provider.GitHubProvider;
|
import stirling.software.common.model.oauth2.GitHubProvider;
|
||||||
import stirling.software.common.model.oauth2.provider.GoogleProvider;
|
import stirling.software.common.model.oauth2.GoogleProvider;
|
||||||
import stirling.software.common.model.oauth2.provider.Provider;
|
import stirling.software.common.model.oauth2.Provider;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
class ProviderUtilTest {
|
class ProviderUtilsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testSuccessfulValidation() {
|
void testSuccessfulValidation() {
|
||||||
@ -26,13 +28,13 @@ class ProviderUtilTest {
|
|||||||
when(provider.getClientSecret()).thenReturn("clientSecret");
|
when(provider.getClientSecret()).thenReturn("clientSecret");
|
||||||
when(provider.getScopes()).thenReturn(List.of("read:user"));
|
when(provider.getScopes()).thenReturn(List.of("read:user"));
|
||||||
|
|
||||||
Assertions.assertTrue(ProviderUtil.validateProvider(provider));
|
assertTrue(ProviderUtils.validateProvider(provider));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("providerParams")
|
@MethodSource("providerParams")
|
||||||
void testUnsuccessfulValidation(Provider provider) {
|
void testUnsuccessfulValidation(Provider provider) {
|
||||||
Assertions.assertFalse(ProviderUtil.validateProvider(provider));
|
assertFalse(ProviderUtils.validateProvider(provider));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Stream<Arguments> providerParams() {
|
public static Stream<Arguments> providerParams() {
|
@ -1,311 +0,0 @@
|
|||||||
package stirling.software.common.util;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
|
||||||
import org.junit.jupiter.params.provider.ValueSource;
|
|
||||||
|
|
||||||
public class RequestUriUtilTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testIsStaticResource() {
|
|
||||||
// Test static resources without context path
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isStaticResource("/css/styles.css"), "CSS files should be static");
|
|
||||||
assertTrue(RequestUriUtil.isStaticResource("/js/script.js"), "JS files should be static");
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isStaticResource("/images/logo.png"),
|
|
||||||
"Image files should be static");
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isStaticResource("/public/index.html"),
|
|
||||||
"Public files should be static");
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isStaticResource("/pdfjs/pdf.worker.js"),
|
|
||||||
"PDF.js files should be static");
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isStaticResource("/api/v1/info/status"),
|
|
||||||
"API status should be static");
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isStaticResource("/some-path/icon.svg"),
|
|
||||||
"SVG files should be static");
|
|
||||||
assertTrue(RequestUriUtil.isStaticResource("/login"), "Login page should be static");
|
|
||||||
assertTrue(RequestUriUtil.isStaticResource("/error"), "Error page should be static");
|
|
||||||
|
|
||||||
// Test non-static resources
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isStaticResource("/api/v1/users"),
|
|
||||||
"API users should not be static");
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isStaticResource("/api/v1/orders"),
|
|
||||||
"API orders should not be static");
|
|
||||||
assertFalse(RequestUriUtil.isStaticResource("/"), "Root path should not be static");
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isStaticResource("/register"),
|
|
||||||
"Register page should not be static");
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isStaticResource("/api/v1/products"),
|
|
||||||
"API products should not be static");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testIsStaticResourceWithContextPath() {
|
|
||||||
String contextPath = "/myapp";
|
|
||||||
|
|
||||||
// Test static resources with context path
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isStaticResource(contextPath, contextPath + "/css/styles.css"),
|
|
||||||
"CSS with context path should be static");
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isStaticResource(contextPath, contextPath + "/js/script.js"),
|
|
||||||
"JS with context path should be static");
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isStaticResource(contextPath, contextPath + "/images/logo.png"),
|
|
||||||
"Images with context path should be static");
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isStaticResource(contextPath, contextPath + "/login"),
|
|
||||||
"Login with context path should be static");
|
|
||||||
|
|
||||||
// Test non-static resources with context path
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isStaticResource(contextPath, contextPath + "/api/v1/users"),
|
|
||||||
"API users with context path should not be static");
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isStaticResource(contextPath, "/"),
|
|
||||||
"Root path with context path should not be static");
|
|
||||||
}
|
|
||||||
|
|
||||||
@ParameterizedTest
|
|
||||||
@ValueSource(
|
|
||||||
strings = {
|
|
||||||
"robots.txt",
|
|
||||||
"/favicon.ico",
|
|
||||||
"/icon.svg",
|
|
||||||
"/image.png",
|
|
||||||
"/site.webmanifest",
|
|
||||||
"/app/logo.svg",
|
|
||||||
"/downloads/document.png",
|
|
||||||
"/assets/brand.ico",
|
|
||||||
"/any/path/with/image.svg",
|
|
||||||
"/deep/nested/folder/icon.png"
|
|
||||||
})
|
|
||||||
void testIsStaticResourceWithFileExtensions(String path) {
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isStaticResource(path),
|
|
||||||
"Files with specific extensions should be static regardless of path");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testIsTrackableResource() {
|
|
||||||
// Test non-trackable resources (returns false)
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isTrackableResource("/js/script.js"),
|
|
||||||
"JS files should not be trackable");
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isTrackableResource("/v1/api-docs"),
|
|
||||||
"API docs should not be trackable");
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isTrackableResource("robots.txt"),
|
|
||||||
"robots.txt should not be trackable");
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isTrackableResource("/images/logo.png"),
|
|
||||||
"Images should not be trackable");
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isTrackableResource("/styles.css"),
|
|
||||||
"CSS files should not be trackable");
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isTrackableResource("/script.js.map"),
|
|
||||||
"Map files should not be trackable");
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isTrackableResource("/icon.svg"),
|
|
||||||
"SVG files should not be trackable");
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isTrackableResource("/popularity.txt"),
|
|
||||||
"Popularity file should not be trackable");
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isTrackableResource("/script.js"),
|
|
||||||
"JS files should not be trackable");
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isTrackableResource("/swagger/index.html"),
|
|
||||||
"Swagger files should not be trackable");
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isTrackableResource("/api/v1/info/status"),
|
|
||||||
"API info should not be trackable");
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isTrackableResource("/site.webmanifest"),
|
|
||||||
"Webmanifest should not be trackable");
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isTrackableResource("/fonts/font.woff"),
|
|
||||||
"Fonts should not be trackable");
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isTrackableResource("/pdfjs/viewer.js"),
|
|
||||||
"PDF.js files should not be trackable");
|
|
||||||
|
|
||||||
// Test trackable resources (returns true)
|
|
||||||
assertTrue(RequestUriUtil.isTrackableResource("/login"), "Login page should be trackable");
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isTrackableResource("/register"),
|
|
||||||
"Register page should be trackable");
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isTrackableResource("/api/v1/users"),
|
|
||||||
"API users should be trackable");
|
|
||||||
assertTrue(RequestUriUtil.isTrackableResource("/"), "Root path should be trackable");
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isTrackableResource("/some-other-path"),
|
|
||||||
"Other paths should be trackable");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testIsTrackableResourceWithContextPath() {
|
|
||||||
String contextPath = "/myapp";
|
|
||||||
|
|
||||||
// Test with context path
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isTrackableResource(contextPath, "/js/script.js"),
|
|
||||||
"JS files should not be trackable with context path");
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isTrackableResource(contextPath, "/login"),
|
|
||||||
"Login page should be trackable with context path");
|
|
||||||
|
|
||||||
// Additional tests with context path
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isTrackableResource(contextPath, "/fonts/custom.woff"),
|
|
||||||
"Font files should not be trackable with context path");
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isTrackableResource(contextPath, "/images/header.png"),
|
|
||||||
"Images should not be trackable with context path");
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isTrackableResource(contextPath, "/swagger/ui.html"),
|
|
||||||
"Swagger UI should not be trackable with context path");
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isTrackableResource(contextPath, "/account/profile"),
|
|
||||||
"Account page should be trackable with context path");
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isTrackableResource(contextPath, "/pdf/view"),
|
|
||||||
"PDF view page should be trackable with context path");
|
|
||||||
}
|
|
||||||
|
|
||||||
@ParameterizedTest
|
|
||||||
@ValueSource(
|
|
||||||
strings = {
|
|
||||||
"/js/util.js",
|
|
||||||
"/v1/api-docs/swagger.json",
|
|
||||||
"/robots.txt",
|
|
||||||
"/images/header/logo.png",
|
|
||||||
"/styles/theme.css",
|
|
||||||
"/build/app.js.map",
|
|
||||||
"/assets/icon.svg",
|
|
||||||
"/data/popularity.txt",
|
|
||||||
"/bundle.js",
|
|
||||||
"/api/swagger-ui.html",
|
|
||||||
"/api/v1/info/health",
|
|
||||||
"/site.webmanifest",
|
|
||||||
"/fonts/roboto.woff",
|
|
||||||
"/pdfjs/viewer.js"
|
|
||||||
})
|
|
||||||
void testNonTrackableResources(String path) {
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isTrackableResource(path),
|
|
||||||
"Resources matching patterns should not be trackable: " + path);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ParameterizedTest
|
|
||||||
@ValueSource(
|
|
||||||
strings = {
|
|
||||||
"/",
|
|
||||||
"/home",
|
|
||||||
"/login",
|
|
||||||
"/register",
|
|
||||||
"/pdf/merge",
|
|
||||||
"/pdf/split",
|
|
||||||
"/api/v1/users/1",
|
|
||||||
"/api/v1/documents/process",
|
|
||||||
"/settings",
|
|
||||||
"/account/profile",
|
|
||||||
"/dashboard",
|
|
||||||
"/help",
|
|
||||||
"/about"
|
|
||||||
})
|
|
||||||
void testTrackableResources(String path) {
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isTrackableResource(path),
|
|
||||||
"App routes should be trackable: " + path);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testEdgeCases() {
|
|
||||||
// Test with empty strings
|
|
||||||
assertFalse(RequestUriUtil.isStaticResource("", ""), "Empty path should not be static");
|
|
||||||
assertTrue(RequestUriUtil.isTrackableResource("", ""), "Empty path should be trackable");
|
|
||||||
|
|
||||||
// Test with null-like behavior (would actually throw NPE in real code)
|
|
||||||
// These are not actual null tests but shows handling of odd cases
|
|
||||||
assertFalse(RequestUriUtil.isStaticResource("null"), "String 'null' should not be static");
|
|
||||||
|
|
||||||
// Test String "null" as a path
|
|
||||||
boolean isTrackable = RequestUriUtil.isTrackableResource("null");
|
|
||||||
assertTrue(isTrackable, "String 'null' should be trackable");
|
|
||||||
|
|
||||||
// Mixed case extensions test - note that Java's endsWith() is case-sensitive
|
|
||||||
// We'll check actual behavior and document it rather than asserting
|
|
||||||
|
|
||||||
// Always test the lowercase versions which should definitely work
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isStaticResource("/logo.png"), "PNG (lowercase) should be static");
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isStaticResource("/icon.svg"), "SVG (lowercase) should be static");
|
|
||||||
|
|
||||||
// Path with query parameters
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isStaticResource("/api/users?page=1"),
|
|
||||||
"Path with query params should respect base path");
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isStaticResource("/images/logo.png?v=123"),
|
|
||||||
"Static resource with query params should still be static");
|
|
||||||
|
|
||||||
// Paths with fragments
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isStaticResource("/css/styles.css#section1"),
|
|
||||||
"CSS with fragment should be static");
|
|
||||||
|
|
||||||
// Multiple dots in filename
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isStaticResource("/js/jquery.min.js"),
|
|
||||||
"JS with multiple dots should be static");
|
|
||||||
|
|
||||||
// Special characters in path
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isStaticResource("/images/user's-photo.png"),
|
|
||||||
"Path with special chars should be handled correctly");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testComplexPaths() {
|
|
||||||
// Test complex static resource paths
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isStaticResource("/css/theme/dark/styles.css"),
|
|
||||||
"Nested CSS should be static");
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isStaticResource("/fonts/open-sans/bold/font.woff"),
|
|
||||||
"Nested font should be static");
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isStaticResource("/js/vendor/jquery/3.5.1/jquery.min.js"),
|
|
||||||
"Versioned JS should be static");
|
|
||||||
|
|
||||||
// Test complex paths with context
|
|
||||||
String contextPath = "/app";
|
|
||||||
assertTrue(
|
|
||||||
RequestUriUtil.isStaticResource(
|
|
||||||
contextPath, contextPath + "/css/theme/dark/styles.css"),
|
|
||||||
"Nested CSS with context should be static");
|
|
||||||
|
|
||||||
// Test boundary cases for isTrackableResource
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isTrackableResource("/js-framework/components"),
|
|
||||||
"Path starting with js- should not be treated as JS resource");
|
|
||||||
assertFalse(
|
|
||||||
RequestUriUtil.isTrackableResource("/fonts-selection"),
|
|
||||||
"Path starting with fonts- should not be treated as font resource");
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,311 @@
|
|||||||
|
package stirling.software.common.util;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
|
|
||||||
|
public class RequestUriUtilsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testIsStaticResource() {
|
||||||
|
// Test static resources without context path
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isStaticResource("/css/styles.css"), "CSS files should be static");
|
||||||
|
assertTrue(RequestUriUtils.isStaticResource("/js/script.js"), "JS files should be static");
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isStaticResource("/images/logo.png"),
|
||||||
|
"Image files should be static");
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isStaticResource("/public/index.html"),
|
||||||
|
"Public files should be static");
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isStaticResource("/pdfjs/pdf.worker.js"),
|
||||||
|
"PDF.js files should be static");
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isStaticResource("/api/v1/info/status"),
|
||||||
|
"API status should be static");
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isStaticResource("/some-path/icon.svg"),
|
||||||
|
"SVG files should be static");
|
||||||
|
assertTrue(RequestUriUtils.isStaticResource("/login"), "Login page should be static");
|
||||||
|
assertTrue(RequestUriUtils.isStaticResource("/error"), "Error page should be static");
|
||||||
|
|
||||||
|
// Test non-static resources
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isStaticResource("/api/v1/users"),
|
||||||
|
"API users should not be static");
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isStaticResource("/api/v1/orders"),
|
||||||
|
"API orders should not be static");
|
||||||
|
assertFalse(RequestUriUtils.isStaticResource("/"), "Root path should not be static");
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isStaticResource("/register"),
|
||||||
|
"Register page should not be static");
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isStaticResource("/api/v1/products"),
|
||||||
|
"API products should not be static");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testIsStaticResourceWithContextPath() {
|
||||||
|
String contextPath = "/myapp";
|
||||||
|
|
||||||
|
// Test static resources with context path
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isStaticResource(contextPath, contextPath + "/css/styles.css"),
|
||||||
|
"CSS with context path should be static");
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isStaticResource(contextPath, contextPath + "/js/script.js"),
|
||||||
|
"JS with context path should be static");
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isStaticResource(contextPath, contextPath + "/images/logo.png"),
|
||||||
|
"Images with context path should be static");
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isStaticResource(contextPath, contextPath + "/login"),
|
||||||
|
"Login with context path should be static");
|
||||||
|
|
||||||
|
// Test non-static resources with context path
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isStaticResource(contextPath, contextPath + "/api/v1/users"),
|
||||||
|
"API users with context path should not be static");
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isStaticResource(contextPath, "/"),
|
||||||
|
"Root path with context path should not be static");
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(
|
||||||
|
strings = {
|
||||||
|
"robots.txt",
|
||||||
|
"/favicon.ico",
|
||||||
|
"/icon.svg",
|
||||||
|
"/image.png",
|
||||||
|
"/site.webmanifest",
|
||||||
|
"/app/logo.svg",
|
||||||
|
"/downloads/document.png",
|
||||||
|
"/assets/brand.ico",
|
||||||
|
"/any/path/with/image.svg",
|
||||||
|
"/deep/nested/folder/icon.png"
|
||||||
|
})
|
||||||
|
void testIsStaticResourceWithFileExtensions(String path) {
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isStaticResource(path),
|
||||||
|
"Files with specific extensions should be static regardless of path");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testIsTrackableResource() {
|
||||||
|
// Test non-trackable resources (returns false)
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isTrackableResource("/js/script.js"),
|
||||||
|
"JS files should not be trackable");
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isTrackableResource("/v1/api-docs"),
|
||||||
|
"API docs should not be trackable");
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isTrackableResource("robots.txt"),
|
||||||
|
"robots.txt should not be trackable");
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isTrackableResource("/images/logo.png"),
|
||||||
|
"Images should not be trackable");
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isTrackableResource("/styles.css"),
|
||||||
|
"CSS files should not be trackable");
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isTrackableResource("/script.js.map"),
|
||||||
|
"Map files should not be trackable");
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isTrackableResource("/icon.svg"),
|
||||||
|
"SVG files should not be trackable");
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isTrackableResource("/popularity.txt"),
|
||||||
|
"Popularity file should not be trackable");
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isTrackableResource("/script.js"),
|
||||||
|
"JS files should not be trackable");
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isTrackableResource("/swagger/index.html"),
|
||||||
|
"Swagger files should not be trackable");
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isTrackableResource("/api/v1/info/status"),
|
||||||
|
"API info should not be trackable");
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isTrackableResource("/site.webmanifest"),
|
||||||
|
"Webmanifest should not be trackable");
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isTrackableResource("/fonts/font.woff"),
|
||||||
|
"Fonts should not be trackable");
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isTrackableResource("/pdfjs/viewer.js"),
|
||||||
|
"PDF.js files should not be trackable");
|
||||||
|
|
||||||
|
// Test trackable resources (returns true)
|
||||||
|
assertTrue(RequestUriUtils.isTrackableResource("/login"), "Login page should be trackable");
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isTrackableResource("/register"),
|
||||||
|
"Register page should be trackable");
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isTrackableResource("/api/v1/users"),
|
||||||
|
"API users should be trackable");
|
||||||
|
assertTrue(RequestUriUtils.isTrackableResource("/"), "Root path should be trackable");
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isTrackableResource("/some-other-path"),
|
||||||
|
"Other paths should be trackable");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testIsTrackableResourceWithContextPath() {
|
||||||
|
String contextPath = "/myapp";
|
||||||
|
|
||||||
|
// Test with context path
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isTrackableResource(contextPath, "/js/script.js"),
|
||||||
|
"JS files should not be trackable with context path");
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isTrackableResource(contextPath, "/login"),
|
||||||
|
"Login page should be trackable with context path");
|
||||||
|
|
||||||
|
// Additional tests with context path
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isTrackableResource(contextPath, "/fonts/custom.woff"),
|
||||||
|
"Font files should not be trackable with context path");
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isTrackableResource(contextPath, "/images/header.png"),
|
||||||
|
"Images should not be trackable with context path");
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isTrackableResource(contextPath, "/swagger/ui.html"),
|
||||||
|
"Swagger UI should not be trackable with context path");
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isTrackableResource(contextPath, "/account/profile"),
|
||||||
|
"Account page should be trackable with context path");
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isTrackableResource(contextPath, "/pdf/view"),
|
||||||
|
"PDF view page should be trackable with context path");
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(
|
||||||
|
strings = {
|
||||||
|
"/js/util.js",
|
||||||
|
"/v1/api-docs/swagger.json",
|
||||||
|
"/robots.txt",
|
||||||
|
"/images/header/logo.png",
|
||||||
|
"/styles/theme.css",
|
||||||
|
"/build/app.js.map",
|
||||||
|
"/assets/icon.svg",
|
||||||
|
"/data/popularity.txt",
|
||||||
|
"/bundle.js",
|
||||||
|
"/api/swagger-ui.html",
|
||||||
|
"/api/v1/info/health",
|
||||||
|
"/site.webmanifest",
|
||||||
|
"/fonts/roboto.woff",
|
||||||
|
"/pdfjs/viewer.js"
|
||||||
|
})
|
||||||
|
void testNonTrackableResources(String path) {
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isTrackableResource(path),
|
||||||
|
"Resources matching patterns should not be trackable: " + path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(
|
||||||
|
strings = {
|
||||||
|
"/",
|
||||||
|
"/home",
|
||||||
|
"/login",
|
||||||
|
"/register",
|
||||||
|
"/pdf/merge",
|
||||||
|
"/pdf/split",
|
||||||
|
"/api/v1/users/1",
|
||||||
|
"/api/v1/documents/process",
|
||||||
|
"/settings",
|
||||||
|
"/account/profile",
|
||||||
|
"/dashboard",
|
||||||
|
"/help",
|
||||||
|
"/about"
|
||||||
|
})
|
||||||
|
void testTrackableResources(String path) {
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isTrackableResource(path),
|
||||||
|
"App routes should be trackable: " + path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testEdgeCases() {
|
||||||
|
// Test with empty strings
|
||||||
|
assertFalse(RequestUriUtils.isStaticResource("", ""), "Empty path should not be static");
|
||||||
|
assertTrue(RequestUriUtils.isTrackableResource("", ""), "Empty path should be trackable");
|
||||||
|
|
||||||
|
// Test with null-like behavior (would actually throw NPE in real code)
|
||||||
|
// These are not actual null tests but shows handling of odd cases
|
||||||
|
assertFalse(RequestUriUtils.isStaticResource("null"), "String 'null' should not be static");
|
||||||
|
|
||||||
|
// Test String "null" as a path
|
||||||
|
boolean isTrackable = RequestUriUtils.isTrackableResource("null");
|
||||||
|
assertTrue(isTrackable, "String 'null' should be trackable");
|
||||||
|
|
||||||
|
// Mixed case extensions test - note that Java's endsWith() is case-sensitive
|
||||||
|
// We'll check actual behavior and document it rather than asserting
|
||||||
|
|
||||||
|
// Always test the lowercase versions which should definitely work
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isStaticResource("/logo.png"), "PNG (lowercase) should be static");
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isStaticResource("/icon.svg"), "SVG (lowercase) should be static");
|
||||||
|
|
||||||
|
// Path with query parameters
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isStaticResource("/api/users?page=1"),
|
||||||
|
"Path with query params should respect base path");
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isStaticResource("/images/logo.png?v=123"),
|
||||||
|
"Static resource with query params should still be static");
|
||||||
|
|
||||||
|
// Paths with fragments
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isStaticResource("/css/styles.css#section1"),
|
||||||
|
"CSS with fragment should be static");
|
||||||
|
|
||||||
|
// Multiple dots in filename
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isStaticResource("/js/jquery.min.js"),
|
||||||
|
"JS with multiple dots should be static");
|
||||||
|
|
||||||
|
// Special characters in path
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isStaticResource("/images/user's-photo.png"),
|
||||||
|
"Path with special chars should be handled correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testComplexPaths() {
|
||||||
|
// Test complex static resource paths
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isStaticResource("/css/theme/dark/styles.css"),
|
||||||
|
"Nested CSS should be static");
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isStaticResource("/fonts/open-sans/bold/font.woff"),
|
||||||
|
"Nested font should be static");
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isStaticResource("/js/vendor/jquery/3.5.1/jquery.min.js"),
|
||||||
|
"Versioned JS should be static");
|
||||||
|
|
||||||
|
// Test complex paths with context
|
||||||
|
String contextPath = "/app";
|
||||||
|
assertTrue(
|
||||||
|
RequestUriUtils.isStaticResource(
|
||||||
|
contextPath, contextPath + "/css/theme/dark/styles.css"),
|
||||||
|
"Nested CSS with context should be static");
|
||||||
|
|
||||||
|
// Test boundary cases for isTrackableResource
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isTrackableResource("/js-framework/components"),
|
||||||
|
"Path starting with js- should not be treated as JS resource");
|
||||||
|
assertFalse(
|
||||||
|
RequestUriUtils.isTrackableResource("/fonts-selection"),
|
||||||
|
"Path starting with fonts- should not be treated as font resource");
|
||||||
|
}
|
||||||
|
}
|
@ -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:
|
||||||
WITHOUT_ENHANCED_FEATURES: "false"
|
ADDITIONAL_FEATURES_OFF: "false"
|
||||||
SECURITY_ENABLELOGIN: "false"
|
SECURITY_ENABLELOGIN: "false"
|
||||||
PUID: 1002
|
PUID: 1002
|
||||||
PGID: 1002
|
PGID: 1002
|
||||||
|
@ -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:
|
||||||
WITHOUT_ENHANCED_FEATURES: "false"
|
ADDITIONAL_FEATURES_OFF: "false"
|
||||||
SECURITY_ENABLELOGIN: "false"
|
SECURITY_ENABLELOGIN: "false"
|
||||||
PUID: 1002
|
PUID: 1002
|
||||||
PGID: 1002
|
PGID: 1002
|
||||||
|
@ -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:
|
||||||
WITHOUT_ENHANCED_FEATURES: "false"
|
ADDITIONAL_FEATURES_OFF: "false"
|
||||||
SECURITY_ENABLELOGIN: "false"
|
SECURITY_ENABLELOGIN: "false"
|
||||||
PUID: 1002
|
PUID: 1002
|
||||||
PGID: 1002
|
PGID: 1002
|
||||||
|
@ -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:
|
||||||
WITHOUT_ENHANCED_FEATURES: "false"
|
ADDITIONAL_FEATURES_OFF: "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
|
||||||
|
@ -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:
|
||||||
WITHOUT_ENHANCED_FEATURES: "false"
|
ADDITIONAL_FEATURES_OFF: "false"
|
||||||
SECURITY_ENABLELOGIN: "true"
|
SECURITY_ENABLELOGIN: "true"
|
||||||
PUID: 1002
|
PUID: 1002
|
||||||
PGID: 1002
|
PGID: 1002
|
||||||
|
@ -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:
|
||||||
WITHOUT_ENHANCED_FEATURES: "false"
|
ADDITIONAL_FEATURES_OFF: "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
|
||||||
|
@ -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:
|
||||||
WITHOUT_ENHANCED_FEATURES: "true"
|
ADDITIONAL_FEATURES_OFF: "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
|
||||||
|
@ -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:
|
||||||
WITHOUT_ENHANCED_FEATURES: "true"
|
ADDITIONAL_FEATURES_OFF: "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
|
||||||
|
@ -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:
|
||||||
WITHOUT_ENHANCED_FEATURES: "false"
|
ADDITIONAL_FEATURES_OFF: "false"
|
||||||
SECURITY_ENABLELOGIN: "true"
|
SECURITY_ENABLELOGIN: "true"
|
||||||
PUID: 1002
|
PUID: 1002
|
||||||
PGID: 1002
|
PGID: 1002
|
||||||
|
@ -1,45 +1,51 @@
|
|||||||
Stirling PDF Enterprise Edition (EE) license (the “EE License”)
|
Stirling PDF User License
|
||||||
|
|
||||||
Copyright (c) 2025-present Stirling Tools
|
Copyright (c) 2025 Stirling PDF Inc.
|
||||||
|
|
||||||
With regard to the Stirling PDF Software:
|
License Scope & Usage Rights
|
||||||
|
|
||||||
This software and associated documentation files (the "Software") may only be
|
Production use of the Stirling PDF Software is only permitted with a valid Stirling PDF User License.
|
||||||
used in production, if you (and any entity that you represent) have agreed to,
|
|
||||||
and are in compliance with, the Stirling PDF Terms of Service, available
|
|
||||||
at https://www.stirlingpdf.com/terms-and-conditions (the “EE Terms”), or other
|
|
||||||
agreement governing the use of the Software, as agreed by you and Stirling PDF,
|
|
||||||
and otherwise have a valid Stirling PDF Enterprise Edition subscription for the
|
|
||||||
correct number of user seats. Subject to the foregoing sentence, you are free to
|
|
||||||
modify this Software and publish patches to the Software. You agree that Stirling PDF
|
|
||||||
and/or its licensors (as applicable) retain all right, title and interest in and
|
|
||||||
to all such modifications and/or patches, and all such modifications and/or
|
|
||||||
patches may only be used, copied, modified, displayed, distributed, or otherwise
|
|
||||||
exploited with a valid Stirling PDF Enterprise Edition subscription for the correct
|
|
||||||
number of user seats. Notwithstanding the foregoing, you may copy and modify
|
|
||||||
the Software for development and testing purposes, without requiring a
|
|
||||||
subscription. You agree that Stirling PDF and/or its licensors (as applicable) retain
|
|
||||||
all right, title and interest in and to all such modifications. You are not
|
|
||||||
granted any other rights beyond what is expressly stated herein. Subject to the
|
|
||||||
foregoing, it is forbidden to copy, merge, publish, distribute, sublicense,
|
|
||||||
and/or sell the Software.
|
|
||||||
|
|
||||||
This EE License applies only to the part of this Software that is not
|
For purposes of this license, “the Software” refers to the Stirling PDF application and any associated documentation files
|
||||||
distributed as part of MIT License. Any part of this Software
|
provided by Stirling PDF Inc. You or your organization may not use the Software in production, at scale, or for business-critical
|
||||||
distributed as part of MIT License or is served client-side as an image, font,
|
processes unless you have agreed to, and remain in compliance with, the Stirling PDF Subscription Terms of Service
|
||||||
cascading stylesheet (CSS), file which produces or is compiled, arranged,
|
(https://www.stirlingpdf.com/terms) or another valid agreement with Stirling PDF, and hold an active User License subscription
|
||||||
augmented, or combined into client-side JavaScript, in whole or in part, is
|
covering the appropriate number of licensed users.
|
||||||
copyrighted under the MIT Expat license. The full text of this EE License shall
|
|
||||||
be included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
Trial and Minimal Use
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
||||||
For all third party components incorporated into the Stirling PDF Software, those
|
You may use the Software without a paid subscription for the sole purposes of internal trial, evaluation, or minimal use, provided that:
|
||||||
components are licensed under the original license provided by the owner of the
|
* Use is limited to the capabilities and restrictions defined by the Software itself;
|
||||||
applicable component.
|
* 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.
|
||||||
|
@ -1,41 +1,29 @@
|
|||||||
plugins {
|
|
||||||
id 'java-library'
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
maven { url = "https://build.shibboleth.net/maven/releases" }
|
maven { url = "https://build.shibboleth.net/maven/releases" }
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
|
||||||
}
|
|
||||||
|
|
||||||
bootJar {
|
|
||||||
enabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(':common')
|
implementation project(':common')
|
||||||
|
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-jetty'
|
api 'org.springframework:spring-jdbc'
|
||||||
implementation 'io.swagger.core.v3:swagger-core-jakarta:2.2.30'
|
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'
|
implementation 'com.bucket4j:bucket4j_jdk17-core:8.14.0'
|
||||||
|
|
||||||
// https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17
|
// https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17
|
||||||
implementation 'org.bouncycastle:bcprov-jdk18on:1.80'
|
implementation 'org.bouncycastle:bcprov-jdk18on:1.80'
|
||||||
|
|
||||||
implementation 'org.springframework:spring-jdbc:6.2.6'
|
implementation 'io.github.pixee:java-security-toolkit:1.2.1'
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-security'
|
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
|
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-mail'
|
|
||||||
implementation "org.springframework.security:spring-security-core:$springSecuritySamlVersion"
|
|
||||||
implementation "org.springframework.security:spring-security-saml2-service-provider:$springSecuritySamlVersion"
|
|
||||||
implementation 'org.springframework.session:spring-session-core:3.4.3'
|
|
||||||
|
|
||||||
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.3.RELEASE'
|
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.3.RELEASE'
|
||||||
implementation 'io.micrometer:micrometer-registry-prometheus'
|
api 'io.micrometer:micrometer-registry-prometheus'
|
||||||
implementation 'com.unboundid.product.scim2:scim2-sdk-client:2.3.5'
|
implementation 'com.unboundid.product.scim2:scim2-sdk-client:2.3.5'
|
||||||
runtimeOnly 'com.h2database:h2:2.3.232' // Don't upgrade h2database
|
runtimeOnly 'com.h2database:h2:2.3.232' // Don't upgrade h2database
|
||||||
runtimeOnly 'org.postgresql:postgresql:42.7.5'
|
runtimeOnly 'org.postgresql:postgresql:42.7.5'
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
|
||||||
distributionPath=wrapper/dists
|
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip
|
|
||||||
validateDistributionUrl=true
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
|
||||||
zipStorePath=wrapper/dists
|
|
251
proprietary/gradlew
vendored
251
proprietary/gradlew
vendored
@ -1,251 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright © 2015-2021 the original authors.
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
#
|
|
||||||
|
|
||||||
##############################################################################
|
|
||||||
#
|
|
||||||
# Gradle start up script for POSIX generated by Gradle.
|
|
||||||
#
|
|
||||||
# Important for running:
|
|
||||||
#
|
|
||||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
|
||||||
# noncompliant, but you have some other compliant shell such as ksh or
|
|
||||||
# bash, then to run this script, type that shell name before the whole
|
|
||||||
# command line, like:
|
|
||||||
#
|
|
||||||
# ksh Gradle
|
|
||||||
#
|
|
||||||
# Busybox and similar reduced shells will NOT work, because this script
|
|
||||||
# requires all of these POSIX shell features:
|
|
||||||
# * functions;
|
|
||||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
|
||||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
|
||||||
# * compound commands having a testable exit status, especially «case»;
|
|
||||||
# * various built-in commands including «command», «set», and «ulimit».
|
|
||||||
#
|
|
||||||
# Important for patching:
|
|
||||||
#
|
|
||||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
|
||||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
|
||||||
#
|
|
||||||
# The "traditional" practice of packing multiple parameters into a
|
|
||||||
# space-separated string is a well documented source of bugs and security
|
|
||||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
|
||||||
# options in "$@", and eventually passing that to Java.
|
|
||||||
#
|
|
||||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
|
||||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
|
||||||
# see the in-line comments for details.
|
|
||||||
#
|
|
||||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
|
||||||
# Darwin, MinGW, and NonStop.
|
|
||||||
#
|
|
||||||
# (3) This script is generated from the Groovy template
|
|
||||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
|
||||||
# within the Gradle project.
|
|
||||||
#
|
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
|
||||||
#
|
|
||||||
##############################################################################
|
|
||||||
|
|
||||||
# Attempt to set APP_HOME
|
|
||||||
|
|
||||||
# Resolve links: $0 may be a link
|
|
||||||
app_path=$0
|
|
||||||
|
|
||||||
# Need this for daisy-chained symlinks.
|
|
||||||
while
|
|
||||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
|
||||||
[ -h "$app_path" ]
|
|
||||||
do
|
|
||||||
ls=$( ls -ld "$app_path" )
|
|
||||||
link=${ls#*' -> '}
|
|
||||||
case $link in #(
|
|
||||||
/*) app_path=$link ;; #(
|
|
||||||
*) app_path=$APP_HOME$link ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
# This is normally unused
|
|
||||||
# shellcheck disable=SC2034
|
|
||||||
APP_BASE_NAME=${0##*/}
|
|
||||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
|
||||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
|
||||||
MAX_FD=maximum
|
|
||||||
|
|
||||||
warn () {
|
|
||||||
echo "$*"
|
|
||||||
} >&2
|
|
||||||
|
|
||||||
die () {
|
|
||||||
echo
|
|
||||||
echo "$*"
|
|
||||||
echo
|
|
||||||
exit 1
|
|
||||||
} >&2
|
|
||||||
|
|
||||||
# OS specific support (must be 'true' or 'false').
|
|
||||||
cygwin=false
|
|
||||||
msys=false
|
|
||||||
darwin=false
|
|
||||||
nonstop=false
|
|
||||||
case "$( uname )" in #(
|
|
||||||
CYGWIN* ) cygwin=true ;; #(
|
|
||||||
Darwin* ) darwin=true ;; #(
|
|
||||||
MSYS* | MINGW* ) msys=true ;; #(
|
|
||||||
NONSTOP* ) nonstop=true ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
CLASSPATH="\\\"\\\""
|
|
||||||
|
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
|
||||||
if [ -n "$JAVA_HOME" ] ; then
|
|
||||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
|
||||||
# IBM's JDK on AIX uses strange locations for the executables
|
|
||||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
|
||||||
else
|
|
||||||
JAVACMD=$JAVA_HOME/bin/java
|
|
||||||
fi
|
|
||||||
if [ ! -x "$JAVACMD" ] ; then
|
|
||||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
|
||||||
location of your Java installation."
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
JAVACMD=java
|
|
||||||
if ! command -v java >/dev/null 2>&1
|
|
||||||
then
|
|
||||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
|
||||||
location of your Java installation."
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
|
||||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|
||||||
case $MAX_FD in #(
|
|
||||||
max*)
|
|
||||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
|
||||||
# shellcheck disable=SC2039,SC3045
|
|
||||||
MAX_FD=$( ulimit -H -n ) ||
|
|
||||||
warn "Could not query maximum file descriptor limit"
|
|
||||||
esac
|
|
||||||
case $MAX_FD in #(
|
|
||||||
'' | soft) :;; #(
|
|
||||||
*)
|
|
||||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
|
||||||
# shellcheck disable=SC2039,SC3045
|
|
||||||
ulimit -n "$MAX_FD" ||
|
|
||||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Collect all arguments for the java command, stacking in reverse order:
|
|
||||||
# * args from the command line
|
|
||||||
# * the main class name
|
|
||||||
# * -classpath
|
|
||||||
# * -D...appname settings
|
|
||||||
# * --module-path (only if needed)
|
|
||||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
|
||||||
|
|
||||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
|
||||||
if "$cygwin" || "$msys" ; then
|
|
||||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
|
||||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
|
||||||
|
|
||||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
|
||||||
|
|
||||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
|
||||||
for arg do
|
|
||||||
if
|
|
||||||
case $arg in #(
|
|
||||||
-*) false ;; # don't mess with options #(
|
|
||||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
|
||||||
[ -e "$t" ] ;; #(
|
|
||||||
*) false ;;
|
|
||||||
esac
|
|
||||||
then
|
|
||||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
|
||||||
fi
|
|
||||||
# Roll the args list around exactly as many times as the number of
|
|
||||||
# args, so each arg winds up back in the position where it started, but
|
|
||||||
# possibly modified.
|
|
||||||
#
|
|
||||||
# NB: a `for` loop captures its iteration list before it begins, so
|
|
||||||
# changing the positional parameters here affects neither the number of
|
|
||||||
# iterations, nor the values presented in `arg`.
|
|
||||||
shift # remove old arg
|
|
||||||
set -- "$@" "$arg" # push replacement arg
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
|
||||||
|
|
||||||
# Collect all arguments for the java command:
|
|
||||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
|
||||||
# and any embedded shellness will be escaped.
|
|
||||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
|
||||||
# treated as '${Hostname}' itself on the command line.
|
|
||||||
|
|
||||||
set -- \
|
|
||||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
|
||||||
-classpath "$CLASSPATH" \
|
|
||||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
|
||||||
"$@"
|
|
||||||
|
|
||||||
# Stop when "xargs" is not available.
|
|
||||||
if ! command -v xargs >/dev/null 2>&1
|
|
||||||
then
|
|
||||||
die "xargs is not available"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Use "xargs" to parse quoted args.
|
|
||||||
#
|
|
||||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
|
||||||
#
|
|
||||||
# In Bash we could simply go:
|
|
||||||
#
|
|
||||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
|
||||||
# set -- "${ARGS[@]}" "$@"
|
|
||||||
#
|
|
||||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
|
||||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
|
||||||
# character that might be a shell metacharacter, then use eval to reverse
|
|
||||||
# that process (while maintaining the separation between arguments), and wrap
|
|
||||||
# the whole thing up as a single "set" statement.
|
|
||||||
#
|
|
||||||
# This will of course break if any of these variables contains a newline or
|
|
||||||
# an unmatched quote.
|
|
||||||
#
|
|
||||||
|
|
||||||
eval "set -- $(
|
|
||||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
|
||||||
xargs -n1 |
|
|
||||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
|
||||||
tr '\n' ' '
|
|
||||||
)" '"$@"'
|
|
||||||
|
|
||||||
exec "$JAVACMD" "$@"
|
|
94
proprietary/gradlew.bat
vendored
94
proprietary/gradlew.bat
vendored
@ -1,94 +0,0 @@
|
|||||||
@rem
|
|
||||||
@rem Copyright 2015 the original author or authors.
|
|
||||||
@rem
|
|
||||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
@rem you may not use this file except in compliance with the License.
|
|
||||||
@rem You may obtain a copy of the License at
|
|
||||||
@rem
|
|
||||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
@rem
|
|
||||||
@rem Unless required by applicable law or agreed to in writing, software
|
|
||||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
@rem See the License for the specific language governing permissions and
|
|
||||||
@rem limitations under the License.
|
|
||||||
@rem
|
|
||||||
@rem SPDX-License-Identifier: Apache-2.0
|
|
||||||
@rem
|
|
||||||
|
|
||||||
@if "%DEBUG%"=="" @echo off
|
|
||||||
@rem ##########################################################################
|
|
||||||
@rem
|
|
||||||
@rem Gradle startup script for Windows
|
|
||||||
@rem
|
|
||||||
@rem ##########################################################################
|
|
||||||
|
|
||||||
@rem Set local scope for the variables with windows NT shell
|
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
|
||||||
if "%DIRNAME%"=="" set DIRNAME=.
|
|
||||||
@rem This is normally unused
|
|
||||||
set APP_BASE_NAME=%~n0
|
|
||||||
set APP_HOME=%DIRNAME%
|
|
||||||
|
|
||||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
|
||||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
||||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
|
||||||
|
|
||||||
@rem Find java.exe
|
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
|
||||||
|
|
||||||
set JAVA_EXE=java.exe
|
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
|
||||||
if %ERRORLEVEL% equ 0 goto execute
|
|
||||||
|
|
||||||
echo. 1>&2
|
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
|
||||||
echo. 1>&2
|
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
|
||||||
echo location of your Java installation. 1>&2
|
|
||||||
|
|
||||||
goto fail
|
|
||||||
|
|
||||||
:findJavaFromJavaHome
|
|
||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
|
||||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
|
||||||
|
|
||||||
echo. 1>&2
|
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
|
||||||
echo. 1>&2
|
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
|
||||||
echo location of your Java installation. 1>&2
|
|
||||||
|
|
||||||
goto fail
|
|
||||||
|
|
||||||
:execute
|
|
||||||
@rem Setup the command line
|
|
||||||
|
|
||||||
set CLASSPATH=
|
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
|
||||||
|
|
||||||
:end
|
|
||||||
@rem End local scope for the variables with windows NT shell
|
|
||||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
|
||||||
|
|
||||||
:fail
|
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
|
||||||
rem the _cmd.exe /c_ return code!
|
|
||||||
set EXIT_CODE=%ERRORLEVEL%
|
|
||||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
|
||||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
|
||||||
exit /b %EXIT_CODE%
|
|
||||||
|
|
||||||
:mainEnd
|
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
|
||||||
|
|
||||||
:omega
|
|
@ -1,11 +1,8 @@
|
|||||||
package stirling.software.proprietary.security;
|
package stirling.software.proprietary.security;
|
||||||
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.security.authentication.BadCredentialsException;
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
import org.springframework.security.authentication.DisabledException;
|
import org.springframework.security.authentication.DisabledException;
|
||||||
import org.springframework.security.authentication.InternalAuthenticationServiceException;
|
import org.springframework.security.authentication.InternalAuthenticationServiceException;
|
||||||
@ -13,6 +10,13 @@ import org.springframework.security.authentication.LockedException;
|
|||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
||||||
|
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.proprietary.security.model.User;
|
import stirling.software.proprietary.security.model.User;
|
||||||
import stirling.software.proprietary.security.service.LoginAttemptService;
|
import stirling.software.proprietary.security.service.LoginAttemptService;
|
||||||
import stirling.software.proprietary.security.service.UserService;
|
import stirling.software.proprietary.security.service.UserService;
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
package stirling.software.proprietary.security;
|
package stirling.software.proprietary.security;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
|
||||||
|
import org.springframework.security.web.savedrequest.SavedRequest;
|
||||||
|
|
||||||
import jakarta.servlet.ServletException;
|
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 jakarta.servlet.http.HttpSession;
|
import jakarta.servlet.http.HttpSession;
|
||||||
import java.io.IOException;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
|
import stirling.software.common.util.RequestUriUtils;
|
||||||
import org.springframework.security.web.savedrequest.SavedRequest;
|
|
||||||
import stirling.software.common.util.RequestUriUtil;
|
|
||||||
import stirling.software.proprietary.security.service.LoginAttemptService;
|
import stirling.software.proprietary.security.service.LoginAttemptService;
|
||||||
import stirling.software.proprietary.security.service.UserService;
|
import stirling.software.proprietary.security.service.UserService;
|
||||||
|
|
||||||
@ -46,7 +50,7 @@ public class CustomAuthenticationSuccessHandler
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (savedRequest != null
|
if (savedRequest != null
|
||||||
&& !RequestUriUtil.isStaticResource(
|
&& !RequestUriUtils.isStaticResource(
|
||||||
request.getContextPath(), savedRequest.getRedirectUrl())) {
|
request.getContextPath(), savedRequest.getRedirectUrl())) {
|
||||||
// Redirect to the original destination
|
// Redirect to the original destination
|
||||||
super.onAuthenticationSuccess(request, response, authentication);
|
super.onAuthenticationSuccess(request, response, authentication);
|
||||||
|
@ -1,27 +1,32 @@
|
|||||||
package stirling.software.proprietary.security;
|
package stirling.software.proprietary.security;
|
||||||
|
|
||||||
import com.coveo.saml.SamlClient;
|
|
||||||
import com.coveo.saml.SamlException;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.security.interfaces.RSAPrivateKey;
|
import java.security.interfaces.RSAPrivateKey;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||||
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
|
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
|
||||||
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
|
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
|
||||||
|
|
||||||
|
import com.coveo.saml.SamlClient;
|
||||||
|
import com.coveo.saml.SamlException;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.common.configuration.AppConfig;
|
import stirling.software.common.configuration.AppConfig;
|
||||||
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.provider.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.CertificateUtils;
|
||||||
import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal;
|
import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal;
|
||||||
@ -33,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;
|
private final AppConfig appConfig;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -171,9 +177,7 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
|
|||||||
private SamlClient getSamlClient(
|
private SamlClient getSamlClient(
|
||||||
String registrationId, SAML2 samlConf, List<X509Certificate> certificates)
|
String registrationId, SAML2 samlConf, List<X509Certificate> certificates)
|
||||||
throws SamlException {
|
throws SamlException {
|
||||||
// fixMe: move to a config class
|
String serverUrl = appConfig.getBaseUrl() + ":" + appConfig.getServerPort();
|
||||||
String serverUrl =
|
|
||||||
appConfig.getBaseUrl() + ":" + appConfig.getServerPort();
|
|
||||||
|
|
||||||
String relyingPartyIdentifier =
|
String relyingPartyIdentifier =
|
||||||
serverUrl + "/saml2/service-provider-metadata/" + registrationId;
|
serverUrl + "/saml2/service-provider-metadata/" + registrationId;
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
package stirling.software.proprietary.security;
|
package stirling.software.proprietary.security;
|
||||||
|
|
||||||
import jakarta.annotation.PostConstruct;
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import stirling.software.common.model.ApplicationProperties;
|
import stirling.software.common.model.ApplicationProperties;
|
||||||
import stirling.software.common.model.exception.UnsupportedProviderException;
|
|
||||||
import stirling.software.common.model.enumeration.Role;
|
import stirling.software.common.model.enumeration.Role;
|
||||||
|
import stirling.software.common.model.exception.UnsupportedProviderException;
|
||||||
import stirling.software.proprietary.security.service.DatabaseServiceInterface;
|
import stirling.software.proprietary.security.service.DatabaseServiceInterface;
|
||||||
import stirling.software.proprietary.security.service.UserService;
|
import stirling.software.proprietary.security.service.UserService;
|
||||||
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package stirling.software.proprietary.security;
|
package stirling.software.proprietary.security;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
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 stirling.software.proprietary.security.filter.IPRateLimitingFilter;
|
import stirling.software.proprietary.security.filter.IPRateLimitingFilter;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
package stirling.software.proprietary.security.configuration;
|
package stirling.software.proprietary.security.configuration;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
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.autoconfigure.domain.EntityScan;
|
||||||
import org.springframework.boot.jdbc.DataSourceBuilder;
|
import org.springframework.boot.jdbc.DataSourceBuilder;
|
||||||
import org.springframework.boot.jdbc.DatabaseDriver;
|
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 org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
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.exception.UnsupportedProviderException;
|
import stirling.software.common.model.exception.UnsupportedProviderException;
|
||||||
@ -54,14 +58,27 @@ 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()) {
|
||||||
@ -85,16 +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)
|
|
||||||
.driverClassName(DatabaseDriver.H2.getDriverClassName())
|
|
||||||
.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
|
||||||
*
|
*
|
||||||
|
@ -10,6 +10,7 @@ import org.springframework.mail.javamail.JavaMailSenderImpl;
|
|||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.common.model.ApplicationProperties;
|
import stirling.software.common.model.ApplicationProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package stirling.software.proprietary.security.configuration;
|
package stirling.software.proprietary.security.configuration;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
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;
|
||||||
@ -26,7 +26,10 @@ import org.springframework.security.web.authentication.rememberme.PersistentToke
|
|||||||
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
|
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
|
||||||
import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler;
|
import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler;
|
||||||
import org.springframework.security.web.savedrequest.NullRequestCache;
|
import org.springframework.security.web.savedrequest.NullRequestCache;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.common.configuration.AppConfig;
|
import stirling.software.common.configuration.AppConfig;
|
||||||
import stirling.software.common.model.ApplicationProperties;
|
import stirling.software.common.model.ApplicationProperties;
|
||||||
import stirling.software.proprietary.security.CustomAuthenticationFailureHandler;
|
import stirling.software.proprietary.security.CustomAuthenticationFailureHandler;
|
||||||
@ -49,10 +52,10 @@ import stirling.software.proprietary.security.service.LoginAttemptService;
|
|||||||
import stirling.software.proprietary.security.service.UserService;
|
import stirling.software.proprietary.security.service.UserService;
|
||||||
import stirling.software.proprietary.security.session.SessionPersistentRegistry;
|
import stirling.software.proprietary.security.session.SessionPersistentRegistry;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@EnableMethodSecurity
|
@EnableMethodSecurity
|
||||||
@Slf4j
|
|
||||||
@DependsOn("runningProOrHigher")
|
@DependsOn("runningProOrHigher")
|
||||||
public class SecurityConfiguration {
|
public class SecurityConfiguration {
|
||||||
|
|
||||||
@ -167,9 +170,12 @@ public class SecurityConfiguration {
|
|||||||
http.requestCache(requestCache -> requestCache.requestCache(new NullRequestCache()));
|
http.requestCache(requestCache -> requestCache.requestCache(new NullRequestCache()));
|
||||||
http.logout(
|
http.logout(
|
||||||
logout ->
|
logout ->
|
||||||
logout.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
|
logout.logoutRequestMatcher(
|
||||||
|
PathPatternRequestMatcher.withDefaults()
|
||||||
|
.matcher("/logout"))
|
||||||
.logoutSuccessHandler(
|
.logoutSuccessHandler(
|
||||||
new CustomLogoutSuccessHandler(applicationProperties, appConfig))
|
new CustomLogoutSuccessHandler(
|
||||||
|
applicationProperties, appConfig))
|
||||||
.clearAuthentication(true)
|
.clearAuthentication(true)
|
||||||
.invalidateHttpSession(true)
|
.invalidateHttpSession(true)
|
||||||
.deleteCookies("JSESSIONID", "remember-me"));
|
.deleteCookies("JSESSIONID", "remember-me"));
|
||||||
@ -301,8 +307,7 @@ public class SecurityConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ 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.proprietary.security.database.H2SQLCondition;
|
import stirling.software.proprietary.security.database.H2SQLCondition;
|
||||||
import stirling.software.proprietary.security.service.DatabaseService;
|
import stirling.software.proprietary.security.service.DatabaseService;
|
||||||
|
|
||||||
|
@ -29,11 +29,11 @@ import jakarta.servlet.http.HttpServletResponse;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.proprietary.security.model.AuthenticationType;
|
|
||||||
import stirling.software.common.model.enumeration.Role;
|
|
||||||
import stirling.software.proprietary.security.model.User;
|
|
||||||
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.model.api.user.UsernameAndPass;
|
||||||
import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal;
|
import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal;
|
||||||
import stirling.software.proprietary.security.service.UserService;
|
import stirling.software.proprietary.security.service.UserService;
|
||||||
@ -172,15 +172,18 @@ public class UserController {
|
|||||||
*
|
*
|
||||||
* @param updates A map containing the settings to update. The expected structure is:
|
* @param updates A map containing the settings to update. The expected structure is:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li><b>emailNotifications</b> (optional): "true" or "false" - Enable or disable email notifications.</li>
|
* <li><b>emailNotifications</b> (optional): "true" or "false" - Enable or disable email
|
||||||
* <li><b>theme</b> (optional): "light" or "dark" - Set the user's preferred theme.</li>
|
* notifications.
|
||||||
* <li><b>language</b> (optional): A string representing the preferred language (e.g., "en", "fr").</li>
|
* <li><b>theme</b> (optional): "light" or "dark" - Set the user's preferred theme.
|
||||||
|
* <li><b>language</b> (optional): A string representing the preferred language (e.g.,
|
||||||
|
* "en", "fr").
|
||||||
* </ul>
|
* </ul>
|
||||||
* Keys not listed above will be ignored.
|
* Keys not listed above will be ignored.
|
||||||
* @param principal The currently authenticated user.
|
* @param principal The currently authenticated user.
|
||||||
* @return A redirect string to the account page after updating the settings.
|
* @return A redirect string to the account page after updating the settings.
|
||||||
* @throws SQLException If a database error occurs.
|
* @throws SQLException If a database error occurs.
|
||||||
* @throws UnsupportedProviderException If the operation is not supported for the user's provider.
|
* @throws UnsupportedProviderException If the operation is not supported for the user's
|
||||||
|
* provider.
|
||||||
*/
|
*/
|
||||||
public String updateUserSettings(@RequestBody Map<String, String> updates, Principal principal)
|
public String updateUserSettings(@RequestBody Map<String, String> updates, Principal principal)
|
||||||
throws SQLException, UnsupportedProviderException {
|
throws SQLException, UnsupportedProviderException {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package stirling.software.proprietary.security.controller.web;
|
package stirling.software.proprietary.security.controller.web;
|
||||||
|
|
||||||
import static stirling.software.common.util.ProviderUtil.validateProvider;
|
import static stirling.software.common.util.ProviderUtils.validateProvider;
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
@ -29,15 +29,15 @@ import jakarta.servlet.http.HttpServletRequest;
|
|||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.common.model.enumeration.Role;
|
|
||||||
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.oauth2.provider.GitHubProvider;
|
import stirling.software.common.model.enumeration.Role;
|
||||||
import stirling.software.common.model.oauth2.provider.GoogleProvider;
|
import stirling.software.common.model.oauth2.GitHubProvider;
|
||||||
import stirling.software.common.model.oauth2.provider.KeycloakProvider;
|
import stirling.software.common.model.oauth2.GoogleProvider;
|
||||||
|
import stirling.software.common.model.oauth2.KeycloakProvider;
|
||||||
import stirling.software.proprietary.security.database.repository.UserRepository;
|
import stirling.software.proprietary.security.database.repository.UserRepository;
|
||||||
import stirling.software.proprietary.security.model.Authority;
|
import stirling.software.proprietary.security.model.Authority;
|
||||||
import stirling.software.proprietary.security.model.SessionEntity;
|
import stirling.software.proprietary.security.model.SessionEntity;
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
package stirling.software.proprietary.security.database;
|
package stirling.software.proprietary.security.database;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.context.annotation.Conditional;
|
import org.springframework.context.annotation.Conditional;
|
||||||
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 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.DatabaseServiceInterface;
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ 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.proprietary.security.model.Authority;
|
import stirling.software.proprietary.security.model.Authority;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
|
@ -5,6 +5,7 @@ import java.util.Date;
|
|||||||
import org.springframework.security.web.authentication.rememberme.PersistentRememberMeToken;
|
import org.springframework.security.web.authentication.rememberme.PersistentRememberMeToken;
|
||||||
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.proprietary.security.model.PersistentLogin;
|
import stirling.software.proprietary.security.model.PersistentLogin;
|
||||||
|
|
||||||
public class JPATokenRepositoryImpl implements PersistentTokenRepository {
|
public class JPATokenRepositoryImpl implements PersistentTokenRepository {
|
||||||
|
@ -2,6 +2,7 @@ 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.proprietary.security.model.PersistentLogin;
|
import stirling.software.proprietary.security.model.PersistentLogin;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
package stirling.software.proprietary.security.database.repository;
|
package stirling.software.proprietary.security.database.repository;
|
||||||
|
|
||||||
import jakarta.transaction.Transactional;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.data.jpa.repository.Modifying;
|
import org.springframework.data.jpa.repository.Modifying;
|
||||||
import org.springframework.data.jpa.repository.Query;
|
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 jakarta.transaction.Transactional;
|
||||||
|
|
||||||
import stirling.software.proprietary.security.model.SessionEntity;
|
import stirling.software.proprietary.security.model.SessionEntity;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
|
@ -7,6 +7,7 @@ import org.springframework.data.jpa.repository.JpaRepository;
|
|||||||
import org.springframework.data.jpa.repository.Query;
|
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.proprietary.security.model.User;
|
import stirling.software.proprietary.security.model.User;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
|
@ -1,21 +1,25 @@
|
|||||||
package stirling.software.proprietary.security.filter;
|
package stirling.software.proprietary.security.filter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
import jakarta.servlet.FilterChain;
|
import jakarta.servlet.FilterChain;
|
||||||
import jakarta.servlet.ServletException;
|
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 jakarta.servlet.http.HttpSession;
|
import jakarta.servlet.http.HttpSession;
|
||||||
import java.io.IOException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Optional;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.context.annotation.Lazy;
|
|
||||||
import org.springframework.security.core.Authentication;
|
import stirling.software.common.util.RequestUriUtils;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
|
||||||
import stirling.software.common.util.RequestUriUtil;
|
|
||||||
import stirling.software.proprietary.security.model.User;
|
import stirling.software.proprietary.security.model.User;
|
||||||
import stirling.software.proprietary.security.service.UserService;
|
import stirling.software.proprietary.security.service.UserService;
|
||||||
|
|
||||||
@ -37,7 +41,7 @@ public class FirstLoginFilter extends OncePerRequestFilter {
|
|||||||
String requestURI = request.getRequestURI();
|
String requestURI = request.getRequestURI();
|
||||||
String contextPath = request.getContextPath();
|
String contextPath = request.getContextPath();
|
||||||
// Check if the request is for static resources
|
// Check if the request is for static resources
|
||||||
boolean isStaticResource = RequestUriUtil.isStaticResource(contextPath, requestURI);
|
boolean isStaticResource = RequestUriUtils.isStaticResource(contextPath, requestURI);
|
||||||
// If it's a static resource, just continue the filter chain and skip the logic below
|
// If it's a static resource, just continue the filter chain and skip the logic below
|
||||||
if (isStaticResource) {
|
if (isStaticResource) {
|
||||||
filterChain.doFilter(request, response);
|
filterChain.doFilter(request, response);
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
package stirling.software.proprietary.security.filter;
|
package stirling.software.proprietary.security.filter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import jakarta.servlet.Filter;
|
import jakarta.servlet.Filter;
|
||||||
import jakarta.servlet.FilterChain;
|
import jakarta.servlet.FilterChain;
|
||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import jakarta.servlet.ServletRequest;
|
import jakarta.servlet.ServletRequest;
|
||||||
import jakarta.servlet.ServletResponse;
|
import jakarta.servlet.ServletResponse;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import stirling.software.common.util.RequestUriUtil;
|
|
||||||
|
import stirling.software.common.util.RequestUriUtils;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class IPRateLimitingFilter implements Filter {
|
public class IPRateLimitingFilter implements Filter {
|
||||||
@ -30,7 +33,7 @@ public class IPRateLimitingFilter implements Filter {
|
|||||||
String requestURI = httpRequest.getRequestURI();
|
String requestURI = httpRequest.getRequestURI();
|
||||||
// Check if the request is for static resources
|
// Check if the request is for static resources
|
||||||
boolean isStaticResource =
|
boolean isStaticResource =
|
||||||
RequestUriUtil.isStaticResource(httpRequest.getContextPath(), requestURI);
|
RequestUriUtils.isStaticResource(httpRequest.getContextPath(), requestURI);
|
||||||
|
|
||||||
// If it's a static resource, just continue the filter chain and skip the logic below
|
// If it's a static resource, just continue the filter chain and skip the logic below
|
||||||
if (isStaticResource) {
|
if (isStaticResource) {
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
package stirling.software.proprietary.security.filter;
|
package stirling.software.proprietary.security.filter;
|
||||||
|
|
||||||
import jakarta.servlet.FilterChain;
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
@ -20,6 +16,14 @@ import org.springframework.security.core.userdetails.UserDetails;
|
|||||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
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;
|
||||||
|
@ -1,17 +1,10 @@
|
|||||||
package stirling.software.proprietary.security.filter;
|
package stirling.software.proprietary.security.filter;
|
||||||
|
|
||||||
import io.github.bucket4j.Bandwidth;
|
|
||||||
import io.github.bucket4j.Bucket;
|
|
||||||
import io.github.bucket4j.ConsumptionProbe;
|
|
||||||
import io.github.pixee.security.Newlines;
|
|
||||||
import jakarta.servlet.FilterChain;
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
@ -20,6 +13,17 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
|||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
import io.github.bucket4j.Bandwidth;
|
||||||
|
import io.github.bucket4j.Bucket;
|
||||||
|
import io.github.bucket4j.ConsumptionProbe;
|
||||||
|
import io.github.pixee.security.Newlines;
|
||||||
|
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import stirling.software.common.model.enumeration.Role;
|
import stirling.software.common.model.enumeration.Role;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
|
@ -14,6 +14,7 @@ import lombok.Getter;
|
|||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
import stirling.software.common.model.enumeration.Role;
|
import stirling.software.common.model.enumeration.Role;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
|
@ -7,6 +7,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import stirling.software.common.model.api.GeneralFile;
|
import stirling.software.common.model.api.GeneralFile;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
package stirling.software.proprietary.security.oauth2;
|
package stirling.software.proprietary.security.oauth2;
|
||||||
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.security.authentication.BadCredentialsException;
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
import org.springframework.security.authentication.DisabledException;
|
import org.springframework.security.authentication.DisabledException;
|
||||||
import org.springframework.security.authentication.LockedException;
|
import org.springframework.security.authentication.LockedException;
|
||||||
@ -13,6 +10,12 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
|||||||
import org.springframework.security.oauth2.core.OAuth2Error;
|
import org.springframework.security.oauth2.core.OAuth2Error;
|
||||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
||||||
|
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class CustomOAuth2AuthenticationFailureHandler
|
public class CustomOAuth2AuthenticationFailureHandler
|
||||||
extends SimpleUrlAuthenticationFailureHandler {
|
extends SimpleUrlAuthenticationFailureHandler {
|
||||||
|
@ -1,22 +1,26 @@
|
|||||||
package stirling.software.proprietary.security.oauth2;
|
package stirling.software.proprietary.security.oauth2;
|
||||||
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import jakarta.servlet.http.HttpSession;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.security.authentication.LockedException;
|
import org.springframework.security.authentication.LockedException;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||||
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
|
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
|
||||||
import org.springframework.security.web.savedrequest.SavedRequest;
|
import org.springframework.security.web.savedrequest.SavedRequest;
|
||||||
|
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import jakarta.servlet.http.HttpSession;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
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.RequestUriUtil;
|
import stirling.software.common.util.RequestUriUtils;
|
||||||
import stirling.software.proprietary.security.model.AuthenticationType;
|
import stirling.software.proprietary.security.model.AuthenticationType;
|
||||||
import stirling.software.proprietary.security.service.LoginAttemptService;
|
import stirling.software.proprietary.security.service.LoginAttemptService;
|
||||||
import stirling.software.proprietary.security.service.UserService;
|
import stirling.software.proprietary.security.service.UserService;
|
||||||
@ -52,7 +56,7 @@ public class CustomOAuth2AuthenticationSuccessHandler
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (savedRequest != null
|
if (savedRequest != null
|
||||||
&& !RequestUriUtil.isStaticResource(contextPath, savedRequest.getRedirectUrl())) {
|
&& !RequestUriUtils.isStaticResource(contextPath, savedRequest.getRedirectUrl())) {
|
||||||
// Redirect to the original destination
|
// Redirect to the original destination
|
||||||
super.onAuthenticationSuccess(request, response, authentication);
|
super.onAuthenticationSuccess(request, response, authentication);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
package stirling.software.proprietary.security.oauth2;
|
package stirling.software.proprietary.security.oauth2;
|
||||||
|
|
||||||
|
import static org.springframework.security.oauth2.core.AuthorizationGrantType.AUTHORIZATION_CODE;
|
||||||
|
import static stirling.software.common.util.ProviderUtils.validateProvider;
|
||||||
|
import static stirling.software.common.util.ValidationUtils.isStringEmpty;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
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;
|
||||||
@ -19,25 +23,24 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio
|
|||||||
import org.springframework.security.oauth2.client.registration.ClientRegistrations;
|
import org.springframework.security.oauth2.client.registration.ClientRegistrations;
|
||||||
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
|
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
|
||||||
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
|
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
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;
|
||||||
import stirling.software.common.model.enumeration.UsernameAttribute;
|
import stirling.software.common.model.enumeration.UsernameAttribute;
|
||||||
import stirling.software.proprietary.security.model.exception.NoProviderFoundException;
|
import stirling.software.common.model.oauth2.GitHubProvider;
|
||||||
import stirling.software.common.model.oauth2.provider.GitHubProvider;
|
import stirling.software.common.model.oauth2.GoogleProvider;
|
||||||
import stirling.software.common.model.oauth2.provider.GoogleProvider;
|
import stirling.software.common.model.oauth2.KeycloakProvider;
|
||||||
import stirling.software.common.model.oauth2.provider.KeycloakProvider;
|
import stirling.software.common.model.oauth2.Provider;
|
||||||
import stirling.software.common.model.oauth2.provider.Provider;
|
|
||||||
import stirling.software.proprietary.security.model.User;
|
import stirling.software.proprietary.security.model.User;
|
||||||
|
import stirling.software.proprietary.security.model.exception.NoProviderFoundException;
|
||||||
import stirling.software.proprietary.security.service.UserService;
|
import stirling.software.proprietary.security.service.UserService;
|
||||||
import static org.springframework.security.oauth2.core.AuthorizationGrantType.AUTHORIZATION_CODE;
|
|
||||||
import static stirling.software.common.util.ProviderUtil.validateProvider;
|
|
||||||
import static stirling.software.common.util.ValidationUtil.isStringEmpty;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnProperty(value = "security.oauth2.enabled", havingValue = "true")
|
@ConditionalOnBooleanProperty("security.oauth2.enabled")
|
||||||
@ConditionalOnExpression("${docker.enable.security:true}")
|
|
||||||
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/";
|
||||||
@ -52,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<>();
|
||||||
|
@ -6,6 +6,7 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.security.cert.CertificateFactory;
|
import java.security.cert.CertificateFactory;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.security.interfaces.RSAPrivateKey;
|
import java.security.interfaces.RSAPrivateKey;
|
||||||
|
|
||||||
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
|
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
|
||||||
import org.bouncycastle.openssl.PEMKeyPair;
|
import org.bouncycastle.openssl.PEMKeyPair;
|
||||||
import org.bouncycastle.openssl.PEMParser;
|
import org.bouncycastle.openssl.PEMParser;
|
||||||
|
@ -3,6 +3,7 @@ package stirling.software.proprietary.security.saml2;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
|
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
|
||||||
|
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
package stirling.software.proprietary.security.saml2;
|
package stirling.software.proprietary.security.saml2;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.security.authentication.ProviderNotFoundException;
|
import org.springframework.security.authentication.ProviderNotFoundException;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
@ -11,6 +9,11 @@ import org.springframework.security.saml2.core.Saml2Error;
|
|||||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
|
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
|
||||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ConditionalOnProperty(name = "security.saml2.enabled", havingValue = "true")
|
@ConditionalOnProperty(name = "security.saml2.enabled", havingValue = "true")
|
||||||
public class CustomSaml2AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
|
public class CustomSaml2AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
|
||||||
|
@ -1,21 +1,25 @@
|
|||||||
package stirling.software.proprietary.security.saml2;
|
package stirling.software.proprietary.security.saml2;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.springframework.security.authentication.LockedException;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
|
||||||
|
import org.springframework.security.web.savedrequest.SavedRequest;
|
||||||
|
|
||||||
import jakarta.servlet.ServletException;
|
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 jakarta.servlet.http.HttpSession;
|
import jakarta.servlet.http.HttpSession;
|
||||||
import java.io.IOException;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.security.authentication.LockedException;
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
|
|
||||||
import org.springframework.security.web.savedrequest.SavedRequest;
|
|
||||||
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.RequestUriUtil;
|
import stirling.software.common.util.RequestUriUtils;
|
||||||
import stirling.software.proprietary.security.model.AuthenticationType;
|
import stirling.software.proprietary.security.model.AuthenticationType;
|
||||||
import stirling.software.proprietary.security.service.LoginAttemptService;
|
import stirling.software.proprietary.security.service.LoginAttemptService;
|
||||||
import stirling.software.proprietary.security.service.UserService;
|
import stirling.software.proprietary.security.service.UserService;
|
||||||
@ -54,7 +58,7 @@ public class CustomSaml2AuthenticationSuccessHandler
|
|||||||
savedRequest != null);
|
savedRequest != null);
|
||||||
|
|
||||||
if (savedRequest != null
|
if (savedRequest != null
|
||||||
&& !RequestUriUtil.isStaticResource(
|
&& !RequestUriUtils.isStaticResource(
|
||||||
contextPath, savedRequest.getRedirectUrl())) {
|
contextPath, savedRequest.getRedirectUrl())) {
|
||||||
log.debug(
|
log.debug(
|
||||||
"Valid saved request found, redirecting to original destination: {}",
|
"Valid saved request found, redirecting to original destination: {}",
|
||||||
|
@ -5,8 +5,7 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
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;
|
||||||
import org.opensaml.saml.saml2.core.Attribute;
|
import org.opensaml.saml.saml2.core.Attribute;
|
||||||
@ -17,6 +16,10 @@ import org.springframework.core.convert.converter.Converter;
|
|||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider.ResponseToken;
|
import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider.ResponseToken;
|
||||||
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
|
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.proprietary.security.model.User;
|
import stirling.software.proprietary.security.model.User;
|
||||||
import stirling.software.proprietary.security.service.UserService;
|
import stirling.software.proprietary.security.service.UserService;
|
||||||
|
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
package stirling.software.proprietary.security.saml2;
|
package stirling.software.proprietary.security.saml2;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
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 lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.opensaml.saml.saml2.core.AuthnRequest;
|
import org.opensaml.saml.saml2.core.AuthnRequest;
|
||||||
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;
|
||||||
@ -20,6 +18,12 @@ import org.springframework.security.saml2.provider.service.registration.RelyingP
|
|||||||
import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
|
import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
|
||||||
import org.springframework.security.saml2.provider.service.web.HttpSessionSaml2AuthenticationRequestRepository;
|
import org.springframework.security.saml2.provider.service.web.HttpSessionSaml2AuthenticationRequestRepository;
|
||||||
import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver;
|
import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
package stirling.software.proprietary.security.service;
|
package stirling.software.proprietary.security.service;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
import stirling.software.common.configuration.interfaces.ShowAdminInterface;
|
import stirling.software.common.configuration.interfaces.ShowAdminInterface;
|
||||||
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.database.repository.UserRepository;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user