This commit is contained in:
Ludy 2025-09-02 18:23:16 +00:00 committed by GitHub
commit 984aaf9e13
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 544 additions and 89 deletions

View File

@ -106,6 +106,14 @@ public class ApplicationProperties {
private String accessibilityStatement; private String accessibilityStatement;
private String cookiePolicy; private String cookiePolicy;
private String impressum; private String impressum;
private ApiContact apiContact = new ApiContact();
}
@Data
public static class ApiContact {
private String company;
private String website;
private String email;
} }
@Data @Data

View File

@ -1,5 +1,8 @@
package stirling.software.SPDF.config; package stirling.software.SPDF.config;
import java.util.Optional;
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;
@ -11,57 +14,90 @@ import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme; import io.swagger.v3.oas.models.security.SecurityScheme;
import lombok.RequiredArgsConstructor;
import stirling.software.common.model.ApplicationProperties; import stirling.software.common.model.ApplicationProperties;
@Configuration @Configuration
@RequiredArgsConstructor
public class OpenApiConfig { public class OpenApiConfig {
private final ApplicationProperties applicationProperties; private final ApplicationProperties applicationProperties;
private final boolean runningProOrHigher;
private static final String DEFAULT_TITLE = "Stirling PDF API"; public OpenApiConfig(
ApplicationProperties applicationProperties,
@Qualifier("runningProOrHigher") boolean runningProOrHigher) {
this.applicationProperties = applicationProperties;
this.runningProOrHigher = runningProOrHigher;
}
private static final String DEFAULT_COMPANY = "Stirling Software";
private static final String DEFAULT_DESCRIPTION = private static final String DEFAULT_DESCRIPTION =
"API documentation for all Server-Side processing.\n" "API documentation for all Server-Side processing.\n"
+ "Please note some functionality might be UI only and missing from here."; + "Please note some functionality might be UI only and missing from here.";
private static final String DEFAULT_EMAIL = "contact@stirlingpdf.com";
private static final String DEFAULT_TERMS_OF_SERVICE = "https://www.stirlingpdf.com/terms";
private static final String DEFAULT_TITLE = "Stirling PDF API";
private static final String DEFAULT_WEBSITE = "https://www.stirlingpdf.com";
private static final String DEFAULT_VERSION = "1.0.0";
@Bean @Bean
public OpenAPI customOpenAPI() { public OpenAPI customOpenAPI() {
String version = getClass().getPackage().getImplementationVersion(); String version =
if (version == null) { Optional.ofNullable(applicationProperties.getAutomaticallyGenerated())
// default version if all else fails .map(ApplicationProperties.AutomaticallyGenerated::getAppVersion)
version = "1.0.0"; .filter(v -> !v.isBlank())
.orElseGet(
() -> {
String v = getClass().getPackage().getImplementationVersion();
return v != null ? v : DEFAULT_VERSION;
});
String title = DEFAULT_TITLE;
String description = DEFAULT_DESCRIPTION;
String termsOfService = DEFAULT_TERMS_OF_SERVICE;
String company = DEFAULT_COMPANY;
String email = DEFAULT_EMAIL;
String website = DEFAULT_WEBSITE;
License license =
new License()
.name("MIT License")
.url(
"https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/refs/heads/main/LICENSE")
.identifier("MIT");
if (runningProOrHigher) {
ApplicationProperties.Ui ui = applicationProperties.getUi();
ApplicationProperties.Legal legal = applicationProperties.getLegal();
ApplicationProperties.ApiContact apiContact = legal.getApiContact();
title = Optional.ofNullable(ui.getAppName()).orElse(title);
description = Optional.ofNullable(ui.getHomeDescription()).orElse(description);
termsOfService =
Optional.ofNullable(legal.getTermsAndConditions()).orElse(termsOfService);
company = Optional.ofNullable(apiContact.getCompany()).orElse(company);
website = Optional.ofNullable(apiContact.getWebsite()).orElse(website);
email = Optional.ofNullable(apiContact.getEmail()).orElse(email);
} }
Contact contact = new Contact().name(company).url(website).email(email);
Info info = Info info =
new Info() new Info()
.title(DEFAULT_TITLE) .title(title)
.version(version) .version(version)
.license( .license(license)
new License() .termsOfService(termsOfService)
.name("MIT") .contact(contact)
.url( .description(description);
"https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/refs/heads/main/LICENSE")
.identifier("MIT"))
.termsOfService("https://www.stirlingpdf.com/terms")
.contact(
new Contact()
.name("Stirling Software")
.url("https://www.stirlingpdf.com")
.email("contact@stirlingpdf.com"))
.description(DEFAULT_DESCRIPTION);
if (!applicationProperties.getSecurity().getEnableLogin()) { if (!applicationProperties.getSecurity().getEnableLogin()) {
return new OpenAPI().components(new Components()).info(info); return new OpenAPI().components(new Components()).info(info);
} else {
SecurityScheme apiKeyScheme =
new SecurityScheme()
.type(SecurityScheme.Type.APIKEY)
.in(SecurityScheme.In.HEADER)
.name("X-API-KEY");
return new OpenAPI()
.components(new Components().addSecuritySchemes("apiKey", apiKeyScheme))
.info(info)
.addSecurityItem(new SecurityRequirement().addList("apiKey"));
} }
SecurityScheme apiKeyScheme =
new SecurityScheme()
.type(SecurityScheme.Type.APIKEY)
.in(SecurityScheme.In.HEADER)
.name("X-API-KEY");
return new OpenAPI()
.components(new Components().addSecuritySchemes("apiKey", apiKeyScheme))
.info(info)
.addSecurityItem(new SecurityRequirement().addList("apiKey"));
} }
} }

