feat: add license loading at startup from env var or file

- LicenseBeanConfig wires LicenseGate bean with startup validation
- Supports token from CAMELEER_LICENSE_TOKEN env var or CAMELEER_LICENSE_FILE path
- Falls back to open mode when no license or no public key configured
- Add license config properties to application.yml
This commit is contained in:
hsiegeln
2026-04-07 23:11:02 +02:00
parent d734597ec3
commit b969075007
2 changed files with 73 additions and 0 deletions

View File

@@ -0,0 +1,68 @@
package com.cameleer3.server.app.config;
import com.cameleer3.server.core.license.LicenseGate;
import com.cameleer3.server.core.license.LicenseInfo;
import com.cameleer3.server.core.license.LicenseValidator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.nio.file.Files;
import java.nio.file.Path;
@Configuration
public class LicenseBeanConfig {
private static final Logger log = LoggerFactory.getLogger(LicenseBeanConfig.class);
@Value("${license.token:}")
private String licenseToken;
@Value("${license.file:}")
private String licenseFile;
@Value("${license.public-key:}")
private String licensePublicKey;
@Bean
public LicenseGate licenseGate() {
LicenseGate gate = new LicenseGate();
String token = resolveLicenseToken();
if (token == null || token.isBlank()) {
log.info("No license configured — running in open mode (all features enabled)");
return gate;
}
if (licensePublicKey == null || licensePublicKey.isBlank()) {
log.warn("License token provided but no public key configured (CAMELEER_LICENSE_PUBLIC_KEY). Running in open mode.");
return gate;
}
try {
LicenseValidator validator = new LicenseValidator(licensePublicKey);
LicenseInfo info = validator.validate(token);
gate.load(info);
} catch (Exception e) {
log.error("Failed to validate license: {}. Running in open mode.", e.getMessage());
}
return gate;
}
private String resolveLicenseToken() {
if (licenseToken != null && !licenseToken.isBlank()) {
return licenseToken;
}
if (licenseFile != null && !licenseFile.isBlank()) {
try {
return Files.readString(Path.of(licenseFile)).trim();
} catch (Exception e) {
log.warn("Failed to read license file {}: {}", licenseFile, e.getMessage());
}
}
return null;
}
}

View File

@@ -41,6 +41,11 @@ cameleer:
debounce-ms: ${CAMELEER_INDEXER_DEBOUNCE_MS:2000}
queue-size: ${CAMELEER_INDEXER_QUEUE_SIZE:10000}
license:
token: ${CAMELEER_LICENSE_TOKEN:}
file: ${CAMELEER_LICENSE_FILE:}
public-key: ${CAMELEER_LICENSE_PUBLIC_KEY:}
security:
access-token-expiry-ms: 3600000
refresh-token-expiry-ms: 604800000