mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-09-12 17:52:13 +02:00
enterprise check
This commit is contained in:
parent
1441ac23ff
commit
02a951ac63
@ -6,7 +6,7 @@ import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import stirling.software.SPDF.EE.KeygenLicenseVerifier.License;
|
||||
import stirling.software.SPDF.model.ApplicationProperties;
|
||||
import stirling.software.SPDF.model.ApplicationProperties.EnterpriseEdition;
|
||||
import stirling.software.SPDF.model.ApplicationProperties.Premium;
|
||||
@ -27,9 +27,14 @@ public class EEAppConfig {
|
||||
migrateEnterpriseSettingsToPremium(this.applicationProperties);
|
||||
}
|
||||
|
||||
@Bean(name = "runningProOrHigher")
|
||||
public boolean runningProOrHigher() {
|
||||
return licenseKeyChecker.getPremiumLicenseEnabledResult() != License.NORMAL;
|
||||
}
|
||||
|
||||
@Bean(name = "runningEE")
|
||||
public boolean runningEnterpriseEdition() {
|
||||
return licenseKeyChecker.getEnterpriseEnabledResult();
|
||||
public boolean runningEnterprise() {
|
||||
return licenseKeyChecker.getPremiumLicenseEnabledResult() == License.ENTERPRISE;
|
||||
}
|
||||
|
||||
@Bean(name = "SSOAutoLogin")
|
||||
|
@ -25,6 +25,12 @@ import stirling.software.SPDF.utils.GeneralUtils;
|
||||
@Service
|
||||
@Slf4j
|
||||
public class KeygenLicenseVerifier {
|
||||
|
||||
|
||||
enum License{
|
||||
NORMAL, PRO, ENTERPRISE
|
||||
|
||||
}
|
||||
// License verification configuration
|
||||
private static final String ACCOUNT_ID = "e5430f69-e834-4ae4-befd-b602aae5f372";
|
||||
private static final String BASE_URL = "https://api.keygen.sh/v1/accounts";
|
||||
@ -45,19 +51,26 @@ public class KeygenLicenseVerifier {
|
||||
this.applicationProperties = applicationProperties;
|
||||
}
|
||||
|
||||
public boolean verifyLicense(String licenseKeyOrCert) {
|
||||
public License verifyLicense(String licenseKeyOrCert) {
|
||||
if (isCertificateLicense(licenseKeyOrCert)) {
|
||||
log.info("Detected certificate-based license. Processing...");
|
||||
return verifyCertificateLicense(licenseKeyOrCert);
|
||||
return resultToEnum(verifyCertificateLicense(licenseKeyOrCert), License.ENTERPRISE);
|
||||
} else if (isJWTLicense(licenseKeyOrCert)) {
|
||||
log.info("Detected JWT-style license key. Processing...");
|
||||
return verifyJWTLicense(licenseKeyOrCert);
|
||||
return resultToEnum( verifyJWTLicense(licenseKeyOrCert), License.ENTERPRISE);
|
||||
} else {
|
||||
log.info("Detected standard license key. Processing...");
|
||||
return verifyStandardLicense(licenseKeyOrCert);
|
||||
return resultToEnum( verifyStandardLicense(licenseKeyOrCert), License.PRO);
|
||||
}
|
||||
}
|
||||
|
||||
private License resultToEnum(boolean result, License option) {
|
||||
if(result) {
|
||||
return option;
|
||||
}
|
||||
return License.NORMAL;
|
||||
}
|
||||
|
||||
private boolean isCertificateLicense(String license) {
|
||||
return license != null && license.trim().startsWith(CERT_PREFIX);
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import stirling.software.SPDF.EE.KeygenLicenseVerifier.License;
|
||||
import stirling.software.SPDF.model.ApplicationProperties;
|
||||
import stirling.software.SPDF.utils.GeneralUtils;
|
||||
|
||||
@ -24,7 +24,7 @@ public class LicenseKeyChecker {
|
||||
|
||||
private final ApplicationProperties applicationProperties;
|
||||
|
||||
private boolean premiumEnabledResult = false;
|
||||
private License premiumEnabledResult = License.NORMAL;
|
||||
|
||||
@Autowired
|
||||
public LicenseKeyChecker(
|
||||
@ -41,19 +41,21 @@ public class LicenseKeyChecker {
|
||||
|
||||
private void checkLicense() {
|
||||
if (!applicationProperties.getPremium().isEnabled()) {
|
||||
premiumEnabledResult = false;
|
||||
premiumEnabledResult = License.NORMAL;
|
||||
} else {
|
||||
String licenseKey = getLicenseKeyContent(applicationProperties.getPremium().getKey());
|
||||
if (licenseKey != null) {
|
||||
premiumEnabledResult = licenseService.verifyLicense(licenseKey);
|
||||
if (premiumEnabledResult) {
|
||||
log.info("License key is valid.");
|
||||
if (License.ENTERPRISE == premiumEnabledResult) {
|
||||
log.info("License key is Enterprise.");
|
||||
} else if(License.PRO == premiumEnabledResult){
|
||||
log.info("License key is Pro.");
|
||||
} else {
|
||||
log.info("License key is invalid.");
|
||||
log.info("License key is invalid, defaulting to non pro license.");
|
||||
}
|
||||
} else {
|
||||
log.error("Failed to obtain license key content.");
|
||||
premiumEnabledResult = false;
|
||||
premiumEnabledResult = License.NORMAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -91,7 +93,7 @@ public class LicenseKeyChecker {
|
||||
checkLicense();
|
||||
}
|
||||
|
||||
public boolean getEnterpriseEnabledResult() {
|
||||
public License getPremiumLicenseEnabledResult() {
|
||||
return premiumEnabledResult;
|
||||
}
|
||||
}
|
||||
|
@ -23,14 +23,14 @@ public class EndpointConfiguration {
|
||||
private final ApplicationProperties applicationProperties;
|
||||
private Map<String, Boolean> endpointStatuses = new ConcurrentHashMap<>();
|
||||
private Map<String, Set<String>> endpointGroups = new ConcurrentHashMap<>();
|
||||
private final boolean runningEE;
|
||||
private final boolean runningProOrHigher;
|
||||
|
||||
@Autowired
|
||||
public EndpointConfiguration(
|
||||
ApplicationProperties applicationProperties,
|
||||
@Qualifier("runningEE") boolean runningEE) {
|
||||
@Qualifier("runningProOrHigher") boolean runningProOrHigher) {
|
||||
this.applicationProperties = applicationProperties;
|
||||
this.runningEE = runningEE;
|
||||
this.runningProOrHigher = runningProOrHigher;
|
||||
init();
|
||||
processEnvironmentConfigs();
|
||||
}
|
||||
@ -286,7 +286,7 @@ public class EndpointConfiguration {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!runningEE) {
|
||||
if (!runningProOrHigher) {
|
||||
disableGroup("enterprise");
|
||||
}
|
||||
|
||||
|
@ -14,10 +14,10 @@ import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
@Component
|
||||
public class EnterpriseEndpointFilter extends OncePerRequestFilter {
|
||||
private final boolean runningEE;
|
||||
private final boolean runningProOrHigher;
|
||||
|
||||
public EnterpriseEndpointFilter(@Qualifier("runningEE") boolean runningEE) {
|
||||
this.runningEE = runningEE;
|
||||
public EnterpriseEndpointFilter(@Qualifier("runningProOrHigher") boolean runningProOrHigher) {
|
||||
this.runningProOrHigher = runningProOrHigher;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -25,7 +25,7 @@ public class EnterpriseEndpointFilter extends OncePerRequestFilter {
|
||||
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
|
||||
if (!runningEE && isPrometheusEndpointRequest(request)) {
|
||||
if (!runningProOrHigher && isPrometheusEndpointRequest(request)) {
|
||||
response.setStatus(HttpStatus.NOT_FOUND.value());
|
||||
return;
|
||||
}
|
||||
|
@ -46,13 +46,13 @@ import stirling.software.SPDF.repository.PersistentLoginRepository;
|
||||
@EnableWebSecurity
|
||||
@EnableMethodSecurity
|
||||
@Slf4j
|
||||
@DependsOn("runningEE")
|
||||
@DependsOn("runningProOrHigher")
|
||||
public class SecurityConfiguration {
|
||||
|
||||
private final CustomUserDetailsService userDetailsService;
|
||||
private final UserService userService;
|
||||
private final boolean loginEnabledValue;
|
||||
private final boolean runningEE;
|
||||
private final boolean runningProOrHigher;
|
||||
|
||||
private final ApplicationProperties applicationProperties;
|
||||
private final UserAuthenticationFilter userAuthenticationFilter;
|
||||
@ -69,7 +69,7 @@ public class SecurityConfiguration {
|
||||
CustomUserDetailsService userDetailsService,
|
||||
@Lazy UserService userService,
|
||||
@Qualifier("loginEnabled") boolean loginEnabledValue,
|
||||
@Qualifier("runningEE") boolean runningEE,
|
||||
@Qualifier("runningProOrHigher") boolean runningProOrHigher,
|
||||
ApplicationProperties applicationProperties,
|
||||
UserAuthenticationFilter userAuthenticationFilter,
|
||||
LoginAttemptService loginAttemptService,
|
||||
@ -83,7 +83,7 @@ public class SecurityConfiguration {
|
||||
this.userDetailsService = userDetailsService;
|
||||
this.userService = userService;
|
||||
this.loginEnabledValue = loginEnabledValue;
|
||||
this.runningEE = runningEE;
|
||||
this.runningProOrHigher = runningProOrHigher;
|
||||
this.applicationProperties = applicationProperties;
|
||||
this.userAuthenticationFilter = userAuthenticationFilter;
|
||||
this.loginAttemptService = loginAttemptService;
|
||||
@ -254,7 +254,7 @@ public class SecurityConfiguration {
|
||||
.permitAll());
|
||||
}
|
||||
// Handle SAML
|
||||
if (applicationProperties.getSecurity().isSaml2Active() && runningEE) {
|
||||
if (applicationProperties.getSecurity().isSaml2Active() && runningProOrHigher) {
|
||||
// Configure the authentication provider
|
||||
OpenSaml4AuthenticationProvider authenticationProvider =
|
||||
new OpenSaml4AuthenticationProvider();
|
||||
|
@ -27,18 +27,18 @@ public class DatabaseConfig {
|
||||
public static final String POSTGRES_DRIVER = "org.postgresql.Driver";
|
||||
|
||||
private final ApplicationProperties applicationProperties;
|
||||
private final boolean runningEE;
|
||||
private final boolean runningProOrHigher;
|
||||
|
||||
public DatabaseConfig(
|
||||
ApplicationProperties applicationProperties,
|
||||
@Qualifier("runningEE") boolean runningEE) {
|
||||
@Qualifier("runningProOrHigher") boolean runningProOrHigher) {
|
||||
DATASOURCE_DEFAULT_URL =
|
||||
"jdbc:h2:file:"
|
||||
+ InstallationPathConfig.getConfigPath()
|
||||
+ "stirling-pdf-DB-2.3.232;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE";
|
||||
log.debug("Database URL: {}", DATASOURCE_DEFAULT_URL);
|
||||
this.applicationProperties = applicationProperties;
|
||||
this.runningEE = runningEE;
|
||||
this.runningProOrHigher = runningProOrHigher;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -54,7 +54,7 @@ public class DatabaseConfig {
|
||||
public DataSource dataSource() throws UnsupportedProviderException {
|
||||
DataSourceBuilder<?> dataSourceBuilder = DataSourceBuilder.create();
|
||||
|
||||
if (!runningEE) {
|
||||
if (!runningProOrHigher) {
|
||||
return useDefaultDataSource(dataSourceBuilder);
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
@ -56,14 +57,15 @@ public class AccountWebController {
|
||||
private final SessionPersistentRegistry sessionPersistentRegistry;
|
||||
// Assuming you have a repository for user operations
|
||||
private final UserRepository userRepository;
|
||||
|
||||
private final boolean runningEE;
|
||||
public AccountWebController(
|
||||
ApplicationProperties applicationProperties,
|
||||
SessionPersistentRegistry sessionPersistentRegistry,
|
||||
UserRepository userRepository) {
|
||||
UserRepository userRepository, @Qualifier("runningEE") boolean runningEE) {
|
||||
this.applicationProperties = applicationProperties;
|
||||
this.sessionPersistentRegistry = sessionPersistentRegistry;
|
||||
this.userRepository = userRepository;
|
||||
this.runningEE = runningEE;
|
||||
}
|
||||
|
||||
@GetMapping("/login")
|
||||
@ -197,6 +199,9 @@ public class AccountWebController {
|
||||
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||
@GetMapping("/usage")
|
||||
public String showUsage() {
|
||||
if(!runningEE) {
|
||||
return "error";
|
||||
}
|
||||
return "usage";
|
||||
}
|
||||
|
||||
@ -325,7 +330,7 @@ public class AccountWebController {
|
||||
model.addAttribute("activeUsers", activeUsers);
|
||||
model.addAttribute("disabledUsers", disabledUsers);
|
||||
|
||||
model.addAttribute("maxEnterpriseUsers", applicationProperties.getPremium().getMaxUsers());
|
||||
model.addAttribute("maxPaidUsers", applicationProperties.getPremium().getMaxUsers());
|
||||
return "adminSettings";
|
||||
}
|
||||
|
||||
|
@ -17,18 +17,18 @@ public class PdfMetadataService {
|
||||
private final ApplicationProperties applicationProperties;
|
||||
private final String stirlingPDFLabel;
|
||||
private final UserServiceInterface userService;
|
||||
private final boolean runningEE;
|
||||
private final boolean runningProOrHigher;
|
||||
|
||||
@Autowired
|
||||
public PdfMetadataService(
|
||||
ApplicationProperties applicationProperties,
|
||||
@Qualifier("StirlingPDFLabel") String stirlingPDFLabel,
|
||||
@Qualifier("runningEE") boolean runningEE,
|
||||
@Qualifier("runningProOrHigher") boolean runningProOrHigher,
|
||||
@Autowired(required = false) UserServiceInterface userService) {
|
||||
this.applicationProperties = applicationProperties;
|
||||
this.stirlingPDFLabel = stirlingPDFLabel;
|
||||
this.userService = userService;
|
||||
this.runningEE = runningEE;
|
||||
this.runningProOrHigher = runningProOrHigher;
|
||||
}
|
||||
|
||||
public PdfMetadata extractMetadataFromPdf(PDDocument pdf) {
|
||||
@ -69,7 +69,7 @@ public class PdfMetadataService {
|
||||
.getProFeatures()
|
||||
.getCustomMetadata()
|
||||
.isAutoUpdateMetadata()
|
||||
&& runningEE) {
|
||||
&& runningProOrHigher) {
|
||||
|
||||
creator =
|
||||
applicationProperties
|
||||
@ -98,7 +98,7 @@ public class PdfMetadataService {
|
||||
.getProFeatures()
|
||||
.getCustomMetadata()
|
||||
.isAutoUpdateMetadata()
|
||||
&& runningEE) {
|
||||
&& runningProOrHigher) {
|
||||
author =
|
||||
applicationProperties
|
||||
.getPremium()
|
||||
|
@ -34,10 +34,10 @@
|
||||
<!-- User Settings Title -->
|
||||
<div style="background: var(--md-sys-color-outline-variant);padding: .8rem; margin: 10px 0; border-radius: 2rem; text-align: center;">
|
||||
<a href="#"
|
||||
th:data-bs-toggle="${@runningEE && totalUsers >= maxEnterpriseUsers} ? null : 'modal'"
|
||||
th:data-bs-target="${@runningEE && totalUsers >= maxEnterpriseUsers} ? null : '#addUserModal'"
|
||||
th:class="${@runningEE && totalUsers >= maxEnterpriseUsers} ? 'btn btn-danger' : 'btn btn-outline-success'"
|
||||
th:title="${@runningEE && totalUsers >= maxEnterpriseUsers} ? #{adminUserSettings.maxUsersReached} : #{adminUserSettings.addUser}">
|
||||
th:data-bs-toggle="${@runningProOrHigher && totalUsers >= maxPaidUsers} ? null : 'modal'"
|
||||
th:data-bs-target="${@runningProOrHigher && totalUsers >= maxPaidUsers} ? null : '#addUserModal'"
|
||||
th:class="${@runningProOrHigher && totalUsers >= maxPaidUsers} ? 'btn btn-danger' : 'btn btn-outline-success'"
|
||||
th:title="${@runningProOrHigher && totalUsers >= maxPaidUsers} ? #{adminUserSettings.maxUsersReached} : #{adminUserSettings.addUser}">
|
||||
<span class="material-symbols-rounded">person_add</span>
|
||||
<span th:text="#{adminUserSettings.addUser}">Add New User</span>
|
||||
</a>
|
||||
@ -51,7 +51,7 @@
|
||||
<span th:text="#{adminUserSettings.changeUserRole}">Change User's Role</span>
|
||||
</a>
|
||||
|
||||
<a href="/usage"
|
||||
<a href="/usage" th:if="${@runningEE}"
|
||||
class="btn btn-outline-success"
|
||||
th:title="#{adminUserSettings.usage}">
|
||||
<span class="material-symbols-rounded">analytics</span>
|
||||
@ -61,7 +61,7 @@
|
||||
<div class="my-4">
|
||||
<strong style="margin-left: 20px;" th:text="#{adminUserSettings.totalUsers}">Total Users:</strong>
|
||||
<span th:text="${totalUsers}"></span>
|
||||
<span th:if="${@runningEE}" th:text="'/'+${maxEnterpriseUsers}"></span>
|
||||
<span th:if="${@runningProOrHigher}" th:text="'/'+${maxPaidUsers}"></span>
|
||||
|
||||
<strong style="margin-left: 20px;" th:text="#{adminUserSettings.activeUsers}">Active Users:</strong>
|
||||
<span th:text="${activeUsers}"></span>
|
||||
@ -126,7 +126,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p th:if="${!@runningEE}" th:text="#{enterpriseEdition.ssoAdvert}"></p>
|
||||
<p th:if="${!@runningProOrHigher}" th:text="#{enterpriseEdition.ssoAdvert}"></p>
|
||||
|
||||
<script th:inline="javascript">
|
||||
const delete_confirm_text = /*[[#{adminUserSettings.confirmDeleteUser}]]*/ 'Should the user be deleted?';
|
||||
|
@ -170,7 +170,7 @@
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="nav-item" th:if="${!@runningEE}">
|
||||
<li class="nav-item" th:if="${!@runningProOrHigher}">
|
||||
<a href="https://stirlingpdf.com/pricing" class="nav-link go-pro-link" target="_blank"
|
||||
rel="noopener noreferrer">
|
||||
<span class="go-pro-badge" th:text="#{enterpriseEdition.button}"></span>
|
||||
|
@ -39,7 +39,7 @@
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
const runningEE = /*[[${@runningEE}]]*/ false;
|
||||
const runningProOrHigher = /*[[${@runningProOrHigher}]]*/ false;
|
||||
const SSOAutoLogin = /*[[${@SSOAutoLogin}]]*/ false;
|
||||
const loginMethod = /*[[${loginMethod}]]*/ 'normal';
|
||||
const providerList = /*[[${providerList}]]*/ {};
|
||||
@ -47,7 +47,7 @@
|
||||
!hasLogout &&
|
||||
!hasMessage &&
|
||||
redirectAttempts < MAX_REDIRECT_ATTEMPTS &&
|
||||
loginMethod !== 'normal' && runningEE && SSOAutoLogin;
|
||||
loginMethod !== 'normal' && runningProOrHigher && SSOAutoLogin;
|
||||
|
||||
console.log('Should redirect:', shouldAutoRedirect, {
|
||||
'No error': !hasRedirectError,
|
||||
|
Loading…
Reference in New Issue
Block a user