mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-06-12 18:45:03 +00:00
Multi module refactor (#3640)
# Description of Changes Migrated Stirling PDF to a multi-module structure: * Introduced new `:stirling-pdf` module * Moved all the core logic and features of Stirling PDF into `:stirling-pdf` * Updated paths of jobs and scripts --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing) for more details.
This commit is contained in:
parent
baaaa5a0b2
commit
c7d6a063d7
14
.gitattributes
vendored
14
.gitattributes
vendored
@ -1,10 +1,10 @@
|
|||||||
* text=auto eol=lf
|
* text=auto eol=lf
|
||||||
|
|
||||||
# Ignore all JavaScript files in a directory
|
# Ignore all JavaScript files in a directory
|
||||||
src/main/resources/static/pdfjs/* linguist-vendored
|
stirling-pdf/src/main/resources/static/pdfjs/* linguist-vendored
|
||||||
src/main/resources/static/pdfjs/** linguist-vendored
|
stirling-pdf/src/main/resources/static/pdfjs/** linguist-vendored
|
||||||
src/main/resources/static/pdfjs-legacy/* linguist-vendored
|
stirling-pdf/src/main/resources/static/pdfjs-legacy/* linguist-vendored
|
||||||
src/main/resources/static/pdfjs-legacy/** linguist-vendored
|
stirling-pdf/src/main/resources/static/pdfjs-legacy/** linguist-vendored
|
||||||
src/main/resources/static/css/bootstrap-icons.css linguist-vendored
|
stirling-pdf/src/main/resources/static/css/bootstrap-icons.css linguist-vendored
|
||||||
src/main/resources/static/css/bootstrap.min.css linguist-vendored
|
stirling-pdf/src/main/resources/static/css/bootstrap.min.css linguist-vendored
|
||||||
src/main/resources/static/css/fonts/* linguist-vendored
|
stirling-pdf/src/main/resources/static/css/fonts/* linguist-vendored
|
||||||
|
57
.github/labeler-config.yml
vendored
57
.github/labeler-config.yml
vendored
@ -1,60 +1,45 @@
|
|||||||
Translation:
|
Translation:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file: 'src/main/resources/messages_*_*.properties'
|
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/messages_*_*.properties'
|
||||||
- any-glob-to-any-file: 'scripts/ignore_translation.toml'
|
- any-glob-to-any-file: 'scripts/ignore_translation.toml'
|
||||||
- any-glob-to-any-file: 'src/main/resources/templates/fragments/languages.html'
|
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/templates/fragments/languages.html'
|
||||||
|
|
||||||
Front End:
|
Front End:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file: 'src/main/resources/templates/**/*'
|
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/templates/**/*'
|
||||||
- any-glob-to-any-file: 'src/main/resources/static/**/*'
|
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/static/**/*'
|
||||||
- any-glob-to-any-file: '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: '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:
|
||||||
- any-glob-to-any-file: 'src/main/java/**/*.java'
|
- any-glob-to-any-file: 'common/src/main/java/**/*.java'
|
||||||
|
- any-glob-to-any-file: 'proprietary/src/main/java/**/*.java'
|
||||||
|
- any-glob-to-any-file: 'stirling-pdf/src/main/java/**/*.java'
|
||||||
|
|
||||||
Back End:
|
Back End:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file: '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: '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: 'src/main/resources/settings.yml.template'
|
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/settings.yml.template'
|
||||||
- any-glob-to-any-file: 'src/main/resources/application.properties'
|
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/application.properties'
|
||||||
- any-glob-to-any-file: 'src/main/resources/banner.txt'
|
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/banner.txt'
|
||||||
- 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'
|
||||||
|
|
||||||
Security:
|
Security:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/config/interfaces/DatabaseInterface.java'
|
- any-glob-to-any-file: 'proprietary/src/main/java/stirling/software/proprietary/security/**/*'
|
||||||
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/config/security/**/*'
|
|
||||||
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/controller/api/DatabaseController.java'
|
|
||||||
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/controller/api/EmailController.java'
|
|
||||||
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/controller/api/H2SQLController.java'
|
|
||||||
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java'
|
|
||||||
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/controller/web/DatabaseWebController.java'
|
|
||||||
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/controller/api/UserController.java'
|
|
||||||
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/api/Email.java'
|
|
||||||
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/exception/BackupNotFoundException.java'
|
|
||||||
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/exception/NoProviderFoundExceptionjava'
|
|
||||||
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/provider/**/*'
|
|
||||||
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/AuthenticationType.java'
|
|
||||||
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/ApiKeyAuthenticationToken.java'
|
|
||||||
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/AttemptCounter.java'
|
|
||||||
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/Authority.java'
|
|
||||||
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/PersistentLogin.java'
|
|
||||||
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/SessionEntity.java'
|
|
||||||
- any-glob-to-any-file: 'scripts/download-security-jar.sh'
|
- any-glob-to-any-file: 'scripts/download-security-jar.sh'
|
||||||
- any-glob-to-any-file: '.github/workflows/dependency-review.yml'
|
- any-glob-to-any-file: '.github/workflows/dependency-review.yml'
|
||||||
- any-glob-to-any-file: '.github/workflows/scorecards.yml'
|
- any-glob-to-any-file: '.github/workflows/scorecards.yml'
|
||||||
|
|
||||||
API:
|
API:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file: '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: '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: '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: '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'
|
||||||
@ -88,7 +73,9 @@ Devtools:
|
|||||||
Test:
|
Test:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file: 'cucumber/**/*'
|
- any-glob-to-any-file: 'cucumber/**/*'
|
||||||
- any-glob-to-any-file: 'src/test/**/*'
|
- any-glob-to-any-file: 'common/src/test/**/*'
|
||||||
|
- any-glob-to-any-file: 'proprietary/src/test/**/*'
|
||||||
|
- any-glob-to-any-file: 'stirling-pdf/src/test/**/*'
|
||||||
- any-glob-to-any-file: 'src/testing/**/*'
|
- any-glob-to-any-file: 'src/testing/**/*'
|
||||||
- any-glob-to-any-file: '.pre-commit-config'
|
- any-glob-to-any-file: '.pre-commit-config'
|
||||||
- any-glob-to-any-file: '.github/workflows/pre_commit.yml'
|
- any-glob-to-any-file: '.github/workflows/pre_commit.yml'
|
||||||
|
2
.github/scripts/check_language_properties.py
vendored
2
.github/scripts/check_language_properties.py
vendored
@ -317,7 +317,7 @@ def check_for_differences(reference_file, file_list, branch, actor):
|
|||||||
report.append("## ❌ Overall Check Status: **_Failed_**")
|
report.append("## ❌ Overall Check Status: **_Failed_**")
|
||||||
report.append("")
|
report.append("")
|
||||||
report.append(
|
report.append(
|
||||||
f"@{actor} please check your translation if it conforms to the standard. Follow the format of [messages_en_GB.properties](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/resources/messages_en_GB.properties)"
|
f"@{actor} please check your translation if it conforms to the standard. Follow the format of [messages_en_GB.properties](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/stirling-pdf/src/main/resources/messages_en_GB.properties)"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
report.append("## ✅ Overall Check Status: **_Success_**")
|
report.append("## ✅ Overall Check Status: **_Success_**")
|
||||||
|
25
.github/workflows/check_properties.yml
vendored
25
.github/workflows/check_properties.yml
vendored
@ -4,7 +4,7 @@ on:
|
|||||||
pull_request_target:
|
pull_request_target:
|
||||||
types: [opened, synchronize, reopened]
|
types: [opened, synchronize, reopened]
|
||||||
paths:
|
paths:
|
||||||
- "src/main/resources/messages_*.properties"
|
- "stirling-pdf/src/main/resources/messages_*.properties"
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read # Allow read access to repository content
|
contents: read # Allow read access to repository content
|
||||||
@ -61,7 +61,20 @@ jobs:
|
|||||||
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..."
|
||||||
gh pr view ${{ steps.get-pr-data.outputs.pr_number }} --json files -q ".files[].path" | grep -E '^src/main/resources/messages_[a-zA-Z_]{2}_[a-zA-Z_]{2,7}\.properties$' > changed_files.txt # Filter only matching property files
|
# Check if PR number exists
|
||||||
|
if [ -z "${{ steps.get-pr-data.outputs.pr_number }}" ]; then
|
||||||
|
echo "Error: PR number is empty"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# Get changed files and filter for properties files, handle case where no matches are found
|
||||||
|
gh pr view ${{ steps.get-pr-data.outputs.pr_number }} --json files -q ".files[].path" | grep -E '^stirling-pdf/src/main/resources/messages_[a-zA-Z_]{2}_[a-zA-Z_]{2,7}\.properties$' > changed_files.txt || echo "No matching properties files found in PR"
|
||||||
|
# Check if any files were found
|
||||||
|
if [ ! -s changed_files.txt ]; then
|
||||||
|
echo "No properties files changed in this PR"
|
||||||
|
echo "Workflow will exit early as no relevant files to check"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "Found $(wc -l < changed_files.txt) matching properties files"
|
||||||
|
|
||||||
- name: Determine reference file test
|
- name: Determine reference file test
|
||||||
id: determine-file
|
id: determine-file
|
||||||
@ -103,7 +116,7 @@ jobs:
|
|||||||
// Filter for relevant files based on the PR changes
|
// Filter for relevant files based on the PR changes
|
||||||
const changedFiles = files
|
const changedFiles = files
|
||||||
.map(file => file.filename)
|
.map(file => file.filename)
|
||||||
.filter(file => /^src\/main\/resources\/messages_[a-zA-Z_]{2}_[a-zA-Z_]{2,7}\.properties$/.test(file));
|
.filter(file => /^stirling-pdf\src\/main\/resources\/messages_[a-zA-Z_]{2}_[a-zA-Z_]{2,7}\.properties$/.test(file));
|
||||||
|
|
||||||
console.log("Changed files:", changedFiles);
|
console.log("Changed files:", changedFiles);
|
||||||
|
|
||||||
@ -141,12 +154,12 @@ jobs:
|
|||||||
|
|
||||||
// Determine reference file
|
// Determine reference file
|
||||||
let referenceFilePath;
|
let referenceFilePath;
|
||||||
if (changedFiles.includes("src/main/resources/messages_en_GB.properties")) {
|
if (changedFiles.includes("stirling-pdf/src/main/resources/messages_en_GB.properties")) {
|
||||||
console.log("Using PR branch reference file.");
|
console.log("Using PR branch reference file.");
|
||||||
const { data: fileContent } = await github.rest.repos.getContent({
|
const { data: fileContent } = await github.rest.repos.getContent({
|
||||||
owner: prRepoOwner,
|
owner: prRepoOwner,
|
||||||
repo: prRepoName,
|
repo: prRepoName,
|
||||||
path: "src/main/resources/messages_en_GB.properties",
|
path: "stirling-pdf/src/main/resources/messages_en_GB.properties",
|
||||||
ref: branch,
|
ref: branch,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -158,7 +171,7 @@ jobs:
|
|||||||
const { data: fileContent } = await github.rest.repos.getContent({
|
const { data: fileContent } = await github.rest.repos.getContent({
|
||||||
owner: repoOwner,
|
owner: repoOwner,
|
||||||
repo: repoName,
|
repo: repoName,
|
||||||
path: "src/main/resources/messages_en_GB.properties",
|
path: "stirling-pdf/src/main/resources/messages_en_GB.properties",
|
||||||
ref: "main",
|
ref: "main",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
4
.github/workflows/licenses-update.yml
vendored
4
.github/workflows/licenses-update.yml
vendored
@ -57,11 +57,11 @@ jobs:
|
|||||||
|
|
||||||
- name: Move and rename license file
|
- name: Move and rename license file
|
||||||
run: |
|
run: |
|
||||||
mv build/reports/dependency-license/index.json src/main/resources/static/3rdPartyLicenses.json
|
mv build/reports/dependency-license/index.json stirling-pdf/src/main/resources/static/3rdPartyLicenses.json
|
||||||
|
|
||||||
- name: Commit changes
|
- name: Commit changes
|
||||||
run: |
|
run: |
|
||||||
git add 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
|
||||||
|
|
||||||
- name: Create Pull Request
|
- name: Create Pull Request
|
||||||
|
10
.github/workflows/sync_files.yml
vendored
10
.github/workflows/sync_files.yml
vendored
@ -8,8 +8,8 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- "build.gradle"
|
- "build.gradle"
|
||||||
- "README.md"
|
- "README.md"
|
||||||
- "src/main/resources/messages_*.properties"
|
- "stirling-pdf/src/main/resources/messages_*.properties"
|
||||||
- "src/main/resources/static/3rdPartyLicenses.json"
|
- "stirling-pdf/src/main/resources/static/3rdPartyLicenses.json"
|
||||||
- "scripts/ignore_translation.toml"
|
- "scripts/ignore_translation.toml"
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
@ -41,11 +41,11 @@ jobs:
|
|||||||
|
|
||||||
- name: Sync translation property files
|
- name: Sync translation property files
|
||||||
run: |
|
run: |
|
||||||
python .github/scripts/check_language_properties.py --reference-file "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: Commit translation files
|
- name: Commit translation files
|
||||||
run: |
|
run: |
|
||||||
git add 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 detected"
|
git diff --staged --quiet || git commit -m ":memo: Sync translation files" || echo "No changes detected"
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
@ -101,4 +101,4 @@ jobs:
|
|||||||
sign-commits: true
|
sign-commits: true
|
||||||
add-paths: |
|
add-paths: |
|
||||||
README.md
|
README.md
|
||||||
src/main/resources/messages_*.properties
|
stirling-pdf/src/main/resources/messages_*.properties
|
||||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -125,6 +125,9 @@ SwaggerDoc.json
|
|||||||
*.rar
|
*.rar
|
||||||
*.db
|
*.db
|
||||||
/build
|
/build
|
||||||
|
/stirling-pdf/build
|
||||||
|
/common/build
|
||||||
|
/proprietary/build
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
@ -194,4 +197,3 @@ id_ed25519.pub
|
|||||||
|
|
||||||
# node_modules
|
# node_modules
|
||||||
node_modules/
|
node_modules/
|
||||||
*.mjs
|
|
||||||
|
@ -20,7 +20,7 @@ repos:
|
|||||||
- --skip="./.*,*.csv,*.json,*.ambr"
|
- --skip="./.*,*.csv,*.json,*.ambr"
|
||||||
- --quiet-level=2
|
- --quiet-level=2
|
||||||
files: \.(html|css|js|py|md)$
|
files: \.(html|css|js|py|md)$
|
||||||
exclude: (.vscode|.devcontainer|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.26.0
|
rev: v8.26.0
|
||||||
hooks:
|
hooks:
|
||||||
|
@ -137,9 +137,9 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- /stirling/latest/data:/usr/share/tessdata:rw
|
- ./stirling/latest/data:/usr/share/tessdata:rw
|
||||||
- /stirling/latest/config:/configs:rw
|
- ./stirling/latest/config:/configs:rw
|
||||||
- /stirling/latest/logs:/logs:rw
|
- ./stirling/latest/logs:/logs:rw
|
||||||
environment:
|
environment:
|
||||||
DISABLE_ADDITIONAL_FEATURES: "false"
|
DISABLE_ADDITIONAL_FEATURES: "false"
|
||||||
SECURITY_ENABLELOGIN: "true"
|
SECURITY_ENABLELOGIN: "true"
|
||||||
@ -332,7 +332,7 @@ Thymeleaf is a server-side Java HTML template engine. It is used in Stirling-PDF
|
|||||||
|
|
||||||
### Thymeleaf overview
|
### Thymeleaf overview
|
||||||
|
|
||||||
In Stirling-PDF, Thymeleaf is used to create HTML templates that are rendered on the server side. These templates are located in the `src/main/resources/templates` directory. Thymeleaf templates use a combination of HTML and special Thymeleaf attributes to dynamically generate content.
|
In Stirling-PDF, Thymeleaf is used to create HTML templates that are rendered on the server side. These templates are located in the `stirling-pdf/src/main/resources/templates` directory. Thymeleaf templates use a combination of HTML and special Thymeleaf attributes to dynamically generate content.
|
||||||
|
|
||||||
Some examples of this are:
|
Some examples of this are:
|
||||||
|
|
||||||
@ -384,7 +384,7 @@ 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 `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")`.
|
||||||
|
|
||||||
@ -411,7 +411,7 @@ 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 `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
|
||||||
@ -463,7 +463,7 @@ This would generate n entries of tr for each person in exampleData
|
|||||||
### Adding a New Feature to the Frontend (UI)
|
### Adding a New Feature to the Frontend (UI)
|
||||||
|
|
||||||
1. **Create a New Thymeleaf Template:**
|
1. **Create a New Thymeleaf Template:**
|
||||||
- Create a new HTML file in the `src/main/resources/templates` directory.
|
- Create a new HTML file in the `stirling-pdf/src/main/resources/templates` directory.
|
||||||
- Use Thymeleaf attributes to dynamically generate content.
|
- Use Thymeleaf attributes to dynamically generate content.
|
||||||
- Use `extract-page.html` as a base example for the HTML template, which is useful to ensure importing of the general layout, navbar, and footer.
|
- Use `extract-page.html` as a base example for the HTML template, which is useful to ensure importing of the general layout, navbar, and footer.
|
||||||
|
|
||||||
@ -507,7 +507,7 @@ 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 `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
|
||||||
@ -537,7 +537,7 @@ This would generate n entries of tr for each person in exampleData
|
|||||||
|
|
||||||
3. **Update the Navigation Bar:**
|
3. **Update the Navigation Bar:**
|
||||||
- Add a link to the new feature page in the navigation bar.
|
- Add a link to the new feature page in the navigation bar.
|
||||||
- Update the `src/main/resources/templates/fragments/navbar.html` file.
|
- Update the `stirling-pdf/src/main/resources/templates/fragments/navbar.html` file.
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
@ -551,7 +551,7 @@ When adding a new feature or modifying existing ones in Stirling-PDF, you'll nee
|
|||||||
|
|
||||||
### 1. Locate Existing Language Files
|
### 1. Locate Existing Language Files
|
||||||
|
|
||||||
Find the existing `messages.properties` files in the `src/main/resources` directory. You'll see files like:
|
Find the existing `messages.properties` files in the `stirling-pdf/src/main/resources` directory. You'll see files like:
|
||||||
|
|
||||||
- `messages.properties` (default, usually English)
|
- `messages.properties` (default, usually English)
|
||||||
- `messages_en_GB.properties`
|
- `messages_en_GB.properties`
|
||||||
|
@ -4,7 +4,7 @@ FROM alpine:3.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be02
|
|||||||
# Copy necessary files
|
# Copy necessary files
|
||||||
COPY scripts /scripts
|
COPY scripts /scripts
|
||||||
COPY pipeline /pipeline
|
COPY pipeline /pipeline
|
||||||
COPY src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
|
COPY stirling-pdf/src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
|
||||||
#COPY src/main/resources/static/fonts/*.otf /usr/share/fonts/opentype/noto/
|
#COPY src/main/resources/static/fonts/*.otf /usr/share/fonts/opentype/noto/
|
||||||
COPY build/libs/*.jar app.jar
|
COPY build/libs/*.jar app.jar
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ FROM alpine:3.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be02
|
|||||||
# Copy necessary files
|
# Copy necessary files
|
||||||
COPY scripts /scripts
|
COPY scripts /scripts
|
||||||
COPY pipeline /pipeline
|
COPY pipeline /pipeline
|
||||||
COPY src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
|
COPY stirling-pdf/src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
|
||||||
COPY --from=build /app/build/libs/*.jar app.jar
|
COPY --from=build /app/build/libs/*.jar app.jar
|
||||||
|
|
||||||
ARG VERSION_TAG
|
ARG VERSION_TAG
|
||||||
|
@ -10,7 +10,7 @@ Fork Stirling-PDF and create a new branch out of `main`.
|
|||||||
|
|
||||||
Then add a reference to the language in the navbar by adding a new language entry to the dropdown:
|
Then add a reference to the language in the navbar by adding a new language entry to the dropdown:
|
||||||
|
|
||||||
- Edit the file: [languages.html](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/resources/templates/fragments/languages.html)
|
- Edit the file: [languages.html](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/stirling-pdf/src/main/resources/templates/fragments/languages.html)
|
||||||
|
|
||||||
|
|
||||||
For example, to add Polish, you would add:
|
For example, to add Polish, you would add:
|
||||||
@ -25,7 +25,7 @@ The `data-bs-language-code` is the code used to reference the file in the next s
|
|||||||
|
|
||||||
Start by copying the existing English property file:
|
Start by copying the existing English property file:
|
||||||
|
|
||||||
- [messages_en_GB.properties](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/resources/messages_en_GB.properties)
|
- [messages_en_GB.properties](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/stirling-pdf/src/main/resources/messages_en_GB.properties)
|
||||||
|
|
||||||
Copy and rename it to `messages_{your data-bs-language-code here}.properties`. In the Polish example, you would set the name to `messages_pl_PL.properties`.
|
Copy and rename it to `messages_{your data-bs-language-code here}.properties`. In the Polish example, you would set the name to `messages_pl_PL.properties`.
|
||||||
|
|
||||||
|
340
build.gradle
340
build.gradle
@ -26,21 +26,124 @@ ext {
|
|||||||
bouncycastleVersion = "1.80"
|
bouncycastleVersion = "1.80"
|
||||||
springSecuritySamlVersion = "6.5.0"
|
springSecuritySamlVersion = "6.5.0"
|
||||||
openSamlVersion = "4.3.2"
|
openSamlVersion = "4.3.2"
|
||||||
|
commonmarkVersion = "0.24.0"
|
||||||
tempJrePath = null
|
tempJrePath = null
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "stirling.software"
|
jar {
|
||||||
version = "0.46.2"
|
enabled = false
|
||||||
|
manifest {
|
||||||
java {
|
attributes "Implementation-Title": "Stirling-PDF",
|
||||||
// 17 is lowest but we support and recommend 21
|
"Implementation-Version": project.version
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
bootJar {
|
||||||
mavenCentral()
|
enabled = false
|
||||||
maven { url = "https://build.shibboleth.net/maven/releases" }
|
}
|
||||||
maven { url = "https://maven.pkg.github.com/jcefmaven/jcefmaven" }
|
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
|
java {
|
||||||
|
if (System.getenv('DOCKER_ENABLE_SECURITY') == 'false' || System.getenv('DISABLE_ADDITIONAL_FEATURES') == 'true'
|
||||||
|
|| (project.hasProperty('DISABLE_ADDITIONAL_FEATURES')
|
||||||
|
&& System.getProperty('DISABLE_ADDITIONAL_FEATURES') == 'true')) {
|
||||||
|
exclude 'stirling/software/proprietary/security/**'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (System.getenv('STIRLING_PDF_DESKTOP_UI') == 'false') {
|
||||||
|
exclude 'stirling/software/SPDF/UI/impl/**'
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
java {
|
||||||
|
if (System.getenv('DOCKER_ENABLE_SECURITY') == 'false' || System.getenv('DISABLE_ADDITIONAL_FEATURES') == 'true'
|
||||||
|
|| (project.hasProperty('DISABLE_ADDITIONAL_FEATURES')
|
||||||
|
&& System.getProperty('DISABLE_ADDITIONAL_FEATURES') == 'true')) {
|
||||||
|
exclude 'stirling/software/proprietary/security/**'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (System.getenv('STIRLING_PDF_DESKTOP_UI') == 'false') {
|
||||||
|
exclude 'stirling/software/SPDF/UI/impl/**'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
group = 'stirling.software'
|
||||||
|
version = '0.46.2'
|
||||||
|
|
||||||
|
configurations.configureEach {
|
||||||
|
exclude group: 'commons-logging', module: 'commons-logging'
|
||||||
|
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
subprojects {
|
||||||
|
apply plugin: 'java'
|
||||||
|
apply plugin: 'java-library'
|
||||||
|
apply plugin: 'com.diffplug.spotless'
|
||||||
|
apply plugin: 'org.springframework.boot'
|
||||||
|
apply plugin: 'io.spring.dependency-management'
|
||||||
|
|
||||||
|
java {
|
||||||
|
// 17 is lowest but we support and recommend 21
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
|
}
|
||||||
|
|
||||||
|
bootJar {
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations.configureEach {
|
||||||
|
exclude group: 'commons-logging', module: 'commons-logging'
|
||||||
|
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
|
||||||
|
// Exclude vulnerable BouncyCastle version used in tableau
|
||||||
|
exclude group: 'org.bouncycastle', module: 'bcpkix-jdk15on'
|
||||||
|
exclude group: 'org.bouncycastle', module: 'bcutil-jdk15on'
|
||||||
|
exclude group: 'org.bouncycastle', module: 'bcmail-jdk15on'
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencyManagement {
|
||||||
|
imports {
|
||||||
|
mavenBom "org.springframework.boot:spring-boot-dependencies:$springBootVersion"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'org.springframework.boot:spring-boot-starter-actuator'
|
||||||
|
implementation 'io.github.pixee:java-security-toolkit:1.2.1'
|
||||||
|
|
||||||
|
//tmp for security bumps
|
||||||
|
implementation 'ch.qos.logback:logback-core:1.5.18'
|
||||||
|
implementation 'ch.qos.logback:logback-classic:1.5.18'
|
||||||
|
compileOnly "org.projectlombok:lombok:$lombokVersion"
|
||||||
|
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
||||||
|
|
||||||
|
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||||
|
testRuntimeOnly 'org.mockito:mockito-inline:5.2.0'
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile).configureEach {
|
||||||
|
options.encoding = "UTF-8"
|
||||||
|
dependsOn "spotlessApply"
|
||||||
|
}
|
||||||
|
|
||||||
|
compileJava {
|
||||||
|
options.compilerArgs << "-parameters"
|
||||||
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
licenseReport {
|
licenseReport {
|
||||||
@ -99,10 +202,9 @@ jpackage {
|
|||||||
mainJar = "Stirling-PDF-${project.version}.jar"
|
mainJar = "Stirling-PDF-${project.version}.jar"
|
||||||
appName = "Stirling PDF"
|
appName = "Stirling PDF"
|
||||||
appVersion = project.version
|
appVersion = project.version
|
||||||
// appVersion = "2005.45.1"
|
|
||||||
vendor = "Stirling PDF Inc"
|
vendor = "Stirling PDF Inc"
|
||||||
appDescription = "Stirling PDF - Your Local PDF Editor"
|
appDescription = "Stirling PDF - Your Local PDF Editor"
|
||||||
icon = "src/main/resources/static/favicon.ico"
|
icon = "stirling-pdf/src/main/resources/static/favicon.ico"
|
||||||
verbose = true
|
verbose = true
|
||||||
// mainClass = "org.springframework.boot.loader.launch.JarLauncher"
|
// mainClass = "org.springframework.boot.loader.launch.JarLauncher"
|
||||||
|
|
||||||
@ -141,10 +243,10 @@ jpackage {
|
|||||||
installDir = "C:/Program Files/Stirling-PDF"
|
installDir = "C:/Program Files/Stirling-PDF"
|
||||||
}
|
}
|
||||||
|
|
||||||
// macOS-specific configuration
|
// MacOS-specific configuration
|
||||||
mac {
|
mac {
|
||||||
appVersion = getMacVersion(project.version.toString())
|
appVersion = getMacVersion(project.version.toString())
|
||||||
icon = "src/main/resources/static/favicon.icns"
|
icon = "stirling-pdf/src/main/resources/static/favicon.icns"
|
||||||
type = "dmg"
|
type = "dmg"
|
||||||
macPackageIdentifier = "Stirling PDF"
|
macPackageIdentifier = "Stirling PDF"
|
||||||
macPackageName = "Stirling PDF"
|
macPackageName = "Stirling PDF"
|
||||||
@ -166,7 +268,7 @@ jpackage {
|
|||||||
// Linux-specific configuration
|
// Linux-specific configuration
|
||||||
linux {
|
linux {
|
||||||
appVersion = project.version
|
appVersion = project.version
|
||||||
icon = "src/main/resources/static/favicon.png"
|
icon = "stirling-pdf/src/main/resources/static/favicon.png"
|
||||||
type = "deb" // Can also use "rpm" for Red Hat-based systems
|
type = "deb" // Can also use "rpm" for Red Hat-based systems
|
||||||
|
|
||||||
// Debian package configuration
|
// Debian package configuration
|
||||||
@ -202,10 +304,15 @@ jpackage {
|
|||||||
]*/
|
]*/
|
||||||
|
|
||||||
// Add copyright and license information
|
// Add copyright and license information
|
||||||
copyright = "Copyright © 2024 Stirling Software"
|
copyright = "Copyright © 2025 Stirling PDF Inc."
|
||||||
licenseFile = "LICENSE"
|
licenseFile = "LICENSE"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//tasks.wrapper {
|
||||||
|
// gradleVersion = "8.14"
|
||||||
|
// distributionType = Wrapper.DistributionType.ALL
|
||||||
|
//}
|
||||||
|
|
||||||
tasks.register('jpackageMacX64') {
|
tasks.register('jpackageMacX64') {
|
||||||
group = 'distribution'
|
group = 'distribution'
|
||||||
description = 'Packages app for MacOS x86_64'
|
description = 'Packages app for MacOS x86_64'
|
||||||
@ -238,7 +345,7 @@ tasks.register('jpackageMacX64') {
|
|||||||
'--main-class', 'org.springframework.boot.loader.launch.JarLauncher',
|
'--main-class', 'org.springframework.boot.loader.launch.JarLauncher',
|
||||||
'--runtime-image', file(jrePath + "/zulu-17.jre/Contents/Home"),
|
'--runtime-image', file(jrePath + "/zulu-17.jre/Contents/Home"),
|
||||||
'--dest', 'build/jpackage/x86_64',
|
'--dest', 'build/jpackage/x86_64',
|
||||||
'--icon', 'src/main/resources/static/favicon.icns',
|
'--icon', 'stirling-pdf/src/main/resources/static/favicon.icns',
|
||||||
'--app-version', getMacVersion(project.version.toString()),
|
'--app-version', getMacVersion(project.version.toString()),
|
||||||
'--mac-package-name', 'Stirling PDF (x86_64)',
|
'--mac-package-name', 'Stirling PDF (x86_64)',
|
||||||
'--mac-package-identifier', 'Stirling PDF (x86_64)',
|
'--mac-package-identifier', 'Stirling PDF (x86_64)',
|
||||||
@ -287,12 +394,12 @@ tasks.register('downloadTempJre') {
|
|||||||
def jreArchive = new File(tmpDir, 'jre.tar.gz')
|
def jreArchive = new File(tmpDir, 'jre.tar.gz')
|
||||||
def jreDir = new File(tmpDir, 'jre')
|
def jreDir = new File(tmpDir, 'jre')
|
||||||
|
|
||||||
println "Downloading JRE to $jreArchive..."
|
println "Downloading JRE to $jreArchive"
|
||||||
jreArchive.withOutputStream { out ->
|
jreArchive.withOutputStream { out ->
|
||||||
new URI(jreUrl).toURL().withInputStream { from -> out << from }
|
new URI(jreUrl).toURL().withInputStream { from -> out << from }
|
||||||
}
|
}
|
||||||
|
|
||||||
println "Extracting JRE to $jreDir..."
|
println "Extracting JRE to $jreDir"
|
||||||
jreDir.mkdirs()
|
jreDir.mkdirs()
|
||||||
providers.exec {
|
providers.exec {
|
||||||
commandLine 'tar', '-xzf', jreArchive.absolutePath, '-C', jreDir.absolutePath, '--strip-components=1'
|
commandLine 'tar', '-xzf', jreArchive.absolutePath, '-C', jreDir.absolutePath, '--strip-components=1'
|
||||||
@ -324,7 +431,7 @@ tasks.register('cleanTempJre') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
launch4j {
|
launch4j {
|
||||||
icon = "${projectDir}/src/main/resources/static/favicon.ico"
|
icon = "${projectDir}/stirling-pdf/src/main/resources/static/favicon.ico"
|
||||||
|
|
||||||
outfile="Stirling-PDF.exe"
|
outfile="Stirling-PDF.exe"
|
||||||
|
|
||||||
@ -335,7 +442,7 @@ launch4j {
|
|||||||
}
|
}
|
||||||
jarTask = tasks.bootJar
|
jarTask = tasks.bootJar
|
||||||
|
|
||||||
errTitle="Encountered error, Do you have Java 21?"
|
errTitle="Encountered error, do you have Java 21?"
|
||||||
downloadUrl="https://download.oracle.com/java/21/latest/jdk-21_windows-x64_bin.exe"
|
downloadUrl="https://download.oracle.com/java/21/latest/jdk-21_windows-x64_bin.exe"
|
||||||
|
|
||||||
if(System.getenv("STIRLING_PDF_DESKTOP_UI") == 'true') {
|
if(System.getenv("STIRLING_PDF_DESKTOP_UI") == 'true') {
|
||||||
@ -377,159 +484,12 @@ sonar {
|
|||||||
property "sonar.projectKey", "Stirling-Tools_Stirling-PDF"
|
property "sonar.projectKey", "Stirling-Tools_Stirling-PDF"
|
||||||
property "sonar.organization", "stirling-tools"
|
property "sonar.organization", "stirling-tools"
|
||||||
|
|
||||||
property "sonar.exclusions", "**/build-wrapper-dump.json, src/main/java/org/apache/**, src/main/resources/static/pdfjs/**, src/main/resources/static/pdfjs-legacy/**, src/main/resources/static/js/thirdParty/**"
|
property "sonar.exclusions", "**/build-wrapper-dump.json, **/src/main/java/org/apache/**, **/src/main/resources/static/pdfjs/**, **/src/main/resources/static/pdfjs-legacy/**, **/src/main/resources/static/js/thirdParty/**"
|
||||||
property "sonar.coverage.exclusions", "src/main/java/org/apache/**, src/main/resources/static/pdfjs/**, src/main/resources/static/pdfjs-legacy/**, src/main/resources/static/js/thirdParty/**"
|
property "sonar.coverage.exclusions", "**/src/main/java/org/apache/**, **/src/main/resources/static/pdfjs/**, **/src/main/resources/static/pdfjs-legacy/**, **/src/main/resources/static/js/thirdParty/**"
|
||||||
property "sonar.cpd.exclusions", "src/main/java/org/apache/**, src/main/resources/static/pdfjs/**, src/main/resources/static/pdfjs-legacy/**, src/main/resources/static/js/thirdParty/**"
|
property "sonar.cpd.exclusions", "**/src/main/java/org/apache/**, **/src/main/resources/static/pdfjs/**, **/src/main/resources/static/pdfjs-legacy/**, **/src/main/resources/static/js/thirdParty/**"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//gradleLint {
|
|
||||||
// rules=['unused-dependency']
|
|
||||||
// }
|
|
||||||
tasks.wrapper {
|
|
||||||
gradleVersion = "8.14"
|
|
||||||
distributionType = Wrapper.DistributionType.ALL
|
|
||||||
}
|
|
||||||
//tasks.withType(JavaCompile) {
|
|
||||||
// options.compilerArgs << "-Xlint:deprecation"
|
|
||||||
//}
|
|
||||||
configurations.all {
|
|
||||||
// Remove all commons-logging dependencies so that only spring-jcl is used
|
|
||||||
exclude group: 'commons-logging', module: 'commons-logging'
|
|
||||||
// Exclude Tomcat
|
|
||||||
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation project(':common')
|
|
||||||
|
|
||||||
//tmp for security bumps
|
|
||||||
implementation 'ch.qos.logback:logback-core:1.5.18'
|
|
||||||
implementation 'ch.qos.logback:logback-classic:1.5.18'
|
|
||||||
|
|
||||||
// Exclude vulnerable BouncyCastle version used in tableau
|
|
||||||
configurations.all {
|
|
||||||
exclude group: 'org.bouncycastle', module: 'bcpkix-jdk15on'
|
|
||||||
exclude group: 'org.bouncycastle', module: 'bcutil-jdk15on'
|
|
||||||
exclude group: 'org.bouncycastle', module: 'bcmail-jdk15on'
|
|
||||||
}
|
|
||||||
|
|
||||||
if (System.getenv("STIRLING_PDF_DESKTOP_UI") != "false") {
|
|
||||||
implementation "me.friwi:jcefmaven:135.0.20"
|
|
||||||
implementation "org.openjfx:javafx-controls:21"
|
|
||||||
implementation "org.openjfx:javafx-swing:21"
|
|
||||||
}
|
|
||||||
|
|
||||||
//security updates
|
|
||||||
implementation "org.springframework:spring-webmvc:6.2.7"
|
|
||||||
|
|
||||||
implementation("io.github.pixee:java-security-toolkit:1.2.1")
|
|
||||||
|
|
||||||
// Exclude Tomcat and include Jetty
|
|
||||||
// implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
|
|
||||||
implementation "org.springframework.boot:spring-boot-starter-jetty:$springBootVersion"
|
|
||||||
// implementation "org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVersion"
|
|
||||||
implementation 'com.posthog.java:posthog:1.2.0'
|
|
||||||
implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1'
|
|
||||||
implementation 'org.snakeyaml:snakeyaml-engine:2.9'
|
|
||||||
|
|
||||||
if (System.getenv("DOCKER_ENABLE_SECURITY") != "false" || System.getenv('DISABLE_ADDITIONAL_FEATURES') != 'true'
|
|
||||||
|| (project.hasProperty('DISABLE_ADDITIONAL_FEATURES')
|
|
||||||
&& System.getProperty('DISABLE_ADDITIONAL_FEATURES') != 'true')) {
|
|
||||||
implementation project(':proprietary')
|
|
||||||
}
|
|
||||||
|
|
||||||
// Batik
|
|
||||||
implementation "org.apache.xmlgraphics:batik-all:1.19"
|
|
||||||
|
|
||||||
// TwelveMonkeys
|
|
||||||
runtimeOnly "com.twelvemonkeys.imageio:imageio-batik:$imageioVersion"
|
|
||||||
runtimeOnly "com.twelvemonkeys.imageio:imageio-bmp:$imageioVersion"
|
|
||||||
runtimeOnly "com.twelvemonkeys.imageio:imageio-jpeg:$imageioVersion"
|
|
||||||
runtimeOnly "com.twelvemonkeys.imageio:imageio-tiff:$imageioVersion"
|
|
||||||
runtimeOnly "com.twelvemonkeys.imageio:imageio-webp:$imageioVersion"
|
|
||||||
// runtimeOnly "com.twelvemonkeys.imageio:imageio-hdr:$imageioVersion"
|
|
||||||
// runtimeOnly "com.twelvemonkeys.imageio:imageio-icns:$imageioVersion"
|
|
||||||
// runtimeOnly "com.twelvemonkeys.imageio:imageio-iff:$imageioVersion"
|
|
||||||
// runtimeOnly "com.twelvemonkeys.imageio:imageio-pcx:$imageioVersion@
|
|
||||||
// runtimeOnly "com.twelvemonkeys.imageio:imageio-pict:$imageioVersion"
|
|
||||||
// runtimeOnly "com.twelvemonkeys.imageio:imageio-pnm:$imageioVersion"
|
|
||||||
// runtimeOnly "com.twelvemonkeys.imageio:imageio-psd:$imageioVersion"
|
|
||||||
// runtimeOnly "com.twelvemonkeys.imageio:imageio-sgi:$imageioVersion"
|
|
||||||
// runtimeOnly "com.twelvemonkeys.imageio:imageio-tga:$imageioVersion"
|
|
||||||
// runtimeOnly "com.twelvemonkeys.imageio:imageio-thumbsdb:$imageioVersion"
|
|
||||||
// runtimeOnly "com.twelvemonkeys.imageio:imageio-xwd:$imageioVersion"
|
|
||||||
|
|
||||||
// Image metadata extractor
|
|
||||||
implementation "com.drewnoakes:metadata-extractor:2.19.0"
|
|
||||||
implementation "commons-io:commons-io:2.19.0"
|
|
||||||
// implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8"
|
|
||||||
|
|
||||||
// General PDF
|
|
||||||
// https://mvnrepository.com/artifact/com.opencsv/opencsv
|
|
||||||
implementation ("com.opencsv:opencsv:5.11")
|
|
||||||
// implementation ("org.apache.pdfbox:pdfbox:$pdfboxVersion")
|
|
||||||
implementation "org.apache.pdfbox:preflight:$pdfboxVersion"
|
|
||||||
implementation ("org.apache.pdfbox:xmpbox:$pdfboxVersion")
|
|
||||||
|
|
||||||
// https://mvnrepository.com/artifact/technology.tabula/tabula
|
|
||||||
implementation ('technology.tabula:tabula:1.0.5') {
|
|
||||||
exclude group: "org.slf4j", module: "slf4j-simple"
|
|
||||||
exclude group: "org.bouncycastle", module: "bcprov-jdk15on"
|
|
||||||
exclude group: "com.google.code.gson", module: "gson"
|
|
||||||
exclude group: "commons-io", module: "commons-io"
|
|
||||||
}
|
|
||||||
|
|
||||||
implementation 'org.apache.pdfbox:jbig2-imageio:3.0.4'
|
|
||||||
|
|
||||||
implementation "org.bouncycastle:bcprov-jdk18on:$bouncycastleVersion"
|
|
||||||
implementation "org.bouncycastle:bcpkix-jdk18on:$bouncycastleVersion"
|
|
||||||
implementation "org.springframework.boot:spring-boot-starter-actuator:$springBootVersion"
|
|
||||||
implementation "io.micrometer:micrometer-core:1.15.0"
|
|
||||||
implementation group: "com.google.zxing", name: "core", version: "3.5.3"
|
|
||||||
// https://mvnrepository.com/artifact/org.commonmark/commonmark
|
|
||||||
implementation "org.commonmark:commonmark:0.24.0"
|
|
||||||
implementation "org.commonmark:commonmark-ext-gfm-tables:0.24.0"
|
|
||||||
// https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17
|
|
||||||
implementation "com.bucket4j:bucket4j_jdk17-core:8.14.0"
|
|
||||||
implementation "com.fathzer:javaluator:3.0.6"
|
|
||||||
implementation 'com.vladsch.flexmark:flexmark-html2md-converter:0.64.8'
|
|
||||||
|
|
||||||
developmentOnly("org.springframework.boot:spring-boot-devtools:$springBootVersion")
|
|
||||||
compileOnly "org.projectlombok:lombok:$lombokVersion"
|
|
||||||
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
|
||||||
|
|
||||||
// Mockito (core)
|
|
||||||
testImplementation 'org.mockito:mockito-core:5.18.0'
|
|
||||||
testRuntimeOnly 'org.mockito:mockito-inline:5.2.0'
|
|
||||||
testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType(JavaCompile).configureEach {
|
|
||||||
options.encoding = "UTF-8"
|
|
||||||
dependsOn "spotlessApply"
|
|
||||||
}
|
|
||||||
compileJava {
|
|
||||||
options.compilerArgs << "-parameters"
|
|
||||||
}
|
|
||||||
|
|
||||||
task writeVersion {
|
|
||||||
def propsFile = file("$projectDir/src/main/resources/version.properties")
|
|
||||||
def propsDir = propsFile.parentFile
|
|
||||||
|
|
||||||
doLast {
|
|
||||||
if (!propsDir.exists()) {
|
|
||||||
propsDir.mkdirs()
|
|
||||||
}
|
|
||||||
|
|
||||||
def props = new Properties()
|
|
||||||
props.setProperty("version", version)
|
|
||||||
props.store(propsFile.newWriter(), null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
processResources.dependsOn(writeVersion)
|
|
||||||
|
|
||||||
swaggerhubUpload {
|
swaggerhubUpload {
|
||||||
// dependsOn = generateOpenApiDocs // Depends on your task generating Swagger docs
|
// dependsOn = generateOpenApiDocs // Depends on your task generating Swagger docs
|
||||||
api = "Stirling-PDF" // The name of your API on SwaggerHub
|
api = "Stirling-PDF" // The name of your API on SwaggerHub
|
||||||
@ -540,25 +500,43 @@ swaggerhubUpload {
|
|||||||
oas = "3.0.0" // The version of the OpenAPI Specification you"re using
|
oas = "3.0.0" // The version of the OpenAPI Specification you"re using
|
||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
|
||||||
enabled = false
|
|
||||||
manifest {
|
|
||||||
attributes "Implementation-Title": "Stirling-PDF",
|
|
||||||
"Implementation-Version": project.version
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.named("test") {
|
tasks.named("test") {
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
}
|
}
|
||||||
|
|
||||||
task printVersion {
|
tasks.register('writeVersion') {
|
||||||
|
def propsFile = file("$projectDir/stirling-pdf/src/main/resources/version.properties")
|
||||||
|
def propsDir = propsFile.parentFile
|
||||||
|
|
||||||
|
doLast {
|
||||||
|
if (propsDir.exists()) {
|
||||||
|
if (propsFile.exists()) {
|
||||||
|
println "File exists: $propsFile"
|
||||||
|
} else {
|
||||||
|
println "$propsFile does not exist. Creating file."
|
||||||
|
propsFile.createNewFile()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println "Creating directory: $propsDir"
|
||||||
|
propsDir.mkdirs()
|
||||||
|
propsFile.createNewFile()
|
||||||
|
}
|
||||||
|
|
||||||
|
def props = new Properties()
|
||||||
|
props.setProperty("version", version)
|
||||||
|
props.store(propsFile.newWriter(), null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processResources.dependsOn(writeVersion)
|
||||||
|
|
||||||
|
tasks.register('printVersion') {
|
||||||
doLast {
|
doLast {
|
||||||
println project.version
|
println project.version
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task printMacVersion {
|
tasks.register('printMacVersion') {
|
||||||
doLast {
|
doLast {
|
||||||
println getMacVersion(project.version.toString())
|
println getMacVersion(project.version.toString())
|
||||||
}
|
}
|
||||||
|
2
common/.gitignore
vendored
2
common/.gitignore
vendored
@ -124,6 +124,7 @@ SwaggerDoc.json
|
|||||||
*.rar
|
*.rar
|
||||||
*.db
|
*.db
|
||||||
/build
|
/build
|
||||||
|
/common/build/
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
@ -193,4 +194,3 @@ id_ed25519.pub
|
|||||||
|
|
||||||
# node_modules
|
# node_modules
|
||||||
node_modules/
|
node_modules/
|
||||||
*.mjs
|
|
||||||
|
@ -1,41 +1,9 @@
|
|||||||
plugins {
|
|
||||||
id 'java-library'
|
|
||||||
id 'io.spring.dependency-management' version '1.1.7'
|
|
||||||
}
|
|
||||||
|
|
||||||
group = 'stirling.software'
|
|
||||||
version = '0.46.2'
|
|
||||||
|
|
||||||
ext {
|
|
||||||
lombokVersion = "1.18.38"
|
|
||||||
}
|
|
||||||
|
|
||||||
java {
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations.all {
|
|
||||||
exclude group: 'commons-logging', module: 'commons-logging'
|
|
||||||
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencyManagement {
|
|
||||||
imports {
|
|
||||||
mavenBom 'org.springframework.boot:spring-boot-dependencies:3.5.0'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api 'org.springframework.boot:spring-boot-starter-web'
|
api 'org.springframework.boot:spring-boot-starter-web'
|
||||||
api 'org.springframework.boot:spring-boot-starter-thymeleaf'
|
api 'org.springframework.boot:spring-boot-starter-thymeleaf'
|
||||||
api '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'
|
||||||
api 'com.fathzer:javaluator:3.0.6'
|
api 'com.fathzer:javaluator:3.0.6'
|
||||||
api 'com.posthog.java:posthog:1.2.0'
|
api 'com.posthog.java:posthog:1.2.0'
|
||||||
api 'io.github.pixee:java-security-toolkit:1.2.1'
|
|
||||||
api 'org.apache.commons:commons-lang3:3.17.0'
|
api 'org.apache.commons:commons-lang3:3.17.0'
|
||||||
api 'com.drewnoakes:metadata-extractor:2.19.0' // Image metadata extractor
|
api 'com.drewnoakes:metadata-extractor:2.19.0' // Image metadata extractor
|
||||||
api 'com.vladsch.flexmark:flexmark-html2md-converter:0.64.8'
|
api 'com.vladsch.flexmark:flexmark-html2md-converter:0.64.8'
|
||||||
@ -44,9 +12,4 @@ dependencies {
|
|||||||
api 'org.snakeyaml:snakeyaml-engine:2.9'
|
api 'org.snakeyaml:snakeyaml-engine:2.9'
|
||||||
api "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8"
|
api "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8"
|
||||||
api 'jakarta.mail:jakarta.mail-api:2.1.3'
|
api 'jakarta.mail:jakarta.mail-api:2.1.3'
|
||||||
compileOnly "org.projectlombok:lombok:$lombokVersion"
|
|
||||||
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
|
||||||
|
|
||||||
testImplementation "org.springframework.boot:spring-boot-starter-test"
|
|
||||||
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;
|
||||||
@ -149,12 +151,12 @@ public class AppConfig {
|
|||||||
|
|
||||||
@Bean(name = "activeSecurity")
|
@Bean(name = "activeSecurity")
|
||||||
public boolean activeSecurity() {
|
public boolean activeSecurity() {
|
||||||
String additionalFeaturesOff = env.getProperty("DISABLE_ADDITIONAL_FEATURES");
|
String disableAdditionalFeatures = env.getProperty("DISABLE_ADDITIONAL_FEATURES");
|
||||||
|
|
||||||
if (additionalFeaturesOff != null) {
|
if (disableAdditionalFeatures != null) {
|
||||||
// DISABLE_ADDITIONAL_FEATURES=true means security OFF, so return false
|
// DISABLE_ADDITIONAL_FEATURES=true means security OFF, so return false
|
||||||
// DISABLE_ADDITIONAL_FEATURES=false means security ON, so return true
|
// DISABLE_ADDITIONAL_FEATURES=false means security ON, so return true
|
||||||
return !Boolean.parseBoolean(additionalFeaturesOff);
|
return !Boolean.parseBoolean(disableAdditionalFeatures);
|
||||||
}
|
}
|
||||||
|
|
||||||
return env.getProperty("DOCKER_ENABLE_SECURITY", Boolean.class, true);
|
return env.getProperty("DOCKER_ENABLE_SECURITY", Boolean.class, true);
|
||||||
@ -164,7 +166,7 @@ public class AppConfig {
|
|||||||
@ConditionalOnMissingClass(
|
@ConditionalOnMissingClass(
|
||||||
"stirling.software.proprietary.security.configuration.SecurityConfiguration")
|
"stirling.software.proprietary.security.configuration.SecurityConfiguration")
|
||||||
public boolean missingActiveSecurity() {
|
public boolean missingActiveSecurity() {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean(name = "directoryFilter")
|
@Bean(name = "directoryFilter")
|
||||||
|
@ -344,10 +344,10 @@ public class ApplicationProperties {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return """
|
return """
|
||||||
Driver {
|
Driver {
|
||||||
driverName='%s'
|
driverName='%s'
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
.formatted(driverName);
|
.formatted(driverName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
package stirling.software.common.util;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
public class ValidationUtil {
|
||||||
|
|
||||||
|
public static boolean isStringEmpty(String input) {
|
||||||
|
return input == null || input.isBlank();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isCollectionEmpty(Collection<String> input) {
|
||||||
|
return input == null || input.isEmpty();
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,14 @@
|
|||||||
package stirling.software.common.util;
|
package stirling.software.common.util;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.MockedStatic;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
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;
|
||||||
@ -10,18 +19,6 @@ import static org.mockito.Mockito.times;
|
|||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.mockito.MockedStatic;
|
|
||||||
import org.mockito.Mockito;
|
|
||||||
|
|
||||||
import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult;
|
|
||||||
|
|
||||||
class CheckProgramInstallTest {
|
class CheckProgramInstallTest {
|
||||||
|
|
||||||
private MockedStatic<ProcessExecutor> mockProcessExecutor;
|
private MockedStatic<ProcessExecutor> mockProcessExecutor;
|
||||||
|
@ -19,7 +19,6 @@ import org.junit.jupiter.api.io.TempDir;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
import stirling.software.common.configuration.RuntimePathConfig;
|
import stirling.software.common.configuration.RuntimePathConfig;
|
||||||
|
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
package stirling.software.common.util;
|
package stirling.software.common.util;
|
||||||
|
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@ -12,11 +9,13 @@ import org.junit.jupiter.params.ParameterizedTest;
|
|||||||
import org.junit.jupiter.params.provider.Arguments;
|
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.GitHubProvider;
|
import stirling.software.common.model.oauth2.GitHubProvider;
|
||||||
import stirling.software.common.model.oauth2.GoogleProvider;
|
import stirling.software.common.model.oauth2.GoogleProvider;
|
||||||
import stirling.software.common.model.oauth2.Provider;
|
import stirling.software.common.model.oauth2.Provider;
|
||||||
|
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 ProviderUtilsTest {
|
class ProviderUtilsTest {
|
||||||
@ -29,19 +28,19 @@ class ProviderUtilsTest {
|
|||||||
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(ProviderUtils.validateProvider(provider));
|
assertTrue(ProviderUtils.validateProvider(provider));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("providerParams")
|
@MethodSource("providerParams")
|
||||||
void testUnsuccessfulValidation(Provider provider) {
|
void testUnsuccessfulValidation(Provider provider) {
|
||||||
Assertions.assertFalse(ProviderUtils.validateProvider(provider));
|
assertFalse(ProviderUtils.validateProvider(provider));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Stream<Arguments> providerParams() {
|
public static Stream<Arguments> providerParams() {
|
||||||
Provider generic = null;
|
Provider generic = null;
|
||||||
var google =
|
var google =
|
||||||
new GoogleProvider(null, "clientSecret", List.of("scope"), UsernameAttribute.EMAIL);
|
new GoogleProvider(null, "clientSecret", List.of("scope"), UsernameAttribute.EMAIL);
|
||||||
var github = new GitHubProvider("clientId", "", List.of("scope"), UsernameAttribute.LOGIN);
|
var github = new GitHubProvider("clientId", "", List.of("scope"), UsernameAttribute.LOGIN);
|
||||||
|
|
||||||
return Stream.of(Arguments.of(generic), Arguments.of(google), Arguments.of(github));
|
return Stream.of(Arguments.of(generic), Arguments.of(google), Arguments.of(github));
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
package stirling.software.common.util.misc;
|
package stirling.software.common.util.misc;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
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;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
|
||||||
class HighContrastColorReplaceDeciderTest {
|
class HighContrastColorReplaceDeciderTest {
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@ import org.junit.jupiter.api.Test;
|
|||||||
import org.springframework.core.io.InputStreamResource;
|
import org.springframework.core.io.InputStreamResource;
|
||||||
import org.springframework.mock.web.MockMultipartFile;
|
import org.springframework.mock.web.MockMultipartFile;
|
||||||
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;
|
||||||
|
|
||||||
class InvertFullColorStrategyTest {
|
class InvertFullColorStrategyTest {
|
||||||
|
@ -9,7 +9,6 @@ import org.junit.jupiter.api.Test;
|
|||||||
import org.springframework.core.io.InputStreamResource;
|
import org.springframework.core.io.InputStreamResource;
|
||||||
import org.springframework.mock.web.MockMultipartFile;
|
import org.springframework.mock.web.MockMultipartFile;
|
||||||
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;
|
||||||
|
|
||||||
class ReplaceAndInvertColorStrategyTest {
|
class ReplaceAndInvertColorStrategyTest {
|
||||||
|
@ -1,17 +1,14 @@
|
|||||||
package stirling.software.common.util.propertyeditor;
|
package stirling.software.common.util.propertyeditor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import stirling.software.common.model.api.security.RedactionArea;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
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.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import stirling.software.common.model.api.security.RedactionArea;
|
|
||||||
|
|
||||||
class StringToArrayListPropertyEditorTest {
|
class StringToArrayListPropertyEditorTest {
|
||||||
|
|
||||||
private StringToArrayListPropertyEditor editor;
|
private StringToArrayListPropertyEditor editor;
|
||||||
|
@ -14,9 +14,9 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- /stirling/latest/data:/usr/share/tessdata:rw
|
- ./stirling/latest/data:/usr/share/tessdata:rw
|
||||||
- /stirling/latest/config:/configs:rw
|
- ./stirling/latest/config:/configs:rw
|
||||||
- /stirling/latest/logs:/logs:rw
|
- ./stirling/latest/logs:/logs:rw
|
||||||
environment:
|
environment:
|
||||||
DISABLE_ADDITIONAL_FEATURES: "false"
|
DISABLE_ADDITIONAL_FEATURES: "false"
|
||||||
SECURITY_ENABLELOGIN: "true"
|
SECURITY_ENABLELOGIN: "true"
|
||||||
|
@ -14,9 +14,9 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- /stirling/latest/data:/usr/share/tessdata:rw
|
- ./stirling/latest/data:/usr/share/tessdata:rw
|
||||||
- /stirling/latest/config:/configs:rw
|
- ./stirling/latest/config:/configs:rw
|
||||||
- /stirling/latest/logs:/logs:rw
|
- ./stirling/latest/logs:/logs:rw
|
||||||
environment:
|
environment:
|
||||||
DISABLE_ADDITIONAL_FEATURES: "false"
|
DISABLE_ADDITIONAL_FEATURES: "false"
|
||||||
SECURITY_ENABLELOGIN: "true"
|
SECURITY_ENABLELOGIN: "true"
|
||||||
|
@ -14,8 +14,8 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- /stirling/latest/config:/configs:rw
|
- ./stirling/latest/config:/configs:rw
|
||||||
- /stirling/latest/logs:/logs:rw
|
- ./stirling/latest/logs:/logs:rw
|
||||||
environment:
|
environment:
|
||||||
DISABLE_ADDITIONAL_FEATURES: "true"
|
DISABLE_ADDITIONAL_FEATURES: "true"
|
||||||
SECURITY_ENABLELOGIN: "false"
|
SECURITY_ENABLELOGIN: "false"
|
||||||
|
@ -14,9 +14,9 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- /stirling/latest/data:/usr/share/tessdata:rw
|
- ./stirling/latest/data:/usr/share/tessdata:rw
|
||||||
- /stirling/latest/config:/configs:rw
|
- ./stirling/latest/config:/configs:rw
|
||||||
- /stirling/latest/logs:/logs:rw
|
- ./stirling/latest/logs:/logs:rw
|
||||||
environment:
|
environment:
|
||||||
DISABLE_ADDITIONAL_FEATURES: "true"
|
DISABLE_ADDITIONAL_FEATURES: "true"
|
||||||
SECURITY_ENABLELOGIN: "false"
|
SECURITY_ENABLELOGIN: "false"
|
||||||
|
@ -14,9 +14,9 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- 8080:8080
|
- 8080:8080
|
||||||
volumes:
|
volumes:
|
||||||
- /stirling/latest/data:/usr/share/tessdata:rw
|
- ./stirling/latest/data:/usr/share/tessdata:rw
|
||||||
- /stirling/latest/config:/configs:rw
|
- ./stirling/latest/config:/configs:rw
|
||||||
- /stirling/latest/logs:/logs:rw
|
- ./stirling/latest/logs:/logs:rw
|
||||||
environment:
|
environment:
|
||||||
DISABLE_ADDITIONAL_FEATURES: "false"
|
DISABLE_ADDITIONAL_FEATURES: "false"
|
||||||
SECURITY_ENABLELOGIN: "true"
|
SECURITY_ENABLELOGIN: "true"
|
||||||
|
2
proprietary/.gitignore
vendored
2
proprietary/.gitignore
vendored
@ -124,6 +124,7 @@ SwaggerDoc.json
|
|||||||
*.rar
|
*.rar
|
||||||
*.db
|
*.db
|
||||||
/build
|
/build
|
||||||
|
/proprietary/build/
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
@ -193,4 +194,3 @@ id_ed25519.pub
|
|||||||
|
|
||||||
# node_modules
|
# node_modules
|
||||||
node_modules/
|
node_modules/
|
||||||
*.mjs
|
|
||||||
|
@ -1,28 +1,7 @@
|
|||||||
plugins {
|
|
||||||
id 'java-library'
|
|
||||||
id 'io.spring.dependency-management' version '1.1.7'
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
|
||||||
maven { url = "https://build.shibboleth.net/maven/releases" }
|
maven { url = "https://build.shibboleth.net/maven/releases" }
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations.all {
|
|
||||||
exclude group: 'commons-logging', module: 'commons-logging'
|
|
||||||
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencyManagement {
|
|
||||||
imports {
|
|
||||||
mavenBom 'org.springframework.boot:spring-boot-dependencies:3.5.0'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(':common')
|
implementation project(':common')
|
||||||
|
|
||||||
@ -42,7 +21,6 @@ dependencies {
|
|||||||
// 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 'io.github.pixee:java-security-toolkit:1.2.1'
|
|
||||||
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.3.RELEASE'
|
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.3.RELEASE'
|
||||||
api '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'
|
||||||
@ -54,14 +32,6 @@ dependencies {
|
|||||||
implementation "org.opensaml:opensaml-saml-impl:$openSamlVersion"
|
implementation "org.opensaml:opensaml-saml-impl:$openSamlVersion"
|
||||||
}
|
}
|
||||||
implementation 'com.coveo:saml-client:5.0.0'
|
implementation 'com.coveo:saml-client:5.0.0'
|
||||||
|
|
||||||
compileOnly "org.projectlombok:lombok:$lombokVersion"
|
|
||||||
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
|
||||||
|
|
||||||
testImplementation platform('org.junit:junit-bom:5.10.0')
|
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter'
|
|
||||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
|
||||||
testRuntimeOnly 'org.mockito:mockito-inline:5.2.0'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register('prepareKotlinBuildScriptModel') {}
|
tasks.register('prepareKotlinBuildScriptModel') {}
|
||||||
|
@ -38,6 +38,7 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
|
|||||||
public static final String LOGOUT_PATH = "/login?logout=true";
|
public static final String LOGOUT_PATH = "/login?logout=true";
|
||||||
|
|
||||||
private final ApplicationProperties applicationProperties;
|
private final ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
private final AppConfig appConfig;
|
private final AppConfig appConfig;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -6,6 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.DependsOn;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.security.authentication.ProviderManager;
|
import org.springframework.security.authentication.ProviderManager;
|
||||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||||
@ -55,6 +56,7 @@ import stirling.software.proprietary.security.session.SessionPersistentRegistry;
|
|||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@EnableMethodSecurity
|
@EnableMethodSecurity
|
||||||
|
@DependsOn("runningProOrHigher")
|
||||||
public class SecurityConfiguration {
|
public class SecurityConfiguration {
|
||||||
|
|
||||||
private final CustomUserDetailsService userDetailsService;
|
private final CustomUserDetailsService userDetailsService;
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
package stirling.software.SPDF.EE;
|
package stirling.software.proprietary.security.configuration.ee;
|
||||||
|
|
||||||
|
import static stirling.software.proprietary.security.configuration.ee.KeygenLicenseVerifier.License;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
import stirling.software.SPDF.EE.KeygenLicenseVerifier.License;
|
|
||||||
import stirling.software.common.model.ApplicationProperties;
|
import stirling.software.common.model.ApplicationProperties;
|
||||||
import stirling.software.common.model.ApplicationProperties.EnterpriseEdition;
|
import stirling.software.common.model.ApplicationProperties.EnterpriseEdition;
|
||||||
import stirling.software.common.model.ApplicationProperties.Premium;
|
import stirling.software.common.model.ApplicationProperties.Premium;
|
||||||
@ -15,7 +15,6 @@ import stirling.software.common.model.ApplicationProperties.Premium.ProFeatures.
|
|||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||||
@Slf4j
|
|
||||||
public class EEAppConfig {
|
public class EEAppConfig {
|
||||||
|
|
||||||
private final ApplicationProperties applicationProperties;
|
private final ApplicationProperties applicationProperties;
|
||||||
@ -30,6 +29,7 @@ public class EEAppConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean(name = "runningProOrHigher")
|
@Bean(name = "runningProOrHigher")
|
||||||
|
@Qualifier("runningProOrHigher")
|
||||||
public boolean runningProOrHigher() {
|
public boolean runningProOrHigher() {
|
||||||
return licenseKeyChecker.getPremiumLicenseEnabledResult() != License.NORMAL;
|
return licenseKeyChecker.getPremiumLicenseEnabledResult() != License.NORMAL;
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package stirling.software.SPDF.EE;
|
package stirling.software.proprietary.security.configuration.ee;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.http.HttpClient;
|
import java.net.http.HttpClient;
|
||||||
@ -27,7 +27,7 @@ import stirling.software.common.util.GeneralUtils;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class KeygenLicenseVerifier {
|
public class KeygenLicenseVerifier {
|
||||||
|
|
||||||
enum License {
|
public enum License {
|
||||||
NORMAL,
|
NORMAL,
|
||||||
PRO,
|
PRO,
|
||||||
ENTERPRISE
|
ENTERPRISE
|
@ -1,4 +1,4 @@
|
|||||||
package stirling.software.SPDF.EE;
|
package stirling.software.proprietary.security.configuration.ee;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@ -10,12 +10,12 @@ import org.springframework.stereotype.Component;
|
|||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.SPDF.EE.KeygenLicenseVerifier.License;
|
|
||||||
import stirling.software.common.model.ApplicationProperties;
|
import stirling.software.common.model.ApplicationProperties;
|
||||||
import stirling.software.common.util.GeneralUtils;
|
import stirling.software.common.util.GeneralUtils;
|
||||||
|
import stirling.software.proprietary.security.configuration.ee.KeygenLicenseVerifier.License;
|
||||||
|
|
||||||
@Component
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@Component
|
||||||
public class LicenseKeyChecker {
|
public class LicenseKeyChecker {
|
||||||
|
|
||||||
private static final String FILE_PREFIX = "file:";
|
private static final String FILE_PREFIX = "file:";
|
@ -5,7 +5,6 @@ import java.util.Collections;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.opensaml.saml.saml2.core.AuthnRequest;
|
import org.opensaml.saml.saml2.core.AuthnRequest;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@ -30,8 +29,8 @@ import stirling.software.common.model.ApplicationProperties.Security.SAML2;
|
|||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@ConditionalOnProperty(value = "security.saml2.enabled", havingValue = "true")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@ConditionalOnBooleanProperty("security.saml2.enabled")
|
|
||||||
public class SAML2Configuration {
|
public class SAML2Configuration {
|
||||||
|
|
||||||
private final ApplicationProperties applicationProperties;
|
private final ApplicationProperties applicationProperties;
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package stirling.software.SPDF.EE;
|
package stirling.software.proprietary.security.configuration.ee;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyNoInteractions;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
import static stirling.software.proprietary.security.configuration.ee.KeygenLicenseVerifier.License;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@ -13,7 +16,6 @@ import org.junit.jupiter.api.io.TempDir;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
import stirling.software.SPDF.EE.KeygenLicenseVerifier.License;
|
|
||||||
import stirling.software.common.model.ApplicationProperties;
|
import stirling.software.common.model.ApplicationProperties;
|
||||||
|
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
@ -1,5 +1,5 @@
|
|||||||
echo "Running Stirling PDF with DISABLE_ADDITIONAL_FEATURES=${DISABLE_ADDITIONAL_FEATURES} and VERSION_TAG=${VERSION_TAG}"
|
echo "Running Stirling PDF with DISABLE_ADDITIONAL_FEATURES=${DISABLE_ADDITIONAL_FEATURES} and VERSION_TAG=${VERSION_TAG}"
|
||||||
# Check for $DISABLE_ADDITIONAL_FEATURES and download the appropriate JAR if required
|
# Check for DISABLE_ADDITIONAL_FEATURES and download the appropriate JAR if required
|
||||||
if [ "$DISABLE_ADDITIONAL_FEATURES" = "false" ] && [ "$VERSION_TAG" != "alpha" ]; then
|
if [ "$DISABLE_ADDITIONAL_FEATURES" = "false" ] && [ "$VERSION_TAG" != "alpha" ]; then
|
||||||
if [ ! -f app-security.jar ]; then
|
if [ ! -f app-security.jar ]; then
|
||||||
echo "Trying to download from: https://files.stirlingpdf.com/v$VERSION_TAG/Stirling-PDF-with-login.jar"
|
echo "Trying to download from: https://files.stirlingpdf.com/v$VERSION_TAG/Stirling-PDF-with-login.jar"
|
||||||
|
@ -4,4 +4,4 @@ plugins {
|
|||||||
}
|
}
|
||||||
rootProject.name = 'Stirling-PDF'
|
rootProject.name = 'Stirling-PDF'
|
||||||
|
|
||||||
include 'common', 'proprietary'
|
include 'stirling-pdf', 'common', 'proprietary'
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
package stirling.software.SPDF.model.api;
|
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@NoArgsConstructor
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@ConditionalOnProperty(value = "mail.enabled", havingValue = "true", matchIfMissing = false)
|
|
||||||
public class Email extends GeneralFile {
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "The recipient's email address",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED,
|
|
||||||
format = "email")
|
|
||||||
private String to;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "The subject of the email",
|
|
||||||
defaultValue = "Stirling Software PDF Notification",
|
|
||||||
requiredMode = Schema.RequiredMode.NOT_REQUIRED)
|
|
||||||
private String subject;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "The body of the email",
|
|
||||||
requiredMode = Schema.RequiredMode.NOT_REQUIRED,
|
|
||||||
defaultValue =
|
|
||||||
"This message was automatically generated by Stirling-PDF, an innovative"
|
|
||||||
+ " solution from Stirling Software. For more information, visit our <a"
|
|
||||||
+ " href=\"https://stirling-software.com\">website</a>.<br><br>Please do"
|
|
||||||
+ " not reply directly to this email.")
|
|
||||||
private String body;
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
package stirling.software.SPDF.model.api;
|
|
||||||
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode
|
|
||||||
public class GeneralFile {
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "The input file",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED,
|
|
||||||
format = "binary")
|
|
||||||
private MultipartFile fileInput;
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
package stirling.software.SPDF.model.api.converters;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
import stirling.software.SPDF.model.api.PDFWithPageNums;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class ConvertToImageRequest extends PDFWithPageNums {
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "The output image format",
|
|
||||||
defaultValue = "png",
|
|
||||||
allowableValues = {"png", "jpeg", "jpg", "gif", "webp"},
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private String imageFormat;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description =
|
|
||||||
"Choose between a single image containing all pages or separate images for each"
|
|
||||||
+ " page",
|
|
||||||
defaultValue = "multiple",
|
|
||||||
allowableValues = {"single", "multiple"},
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private String singleOrMultiple;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "The color type of the output image(s)",
|
|
||||||
defaultValue = "color",
|
|
||||||
allowableValues = {"color", "greyscale", "blackwhite"},
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private String colorType;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "The DPI (dots per inch) for the output image(s)",
|
|
||||||
defaultValue = "300",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private Integer dpi;
|
|
||||||
}
|
|
@ -1,46 +0,0 @@
|
|||||||
package stirling.software.SPDF.model.api.general;
|
|
||||||
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
import stirling.software.common.model.api.PDFFile;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class OverlayPdfsRequest extends PDFFile {
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description =
|
|
||||||
"An array of PDF files to be used as overlays on the base PDF. The order in"
|
|
||||||
+ " these files is applied based on the selected mode.",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private MultipartFile[] overlayFiles;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description =
|
|
||||||
"The mode of overlaying: 'SequentialOverlay' for sequential application,"
|
|
||||||
+ " 'InterleavedOverlay' for round-robin application, 'FixedRepeatOverlay'"
|
|
||||||
+ " for fixed repetition based on provided counts",
|
|
||||||
allowableValues = {"SequentialOverlay", "InterleavedOverlay", "FixedRepeatOverlay"},
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private String overlayMode;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description =
|
|
||||||
"An array of integers specifying the number of times each corresponding overlay"
|
|
||||||
+ " file should be applied in the 'FixedRepeatOverlay' mode. This should"
|
|
||||||
+ " match the length of the overlayFiles array.",
|
|
||||||
requiredMode = Schema.RequiredMode.NOT_REQUIRED)
|
|
||||||
private int[] counts;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "Overlay position 0 is Foregound, 1 is Background",
|
|
||||||
allowableValues = {"0", "1"},
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED,
|
|
||||||
type = "number")
|
|
||||||
private int overlayPosition;
|
|
||||||
}
|
|
@ -1,87 +0,0 @@
|
|||||||
package stirling.software.SPDF.model.api.misc;
|
|
||||||
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
import stirling.software.SPDF.model.api.PDFWithPageNums;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class AddStampRequest extends PDFWithPageNums {
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "The stamp type (text or image)",
|
|
||||||
allowableValues = {"text", "image"},
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private String stampType;
|
|
||||||
|
|
||||||
@Schema(description = "The stamp text", defaultValue = "Stirling Software")
|
|
||||||
private String stampText;
|
|
||||||
|
|
||||||
@Schema(description = "The stamp image")
|
|
||||||
private MultipartFile stampImage;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "The selected alphabet of the stamp text",
|
|
||||||
allowableValues = {"roman", "arabic", "japanese", "korean", "chinese"},
|
|
||||||
defaultValue = "roman")
|
|
||||||
private String alphabet = "roman";
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "The font size of the stamp text and image",
|
|
||||||
defaultValue = "30",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private float fontSize;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "The rotation of the stamp in degrees",
|
|
||||||
defaultValue = "0",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private float rotation;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "The opacity of the stamp (0.0 - 1.0)",
|
|
||||||
defaultValue = "0.5",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private float opacity;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description =
|
|
||||||
"Position for stamp placement based on a 1-9 grid (1: bottom-left, 2: bottom-center,"
|
|
||||||
+ " 3: bottom-right, 4: middle-left, 5: middle-center, 6: middle-right,"
|
|
||||||
+ " 7: top-left, 8: top-center, 9: top-right)",
|
|
||||||
allowableValues = {"1", "2", "3", "4", "5", "6", "7", "8", "9"},
|
|
||||||
defaultValue = "5",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private int position;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description =
|
|
||||||
"Override X coordinate for stamp placement. If set, it will override the"
|
|
||||||
+ " position-based calculation. Negative value means no override.",
|
|
||||||
defaultValue = "-1",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private float overrideX; // Default to -1 indicating no override
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description =
|
|
||||||
"Override Y coordinate for stamp placement. If set, it will override the"
|
|
||||||
+ " position-based calculation. Negative value means no override.",
|
|
||||||
defaultValue = "-1",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private float overrideY; // Default to -1 indicating no override
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "Specifies the margin size for the stamp.",
|
|
||||||
allowableValues = {"small", "medium", "large", "x-large"},
|
|
||||||
defaultValue = "medium",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private String customMargin;
|
|
||||||
|
|
||||||
@Schema(description = "The color of the stamp text", defaultValue = "#d3d3d3")
|
|
||||||
private String customColor;
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
package stirling.software.SPDF.model.api.misc;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
import stirling.software.common.model.api.PDFFile;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class MetadataRequest extends PDFFile {
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "Delete all metadata if set to true",
|
|
||||||
defaultValue = "false",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private Boolean deleteAll;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "The author of the document",
|
|
||||||
defaultValue = "author",
|
|
||||||
requiredMode = Schema.RequiredMode.NOT_REQUIRED)
|
|
||||||
private String author;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "The creation date of the document (format: yyyy/MM/dd HH:mm:ss)",
|
|
||||||
pattern = "yyyy/MM/dd HH:mm:ss",
|
|
||||||
defaultValue = "2023/10/01 12:00:00",
|
|
||||||
requiredMode = Schema.RequiredMode.NOT_REQUIRED)
|
|
||||||
private String creationDate;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "The creator of the document",
|
|
||||||
defaultValue = "creator",
|
|
||||||
requiredMode = Schema.RequiredMode.NOT_REQUIRED)
|
|
||||||
private String creator;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "The keywords for the document",
|
|
||||||
defaultValue = "keywords",
|
|
||||||
requiredMode = Schema.RequiredMode.NOT_REQUIRED)
|
|
||||||
private String keywords;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "The modification date of the document (format: yyyy/MM/dd HH:mm:ss)",
|
|
||||||
pattern = "yyyy/MM/dd HH:mm:ss",
|
|
||||||
defaultValue = "2023/10/01 12:00:00",
|
|
||||||
requiredMode = Schema.RequiredMode.NOT_REQUIRED)
|
|
||||||
private String modificationDate;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "The producer of the document",
|
|
||||||
defaultValue = "producer",
|
|
||||||
requiredMode = Schema.RequiredMode.NOT_REQUIRED)
|
|
||||||
private String producer;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "The subject of the document",
|
|
||||||
defaultValue = "subject",
|
|
||||||
requiredMode = Schema.RequiredMode.NOT_REQUIRED)
|
|
||||||
private String subject;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "The title of the document",
|
|
||||||
defaultValue = "title",
|
|
||||||
requiredMode = Schema.RequiredMode.NOT_REQUIRED)
|
|
||||||
private String title;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "The trapped status of the document",
|
|
||||||
defaultValue = "False",
|
|
||||||
allowableValues = {"True", "False", "Unknown"},
|
|
||||||
requiredMode = Schema.RequiredMode.NOT_REQUIRED)
|
|
||||||
private String trapped;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description =
|
|
||||||
"Map list of key and value of custom parameters. Note these must start with"
|
|
||||||
+ " customKey and customValue if they are non-standard")
|
|
||||||
private Map<String, String> allRequestParams;
|
|
||||||
}
|
|
@ -1,49 +0,0 @@
|
|||||||
package stirling.software.SPDF.model.api.security;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
import stirling.software.common.model.api.PDFFile;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class RedactPdfRequest extends PDFFile {
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "List of text to redact from the PDF",
|
|
||||||
defaultValue = "text,text2",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private String listOfText;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "Whether to use regex for the listOfText",
|
|
||||||
defaultValue = "false",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private Boolean useRegex;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "Whether to use whole word search",
|
|
||||||
defaultValue = "false",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private Boolean wholeWordSearch;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "The color for redaction",
|
|
||||||
defaultValue = "#000000",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private String redactColor;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "Custom padding for redaction",
|
|
||||||
type = "number",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private float customPadding;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "Convert the redacted PDF to an image",
|
|
||||||
defaultValue = "false",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private Boolean convertPDFToImage;
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
package stirling.software.SPDF.model.api.security;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode
|
|
||||||
public class RedactionArea {
|
|
||||||
@Schema(description = "The left edge point of the area to be redacted.")
|
|
||||||
private Double x;
|
|
||||||
|
|
||||||
@Schema(description = "The top edge point of the area to be redacted.")
|
|
||||||
private Double y;
|
|
||||||
|
|
||||||
@Schema(description = "The height of the area to be redacted.")
|
|
||||||
private Double height;
|
|
||||||
|
|
||||||
@Schema(description = "The width of the area to be redacted.")
|
|
||||||
private Double width;
|
|
||||||
|
|
||||||
@Schema(description = "The page on which the area should be redacted.")
|
|
||||||
private Integer page;
|
|
||||||
|
|
||||||
@Schema(description = "The color used to redact the specified area.")
|
|
||||||
private String color;
|
|
||||||
}
|
|
@ -1,49 +0,0 @@
|
|||||||
package stirling.software.SPDF.model.api.security;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
import stirling.software.common.model.api.PDFFile;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class SanitizePdfRequest extends PDFFile {
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "Remove JavaScript actions from the PDF",
|
|
||||||
defaultValue = "true",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private Boolean removeJavaScript;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "Remove embedded files from the PDF",
|
|
||||||
defaultValue = "true",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private Boolean removeEmbeddedFiles;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "Remove XMP metadata from the PDF",
|
|
||||||
defaultValue = "false",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private Boolean removeXMPMetadata;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "Remove document info metadata from the PDF",
|
|
||||||
defaultValue = "false",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private Boolean removeMetadata;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "Remove links from the PDF",
|
|
||||||
defaultValue = "false",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private Boolean removeLinks;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "Remove fonts from the PDF",
|
|
||||||
defaultValue = "false",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private Boolean removeFonts;
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
package stirling.software.SPDF.model.api.user;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class UpdateUserDetails extends UpdateUserUsername {
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "new password for user",
|
|
||||||
format = "password",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private String newPassword;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
package stirling.software.SPDF.model.api.user;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class UpdateUserUsername extends UsernameAndPass {
|
|
||||||
|
|
||||||
@Schema(description = "new username for user")
|
|
||||||
private String newUsername;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
package stirling.software.SPDF.model.api.user;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode
|
|
||||||
public class Username {
|
|
||||||
|
|
||||||
@Schema(description = "username of user", requiredMode = Schema.RequiredMode.REQUIRED)
|
|
||||||
private String username;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
package stirling.software.SPDF.model.api.user;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class UsernameAndPass extends Username {
|
|
||||||
|
|
||||||
@Schema(description = "password of user", format = "password")
|
|
||||||
private String password;
|
|
||||||
}
|
|
196
stirling-pdf/.gitignore
vendored
Normal file
196
stirling-pdf/.gitignore
vendored
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
### Eclipse ###
|
||||||
|
.metadata
|
||||||
|
bin/
|
||||||
|
tmp/
|
||||||
|
*.tmp
|
||||||
|
*.bak
|
||||||
|
*.exe
|
||||||
|
*.swp
|
||||||
|
*~.nib
|
||||||
|
local.properties
|
||||||
|
.settings/
|
||||||
|
.loadpath
|
||||||
|
.recommenders
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
version.properties
|
||||||
|
|
||||||
|
#### Stirling-PDF Files ###
|
||||||
|
pipeline/watchedFolders/
|
||||||
|
pipeline/finishedFolders/
|
||||||
|
customFiles/
|
||||||
|
configs/
|
||||||
|
watchedFolders/
|
||||||
|
clientWebUI/
|
||||||
|
!cucumber/
|
||||||
|
!cucumber/exampleFiles/
|
||||||
|
!cucumber/exampleFiles/example_html.zip
|
||||||
|
exampleYmlFiles/stirling/
|
||||||
|
/testing/file_snapshots
|
||||||
|
SwaggerDoc.json
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.gradle
|
||||||
|
.lock
|
||||||
|
|
||||||
|
# External tool builders
|
||||||
|
.externalToolBuilders/
|
||||||
|
|
||||||
|
# Locally stored "Eclipse launch configurations"
|
||||||
|
*.launch
|
||||||
|
|
||||||
|
# PyDev specific (Python IDE for Eclipse)
|
||||||
|
*.pydevproject
|
||||||
|
|
||||||
|
# CDT-specific (C/C++ Development Tooling)
|
||||||
|
.cproject
|
||||||
|
|
||||||
|
# CDT- autotools
|
||||||
|
.autotools
|
||||||
|
|
||||||
|
# Java annotation processor (APT)
|
||||||
|
.factorypath
|
||||||
|
|
||||||
|
# PDT-specific (PHP Development Tools)
|
||||||
|
.buildpath
|
||||||
|
|
||||||
|
# sbteclipse plugin
|
||||||
|
.target
|
||||||
|
|
||||||
|
# Tern plugin
|
||||||
|
.tern-project
|
||||||
|
|
||||||
|
# TeXlipse plugin
|
||||||
|
.texlipse
|
||||||
|
|
||||||
|
# STS (Spring Tool Suite)
|
||||||
|
.springBeans
|
||||||
|
|
||||||
|
# Code Recommenders
|
||||||
|
.recommenders/
|
||||||
|
|
||||||
|
# Annotation Processing
|
||||||
|
.apt_generated/
|
||||||
|
.apt_generated_test/
|
||||||
|
|
||||||
|
# Scala IDE specific (Scala & Java development for Eclipse)
|
||||||
|
.cache-main
|
||||||
|
.scala_dependencies
|
||||||
|
.worksheet
|
||||||
|
|
||||||
|
# Uncomment this line if you wish to ignore the project description file.
|
||||||
|
# Typically, this file would be tracked if it contains build/dependency configurations:
|
||||||
|
#.project
|
||||||
|
|
||||||
|
### Eclipse Patch ###
|
||||||
|
# Spring Boot Tooling
|
||||||
|
.sts4-cache/
|
||||||
|
|
||||||
|
### Git ###
|
||||||
|
# Created by git for backups. To disable backups in Git:
|
||||||
|
# $ git config --global mergetool.keepBackup false
|
||||||
|
*.orig
|
||||||
|
|
||||||
|
# Created by git when using merge tools for conflicts
|
||||||
|
*.BACKUP.*
|
||||||
|
*.BASE.*
|
||||||
|
*.LOCAL.*
|
||||||
|
*.REMOTE.*
|
||||||
|
*_BACKUP_*.txt
|
||||||
|
*_BASE_*.txt
|
||||||
|
*_LOCAL_*.txt
|
||||||
|
*_REMOTE_*.txt
|
||||||
|
|
||||||
|
### Java ###
|
||||||
|
# Compiled class file
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Log file
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# BlueJ files
|
||||||
|
*.ctxt
|
||||||
|
|
||||||
|
# Mobile Tools for Java (J2ME)
|
||||||
|
.mtj.tmp/
|
||||||
|
|
||||||
|
# Package Files #
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.nar
|
||||||
|
*.ear
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
*.rar
|
||||||
|
*.db
|
||||||
|
/build/*
|
||||||
|
/stirling-pdf/build/*
|
||||||
|
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*.pyo
|
||||||
|
|
||||||
|
# Virtual environments
|
||||||
|
.env*
|
||||||
|
.venv*
|
||||||
|
env*/
|
||||||
|
venv*/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# VS Code
|
||||||
|
/.vscode/**/*
|
||||||
|
!/.vscode/settings.json
|
||||||
|
!/.vscode/extensions.json
|
||||||
|
|
||||||
|
# IntelliJ IDEA
|
||||||
|
.idea/
|
||||||
|
*.iml
|
||||||
|
out/
|
||||||
|
|
||||||
|
# Ignore Mac DS_Store files
|
||||||
|
.DS_Store
|
||||||
|
**/.DS_Store
|
||||||
|
|
||||||
|
# cucumber
|
||||||
|
/cucumber/reports/**
|
||||||
|
|
||||||
|
# Certs and Security Files
|
||||||
|
*.p12
|
||||||
|
*.pk8
|
||||||
|
*.pem
|
||||||
|
*.crt
|
||||||
|
*.cer
|
||||||
|
*.cert
|
||||||
|
*.der
|
||||||
|
*.key
|
||||||
|
*.csr
|
||||||
|
*.kdbx
|
||||||
|
*.jks
|
||||||
|
*.asc
|
||||||
|
|
||||||
|
# SSH Keys
|
||||||
|
*.pub
|
||||||
|
*.priv
|
||||||
|
id_rsa
|
||||||
|
id_rsa.pub
|
||||||
|
id_ecdsa
|
||||||
|
id_ecdsa.pub
|
||||||
|
id_ed25519
|
||||||
|
id_ed25519.pub
|
||||||
|
.ssh/
|
||||||
|
*ssh
|
||||||
|
|
||||||
|
# cache
|
||||||
|
.cache
|
||||||
|
.ruff_cache
|
||||||
|
.mypy_cache
|
||||||
|
.pytest_cache
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
**/jcef-bundle/
|
||||||
|
|
||||||
|
# node_modules
|
||||||
|
node_modules/
|
95
stirling-pdf/build.gradle
Normal file
95
stirling-pdf/build.gradle
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
repositories {
|
||||||
|
maven { url = 'https://build.shibboleth.net/maven/releases' }
|
||||||
|
maven { url = 'https://maven.pkg.github.com/jcefmaven/jcefmaven' }
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
if (System.getenv('STIRLING_PDF_DESKTOP_UI') != 'false'
|
||||||
|
|| (project.hasProperty('STIRLING_PDF_DESKTOP_UI')
|
||||||
|
&& project.getProperty('STIRLING_PDF_DESKTOP_UI') != 'false')) {
|
||||||
|
implementation 'me.friwi:jcefmaven:132.3.1'
|
||||||
|
implementation 'org.openjfx:javafx-controls:21'
|
||||||
|
implementation 'org.openjfx:javafx-swing:21'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (System.getenv('DISABLE_ADDITIONAL_FEATURES') != 'true'
|
||||||
|
|| (project.hasProperty('DISABLE_ADDITIONAL_FEATURES')
|
||||||
|
&& System.getProperty('DISABLE_ADDITIONAL_FEATURES') != 'true')) {
|
||||||
|
implementation project(':proprietary')
|
||||||
|
}
|
||||||
|
|
||||||
|
implementation project(':common')
|
||||||
|
implementation 'org.springframework.boot:spring-boot-starter-jetty'
|
||||||
|
implementation 'com.posthog.java:posthog:1.2.0'
|
||||||
|
implementation 'commons-io:commons-io:2.19.0'
|
||||||
|
implementation "org.bouncycastle:bcprov-jdk18on:$bouncycastleVersion"
|
||||||
|
implementation "org.bouncycastle:bcpkix-jdk18on:$bouncycastleVersion"
|
||||||
|
implementation 'io.micrometer:micrometer-core:1.14.6'
|
||||||
|
implementation 'com.google.zxing:core:3.5.3'
|
||||||
|
implementation "org.commonmark:commonmark:$commonmarkVersion" // https://mvnrepository.com/artifact/org.commonmark/commonmark
|
||||||
|
implementation "org.commonmark:commonmark-ext-gfm-tables:$commonmarkVersion"
|
||||||
|
|
||||||
|
// General PDF dependencies
|
||||||
|
implementation "org.apache.pdfbox:preflight:$pdfboxVersion"
|
||||||
|
implementation "org.apache.pdfbox:xmpbox:$pdfboxVersion"
|
||||||
|
|
||||||
|
// https://mvnrepository.com/artifact/technology.tabula/tabula
|
||||||
|
implementation ('technology.tabula:tabula:1.0.5') {
|
||||||
|
exclude group: 'org.slf4j', module: 'slf4j-simple'
|
||||||
|
exclude group: 'org.bouncycastle', module: 'bcprov-jdk15on'
|
||||||
|
exclude group: 'com.google.code.gson', module: 'gson'
|
||||||
|
}
|
||||||
|
implementation 'org.apache.pdfbox:jbig2-imageio:3.0.4'
|
||||||
|
implementation 'com.opencsv:opencsv:5.11' // https://mvnrepository.com/artifact/com.opencsv/opencsv
|
||||||
|
|
||||||
|
// Batik
|
||||||
|
implementation 'org.apache.xmlgraphics:batik-all:1.18'
|
||||||
|
|
||||||
|
// TwelveMonkeys
|
||||||
|
runtimeOnly "com.twelvemonkeys.imageio:imageio-batik:$imageioVersion"
|
||||||
|
runtimeOnly "com.twelvemonkeys.imageio:imageio-bmp:$imageioVersion"
|
||||||
|
runtimeOnly "com.twelvemonkeys.imageio:imageio-jpeg:$imageioVersion"
|
||||||
|
runtimeOnly "com.twelvemonkeys.imageio:imageio-tiff:$imageioVersion"
|
||||||
|
runtimeOnly "com.twelvemonkeys.imageio:imageio-webp:$imageioVersion"
|
||||||
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-hdr:$imageioVersion"
|
||||||
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-icns:$imageioVersion"
|
||||||
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-iff:$imageioVersion"
|
||||||
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-pcx:$imageioVersion@
|
||||||
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-pict:$imageioVersion"
|
||||||
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-pnm:$imageioVersion"
|
||||||
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-psd:$imageioVersion"
|
||||||
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-sgi:$imageioVersion"
|
||||||
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-tga:$imageioVersion"
|
||||||
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-thumbsdb:$imageioVersion"
|
||||||
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-xwd:$imageioVersion"
|
||||||
|
|
||||||
|
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
|
resources {
|
||||||
|
srcDirs += ['../configs']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||||
|
zip64 = true
|
||||||
|
|
||||||
|
from {
|
||||||
|
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
manifest {
|
||||||
|
attributes(
|
||||||
|
'Main-Class': 'stirling.software.SPDF.SPDFApplication',
|
||||||
|
'Implementation-Title': 'Stirling-PDF',
|
||||||
|
'Implementation-Version': project.version
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jar.dependsOn ':common:jar'
|
||||||
|
jar.dependsOn ':proprietary:jar'
|
@ -11,7 +11,6 @@ import java.util.Map;
|
|||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||||
@ -27,6 +26,7 @@ import jakarta.annotation.PreDestroy;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.SPDF.UI.WebBrowser;
|
import stirling.software.SPDF.UI.WebBrowser;
|
||||||
|
import stirling.software.common.configuration.AppConfig;
|
||||||
import stirling.software.common.configuration.ConfigInitializer;
|
import stirling.software.common.configuration.ConfigInitializer;
|
||||||
import stirling.software.common.configuration.InstallationPathConfig;
|
import stirling.software.common.configuration.InstallationPathConfig;
|
||||||
import stirling.software.common.model.ApplicationProperties;
|
import stirling.software.common.model.ApplicationProperties;
|
||||||
@ -36,9 +36,9 @@ import stirling.software.common.util.UrlUtils;
|
|||||||
@EnableScheduling
|
@EnableScheduling
|
||||||
@SpringBootApplication(
|
@SpringBootApplication(
|
||||||
scanBasePackages = {
|
scanBasePackages = {
|
||||||
"stirling.software.common",
|
|
||||||
"stirling.software.SPDF",
|
"stirling.software.SPDF",
|
||||||
"stirling.software.proprietary.security"
|
"stirling.software.common",
|
||||||
|
"stirling.software.proprietary"
|
||||||
},
|
},
|
||||||
exclude = {
|
exclude = {
|
||||||
DataSourceAutoConfiguration.class,
|
DataSourceAutoConfiguration.class,
|
||||||
@ -50,20 +50,17 @@ public class SPDFApplication {
|
|||||||
private static String baseUrlStatic;
|
private static String baseUrlStatic;
|
||||||
private static String contextPathStatic;
|
private static String contextPathStatic;
|
||||||
|
|
||||||
|
private final AppConfig appConfig;
|
||||||
private final Environment env;
|
private final Environment env;
|
||||||
private final ApplicationProperties applicationProperties;
|
private final ApplicationProperties applicationProperties;
|
||||||
private final WebBrowser webBrowser;
|
private final WebBrowser webBrowser;
|
||||||
|
|
||||||
@Value("${baseUrl:http://localhost}")
|
|
||||||
private String baseUrl;
|
|
||||||
|
|
||||||
@Value("${server.servlet.context-path:/}")
|
|
||||||
private String contextPath;
|
|
||||||
|
|
||||||
public SPDFApplication(
|
public SPDFApplication(
|
||||||
|
AppConfig appConfig,
|
||||||
Environment env,
|
Environment env,
|
||||||
ApplicationProperties applicationProperties,
|
ApplicationProperties applicationProperties,
|
||||||
@Autowired(required = false) WebBrowser webBrowser) {
|
@Autowired(required = false) WebBrowser webBrowser) {
|
||||||
|
this.appConfig = appConfig;
|
||||||
this.env = env;
|
this.env = env;
|
||||||
this.applicationProperties = applicationProperties;
|
this.applicationProperties = applicationProperties;
|
||||||
this.webBrowser = webBrowser;
|
this.webBrowser = webBrowser;
|
||||||
@ -152,9 +149,14 @@ public class SPDFApplication {
|
|||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
baseUrlStatic = this.baseUrl;
|
String baseUrl = appConfig.getBaseUrl();
|
||||||
contextPathStatic = this.contextPath;
|
String contextPath = appConfig.getContextPath();
|
||||||
|
String serverPort = appConfig.getServerPort();
|
||||||
|
baseUrlStatic = baseUrl;
|
||||||
|
contextPathStatic = contextPath;
|
||||||
|
serverPortStatic = serverPort;
|
||||||
String url = baseUrl + ":" + getStaticPort() + contextPath;
|
String url = baseUrl + ":" + getStaticPort() + contextPath;
|
||||||
|
|
||||||
if (webBrowser != null
|
if (webBrowser != null
|
||||||
&& Boolean.parseBoolean(System.getProperty("STIRLING_PDF_DESKTOP_UI", "false"))) {
|
&& Boolean.parseBoolean(System.getProperty("STIRLING_PDF_DESKTOP_UI", "false"))) {
|
||||||
webBrowser.initWebUI(url);
|
webBrowser.initWebUI(url);
|
||||||
@ -165,6 +167,7 @@ public class SPDFApplication {
|
|||||||
try {
|
try {
|
||||||
String os = System.getProperty("os.name").toLowerCase();
|
String os = System.getProperty("os.name").toLowerCase();
|
||||||
Runtime rt = Runtime.getRuntime();
|
Runtime rt = Runtime.getRuntime();
|
||||||
|
|
||||||
if (os.contains("win")) {
|
if (os.contains("win")) {
|
||||||
// For Windows
|
// For Windows
|
||||||
SystemCommand.runCommand(rt, "rundll32 url.dll,FileProtocolHandler " + url);
|
SystemCommand.runCommand(rt, "rundll32 url.dll,FileProtocolHandler " + url);
|
||||||
@ -181,17 +184,6 @@ public class SPDFApplication {
|
|||||||
log.info("Running configs {}", applicationProperties.toString());
|
log.info("Running configs {}", applicationProperties.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Value("${server.port:8080}")
|
|
||||||
public void setServerPort(String port) {
|
|
||||||
if ("auto".equalsIgnoreCase(port)) {
|
|
||||||
// Use Spring Boot's automatic port assignment (server.port=0)
|
|
||||||
SPDFApplication.serverPortStatic =
|
|
||||||
"0"; // This will let Spring Boot assign an available port
|
|
||||||
} else {
|
|
||||||
SPDFApplication.serverPortStatic = port;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setServerPortStatic(String port) {
|
public static void setServerPortStatic(String port) {
|
||||||
if ("auto".equalsIgnoreCase(port)) {
|
if ("auto".equalsIgnoreCase(port)) {
|
||||||
// Use Spring Boot's automatic port assignment (server.port=0)
|
// Use Spring Boot's automatic port assignment (server.port=0)
|
@ -14,21 +14,21 @@ import jakarta.servlet.http.HttpServletResponse;
|
|||||||
public class CleanUrlInterceptor implements HandlerInterceptor {
|
public class CleanUrlInterceptor implements HandlerInterceptor {
|
||||||
|
|
||||||
private static final List<String> ALLOWED_PARAMS =
|
private static final List<String> ALLOWED_PARAMS =
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
"lang",
|
"lang",
|
||||||
"endpoint",
|
"endpoint",
|
||||||
"endpoints",
|
"endpoints",
|
||||||
"logout",
|
"logout",
|
||||||
"error",
|
"error",
|
||||||
"errorOAuth",
|
"errorOAuth",
|
||||||
"file",
|
"file",
|
||||||
"messageType",
|
"messageType",
|
||||||
"infoMessage");
|
"infoMessage");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean preHandle(
|
public boolean preHandle(
|
||||||
HttpServletRequest request, HttpServletResponse response, Object handler)
|
HttpServletRequest request, HttpServletResponse response, Object handler)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
String queryString = request.getQueryString();
|
String queryString = request.getQueryString();
|
||||||
if (queryString != null && !queryString.isEmpty()) {
|
if (queryString != null && !queryString.isEmpty()) {
|
||||||
String requestURI = request.getRequestURI();
|
String requestURI = request.getRequestURI();
|
||||||
@ -69,15 +69,15 @@ public class CleanUrlInterceptor implements HandlerInterceptor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postHandle(
|
public void postHandle(
|
||||||
HttpServletRequest request,
|
HttpServletRequest request,
|
||||||
HttpServletResponse response,
|
HttpServletResponse response,
|
||||||
Object handler,
|
Object handler,
|
||||||
ModelAndView modelAndView) {}
|
ModelAndView modelAndView) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterCompletion(
|
public void afterCompletion(
|
||||||
HttpServletRequest request,
|
HttpServletRequest request,
|
||||||
HttpServletResponse response,
|
HttpServletResponse response,
|
||||||
Object handler,
|
Object handler,
|
||||||
Exception ex) {}
|
Exception ex) {}
|
||||||
}
|
}
|
@ -39,14 +39,14 @@ public class EndpointInspector implements ApplicationListener<ContextRefreshedEv
|
|||||||
private void discoverEndpoints() {
|
private void discoverEndpoints() {
|
||||||
try {
|
try {
|
||||||
Map<String, RequestMappingHandlerMapping> mappings =
|
Map<String, RequestMappingHandlerMapping> mappings =
|
||||||
applicationContext.getBeansOfType(RequestMappingHandlerMapping.class);
|
applicationContext.getBeansOfType(RequestMappingHandlerMapping.class);
|
||||||
|
|
||||||
for (Map.Entry<String, RequestMappingHandlerMapping> entry : mappings.entrySet()) {
|
for (Map.Entry<String, RequestMappingHandlerMapping> entry : mappings.entrySet()) {
|
||||||
RequestMappingHandlerMapping mapping = entry.getValue();
|
RequestMappingHandlerMapping mapping = entry.getValue();
|
||||||
Map<RequestMappingInfo, HandlerMethod> handlerMethods = mapping.getHandlerMethods();
|
Map<RequestMappingInfo, HandlerMethod> handlerMethods = mapping.getHandlerMethods();
|
||||||
|
|
||||||
for (Map.Entry<RequestMappingInfo, HandlerMethod> handlerEntry :
|
for (Map.Entry<RequestMappingInfo, HandlerMethod> handlerEntry :
|
||||||
handlerMethods.entrySet()) {
|
handlerMethods.entrySet()) {
|
||||||
RequestMappingInfo mappingInfo = handlerEntry.getKey();
|
RequestMappingInfo mappingInfo = handlerEntry.getKey();
|
||||||
HandlerMethod handlerMethod = handlerEntry.getValue();
|
HandlerMethod handlerMethod = handlerEntry.getValue();
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ public class EndpointInspector implements ApplicationListener<ContextRefreshedEv
|
|||||||
String infoString = mappingInfo.toString();
|
String infoString = mappingInfo.toString();
|
||||||
if (infoString.contains("{")) {
|
if (infoString.contains("{")) {
|
||||||
String patternsSection =
|
String patternsSection =
|
||||||
infoString.substring(infoString.indexOf("{") + 1, infoString.indexOf("}"));
|
infoString.substring(infoString.indexOf("{") + 1, infoString.indexOf("}"));
|
||||||
|
|
||||||
for (String pattern : patternsSection.split(",")) {
|
for (String pattern : patternsSection.split(",")) {
|
||||||
pattern = pattern.trim();
|
pattern = pattern.trim();
|
@ -18,8 +18,8 @@ public class EndpointInterceptor implements HandlerInterceptor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean preHandle(
|
public boolean preHandle(
|
||||||
HttpServletRequest request, HttpServletResponse response, Object handler)
|
HttpServletRequest request, HttpServletResponse response, Object handler)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
String requestURI = request.getRequestURI();
|
String requestURI = request.getRequestURI();
|
||||||
boolean isEnabled;
|
boolean isEnabled;
|
||||||
|
|
@ -25,23 +25,23 @@ public class ExternalAppDepConfig {
|
|||||||
private final Map<String, List<String>> commandToGroupMapping;
|
private final Map<String, List<String>> commandToGroupMapping;
|
||||||
|
|
||||||
public ExternalAppDepConfig(
|
public ExternalAppDepConfig(
|
||||||
EndpointConfiguration endpointConfiguration, RuntimePathConfig runtimePathConfig) {
|
EndpointConfiguration endpointConfiguration, RuntimePathConfig runtimePathConfig) {
|
||||||
this.endpointConfiguration = endpointConfiguration;
|
this.endpointConfiguration = endpointConfiguration;
|
||||||
weasyprintPath = runtimePathConfig.getWeasyPrintPath();
|
weasyprintPath = runtimePathConfig.getWeasyPrintPath();
|
||||||
unoconvPath = runtimePathConfig.getUnoConvertPath();
|
unoconvPath = runtimePathConfig.getUnoConvertPath();
|
||||||
|
|
||||||
commandToGroupMapping =
|
commandToGroupMapping =
|
||||||
new HashMap<>() {
|
new HashMap<>() {
|
||||||
|
|
||||||
{
|
{
|
||||||
put("soffice", List.of("LibreOffice"));
|
put("soffice", List.of("LibreOffice"));
|
||||||
put(weasyprintPath, List.of("Weasyprint"));
|
put(weasyprintPath, List.of("Weasyprint"));
|
||||||
put("pdftohtml", List.of("Pdftohtml"));
|
put("pdftohtml", List.of("Pdftohtml"));
|
||||||
put(unoconvPath, List.of("Unoconvert"));
|
put(unoconvPath, List.of("Unoconvert"));
|
||||||
put("qpdf", List.of("qpdf"));
|
put("qpdf", List.of("qpdf"));
|
||||||
put("tesseract", List.of("tesseract"));
|
put("tesseract", List.of("tesseract"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isCommandAvailable(String command) {
|
private boolean isCommandAvailable(String command) {
|
||||||
@ -63,8 +63,8 @@ public class ExternalAppDepConfig {
|
|||||||
|
|
||||||
private List<String> getAffectedFeatures(String group) {
|
private List<String> getAffectedFeatures(String group) {
|
||||||
return endpointConfiguration.getEndpointsForGroup(group).stream()
|
return endpointConfiguration.getEndpointsForGroup(group).stream()
|
||||||
.map(endpoint -> formatEndpointAsFeature(endpoint))
|
.map(endpoint -> formatEndpointAsFeature(endpoint))
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String formatEndpointAsFeature(String endpoint) {
|
private String formatEndpointAsFeature(String endpoint) {
|
||||||
@ -72,8 +72,8 @@ public class ExternalAppDepConfig {
|
|||||||
String feature = endpoint.replace("-", " ").replace("pdf", "PDF").replace("img", "image");
|
String feature = endpoint.replace("-", " ").replace("pdf", "PDF").replace("img", "image");
|
||||||
// Split into words and capitalize each word
|
// Split into words and capitalize each word
|
||||||
return Arrays.stream(feature.split("\\s+"))
|
return Arrays.stream(feature.split("\\s+"))
|
||||||
.map(word -> capitalizeWord(word))
|
.map(word -> capitalizeWord(word))
|
||||||
.collect(Collectors.joining(" "));
|
.collect(Collectors.joining(" "));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String capitalizeWord(String word) {
|
private String capitalizeWord(String word) {
|
||||||
@ -95,12 +95,12 @@ public class ExternalAppDepConfig {
|
|||||||
List<String> affectedFeatures = getAffectedFeatures(group);
|
List<String> affectedFeatures = getAffectedFeatures(group);
|
||||||
endpointConfiguration.disableGroup(group);
|
endpointConfiguration.disableGroup(group);
|
||||||
log.warn(
|
log.warn(
|
||||||
"Missing dependency: {} - Disabling group: {} (Affected features: {})",
|
"Missing dependency: {} - Disabling group: {} (Affected features: {})",
|
||||||
command,
|
command,
|
||||||
group,
|
group,
|
||||||
affectedFeatures != null && !affectedFeatures.isEmpty()
|
affectedFeatures != null && !affectedFeatures.isEmpty()
|
||||||
? String.join(", ", affectedFeatures)
|
? String.join(", ", affectedFeatures)
|
||||||
: "unknown");
|
: "unknown");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,9 +123,9 @@ public class ExternalAppDepConfig {
|
|||||||
endpointConfiguration.disableGroup("Python");
|
endpointConfiguration.disableGroup("Python");
|
||||||
endpointConfiguration.disableGroup("OpenCV");
|
endpointConfiguration.disableGroup("OpenCV");
|
||||||
log.warn(
|
log.warn(
|
||||||
"Missing dependency: Python - Disabling Python features: {} and OpenCV features: {}",
|
"Missing dependency: Python - Disabling Python features: {} and OpenCV features: {}",
|
||||||
String.join(", ", pythonFeatures),
|
String.join(", ", pythonFeatures),
|
||||||
String.join(", ", openCVFeatures));
|
String.join(", ", openCVFeatures));
|
||||||
} else {
|
} else {
|
||||||
// If Python is available, check for OpenCV
|
// If Python is available, check for OpenCV
|
||||||
try {
|
try {
|
||||||
@ -141,16 +141,16 @@ public class ExternalAppDepConfig {
|
|||||||
List<String> openCVFeatures = getAffectedFeatures("OpenCV");
|
List<String> openCVFeatures = getAffectedFeatures("OpenCV");
|
||||||
endpointConfiguration.disableGroup("OpenCV");
|
endpointConfiguration.disableGroup("OpenCV");
|
||||||
log.warn(
|
log.warn(
|
||||||
"OpenCV not available in Python - Disabling OpenCV features: {}",
|
"OpenCV not available in Python - Disabling OpenCV features: {}",
|
||||||
String.join(", ", openCVFeatures));
|
String.join(", ", openCVFeatures));
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
List<String> openCVFeatures = getAffectedFeatures("OpenCV");
|
List<String> openCVFeatures = getAffectedFeatures("OpenCV");
|
||||||
endpointConfiguration.disableGroup("OpenCV");
|
endpointConfiguration.disableGroup("OpenCV");
|
||||||
log.warn(
|
log.warn(
|
||||||
"Error checking OpenCV: {} - Disabling OpenCV features: {}",
|
"Error checking OpenCV: {} - Disabling OpenCV features: {}",
|
||||||
e.getMessage(),
|
e.getMessage(),
|
||||||
String.join(", ", openCVFeatures));
|
String.join(", ", openCVFeatures));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
endpointConfiguration.logDisabledEndpointsSummary();
|
endpointConfiguration.logDisabledEndpointsSummary();
|
@ -59,7 +59,7 @@ public class InitialSetup {
|
|||||||
|
|
||||||
public void initEnableCSRFSecurity() throws IOException {
|
public void initEnableCSRFSecurity() throws IOException {
|
||||||
if (GeneralUtils.isVersionHigher(
|
if (GeneralUtils.isVersionHigher(
|
||||||
"0.36.0", applicationProperties.getAutomaticallyGenerated().getAppVersion())) {
|
"0.46.0", applicationProperties.getAutomaticallyGenerated().getAppVersion())) {
|
||||||
Boolean csrf = applicationProperties.getSecurity().getCsrfDisabled();
|
Boolean csrf = applicationProperties.getSecurity().getCsrfDisabled();
|
||||||
if (!csrf) {
|
if (!csrf) {
|
||||||
GeneralUtils.saveKeyToSettings("security.csrfDisabled", false);
|
GeneralUtils.saveKeyToSettings("security.csrfDisabled", false);
|
@ -25,7 +25,11 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
|||||||
// Handler for external static resources
|
// Handler for external static resources
|
||||||
registry.addResourceHandler("/**")
|
registry.addResourceHandler("/**")
|
||||||
.addResourceLocations(
|
.addResourceLocations(
|
||||||
"file:" + InstallationPathConfig.getStaticPath(), "classpath:/static/");
|
"file:" + InstallationPathConfig.getStaticPath(),
|
||||||
|
"classpath:/static/"
|
||||||
|
);
|
||||||
|
registry.addResourceHandler("/js/**").addResourceLocations("classpath:/static/js/");
|
||||||
|
registry.addResourceHandler("/css/**").addResourceLocations("classpath:/static/css/");
|
||||||
// .setCachePeriod(0); // Optional: disable caching
|
// .setCachePeriod(0); // Optional: disable caching
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,7 +12,7 @@
|
|||||||
// import jakarta.servlet.http.HttpServletResponse;
|
// import jakarta.servlet.http.HttpServletResponse;
|
||||||
// import jakarta.servlet.http.HttpSession;
|
// import jakarta.servlet.http.HttpSession;
|
||||||
// import lombok.extern.slf4j.Slf4j;
|
// import lombok.extern.slf4j.Slf4j;
|
||||||
// import stirling.software.SPDF.utils.RequestUriUtils;
|
// import stirling.software.common.util.RequestUriUtils;
|
||||||
//
|
//
|
||||||
//// @Component
|
//// @Component
|
||||||
// @Slf4j
|
// @Slf4j
|
@ -36,9 +36,9 @@ public class SettingsController {
|
|||||||
public ResponseEntity<String> updateApiKey(@RequestBody Boolean enabled) throws IOException {
|
public ResponseEntity<String> updateApiKey(@RequestBody Boolean enabled) throws IOException {
|
||||||
if (applicationProperties.getSystem().getEnableAnalytics() != null) {
|
if (applicationProperties.getSystem().getEnableAnalytics() != null) {
|
||||||
return ResponseEntity.status(HttpStatus.ALREADY_REPORTED)
|
return ResponseEntity.status(HttpStatus.ALREADY_REPORTED)
|
||||||
.body(
|
.body(
|
||||||
"Setting has already been set, To adjust please edit "
|
"Setting has already been set, To adjust please edit "
|
||||||
+ InstallationPathConfig.getSettingsPath());
|
+ InstallationPathConfig.getSettingsPath());
|
||||||
}
|
}
|
||||||
GeneralUtils.saveKeyToSettings("system.enableAnalytics", enabled);
|
GeneralUtils.saveKeyToSettings("system.enableAnalytics", enabled);
|
||||||
applicationProperties.getSystem().setEnableAnalytics(enabled);
|
applicationProperties.getSystem().setEnableAnalytics(enabled);
|
@ -27,9 +27,9 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.SPDF.model.api.PDFWithPageNums;
|
|
||||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||||
import stirling.software.common.util.WebResponseUtils;
|
import stirling.software.common.util.WebResponseUtils;
|
||||||
|
import stirling.software.SPDF.model.api.PDFWithPageNums;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/general")
|
@RequestMapping("/api/v1/general")
|
@ -31,11 +31,11 @@ import lombok.NoArgsConstructor;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.SPDF.model.api.SplitPdfByChaptersRequest;
|
|
||||||
import stirling.software.common.model.PdfMetadata;
|
import stirling.software.common.model.PdfMetadata;
|
||||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||||
import stirling.software.common.service.PdfMetadataService;
|
import stirling.software.common.service.PdfMetadataService;
|
||||||
import stirling.software.common.util.WebResponseUtils;
|
import stirling.software.common.util.WebResponseUtils;
|
||||||
|
import stirling.software.SPDF.model.api.SplitPdfByChaptersRequest;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/general")
|
@RequestMapping("/api/v1/general")
|
@ -31,9 +31,9 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
import stirling.software.SPDF.model.api.SplitPdfBySectionsRequest;
|
|
||||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||||
import stirling.software.common.util.WebResponseUtils;
|
import stirling.software.common.util.WebResponseUtils;
|
||||||
|
import stirling.software.SPDF.model.api.SplitPdfBySectionsRequest;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/general")
|
@RequestMapping("/api/v1/general")
|
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