View File

@ -8,11 +8,13 @@ import java.util.Map;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.server.ResponseStatusException;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@ -44,8 +46,7 @@ public class HomeWebController {
public String licensesForm(Model model) { public String licensesForm(Model model) {
model.addAttribute("currentPage", "licenses"); model.addAttribute("currentPage", "licenses");
Resource resource = new ClassPathResource("static/3rdPartyLicenses.json"); Resource resource = new ClassPathResource("static/3rdPartyLicenses.json");
try { try (InputStream is = resource.getInputStream()) {
InputStream is = resource.getInputStream();
String json = new String(is.readAllBytes(), StandardCharsets.UTF_8); String json = new String(is.readAllBytes(), StandardCharsets.UTF_8);
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
Map<String, List<Dependency>> data = mapper.readValue(json, new TypeReference<>() {}); Map<String, List<Dependency>> data = mapper.readValue(json, new TypeReference<>() {});
@ -56,6 +57,42 @@ public class HomeWebController {
return "licenses"; return "licenses";
} }
@GetMapping("/impressum")
@Hidden
public String impressum() {
String impressum = applicationProperties.getLegal().getImpressum();
return internalPage(impressum, "impressum");
}
@GetMapping("/cookiePolicy")
@Hidden
public String cookiePolicy() {
String cookiePolicy = applicationProperties.getLegal().getCookiePolicy();
return internalPage(cookiePolicy, "cookiePolicy");
}
@GetMapping("/privacyPolicy")
@Hidden
public String privacyPolicy() {
String privacyPolicy = applicationProperties.getLegal().getPrivacyPolicy();
return internalPage(privacyPolicy, "privacyPolicy");
}
@GetMapping("/termsAndConditions")
@Hidden
public String termsAndConditions() {
String termsAndConditions = applicationProperties.getLegal().getTermsAndConditions();
return internalPage(termsAndConditions, "termsAndConditions");
}
@GetMapping("/accessibilityStatement")
@Hidden
public String accessibilityStatement() {
String accessibilityStatement =
applicationProperties.getLegal().getAccessibilityStatement();
return internalPage(accessibilityStatement, "accessibilityStatement");
}
@GetMapping("/releases") @GetMapping("/releases")
public String getReleaseNotes(Model model) { public String getReleaseNotes(Model model) {
return "releases"; return "releases";
@ -91,4 +128,11 @@ public class HomeWebController {
return "User-agent: Googlebot\nDisallow: /\n\nUser-agent: *\nDisallow: /"; return "User-agent: Googlebot\nDisallow: /\n\nUser-agent: *\nDisallow: /";
} }
} }
private String internalPage(String configured, String view) {
if (configured != null && (("/" + view).equals(configured) || view.equals(configured))) {
return view;
}
throw new ResponseStatusException(HttpStatus.NOT_FOUND);
}
} }

View File

@ -95,12 +95,33 @@ mail:
password: '' # SMTP server password password: '' # SMTP server password
from: '' # sender email address from: '' # sender email address
#############################################################################################################
# Declaration of settings for URLs #
# #
# To disable, set termsAndConditions, privacyPolicy, accessibilityStatement, cookiePolicy, impressum to '/' #
# #
# If you want to use an internal file, place the file in the 'customFiles/templates/' folder #
# For termsAndConditions, the file must be named termsAndConditions.html #
# For privacyPolicy, the file must be named privacyPolicy.html #
# For accessibilityStatement, the file must be named accessibilityStatement.html #
# For cookiePolicy, the file must be named cookiePolicy.html #
# For impressum, the file must be named impressum.html #
# To use an internal URL, it must be entered without `.html` #
# #
# For example: termsAndConditions: /termsAndConditions #
# #
# You can also use external URLs, for example: https://example.com/terms #
#############################################################################################################
legal: legal:
termsAndConditions: https://www.stirlingpdf.com/terms # URL to the terms and conditions of your application (e.g. https://example.com/terms). Empty string to disable or filename to load from local file in static folder termsAndConditions: / # URL to the terms and conditions of your application
privacyPolicy: https://www.stirlingpdf.com/privacy-policy # URL to the privacy policy of your application (e.g. https://example.com/privacy). Empty string to disable or filename to load from local file in static folder privacyPolicy: / # URL to the privacy policy of your application
accessibilityStatement: '' # URL to the accessibility statement of your application (e.g. https://example.com/accessibility). Empty string to disable or filename to load from local file in static folder accessibilityStatement: / # URL to the accessibility statement of your application
cookiePolicy: '' # URL to the cookie policy of your application (e.g. https://example.com/cookie). Empty string to disable or filename to load from local file in static folder cookiePolicy: / # URL to the cookie policy of your application
impressum: '' # URL to the impressum of your application (e.g. https://example.com/impressum). Empty string to disable or filename to load from local file in static folder impressum: / # URL to the impressum of your application
apiContact: # ONLY pro/enterprise features
company: Stirling Software
email: contact@stirlingpdf.com
website: https://www.stirlingpdf.com
system: system:
defaultLocale: en-US # set the default language (e.g. 'de-DE', 'fr-FR', etc) defaultLocale: en-US # set the default language (e.g. 'de-DE', 'fr-FR', etc)

View File

@ -0,0 +1,58 @@
<!DOCTYPE html>
<html th:lang="${#locale.language}"
th:dir="#{language.direction}"
th:data-language="${#locale.toString()}"
xmlns:th="https://www.thymeleaf.org">
<head>
<th:block th:insert="~{fragments/common :: head(title=#{legal.accessibility}, header=#{legal.accessibility})}"></th:block>
</head>
<body>
<div id="page-container">
<div id="content-wrap">
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
<br><br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8 bg-card">
<div class="tool-header">
<span class="material-symbols-rounded tool-header-icon organize">accessibility</span>
<span class="tool-header-text"
th:text="#{legal.accessibility}">Accessibility</span>
</div>
<!-- start Note: sample page -->
<section id="note-sample-page">
<div class="alert alert-warning"
role="alert">
<strong>Note:</strong> This is a <em>sample page</em>; all information is placeholder content for
demonstration purposes only.
<br>
<br>
<li>Enable <code>customHTMLFiles</code> in the configuration to use custom HTML files, which can be found <a
href="https://docs.stirlingpdf.com/Advanced%20Configuration/UI%20Customisation#custom-files"
target="_blank">here</a>.</li>
<li>Create a file named <code>accessibilityStatement.html</code> in the folder
<code>customFiles/templates</code>.</li>
<li>Copy the content of this file from <a
href="https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/refs/heads/main/app/core/src/main/resources/templates/accessibilityStatement.html"
target="_blank">accessibilityStatement.html</a> into the newly created file.</li>
<li>Customize the layout and design of the page.</li>
</div>
</section>
<!-- end Note: sample page -->
<section>
<h2>Accessibility Statement</h2>
<p>This is the accessibility statement for our application.</p>
</section>
</div>
</div>
</div>
</div>
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
</div>
</body>
</html>

View File

@ -0,0 +1,58 @@
<!DOCTYPE html>
<html th:lang="${#locale.language}"
th:dir="#{language.direction}"
th:data-language="${#locale.toString()}"
xmlns:th="https://www.thymeleaf.org">
<head>
<th:block th:insert="~{fragments/common :: head(title=#{legal.cookie}, header=#{legal.cookie})}"></th:block>
</head>
<body>
<div id="page-container">
<div id="content-wrap">
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
<br><br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8 bg-card">
<div class="tool-header">
<span class="material-symbols-rounded tool-header-icon">cookie</span>
<span class="tool-header-text"
th:text="#{legal.cookie}">Cookie Policy</span>
</div>
<!-- start Note: sample page -->
<section id="note-sample-page">
<div class="alert alert-warning"
role="alert">
<strong>Note:</strong> This is a <em>sample page</em>; all information is placeholder content for
demonstration purposes only.
<br>
<br>
<li>Enable <code>customHTMLFiles</code> in the configuration to use custom HTML files, which can be found <a
href="https://docs.stirlingpdf.com/Advanced%20Configuration/UI%20Customisation#custom-files"
target="_blank">here</a>.</li>
<li>Create a file named <code>cookiePolicy.html</code> in the folder <code>customFiles/templates</code>.</li>
<li>Copy the content of this file from <a
href="https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/refs/heads/main/app/core/src/main/resources/templates/cookiePolicy.html"
target="_blank">cookiePolicy.html</a> into the newly created file.</li>
<li>Customize the layout and design of the page.</li>
</div>
</section>
<!-- end Note: sample page -->
<section>
<h2>Cookie Policy</h2>
<p>This application uses cookies to enhance your browsing experience. By continuing to use the site, you agree
to the use of cookies.</p>
</section>
</div>
</div>
</div>
</div>
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
</div>
</body>
</html>

View File

@ -8,11 +8,11 @@
<li><a class="footer-link px-2" id="licenses" target="_blank" th:href="@{'/licenses'}" th:text="#{licenses.nav}">Licenses</a></li> <li><a class="footer-link px-2" id="licenses" target="_blank" th:href="@{'/licenses'}" th:text="#{licenses.nav}">Licenses</a></li>
<li><a class="footer-link px-2" id="releases" target="_blank" th:href="@{'/releases'}" th:text="#{releases.footer}">Releases</a></li> <li><a class="footer-link px-2" id="releases" target="_blank" th:href="@{'/releases'}" th:text="#{releases.footer}">Releases</a></li>
<li><a class="footer-link px-2" id="survey" target="_blank" href="https://stirlingpdf.info/s/cm28y3niq000o56dv7liv8wsu" th:text="#{survey.nav}">Survey</a></li> <li><a class="footer-link px-2" id="survey" target="_blank" href="https://stirlingpdf.info/s/cm28y3niq000o56dv7liv8wsu" th:text="#{survey.nav}">Survey</a></li>
<li th:if="${@privacyPolicy != ''}"><a class="footer-link px-2" target="_blank" th:href="${@privacyPolicy}" th:text="#{legal.privacy}">privacyPolicy</a></li> <li th:if="${@privacyPolicy != '/'}"><a class="footer-link px-2" target="_blank" th:href="${@privacyPolicy}" th:text="#{legal.privacy}">privacyPolicy</a></li>
<li th:if="${@termsAndConditions != ''}"><a class="footer-link px-2" target="_blank" th:href="${@termsAndConditions}" th:text="#{legal.terms}">termsAndConditions</a></li> <li th:if="${@termsAndConditions != '/'}"><a class="footer-link px-2" target="_blank" th:href="${@termsAndConditions}" th:text="#{legal.terms}">termsAndConditions</a></li>
<li th:if="${@accessibilityStatement != ''}"><a class="footer-link px-2" target="_blank" th:href="${@accessibilityStatement}" th:text="#{legal.accessibility}">accessibilityStatement</a></li> <li th:if="${@accessibilityStatement != '/'}"><a class="footer-link px-2" target="_blank" th:href="${@accessibilityStatement}" th:text="#{legal.accessibility}">accessibilityStatement</a></li>
<li th:if="${@cookiePolicy != ''}"><a class="footer-link px-2" target="_blank" th:href="${@cookiePolicy}" th:text="#{legal.cookie}">cookiePolicy</a></li> <li th:if="${@cookiePolicy != '/'}"><a class="footer-link px-2" target="_blank" th:href="${@cookiePolicy}" th:text="#{legal.cookie}">cookiePolicy</a></li>
<li th:if="${@impressum != ''}"><a class="footer-link px-2" target="_blank" th:href="${@impressum}" th:text="#{legal.impressum}">impressum</a></li> <li th:if="${@impressum != '/'}"><a class="footer-link px-2" target="_blank" th:href="${@impressum}" th:text="#{legal.impressum}">impressum</a></li>
<li th:if="${@analyticsEnabled}"><a class="footer-link px-2" id="cookieBanner" target="_blank" th:text="#{legal.showCookieBanner}" onClick="CookieConsent.show(true)">Cookie Preferences</a></li> <li th:if="${@analyticsEnabled}"><a class="footer-link px-2" id="cookieBanner" target="_blank" th:text="#{legal.showCookieBanner}" onClick="CookieConsent.show(true)">Cookie Preferences</a></li>
</ul> </ul>
</div> </div>

View File

@ -0,0 +1,75 @@
<!DOCTYPE html>
<html th:lang="${#locale.language}"
th:dir="#{language.direction}"
th:data-language="${#locale.toString()}"
xmlns:th="https://www.thymeleaf.org">
<head>
<th:block th:insert="~{fragments/common :: head(title=#{legal.impressum}, header=#{legal.impressum})}">
</th:block>
</head>
<body>
<div id="page-container">
<div id="content-wrap">
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
<br><br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8 bg-card">
<div class="tool-header">
<span class="material-symbols-rounded tool-header-icon">info</span>
<span class="tool-header-text"
th:text="#{legal.impressum}">Impressum / Legal Notice</span>
</div>
<!-- start Note: sample page -->
<section id="note-sample-page">
<div class="alert alert-warning"
role="alert">
<strong>Note:</strong> This is a <em>sample page</em>; all information is placeholder content for
demonstration purposes only.
<br>
<br>
<li>Enable <code>customHTMLFiles</code> in the configuration to use custom HTML files, which can be found <a
href="https://docs.stirlingpdf.com/Advanced%20Configuration/UI%20Customisation#custom-files"
target="_blank">here</a>.</li>
<li>Create a file named <code>impressum.html</code> in the folder <code>customFiles/templates</code>.</li>
<li>Copy the content of this file from <a
href="https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/refs/heads/main/app/core/src/main/resources/templates/impressum.html"
target="_blank">impressum.html</a> into the newly created file.</li>
<li>Customize the layout and design of the page.</li>
</div>
</section>
<!-- end Note: sample page -->
<section>
<h2>Company Information</h2>
<p>Company Name<br>Street Address<br>City, Postal Code<br>Country</p>
</section>
<section>
<h2>Contact</h2>
<p>Telephone: +00 000 0000<br>Email: <a href="mailto:info@example.com">info@example.com</a></p>
</section>
<section>
<h2>Representatives</h2>
<p>Authorized to represent: Jane Doe, John Doe</p>
</section>
<section>
<h2>Registration &amp; VAT</h2>
<p>Commercial Register: Local Court of Exampletown, HRB 00000<br>VAT ID: XX000000000</p>
</section>
<section>
<h2>Disclaimer</h2>
<p>This page provides general company and contact information for international use. Legal requirements vary by
jurisdiction; please ensure compliance with local laws.</p>
</section>
</div>
</div>
</div>
</div>
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
</div>
</body>
</html>

View File

@ -0,0 +1,59 @@
<!DOCTYPE html>
<html th:lang="${#locale.language}"
th:dir="#{language.direction}"
th:data-language="${#locale.toString()}"
xmlns:th="https://www.thymeleaf.org">
<head>
<th:block th:insert="~{fragments/common :: head(title=#{legal.privacy}, header=#{legal.privacy})}"></th:block>
</head>
<body>
<div id="page-container">
<div id="content-wrap">
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
<br><br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8 bg-card">
<div class="tool-header">
<span class="material-symbols-rounded tool-header-icon">privacy_tip</span>
<span class="tool-header-text"
th:text="#{legal.privacy}">Privacy Policy</span>
</div>
<!-- start Note: sample page -->
<section id="note-sample-page">
<div class="alert alert-warning"
role="alert">
<strong>Note:</strong> This is a <em>sample page</em>; all information is placeholder content for
demonstration purposes only.
<br>
<br>
<li>Enable <code>customHTMLFiles</code> in the configuration to use custom HTML files, which can be found <a
href="https://docs.stirlingpdf.com/Advanced%20Configuration/UI%20Customisation#custom-files"
target="_blank">here</a>.</li>
<li>Create a file named <code>privacyPolicy.html</code> in the folder <code>customFiles/templates</code>.
</li>
<li>Copy the content of this file from <a
href="https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/refs/heads/main/app/core/src/main/resources/templates/privacyPolicy.html"
target="_blank">privacyPolicy.html</a> into the newly created file.</li>
<li>Customize the layout and design of the page.</li>
</div>
</section>
<!-- end Note: sample page -->
<section>
<h2>Privacy Policy</h2>
<p>This Privacy Policy explains how we handle your data. No personal information is stored beyond the scope of
providing our services.</p>
</section>
</div>
</div>
</div>
</div>
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
</div>
</body>
</html>

View File

@ -0,0 +1,58 @@
<!DOCTYPE html>
<html th:lang="${#locale.language}"
th:dir="#{language.direction}"
th:data-language="${#locale.toString()}"
xmlns:th="https://www.thymeleaf.org">
<head>
<th:block th:insert="~{fragments/common :: head(title=#{legal.terms}, header=#{legal.terms})}"></th:block>
</head>
<body>
<div id="page-container">
<div id="content-wrap">
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
<br><br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8 bg-card">
<div class="tool-header">
<span class="material-symbols-rounded tool-header-icon">gavel</span>
<span class="tool-header-text"
th:text="#{legal.terms}">Terms and Conditions</span>
</div>
<!-- start Note: sample page -->
<section id="note-sample-page">
<div class="alert alert-warning"
role="alert">
<strong>Note:</strong> This is a <em>sample page</em>; all information is placeholder content for
demonstration purposes only.
<br>
<br>
<li>Enable <code>customHTMLFiles</code> in the configuration to use custom HTML files, which can be found <a
href="https://docs.stirlingpdf.com/Advanced%20Configuration/UI%20Customisation#custom-files"
target="_blank">here</a>.</li>
<li>Create a file named <code>termsAndConditions.html</code> in the folder
<code>customFiles/templates</code>.</li>
<li>Copy the content of this file from <a
href="https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/refs/heads/main/app/core/src/main/resources/templates/termsAndConditions.html"
target="_blank">termsAndConditions.html</a> into the newly created file.</li>
<li>Customize the layout and design of the page.</li>
</div>
</section>
<!-- end Note: sample page -->
<section>
<h2>Terms and Conditions</h2>
<p>This Terms and Conditions document outlines the rules and regulations for using our services.</p>
</section>
</div>
</div>
</div>
</div>
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
</div>
</body>
</html>

View File

@ -81,6 +81,11 @@ public class AccountWebController {
return "redirect:/"; return "redirect:/";
} }
boolean enableLogin = applicationProperties.getSecurity().getEnableLogin();
if (!enableLogin) {
return "redirect:/";
}
Map<String, String> providerList = new HashMap<>(); Map<String, String> providerList = new HashMap<>();
Security securityProps = applicationProperties.getSecurity(); Security securityProps = applicationProperties.getSecurity();
OAUTH2 oauth = securityProps.getOauth2(); OAUTH2 oauth = securityProps.getOauth2();

