Initial Commit
This commit is contained in:
parent
92c43041f0
commit
9d3a4cd1d0
1
.gitignore
vendored
1
.gitignore
vendored
@ -14,6 +14,7 @@ replay_pid*
|
|||||||
.idea
|
.idea
|
||||||
cmake-build-*/
|
cmake-build-*/
|
||||||
*.iws
|
*.iws
|
||||||
|
work/
|
||||||
out/
|
out/
|
||||||
build/
|
build/
|
||||||
.idea_modules/
|
.idea_modules/
|
||||||
|
85
pom.xml
85
pom.xml
@ -3,10 +3,17 @@
|
|||||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
|
</parent>
|
||||||
|
|
||||||
<groupId>me.braydon</groupId>
|
<groupId>me.braydon</groupId>
|
||||||
<artifactId>LicenseServer</artifactId>
|
<artifactId>LicenseServer</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0.0</version>
|
||||||
|
<description>A simple open-source licensing server for your products.</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>20</java.version>
|
<java.version>20</java.version>
|
||||||
@ -15,36 +22,48 @@
|
|||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<build>
|
<dependencies>
|
||||||
<plugins>
|
<!-- Lombok -->
|
||||||
<plugin>
|
<dependency>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<version>3.8.1</version>
|
<version>1.18.26</version>
|
||||||
<configuration>
|
<scope>provided</scope>
|
||||||
<source>${java.version}</source>
|
</dependency>
|
||||||
<target>${java.version}</target>
|
|
||||||
</configuration>
|
<!-- BCrypt -->
|
||||||
</plugin>
|
<dependency>
|
||||||
<plugin>
|
<groupId>org.mindrot</groupId>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<artifactId>jbcrypt</artifactId>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<version>0.4</version>
|
||||||
<version>3.1.0</version>
|
<scope>compile</scope>
|
||||||
<executions>
|
</dependency>
|
||||||
<execution>
|
|
||||||
<phase>package</phase>
|
<!-- MongoDB -->
|
||||||
<goals>
|
<dependency>
|
||||||
<goal>shade</goal>
|
<groupId>org.springframework.boot</groupId>
|
||||||
</goals>
|
<artifactId>spring-boot-starter-data-mongodb</artifactId>
|
||||||
</execution>
|
<scope>compile</scope>
|
||||||
</executions>
|
</dependency>
|
||||||
</plugin>
|
|
||||||
</plugins>
|
<!-- Gson -->
|
||||||
<resources>
|
<dependency>
|
||||||
<resource>
|
<groupId>com.google.code.gson</groupId>
|
||||||
<directory>src/main/resources</directory>
|
<artifactId>gson</artifactId>
|
||||||
<filtering>true</filtering>
|
<version>2.10.1</version>
|
||||||
</resource>
|
<scope>compile</scope>
|
||||||
</resources>
|
</dependency>
|
||||||
</build>
|
|
||||||
|
<!-- Spring -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
</project>
|
</project>
|
39
src/main/java/me/braydon/license/LicenseServer.java
Normal file
39
src/main/java/me/braydon/license/LicenseServer.java
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package me.braydon.license;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Braydon
|
||||||
|
*/
|
||||||
|
@SpringBootApplication
|
||||||
|
@Slf4j
|
||||||
|
public class LicenseServer {
|
||||||
|
public static final Gson GSON = new GsonBuilder()
|
||||||
|
.serializeNulls()
|
||||||
|
.create();
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public static void main(@NonNull String[] args) {
|
||||||
|
File config = new File("application.yml");
|
||||||
|
if (!config.exists()) { // Saving the default config if it doesn't exist locally
|
||||||
|
Files.copy(Objects.requireNonNull(LicenseServer.class.getResourceAsStream("/application.yml")), config.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
log.info("Saved the default configuration to '{}', please re-launch the application", // Log the default config being saved
|
||||||
|
config.getAbsolutePath()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log.info("Found configuration at '{}'", config.getAbsolutePath()); // Log the found config
|
||||||
|
SpringApplication.run(LicenseServer.class, args); // Load the application
|
||||||
|
}
|
||||||
|
}
|
30
src/main/java/me/braydon/license/common/RandomUtils.java
Normal file
30
src/main/java/me/braydon/license/common/RandomUtils.java
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package me.braydon.license.common;
|
||||||
|
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Braydon
|
||||||
|
*/
|
||||||
|
@UtilityClass
|
||||||
|
public final class RandomUtils {
|
||||||
|
/**
|
||||||
|
* The license key format to use.
|
||||||
|
*/
|
||||||
|
private static final String LICENSE_KEY_FORMAT = "%04X-%04X-%04X-%04X";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a random license key.
|
||||||
|
*
|
||||||
|
* @return the random license key
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public static String generateLicenseKey() {
|
||||||
|
int segments = LICENSE_KEY_FORMAT.split("-").length; // The amount of segments
|
||||||
|
Object[] parts = new Object[segments];
|
||||||
|
for (int i = 0; i < segments; i++) { // Generate a random part for each segment
|
||||||
|
parts[i] = (int) (Math.random() * 0xFFFF);
|
||||||
|
}
|
||||||
|
return String.format(LICENSE_KEY_FORMAT, parts);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
package me.braydon.license.controller;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import me.braydon.license.LicenseServer;
|
||||||
|
import me.braydon.license.exception.APIException;
|
||||||
|
import me.braydon.license.model.License;
|
||||||
|
import me.braydon.license.service.LicenseService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Braydon
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping(value = "/", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
public final class LicenseController {
|
||||||
|
/**
|
||||||
|
* The {@link LicenseService} to use.
|
||||||
|
*/
|
||||||
|
@NonNull private final LicenseService service;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public LicenseController(@NonNull LicenseService service) {
|
||||||
|
this.service = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This route handle checking of licenses.
|
||||||
|
*
|
||||||
|
* @param body the body of the request
|
||||||
|
* @return the response entity
|
||||||
|
* @see License for license
|
||||||
|
* @see ResponseEntity for response entity
|
||||||
|
*/
|
||||||
|
@GetMapping("/check")
|
||||||
|
@ResponseBody
|
||||||
|
public ResponseEntity<?> check(@NonNull HttpServletRequest request, @RequestBody @NonNull String body) {
|
||||||
|
try { // Attempt to check the license
|
||||||
|
String ip = request.getRemoteAddr(); // The IP of the requester
|
||||||
|
|
||||||
|
JsonObject jsonObject = LicenseServer.GSON.fromJson(body, JsonObject.class);
|
||||||
|
String key = jsonObject.get("key").getAsString(); // Get the key
|
||||||
|
String product = jsonObject.get("product").getAsString(); // Get the product
|
||||||
|
String hwid = jsonObject.get("hwid").getAsString(); // Get the hwid
|
||||||
|
|
||||||
|
service.check(key, product, ip, hwid); // Check the license
|
||||||
|
return ResponseEntity.ok().build(); // Return OK
|
||||||
|
} catch (APIException ex) { // Handle the exception
|
||||||
|
return ResponseEntity.status(ex.getStatus())
|
||||||
|
.body(Map.of("error", ex.getLocalizedMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
src/main/java/me/braydon/license/exception/APIException.java
Normal file
25
src/main/java/me/braydon/license/exception/APIException.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package me.braydon.license.exception;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an API exception.
|
||||||
|
*
|
||||||
|
* @author Braydon
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public class APIException extends RuntimeException {
|
||||||
|
/**
|
||||||
|
* The status of this exception.
|
||||||
|
*
|
||||||
|
* @see HttpStatus for status
|
||||||
|
*/
|
||||||
|
@NonNull private final HttpStatus status;
|
||||||
|
|
||||||
|
public APIException(@NonNull HttpStatus status, @NonNull String message) {
|
||||||
|
super(message);
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package me.braydon.license.exception;
|
||||||
|
|
||||||
|
import me.braydon.license.model.License;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This exception is raised when
|
||||||
|
* a {@link License} has its HWID
|
||||||
|
* limit exceeded.
|
||||||
|
*
|
||||||
|
* @author Braydon
|
||||||
|
*/
|
||||||
|
public class LicenseHwidLimitExceededException extends APIException {
|
||||||
|
public LicenseHwidLimitExceededException() {
|
||||||
|
super(HttpStatus.BAD_REQUEST, "License key HWID limit has been exceeded");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package me.braydon.license.exception;
|
||||||
|
|
||||||
|
import me.braydon.license.model.License;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This exception is raised when
|
||||||
|
* a {@link License} has its IP
|
||||||
|
* limit exceeded.
|
||||||
|
*
|
||||||
|
* @author Braydon
|
||||||
|
*/
|
||||||
|
public class LicenseIpLimitExceededException extends APIException {
|
||||||
|
public LicenseIpLimitExceededException() {
|
||||||
|
super(HttpStatus.BAD_REQUEST, "License key IP limit has been exceeded");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package me.braydon.license.exception;
|
||||||
|
|
||||||
|
import me.braydon.license.model.License;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This exception is raised when
|
||||||
|
* a {@link License} is not found.
|
||||||
|
*
|
||||||
|
* @author Braydon
|
||||||
|
*/
|
||||||
|
public class LicenseNotFoundException extends APIException {
|
||||||
|
public LicenseNotFoundException() {
|
||||||
|
super(HttpStatus.NOT_FOUND, "License not found");
|
||||||
|
}
|
||||||
|
}
|
92
src/main/java/me/braydon/license/model/License.java
Normal file
92
src/main/java/me/braydon/license/model/License.java
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
package me.braydon.license.model;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import me.braydon.license.exception.APIException;
|
||||||
|
import me.braydon.license.exception.LicenseHwidLimitExceededException;
|
||||||
|
import me.braydon.license.exception.LicenseIpLimitExceededException;
|
||||||
|
import org.springframework.data.annotation.Id;
|
||||||
|
import org.springframework.data.mongodb.core.mapping.Document;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a license key.
|
||||||
|
*
|
||||||
|
* @author Braydon
|
||||||
|
*/
|
||||||
|
@Document("keys")
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
public class License {
|
||||||
|
/**
|
||||||
|
* The key of this license.
|
||||||
|
*/
|
||||||
|
@Id @NonNull private String key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The product this license is for.
|
||||||
|
*/
|
||||||
|
@NonNull private String product;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The optional description of this license.
|
||||||
|
*/
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The amount of uses this license has.
|
||||||
|
*/
|
||||||
|
private int uses;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The IPs used on this license.
|
||||||
|
* <p>
|
||||||
|
* These IPs are encrypted using AES-256.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
private Set<String> ips;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The hardware IDs that were used on this license.
|
||||||
|
*/
|
||||||
|
private Set<String> hwids;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The limit of IPs that can be used on this license.
|
||||||
|
*/
|
||||||
|
private int ipLimit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The limit of HWIDs that can be used on this license.
|
||||||
|
*/
|
||||||
|
private int hwidLimit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The date this license was created.
|
||||||
|
*/
|
||||||
|
@NonNull private Date created;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when this license is used.
|
||||||
|
*
|
||||||
|
* @param ip the ip used
|
||||||
|
* @param hwid the hardware id used
|
||||||
|
*/
|
||||||
|
public void use(@NonNull String ip, @NonNull String hwid) throws APIException {
|
||||||
|
if (!ips.contains(ip) && ips.size() >= ipLimit) { // IP limit has been exceeded
|
||||||
|
throw new LicenseIpLimitExceededException();
|
||||||
|
}
|
||||||
|
if (!hwids.contains(hwid) && hwids.size() >= hwidLimit) { // HWID limit has been exceeded
|
||||||
|
throw new LicenseHwidLimitExceededException();
|
||||||
|
}
|
||||||
|
// The license was used
|
||||||
|
uses++; // Increment uses
|
||||||
|
ips.add(ip); // Add the used IP
|
||||||
|
hwids.add(hwid); // Add the used HWID
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package me.braydon.license.repository;
|
||||||
|
|
||||||
|
import lombok.NonNull;
|
||||||
|
import me.braydon.license.model.License;
|
||||||
|
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||||
|
import org.springframework.data.mongodb.repository.Query;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The repository for {@link License}'s.
|
||||||
|
*
|
||||||
|
* @author Braydon
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public interface LicenseRepository extends MongoRepository<License, String> {
|
||||||
|
/**
|
||||||
|
* Get the license that has the given
|
||||||
|
* key and is for the given product.
|
||||||
|
*
|
||||||
|
* @param key the key to get
|
||||||
|
* @param product the product the key is for
|
||||||
|
* @return the optional license
|
||||||
|
* @see License for license
|
||||||
|
*/
|
||||||
|
@Query("{ key: ?0, product: ?1 }")
|
||||||
|
Optional<License> getLicense(@NonNull String key, @NonNull String product);
|
||||||
|
}
|
102
src/main/java/me/braydon/license/service/LicenseService.java
Normal file
102
src/main/java/me/braydon/license/service/LicenseService.java
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
package me.braydon.license.service;
|
||||||
|
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import me.braydon.license.common.RandomUtils;
|
||||||
|
import me.braydon.license.exception.APIException;
|
||||||
|
import me.braydon.license.exception.LicenseNotFoundException;
|
||||||
|
import me.braydon.license.model.License;
|
||||||
|
import me.braydon.license.repository.LicenseRepository;
|
||||||
|
import org.mindrot.jbcrypt.BCrypt;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The service for managing {@link License}'s.
|
||||||
|
*
|
||||||
|
* @author Braydon
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public final class LicenseService {
|
||||||
|
/**
|
||||||
|
* The {@link LicenseRepository} to use.
|
||||||
|
*/
|
||||||
|
@NonNull private final LicenseRepository repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The salt to use for hashing license keys.
|
||||||
|
*/
|
||||||
|
@Value("${key-salt}")
|
||||||
|
@NonNull private String keySalt;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public LicenseService(@NonNull LicenseRepository repository) {
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void onInitialize() {
|
||||||
|
String key = RandomUtils.generateLicenseKey();
|
||||||
|
log.info(create(key,
|
||||||
|
"CloudSpigot",
|
||||||
|
"Testing " + Math.random(), Integer.MAX_VALUE, Integer.MAX_VALUE).toString());
|
||||||
|
System.out.println("key = " + key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new license key.
|
||||||
|
*
|
||||||
|
* @param key the key of the license
|
||||||
|
* @param product the product the license is for
|
||||||
|
* @param description the optional description of the license
|
||||||
|
* @param ipLimit the IP limit of the license
|
||||||
|
* @param hwidLimit the HWID limit of the license
|
||||||
|
* @return the created license
|
||||||
|
* @see License for license
|
||||||
|
*/
|
||||||
|
public License create(@NonNull String key, @NonNull String product,
|
||||||
|
String description, int ipLimit, int hwidLimit) {
|
||||||
|
// Create the new license
|
||||||
|
License license = new License();
|
||||||
|
license.setKey(BCrypt.hashpw(key, keySalt)); // Hash the key
|
||||||
|
license.setProduct(product); // Use the given product
|
||||||
|
license.setDescription(description); // Use the given description, if any
|
||||||
|
license.setIps(new HashSet<>());
|
||||||
|
license.setHwids(new HashSet<>());
|
||||||
|
license.setIpLimit(ipLimit); // Use the given IP limit
|
||||||
|
license.setHwidLimit(hwidLimit); // Use the given HWID limit
|
||||||
|
license.setCreated(new Date());
|
||||||
|
repository.insert(license); // Insert the newly created license
|
||||||
|
return license;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the given license.
|
||||||
|
*
|
||||||
|
* @param key the key to check
|
||||||
|
* @param product the product of the license
|
||||||
|
* @param ip the ip using the license
|
||||||
|
* @param hwid the hwid using the license
|
||||||
|
* @throws APIException if there was an error checking the license
|
||||||
|
* @see License for license
|
||||||
|
*/
|
||||||
|
public void check(@NonNull String key, @NonNull String product,
|
||||||
|
@NonNull String ip, @NonNull String hwid) throws APIException {
|
||||||
|
Optional<License> optionalLicense = repository.getLicense(BCrypt.hashpw(key, keySalt), product); // Get the license
|
||||||
|
if (optionalLicense.isEmpty()) { // License key not found
|
||||||
|
log.error("License key {} for product {} not found", key, product); // Log the error
|
||||||
|
throw new LicenseNotFoundException();
|
||||||
|
}
|
||||||
|
License license = optionalLicense.get(); // The license found
|
||||||
|
license.use(ip, hwid); // Use the license
|
||||||
|
repository.save(license); // Save the used license
|
||||||
|
log.info("License key {} for product {} was used by {} ({})", key, product, ip, hwid);
|
||||||
|
}
|
||||||
|
}
|
27
src/main/resources/application.yml
Normal file
27
src/main/resources/application.yml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# Server Configuration
|
||||||
|
server:
|
||||||
|
address: 0.0.0.0
|
||||||
|
port: 7500
|
||||||
|
|
||||||
|
# The salt to use when hashing license keys.
|
||||||
|
# This salt should be changed from the default.
|
||||||
|
key-salt: "$2a$10$/nQyzQDMkCf97ZlJLLWa3O"
|
||||||
|
|
||||||
|
# Log Configuration
|
||||||
|
logging:
|
||||||
|
file:
|
||||||
|
path: "./logs"
|
||||||
|
|
||||||
|
# Spring Configuration
|
||||||
|
spring:
|
||||||
|
data:
|
||||||
|
# MongoDB - This is used to store persistent data
|
||||||
|
mongodb:
|
||||||
|
uri: "mongodb://licenseServer:p4$$w0rd@127.0.0.1:27017/licenseServer?authSource=admin"
|
||||||
|
auto-index-creation: true # Automatically create collection indexes
|
||||||
|
|
||||||
|
# Ignore
|
||||||
|
application:
|
||||||
|
name: "License Server"
|
||||||
|
banner:
|
||||||
|
location: "classpath:banner.txt"
|
8
src/main/resources/banner.txt
Normal file
8
src/main/resources/banner.txt
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
_ _ ___
|
||||||
|
| | (_)__ ___ _ _ ___ ___ / __| ___ _ ___ _____ _ _
|
||||||
|
| |__| / _/ -_) ' \(_-</ -_) \__ \/ -_) '_\ V / -_) '_|
|
||||||
|
|____|_\__\___|_||_/__/\___| |___/\___|_| \_/\___|_|
|
||||||
|
|
||||||
|
| API Version - v${application.version}
|
||||||
|
| Spring Version - ${spring-boot.formatted-version}
|
||||||
|
_______________________________________
|
Loading…
x
Reference in New Issue
Block a user