Remove bootstrapToken field/getter/setter from EnvironmentEntity and drop the RuntimeConfig dependency from EnvironmentService. DeploymentService and AgentStatusService now use a TODO-api-key placeholder until the ApiKeyService wiring is complete. All test references to setBootstrapToken removed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
105 lines
4.0 KiB
Java
105 lines
4.0 KiB
Java
package net.siegeln.cameleer.saas.environment;
|
|
|
|
import net.siegeln.cameleer.saas.audit.AuditAction;
|
|
import net.siegeln.cameleer.saas.audit.AuditService;
|
|
import net.siegeln.cameleer.saas.license.LicenseDefaults;
|
|
import net.siegeln.cameleer.saas.license.LicenseRepository;
|
|
import net.siegeln.cameleer.saas.tenant.Tier;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import java.util.List;
|
|
import java.util.Optional;
|
|
import java.util.UUID;
|
|
|
|
@Service
|
|
public class EnvironmentService {
|
|
|
|
private final EnvironmentRepository environmentRepository;
|
|
private final LicenseRepository licenseRepository;
|
|
private final AuditService auditService;
|
|
|
|
public EnvironmentService(EnvironmentRepository environmentRepository,
|
|
LicenseRepository licenseRepository,
|
|
AuditService auditService) {
|
|
this.environmentRepository = environmentRepository;
|
|
this.licenseRepository = licenseRepository;
|
|
this.auditService = auditService;
|
|
}
|
|
|
|
public EnvironmentEntity create(UUID tenantId, String slug, String displayName, UUID actorId) {
|
|
if (environmentRepository.existsByTenantIdAndSlug(tenantId, slug)) {
|
|
throw new IllegalArgumentException("Slug already exists for this tenant: " + slug);
|
|
}
|
|
|
|
enforceTierLimit(tenantId);
|
|
|
|
var entity = new EnvironmentEntity();
|
|
entity.setTenantId(tenantId);
|
|
entity.setSlug(slug);
|
|
entity.setDisplayName(displayName);
|
|
|
|
var saved = environmentRepository.save(entity);
|
|
|
|
auditService.log(actorId, null, tenantId,
|
|
AuditAction.ENVIRONMENT_CREATE, slug,
|
|
null, null, "SUCCESS", null);
|
|
|
|
return saved;
|
|
}
|
|
|
|
public EnvironmentEntity createDefaultForTenant(UUID tenantId) {
|
|
return environmentRepository.findByTenantIdAndSlug(tenantId, "default")
|
|
.orElseGet(() -> create(tenantId, "default", "Default", null));
|
|
}
|
|
|
|
public List<EnvironmentEntity> listByTenantId(UUID tenantId) {
|
|
return environmentRepository.findByTenantId(tenantId);
|
|
}
|
|
|
|
public Optional<EnvironmentEntity> getById(UUID id) {
|
|
return environmentRepository.findById(id);
|
|
}
|
|
|
|
public EnvironmentEntity updateDisplayName(UUID environmentId, String displayName, UUID actorId) {
|
|
var entity = environmentRepository.findById(environmentId)
|
|
.orElseThrow(() -> new IllegalArgumentException("Environment not found: " + environmentId));
|
|
|
|
entity.setDisplayName(displayName);
|
|
var saved = environmentRepository.save(entity);
|
|
|
|
auditService.log(actorId, null, entity.getTenantId(),
|
|
AuditAction.ENVIRONMENT_UPDATE, entity.getSlug(),
|
|
null, null, "SUCCESS", null);
|
|
|
|
return saved;
|
|
}
|
|
|
|
public void delete(UUID environmentId, UUID actorId) {
|
|
var entity = environmentRepository.findById(environmentId)
|
|
.orElseThrow(() -> new IllegalArgumentException("Environment not found: " + environmentId));
|
|
|
|
if ("default".equals(entity.getSlug())) {
|
|
throw new IllegalStateException("Cannot delete the default environment");
|
|
}
|
|
|
|
environmentRepository.delete(entity);
|
|
|
|
auditService.log(actorId, null, entity.getTenantId(),
|
|
AuditAction.ENVIRONMENT_DELETE, entity.getSlug(),
|
|
null, null, "SUCCESS", null);
|
|
}
|
|
|
|
private void enforceTierLimit(UUID tenantId) {
|
|
var license = licenseRepository.findFirstByTenantIdAndRevokedAtIsNullOrderByCreatedAtDesc(tenantId);
|
|
if (license.isEmpty()) {
|
|
throw new IllegalStateException("No active license");
|
|
}
|
|
var limits = LicenseDefaults.limitsForTier(Tier.valueOf(license.get().getTier()));
|
|
var maxEnvs = (int) limits.getOrDefault("max_environments", 1);
|
|
var currentCount = environmentRepository.countByTenantId(tenantId);
|
|
if (maxEnvs != -1 && currentCount >= maxEnvs) {
|
|
throw new IllegalStateException("Environment limit reached for current tier");
|
|
}
|
|
}
|
|
}
|