View File

@ -223,6 +223,22 @@ public class SecurityConfiguration {
.rememberMeCookieName( // Cookie name .rememberMeCookieName( // Cookie name
"remember-me") "remember-me")
.alwaysRemember(false)); .alwaysRemember(false));
String impressumUrl = appConfig.impressum();
boolean internalImpressum = impressumUrl != null && impressumUrl.equals("/impressum");
String accessibilityStatementUrl = appConfig.accessibilityStatement();
boolean internalAccessibilityStatement =
accessibilityStatementUrl != null
&& accessibilityStatementUrl.equals("/accessibilityStatement");
String cookiePolicyUrl = appConfig.cookiePolicy();
boolean internalCookiePolicy =
cookiePolicyUrl != null && cookiePolicyUrl.equals("/cookiePolicy");
String termsAndConditionsUrl = appConfig.termsAndConditions();
boolean internalTermsAndConditions =
termsAndConditionsUrl != null
&& termsAndConditionsUrl.equals("/termsAndConditions");
String privacyPolicyUrl = appConfig.privacyPolicy();
boolean internalPrivacyPolicy =
privacyPolicyUrl != null && privacyPolicyUrl.equals("/privacyPolicy");
http.authorizeHttpRequests( http.authorizeHttpRequests(
authz -> authz ->
authz.requestMatchers( authz.requestMatchers(
@ -250,6 +266,21 @@ public class SecurityConfiguration {
|| trimmedUri.startsWith("/pdfjs/") || trimmedUri.startsWith("/pdfjs/")
|| trimmedUri.startsWith("/pdfjs-legacy/") || trimmedUri.startsWith("/pdfjs-legacy/")
|| trimmedUri.startsWith("/favicon") || trimmedUri.startsWith("/favicon")
|| (internalAccessibilityStatement
&& trimmedUri.startsWith(
"/accessibilityStatement"))
|| (internalImpressum
&& trimmedUri.startsWith(
"/impressum"))
|| (internalCookiePolicy
&& trimmedUri.startsWith(
"/cookiePolicy"))
|| (internalTermsAndConditions
&& trimmedUri.startsWith(
"/termsAndConditions"))
|| (internalPrivacyPolicy
&& trimmedUri.startsWith(
"/privacyPolicy"))
|| trimmedUri.startsWith( || trimmedUri.startsWith(
"/api/v1/info/status") "/api/v1/info/status")
|| trimmedUri.startsWith("/v1/api-docs") || trimmedUri.startsWith("/v1/api-docs")

View File

@ -230,6 +230,11 @@ public class UserAuthenticationFilter extends OncePerRequestFilter {
contextPath + "/error", contextPath + "/error",
contextPath + "/images/", contextPath + "/images/",
contextPath + "/public/", contextPath + "/public/",
contextPath + "/impressum",
contextPath + "/privacyPolicy",
contextPath + "/accessibilityStatement",
contextPath + "/cookiePolicy",
contextPath + "/termsAndConditions",
contextPath + "/css/", contextPath + "/css/",
contextPath + "/fonts/", contextPath + "/fonts/",
contextPath + "/js/", contextPath + "/js/",

View File

@ -1,54 +1,51 @@
/ /
/multi-tool
/merge-pdfs
/split-pdfs
/rotate-pdf
/remove-pages
/pdf-organizer
/multi-page-layout
/scale-pages
/crop
/extract-page
/pdf-to-single-page
/img-to-pdf
/pdf-to-img
/pdf-to-text
/pdf-to-csv
/sign
/add-password
/remove-password
/change-permissions
/add-watermark
/cert-sign
/validate-signature
/remove-cert-sign
/sanitize-pdf
/auto-redact
/redact
/stamp
/view-pdf
/add-page-numbers
/add-image /add-image
/add-page-numbers
/add-password
/add-watermark
/adjust-contrast
/auto-redact
/auto-rename
/auto-split-pdf
/cert-sign
/change-metadata
/change-permissions
/compare
/crop
/extract-images /extract-images
/extract-page
/flatten /flatten
/get-info-on-pdf
/img-to-pdf
/licenses
/merge-pdfs
/multi-page-layout
/multi-tool
/overlay-pdf
/pdf-organizer
/pdf-to-csv
/pdf-to-img
/pdf-to-single-page
/pdf-to-text
/redact
/releases
/remove-annotations /remove-annotations
/remove-blanks /remove-blanks
/compare /remove-cert-sign
/change-metadata
/get-info-on-pdf
/remove-image-pdf /remove-image-pdf
/remove-pages
/remove-password
/replace-and-invert-color-pdf /replace-and-invert-color-pdf
/pipeline /rotate-pdf
/auto-rename /sanitize-pdf
/adjust-contrast /scale-pages
/overlay-pdf
/auto-split-pdf
/split-pdf-by-sections
/split-pdf-by-chapters
/split-by-size-or-count
/show-javascript /show-javascript
/sign
/split-by-size-or-count
/split-pdfs
/split-pdf-by-chapters
/split-pdf-by-sections
/stamp
/swagger-ui/index.html /swagger-ui/index.html
/licenses /validate-signature
/releases /view-pdf
/add-attachments