diff --git a/src/test/java/net/siegeln/cameleer/saas/license/LicenseControllerTest.java b/src/test/java/net/siegeln/cameleer/saas/license/LicenseControllerTest.java index 6e57711..bc9ba6f 100644 --- a/src/test/java/net/siegeln/cameleer/saas/license/LicenseControllerTest.java +++ b/src/test/java/net/siegeln/cameleer/saas/license/LicenseControllerTest.java @@ -35,7 +35,7 @@ class LicenseControllerTest { private String createTenantAndGetId() throws Exception { String slug = "license-tenant-" + System.nanoTime(); - var request = new CreateTenantRequest("License Test Org", slug, "MID", null, null); + var request = new CreateTenantRequest("License Test Org", slug, "TEAM", null, null); var result = mockMvc.perform(post("/api/tenants") .with(jwt().jwt(j -> j @@ -60,8 +60,7 @@ class LicenseControllerTest { new SimpleGrantedAuthority("SCOPE_platform:admin")))) .andExpect(status().isCreated()) .andExpect(jsonPath("$.token").isNotEmpty()) - .andExpect(jsonPath("$.tier").value("MID")) - .andExpect(jsonPath("$.features.correlation").value(true)); + .andExpect(jsonPath("$.tier").value("TEAM")); } @Test @@ -78,7 +77,7 @@ class LicenseControllerTest { .with(jwt().jwt(j -> j.claim("sub", "test-user")) .authorities(new SimpleGrantedAuthority("SCOPE_platform:admin")))) .andExpect(status().isOk()) - .andExpect(jsonPath("$.tier").value("MID")); + .andExpect(jsonPath("$.tier").value("TEAM")); } @Test diff --git a/src/test/java/net/siegeln/cameleer/saas/license/LicenseServiceTest.java b/src/test/java/net/siegeln/cameleer/saas/license/LicenseServiceTest.java index 7e27b8e..f825dae 100644 --- a/src/test/java/net/siegeln/cameleer/saas/license/LicenseServiceTest.java +++ b/src/test/java/net/siegeln/cameleer/saas/license/LicenseServiceTest.java @@ -12,8 +12,10 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import java.security.KeyPair; +import java.security.KeyPairGenerator; import java.time.Duration; -import java.util.Optional; +import java.util.Base64; import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; @@ -30,11 +32,26 @@ class LicenseServiceTest { @Mock private AuditService auditService; + @Mock + private SigningKeyService signingKeyService; + private LicenseService licenseService; + private KeyPair testKeyPair; + @BeforeEach - void setUp() { - licenseService = new LicenseService(licenseRepository, auditService); + void setUp() throws Exception { + licenseService = new LicenseService(licenseRepository, auditService, signingKeyService); + testKeyPair = KeyPairGenerator.getInstance("Ed25519").generateKeyPair(); + } + + private void stubPrivateKey() { + when(signingKeyService.getPrivateKey()).thenReturn(testKeyPair.getPrivate()); + } + + private void stubPublicKey() { + when(signingKeyService.getPublicKeyBase64()).thenReturn( + Base64.getEncoder().encodeToString(testKeyPair.getPublic().getEncoded())); } private TenantEntity createTenant(Tier tier) { @@ -65,69 +82,71 @@ class LicenseServiceTest { } @Test - void generateLicense_producesUuidToken() { - var tenant = createTenant(Tier.MID); + void generateLicense_producesSignedToken() { + var tenant = createTenant(Tier.TEAM); + stubPrivateKey(); when(licenseRepository.save(any(LicenseEntity.class))).thenAnswer(inv -> withGeneratedId(inv.getArgument(0))); var license = licenseService.generateLicense(tenant, Duration.ofDays(365), UUID.randomUUID()); assertThat(license.getToken()).isNotBlank(); - // Token must be a valid UUID string - assertThat(UUID.fromString(license.getToken())).isNotNull(); - assertThat(license.getTier()).isEqualTo("MID"); - } - - @Test - void generateLicense_setsCorrectFeaturesForTier() { - var tenant = createTenant(Tier.HIGH); - when(licenseRepository.save(any(LicenseEntity.class))).thenAnswer(inv -> withGeneratedId(inv.getArgument(0))); - - var license = licenseService.generateLicense(tenant, Duration.ofDays(30), UUID.randomUUID()); - - assertThat(license.getFeatures()).containsEntry("debugger", true); - assertThat(license.getFeatures()).containsEntry("replay", true); + // Ed25519 signed token contains a '.' separator between payload and signature + assertThat(license.getToken()).contains("."); + assertThat(license.getTier()).isEqualTo("TEAM"); } @Test void generateLicense_setsCorrectLimitsForTier() { - var tenant = createTenant(Tier.LOW); + var tenant = createTenant(Tier.STARTER); + stubPrivateKey(); when(licenseRepository.save(any(LicenseEntity.class))).thenAnswer(inv -> withGeneratedId(inv.getArgument(0))); var license = licenseService.generateLicense(tenant, Duration.ofDays(30), UUID.randomUUID()); - assertThat(license.getLimits()).containsEntry("max_agents", 3); - assertThat(license.getLimits()).containsEntry("retention_days", 7); + assertThat(license.getLimits()).containsEntry("max_agents", 20); + assertThat(license.getLimits()).containsEntry("max_environments", 2); + assertThat(license.getLimits()).containsEntry("max_execution_retention_days", 7); } @Test - void verifyLicenseToken_validTokenReturnsPayload() { - var tenant = createTenant(Tier.MID); + void generateLicense_setsGracePeriodAndLabel() { + var tenant = createTenant(Tier.BUSINESS); + stubPrivateKey(); + when(licenseRepository.save(any(LicenseEntity.class))).thenAnswer(inv -> withGeneratedId(inv.getArgument(0))); + + var license = licenseService.generateLicense(tenant, Duration.ofDays(365), UUID.randomUUID()); + + assertThat(license.getGracePeriodDays()).isEqualTo(LicenseDefaults.DEFAULT_GRACE_PERIOD_DAYS); + assertThat(license.getLabel()).contains("Test Tenant"); + } + + @Test + void verifyToken_validTokenReturnsLicenseInfo() { + var tenant = createTenant(Tier.TEAM); + stubPrivateKey(); + stubPublicKey(); when(licenseRepository.save(any(LicenseEntity.class))).thenAnswer(inv -> withGeneratedId(inv.getArgument(0))); var license = licenseService.generateLicense(tenant, Duration.ofDays(30), UUID.randomUUID()); - when(licenseRepository.findByToken(license.getToken())).thenReturn(Optional.of(license)); + var result = licenseService.verifyToken(license.getToken(), "test"); - var payload = licenseService.verifyLicenseToken(license.getToken()); - - assertThat(payload).isPresent(); - assertThat(payload.get().get("tier")).isEqualTo("MID"); - assertThat(payload.get().get("tenant_id")).isEqualTo(tenant.getId().toString()); + assertThat(result).isPresent(); + assertThat(result.get().tenantId()).isEqualTo("test"); } @Test - void verifyLicenseToken_unknownTokenReturnsEmpty() { - when(licenseRepository.findByToken(any())).thenReturn(Optional.empty()); - - var payload = licenseService.verifyLicenseToken("unknown-token"); - - assertThat(payload).isEmpty(); + void verifyToken_invalidTokenReturnsEmpty() { + stubPublicKey(); + var result = licenseService.verifyToken("invalid-token", "test"); + assertThat(result).isEmpty(); } @Test void generateLicense_logsAuditEvent() { - var tenant = createTenant(Tier.LOW); + var tenant = createTenant(Tier.STARTER); var actorId = UUID.randomUUID(); + stubPrivateKey(); when(licenseRepository.save(any(LicenseEntity.class))).thenAnswer(inv -> withGeneratedId(inv.getArgument(0))); licenseService.generateLicense(tenant, Duration.ofDays(30), actorId); diff --git a/src/test/java/net/siegeln/cameleer/saas/portal/TenantPortalControllerTest.java b/src/test/java/net/siegeln/cameleer/saas/portal/TenantPortalControllerTest.java index debc81b..0f375a4 100644 --- a/src/test/java/net/siegeln/cameleer/saas/portal/TenantPortalControllerTest.java +++ b/src/test/java/net/siegeln/cameleer/saas/portal/TenantPortalControllerTest.java @@ -52,7 +52,7 @@ class TenantPortalControllerTest { var tenant = new TenantEntity(); tenant.setName(name); tenant.setSlug(slug); - tenant.setTier(Tier.LOW); + tenant.setTier(Tier.STARTER); tenant.setStatus(TenantStatus.ACTIVE); tenant.setLogtoOrgId(orgId); return tenantRepository.save(tenant); diff --git a/src/test/java/net/siegeln/cameleer/saas/portal/TenantPortalServiceTest.java b/src/test/java/net/siegeln/cameleer/saas/portal/TenantPortalServiceTest.java index 537a0ae..fe28843 100644 --- a/src/test/java/net/siegeln/cameleer/saas/portal/TenantPortalServiceTest.java +++ b/src/test/java/net/siegeln/cameleer/saas/portal/TenantPortalServiceTest.java @@ -85,8 +85,8 @@ class TenantPortalServiceTest { license.setToken("test-token-" + UUID.randomUUID()); license.setIssuedAt(Instant.now()); license.setExpiresAt(expiresAt); - license.setFeatures(Map.of("feature1", true)); - license.setLimits(Map.of("maxApps", 10)); + license.setLimits(Map.of("max_apps", 10)); + license.setGracePeriodDays(14); var f = LicenseEntity.class.getDeclaredField("id"); f.setAccessible(true); f.set(license, UUID.randomUUID()); @@ -97,10 +97,10 @@ class TenantPortalServiceTest { @Test void getDashboard_returnsDashboardData() throws Exception { - var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW, TenantStatus.ACTIVE); + var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER, TenantStatus.ACTIVE); tenant.setServerEndpoint("http://server:8080"); var expiresAt = Instant.now().plus(Duration.ofDays(30)); - var license = licenseWithId(tenantId, "LOW", expiresAt); + var license = licenseWithId(tenantId, "STARTER", expiresAt); when(tenantService.getById(tenantId)).thenReturn(Optional.of(tenant)); when(serverApiClient.getHealth("http://server:8080")).thenReturn(new ServerHealthResponse(true, "UP")); @@ -112,22 +112,21 @@ class TenantPortalServiceTest { assertThat(result.name()).isEqualTo("Acme Corp"); assertThat(result.slug()).isEqualTo("acme-corp"); - assertThat(result.tier()).isEqualTo("LOW"); + assertThat(result.tier()).isEqualTo("STARTER"); assertThat(result.status()).isEqualTo("ACTIVE"); assertThat(result.serverHealthy()).isTrue(); assertThat(result.serverStatus()).isEqualTo("UP"); assertThat(result.serverEndpoint()).isEqualTo("http://server:8080"); - assertThat(result.licenseTier()).isEqualTo("LOW"); + assertThat(result.licenseTier()).isEqualTo("STARTER"); assertThat(result.licenseDaysRemaining()).isGreaterThanOrEqualTo(29); assertThat(result.limits()).isNotEmpty(); - assertThat(result.features()).isNotEmpty(); assertThat(result.agentCount()).isEqualTo(3); assertThat(result.environmentCount()).isEqualTo(1); } @Test void getDashboard_handlesNoServer() throws Exception { - var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW, TenantStatus.PROVISIONING); + var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER, TenantStatus.PROVISIONING); // serverEndpoint is null by default when(tenantService.getById(tenantId)).thenReturn(Optional.of(tenant)); @@ -148,9 +147,9 @@ class TenantPortalServiceTest { @Test void getLicense_returnsLicenseData() throws Exception { - var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW, TenantStatus.ACTIVE); + var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER, TenantStatus.ACTIVE); var expiresAt = Instant.now().plus(Duration.ofDays(60)); - var license = licenseWithId(tenantId, "LOW", expiresAt); + var license = licenseWithId(tenantId, "STARTER", expiresAt); when(tenantService.getById(tenantId)).thenReturn(Optional.of(tenant)); when(licenseService.getActiveLicense(tenantId)).thenReturn(Optional.of(license)); @@ -159,18 +158,18 @@ class TenantPortalServiceTest { assertThat(result).isNotNull(); assertThat(result.id()).isEqualTo(license.getId()); - assertThat(result.tier()).isEqualTo("LOW"); + assertThat(result.tier()).isEqualTo("STARTER"); assertThat(result.token()).isEqualTo(license.getToken()); assertThat(result.issuedAt()).isEqualTo(license.getIssuedAt()); assertThat(result.expiresAt()).isEqualTo(expiresAt); assertThat(result.daysRemaining()).isGreaterThanOrEqualTo(59); - assertThat(result.features()).isEqualTo(Map.of("feature1", true)); - assertThat(result.limits()).isEqualTo(Map.of("maxApps", 10)); + assertThat(result.limits()).isEqualTo(Map.of("max_apps", 10)); + assertThat(result.gracePeriodDays()).isEqualTo(14); } @Test void getLicense_returnsNullWhenNoLicense() throws Exception { - var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW, TenantStatus.ACTIVE); + var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER, TenantStatus.ACTIVE); when(tenantService.getById(tenantId)).thenReturn(Optional.of(tenant)); when(licenseService.getActiveLicense(tenantId)).thenReturn(Optional.empty()); @@ -184,7 +183,7 @@ class TenantPortalServiceTest { @Test void getSettings_returnsSettingsData() throws Exception { - var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.MID, TenantStatus.ACTIVE); + var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.TEAM, TenantStatus.ACTIVE); tenant.setServerEndpoint("http://server:8080"); when(tenantService.getById(tenantId)).thenReturn(Optional.of(tenant)); @@ -193,7 +192,7 @@ class TenantPortalServiceTest { assertThat(result.name()).isEqualTo("Acme Corp"); assertThat(result.slug()).isEqualTo("acme-corp"); - assertThat(result.tier()).isEqualTo("MID"); + assertThat(result.tier()).isEqualTo("TEAM"); assertThat(result.status()).isEqualTo("ACTIVE"); assertThat(result.serverEndpoint()).isEqualTo("https://test.example.com/t/acme-corp/"); assertThat(result.createdAt()).isNull(); // no @PrePersist called in test, createdAt is null diff --git a/src/test/java/net/siegeln/cameleer/saas/tenant/TenantControllerTest.java b/src/test/java/net/siegeln/cameleer/saas/tenant/TenantControllerTest.java index a624cf6..865fc16 100644 --- a/src/test/java/net/siegeln/cameleer/saas/tenant/TenantControllerTest.java +++ b/src/test/java/net/siegeln/cameleer/saas/tenant/TenantControllerTest.java @@ -35,7 +35,7 @@ class TenantControllerTest { @Test void createTenant_returns201() throws Exception { - var request = new CreateTenantRequest("Test Org", "test-org-" + System.nanoTime(), "LOW", null, null); + var request = new CreateTenantRequest("Test Org", "test-org-" + System.nanoTime(), "STARTER", null, null); mockMvc.perform(post("/api/tenants") .with(jwt().jwt(j -> j @@ -47,7 +47,7 @@ class TenantControllerTest { .content(objectMapper.writeValueAsString(request))) .andExpect(status().isCreated()) .andExpect(jsonPath("$.name").value("Test Org")) - .andExpect(jsonPath("$.tier").value("LOW")) + .andExpect(jsonPath("$.tier").value("STARTER")) .andExpect(jsonPath("$.status").value("PROVISIONING")); } diff --git a/src/test/java/net/siegeln/cameleer/saas/tenant/TenantServiceTest.java b/src/test/java/net/siegeln/cameleer/saas/tenant/TenantServiceTest.java index c71de55..a6301d0 100644 --- a/src/test/java/net/siegeln/cameleer/saas/tenant/TenantServiceTest.java +++ b/src/test/java/net/siegeln/cameleer/saas/tenant/TenantServiceTest.java @@ -41,7 +41,7 @@ class TenantServiceTest { @Test void create_savesNewTenantWithCorrectFields() { - var request = new CreateTenantRequest("Acme Corp", "acme-corp", "MID", null, null); + var request = new CreateTenantRequest("Acme Corp", "acme-corp", "TEAM", null, null); var actorId = UUID.randomUUID(); when(tenantRepository.existsBySlugAndStatusNot("acme-corp", TenantStatus.DELETED)).thenReturn(false); @@ -51,7 +51,7 @@ class TenantServiceTest { assertThat(result.getName()).isEqualTo("Acme Corp"); assertThat(result.getSlug()).isEqualTo("acme-corp"); - assertThat(result.getTier()).isEqualTo(Tier.MID); + assertThat(result.getTier()).isEqualTo(Tier.TEAM); assertThat(result.getStatus()).isEqualTo(TenantStatus.PROVISIONING); } @@ -82,7 +82,7 @@ class TenantServiceTest { } @Test - void create_defaultsToLowTier() { + void create_defaultsToStarterTier() { var request = new CreateTenantRequest("Acme Corp", "acme-corp", null, null, null); when(tenantRepository.existsBySlugAndStatusNot("acme-corp", TenantStatus.DELETED)).thenReturn(false); @@ -90,7 +90,7 @@ class TenantServiceTest { var result = tenantService.create(request, UUID.randomUUID()); - assertThat(result.getTier()).isEqualTo(Tier.LOW); + assertThat(result.getTier()).isEqualTo(Tier.STARTER); } @Test diff --git a/src/test/java/net/siegeln/cameleer/saas/vendor/VendorTenantControllerTest.java b/src/test/java/net/siegeln/cameleer/saas/vendor/VendorTenantControllerTest.java index 21644a5..1fc0528 100644 --- a/src/test/java/net/siegeln/cameleer/saas/vendor/VendorTenantControllerTest.java +++ b/src/test/java/net/siegeln/cameleer/saas/vendor/VendorTenantControllerTest.java @@ -51,7 +51,7 @@ class VendorTenantControllerTest { @Test void listTenants_returnsAllTenants() throws Exception { String slug = "list-test-" + System.nanoTime(); - createTenant("List Test Org", slug, "LOW"); + createTenant("List Test Org", slug, "STARTER"); mockMvc.perform(get("/api/vendor/tenants") .with(jwt().jwt(j -> j @@ -65,7 +65,7 @@ class VendorTenantControllerTest { @Test void createTenant_returns201() throws Exception { String slug = "create-test-" + System.nanoTime(); - var request = new CreateTenantRequest("Create Test Org", slug, "MID", null, null); + var request = new CreateTenantRequest("Create Test Org", slug, "TEAM", null, null); mockMvc.perform(post("/api/vendor/tenants") .with(jwt().jwt(j -> j @@ -78,16 +78,16 @@ class VendorTenantControllerTest { .andExpect(status().isCreated()) .andExpect(jsonPath("$.name").value("Create Test Org")) .andExpect(jsonPath("$.slug").value(slug)) - .andExpect(jsonPath("$.tier").value("MID")) + .andExpect(jsonPath("$.tier").value("TEAM")) .andExpect(jsonPath("$.id").isNotEmpty()); } @Test void createTenant_returns409ForDuplicateSlug() throws Exception { String slug = "duplicate-vendor-" + System.nanoTime(); - createTenant("First Org", slug, "LOW"); + createTenant("First Org", slug, "STARTER"); - var request = new CreateTenantRequest("Second Org", slug, "LOW", null, null); + var request = new CreateTenantRequest("Second Org", slug, "STARTER", null, null); mockMvc.perform(post("/api/vendor/tenants") .with(jwt().jwt(j -> j .claim("sub", "test-user") @@ -102,7 +102,7 @@ class VendorTenantControllerTest { @Test void getTenantDetail_returnsDetailWithServerStatus() throws Exception { String slug = "detail-test-" + System.nanoTime(); - String id = createTenant("Detail Test Org", slug, "LOW"); + String id = createTenant("Detail Test Org", slug, "STARTER"); mockMvc.perform(get("/api/vendor/tenants/" + id) .with(jwt().jwt(j -> j @@ -118,7 +118,7 @@ class VendorTenantControllerTest { @Test void suspendTenant_returnsUpdatedStatus() throws Exception { String slug = "suspend-test-" + System.nanoTime(); - String id = createTenant("Suspend Test Org", slug, "LOW"); + String id = createTenant("Suspend Test Org", slug, "STARTER"); mockMvc.perform(post("/api/vendor/tenants/" + id + "/suspend") .with(jwt().jwt(j -> j @@ -132,7 +132,7 @@ class VendorTenantControllerTest { @Test void deleteTenant_returns204() throws Exception { String slug = "delete-test-" + System.nanoTime(); - String id = createTenant("Delete Test Org", slug, "LOW"); + String id = createTenant("Delete Test Org", slug, "STARTER"); mockMvc.perform(delete("/api/vendor/tenants/" + id) .with(jwt().jwt(j -> j @@ -144,7 +144,7 @@ class VendorTenantControllerTest { @Test void createTenant_returns401WithoutAuth() throws Exception { - var request = new CreateTenantRequest("No Auth Org", "no-auth-vendor-" + System.nanoTime(), "LOW", null, null); + var request = new CreateTenantRequest("No Auth Org", "no-auth-vendor-" + System.nanoTime(), "STARTER", null, null); mockMvc.perform(post("/api/vendor/tenants") .contentType(MediaType.APPLICATION_JSON) diff --git a/src/test/java/net/siegeln/cameleer/saas/vendor/VendorTenantServiceTest.java b/src/test/java/net/siegeln/cameleer/saas/vendor/VendorTenantServiceTest.java index 8ef2c1f..c8f30ba 100644 --- a/src/test/java/net/siegeln/cameleer/saas/vendor/VendorTenantServiceTest.java +++ b/src/test/java/net/siegeln/cameleer/saas/vendor/VendorTenantServiceTest.java @@ -9,6 +9,7 @@ import net.siegeln.cameleer.saas.provisioning.TenantDataCleanupService; import net.siegeln.cameleer.saas.provisioning.TenantDatabaseService; import net.siegeln.cameleer.saas.license.LicenseEntity; import net.siegeln.cameleer.saas.license.LicenseService; +import net.siegeln.cameleer.saas.license.SigningKeyService; import net.siegeln.cameleer.saas.provisioning.ProvisionResult; import net.siegeln.cameleer.saas.provisioning.TenantProvisioner; import net.siegeln.cameleer.saas.tenant.TenantEntity; @@ -52,6 +53,9 @@ class VendorTenantServiceTest { @Mock private LicenseService licenseService; + @Mock + private SigningKeyService signingKeyService; + @Mock private TenantProvisioner tenantProvisioner; @@ -85,11 +89,11 @@ class VendorTenantServiceTest { // Pass null for self-proxy initially, then re-create with the instance itself // (in production, Spring's @Lazy proxy handles this circular ref) vendorTenantService = new VendorTenantService( - tenantService, tenantRepository, licenseService, + tenantService, tenantRepository, licenseService, signingKeyService, tenantProvisioner, serverApiClient, logtoClient, logtoConfig, auditService, provisioningProps, dataCleanupService, tenantDatabaseService, null); vendorTenantService = new VendorTenantService( - tenantService, tenantRepository, licenseService, + tenantService, tenantRepository, licenseService, signingKeyService, tenantProvisioner, serverApiClient, logtoClient, logtoConfig, auditService, provisioningProps, dataCleanupService, tenantDatabaseService, vendorTenantService); @@ -133,7 +137,7 @@ class VendorTenantServiceTest { private LicenseEntity licenseWithId(UUID tenantId) throws Exception { var license = new LicenseEntity(); license.setTenantId(tenantId); - license.setTier("LOW"); + license.setTier("STARTER"); license.setToken("test-token-" + UUID.randomUUID()); license.setIssuedAt(Instant.now()); license.setExpiresAt(Instant.now().plus(Duration.ofDays(365))); @@ -147,9 +151,9 @@ class VendorTenantServiceTest { @Test void createAndProvision_createsTenantAndLicense() throws Exception { - var request = new CreateTenantRequest("Acme Corp", "acme-corp", "LOW", null, null); + var request = new CreateTenantRequest("Acme Corp", "acme-corp", "STARTER", null, null); var actorId = UUID.randomUUID(); - var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW); + var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER); var license = licenseWithId(tenant.getId()); when(tenantService.create(request, actorId)).thenReturn(tenant); @@ -167,9 +171,9 @@ class VendorTenantServiceTest { @Test void createAndProvision_setsActiveWhenProvisionerSucceeds() throws Exception { - var request = new CreateTenantRequest("Acme Corp", "acme-corp", "LOW", null, null); + var request = new CreateTenantRequest("Acme Corp", "acme-corp", "STARTER", null, null); var actorId = UUID.randomUUID(); - var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW); + var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER); var license = licenseWithId(tenant.getId()); when(tenantService.create(request, actorId)).thenReturn(tenant); @@ -191,9 +195,9 @@ class VendorTenantServiceTest { @Test void createAndProvision_setsProvisionErrorOnFailure() throws Exception { - var request = new CreateTenantRequest("Acme Corp", "acme-corp", "LOW", null, null); + var request = new CreateTenantRequest("Acme Corp", "acme-corp", "STARTER", null, null); var actorId = UUID.randomUUID(); - var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW); + var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER); var license = licenseWithId(tenant.getId()); when(tenantService.create(request, actorId)).thenReturn(tenant); @@ -214,9 +218,9 @@ class VendorTenantServiceTest { @Test void createAndProvision_worksWithoutProvisioner() throws Exception { - var request = new CreateTenantRequest("Acme Corp", "acme-corp", "LOW", null, null); + var request = new CreateTenantRequest("Acme Corp", "acme-corp", "STARTER", null, null); var actorId = UUID.randomUUID(); - var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW); + var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER); var license = licenseWithId(tenant.getId()); when(tenantService.create(request, actorId)).thenReturn(tenant); @@ -236,8 +240,8 @@ class VendorTenantServiceTest { void suspend_stopsContainersAndSetsStatus() throws Exception { var tenantId = UUID.randomUUID(); var actorId = UUID.randomUUID(); - var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW); - var suspended = tenantWithId("Acme Corp", "acme-corp", Tier.LOW); + var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER); + var suspended = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER); suspended.setStatus(TenantStatus.SUSPENDED); when(tenantService.getById(tenantId)).thenReturn(Optional.of(tenant)); @@ -255,8 +259,8 @@ class VendorTenantServiceTest { void suspend_skipsStopWhenProvisionerUnavailable() throws Exception { var tenantId = UUID.randomUUID(); var actorId = UUID.randomUUID(); - var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW); - var suspended = tenantWithId("Acme Corp", "acme-corp", Tier.LOW); + var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER); + var suspended = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER); suspended.setStatus(TenantStatus.SUSPENDED); when(tenantService.getById(tenantId)).thenReturn(Optional.of(tenant)); @@ -273,7 +277,7 @@ class VendorTenantServiceTest { void delete_removesContainersRevokesLicenseDeletesOrg() throws Exception { var tenantId = UUID.randomUUID(); var actorId = UUID.randomUUID(); - var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW); + var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER); tenant.setLogtoOrgId("org-123"); when(tenantService.getById(tenantId)).thenReturn(Optional.of(tenant)); @@ -294,17 +298,20 @@ class VendorTenantServiceTest { void renewLicense_revokesOldAndGeneratesNew() throws Exception { var tenantId = UUID.randomUUID(); var actorId = UUID.randomUUID(); - var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW); + var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER); tenant.setServerEndpoint("http://server:8080"); var newLicense = licenseWithId(tenantId); when(tenantService.getById(tenantId)).thenReturn(Optional.of(tenant)); - when(licenseService.generateLicense(eq(tenant), any(Duration.class), eq(actorId))).thenReturn(newLicense); + // mintLicense() calls the full generateLicense overload (limits, expiresAt, grace, label, actor) + when(licenseService.generateLicense(eq(tenant), any(java.util.Map.class), any(Instant.class), + any(Integer.class), any(String.class), eq(actorId))).thenReturn(newLicense); var result = vendorTenantService.renewLicense(tenantId, actorId); verify(licenseService).revokeLicense(tenantId, actorId); - verify(licenseService).generateLicense(eq(tenant), any(Duration.class), eq(actorId)); + verify(licenseService).generateLicense(eq(tenant), any(java.util.Map.class), any(Instant.class), + any(Integer.class), any(String.class), eq(actorId)); verify(serverApiClient).pushLicense("http://server:8080", newLicense.getToken()); assertThat(result).isSameAs(newLicense); }