Skip to content

Commit e73d5a7

Browse files
Merge pull request #1378 from Giskard-AI/advanced-giskard-license-hfspaces
[GSK-1664][GSK-1677] Advanced Giskard license for Hugging Face Spaces
2 parents 7a644bf + 8706cd1 commit e73d5a7

File tree

5 files changed

+34
-10
lines changed

5 files changed

+34
-10
lines changed

backend/src/main/java/ai/giskard/service/ee/KeygenLicenseReader.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ public static License read(JsonNode json) {
4444
license.setUserLimit(policyMeta.get("userLimit").asInt(0));
4545
}
4646

47+
if (policyMeta.has("modelPerProjectLimit")) {
48+
license.setModelPerProjectLimit(policyMeta.get("modelPerProjectLimit").asInt(0));
49+
}
4750

4851
license.setFeatures(feats);
4952
JsonNode licenseAttributes = json.get("data").get("attributes"); // NOSONAR

backend/src/main/java/ai/giskard/service/ee/License.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public class License {
1818
private List<String> features;
1919

2020
private Integer projectLimit;
21+
private Integer modelPerProjectLimit;
2122
private Integer userLimit;
2223
private Instant expiresOn;
2324

backend/src/main/java/ai/giskard/service/ee/LicenseService.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import ai.giskard.service.FileLocationService;
55
import com.fasterxml.jackson.databind.JsonNode;
66
import com.fasterxml.jackson.databind.ObjectMapper;
7+
import jakarta.annotation.PostConstruct;
78
import lombok.RequiredArgsConstructor;
89
import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters;
910
import org.bouncycastle.crypto.signers.Ed25519Signer;
@@ -12,7 +13,6 @@
1213
import org.slf4j.LoggerFactory;
1314
import org.springframework.stereotype.Service;
1415

15-
import jakarta.annotation.PostConstruct;
1616
import java.io.IOException;
1717
import java.nio.file.Files;
1818
import java.time.Instant;
@@ -36,18 +36,22 @@ public class LicenseService {
3636
* Also initialize default license (for now)
3737
*/
3838
@PostConstruct
39-
public void init() throws IOException {
39+
public void init() {
4040
try {
4141
this.currentLicense = readLicenseFromFile();
4242
} catch (LicenseException e) {
4343
log.warn("Invalid license file", e);
4444
}
4545
}
4646

47-
public synchronized License readLicenseFromFile() throws IOException {
47+
public synchronized License readLicenseFromFile() {
4848
if (Files.exists(fileLocationService.licensePath())) {
49-
String licenseFile = Files.readString(fileLocationService.licensePath());
50-
return readLicense(licenseFile);
49+
try {
50+
String licenseFile = Files.readString(fileLocationService.licensePath());
51+
return readLicense(licenseFile);
52+
} catch (IOException e) {
53+
log.warn("Invalid license file", e);
54+
}
5155
}
5256
return new License();
5357
}

backend/src/main/java/ai/giskard/web/rest/controllers/ModelController.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,23 @@
1414
import ai.giskard.service.ModelService;
1515
import ai.giskard.service.ProjectFileDeletionService;
1616
import ai.giskard.service.UsageService;
17+
import ai.giskard.service.ee.LicenseException;
18+
import ai.giskard.service.ee.LicenseService;
1719
import ai.giskard.web.dto.*;
1820
import ai.giskard.web.dto.mapper.GiskardMapper;
1921
import ai.giskard.web.dto.ml.ModelDTO;
2022
import ai.giskard.web.rest.errors.Entity;
2123
import ai.giskard.web.rest.errors.EntityNotFoundException;
24+
import jakarta.validation.Valid;
25+
import jakarta.validation.constraints.NotBlank;
26+
import jakarta.validation.constraints.NotNull;
2227
import lombok.RequiredArgsConstructor;
2328
import org.slf4j.Logger;
2429
import org.slf4j.LoggerFactory;
2530
import org.springframework.security.access.prepost.PreAuthorize;
31+
import org.springframework.transaction.annotation.Transactional;
2632
import org.springframework.web.bind.annotation.*;
2733

28-
import jakarta.validation.Valid;
29-
import jakarta.validation.constraints.NotBlank;
30-
import jakarta.validation.constraints.NotNull;
3134
import java.util.HashMap;
3235
import java.util.List;
3336
import java.util.Map;
@@ -46,6 +49,7 @@ public class ModelController {
4649
private final PermissionEvaluator permissionEvaluator;
4750
private final ModelService modelService;
4851
private final ProjectFileDeletionService deletionService;
52+
private final LicenseService licenseService;
4953

5054

5155
/**
@@ -84,12 +88,25 @@ public ModelDTO getModelMeta(@PathVariable("projectKey") @NotNull String project
8488

8589
@PostMapping("project/{projectKey}/models")
8690
@PreAuthorize("@permissionEvaluator.canWriteProjectKey(#projectKey)")
91+
@Transactional
8792
public void createModelMeta(@PathVariable("projectKey") @NotNull String projectKey, @RequestBody @NotNull ModelDTO dto) {
8893
if (modelRepository.existsById(dto.getId())) {
8994
log.info("Model already exists {}", dto.getId());
9095
return;
9196
}
9297
Project project = projectRepository.getOneByKey(projectKey);
98+
Integer modelPerProject = licenseService.getCurrentLicense().getModelPerProjectLimit();
99+
if (modelPerProject != null && project.getModels().size() >= modelPerProject) {
100+
log.info("Exceed model numbers in project '{}'", project.getName());
101+
throw new LicenseException(
102+
"You've reached your limit of " +
103+
licenseService.getCurrentLicense().getModelPerProjectLimit() +
104+
" models per project allowed by the " +
105+
licenseService.getCurrentLicense().getPlanName() +
106+
" plan. " +
107+
"Please upgrade your license to keep more versions."
108+
);
109+
}
93110
ProjectModel model = giskardMapper.fromDTO(dto);
94111
model.setProject(project);
95112
modelRepository.save(model);

backend/src/main/java/ai/giskard/web/rest/controllers/SettingsController.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import org.springframework.web.bind.annotation.RequestBody;
2929
import org.springframework.web.bind.annotation.RestController;
3030

31-
import java.io.IOException;
3231
import java.time.Instant;
3332
import java.time.OffsetDateTime;
3433
import java.time.format.DateTimeFormatter;
@@ -117,7 +116,7 @@ public MLWorkerConnectionInfoDTO getMLWorkerConnectionInfo() {
117116
}
118117

119118
@GetMapping("/api/v2/settings/license")
120-
public LicenseDTO getLicense() throws IOException {
119+
public LicenseDTO getLicense() {
121120
LicenseDTO.LicenseDTOBuilder dtoBuilder = LicenseDTO.builder();
122121
License currentLicense = licenseService.getCurrentLicense();
123122

0 commit comments

Comments
 (0)