feat(license): enforce max_apps at AppService.createApp

Adds CreateGuard hook to AppService.createApp using the same pattern
as T18 (EnvironmentService). AppRepository.count() added; the bean
wires LicenseEnforcer.assertWithinCap("max_apps", current, 1).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-26 13:36:34 +02:00
parent 198811b752
commit 80dafe685b
5 changed files with 117 additions and 2 deletions

View File

@@ -8,6 +8,7 @@ import java.util.UUID;
public interface AppRepository {
List<App> findByEnvironmentId(UUID environmentId);
List<App> findAll();
long count();
Optional<App> findById(UUID id);
Optional<App> findByEnvironmentIdAndSlug(UUID environmentId, String slug);
Optional<App> findBySlug(String slug);

View File

@@ -23,11 +23,18 @@ public class AppService {
private final AppRepository appRepo;
private final AppVersionRepository versionRepo;
private final String jarStoragePath;
private final CreateGuard createGuard;
public AppService(AppRepository appRepo, AppVersionRepository versionRepo, String jarStoragePath) {
this(appRepo, versionRepo, jarStoragePath, CreateGuard.NOOP);
}
public AppService(AppRepository appRepo, AppVersionRepository versionRepo, String jarStoragePath,
CreateGuard createGuard) {
this.appRepo = appRepo;
this.versionRepo = versionRepo;
this.jarStoragePath = jarStoragePath;
this.createGuard = createGuard;
}
public List<App> listAll() { return appRepo.findAll(); }
@@ -55,6 +62,7 @@ public class AppService {
throw new IllegalArgumentException(
"Invalid app slug: must match ^[a-z0-9][a-z0-9-]{0,63}$ (lowercase letters, digits, hyphens)");
}
createGuard.check(appRepo.count());
if (appRepo.findByEnvironmentIdAndSlug(environmentId, slug).isPresent()) {
throw new IllegalArgumentException("App with slug '" + slug + "' already exists in this environment");
}