Skip to content

Commit d1c36c4

Browse files
committed
feat: implement correct license statuses (#13894)
1 parent 0665001 commit d1c36c4

File tree

2 files changed

+94
-4
lines changed

2 files changed

+94
-4
lines changed

airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/InstanceConfigurationHandler.java

+24-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
package io.airbyte.commons.server.handlers;
66

7+
import com.google.common.annotations.VisibleForTesting;
78
import io.airbyte.api.model.generated.AuthConfiguration;
89
import io.airbyte.api.model.generated.AuthConfiguration.ModeEnum;
910
import io.airbyte.api.model.generated.InstanceConfigurationResponse;
@@ -34,6 +35,7 @@
3435
import jakarta.inject.Named;
3536
import jakarta.inject.Singleton;
3637
import java.io.IOException;
38+
import java.time.Clock;
3739
import java.util.Optional;
3840
import java.util.Set;
3941
import java.util.UUID;
@@ -62,6 +64,7 @@ public class InstanceConfigurationHandler {
6264
private final String trackingStrategy;
6365
private final AuthConfigs authConfigs;
6466
private final PermissionService permissionService;
67+
private final Clock clock;
6568

6669
public InstanceConfigurationHandler(@Named("airbyteUrl") final Optional<String> airbyteUrl,
6770
@Value("${airbyte.tracking.strategy:}") final String trackingStrategy,
@@ -73,7 +76,8 @@ public InstanceConfigurationHandler(@Named("airbyteUrl") final Optional<String>
7376
final UserPersistence userPersistence,
7477
final OrganizationPersistence organizationPersistence,
7578
final AuthConfigs authConfigs,
76-
final PermissionService permissionService) {
79+
final PermissionService permissionService,
80+
final Optional<Clock> clock) {
7781
this.airbyteUrl = airbyteUrl;
7882
this.trackingStrategy = trackingStrategy;
7983
this.airbyteEdition = airbyteEdition;
@@ -85,6 +89,7 @@ public InstanceConfigurationHandler(@Named("airbyteUrl") final Optional<String>
8589
this.organizationPersistence = organizationPersistence;
8690
this.authConfigs = authConfigs;
8791
this.permissionService = permissionService;
92+
this.clock = clock.orElse(Clock.systemUTC());
8893
}
8994

9095
public InstanceConfigurationResponse getInstanceConfiguration() throws IOException {
@@ -212,7 +217,7 @@ public LicenseInfoResponse licenseInfo() {
212217
.usedNodes(0)
213218
.maxEditors(license.maxEditors().orElse(null))
214219
.maxNodes(license.maxNodes().orElse(null))
215-
.licenseStatus(LicenseStatus.PRO);
220+
.licenseStatus(getLicenseStatus());
216221
}
217222
return null;
218223
}
@@ -235,4 +240,21 @@ private Integer editorsUsage() {
235240
return editors.size();
236241
}
237242

243+
@VisibleForTesting
244+
LicenseStatus currentLicenseStatus() {
245+
if (activeAirbyteLicense.isEmpty()
246+
|| activeAirbyteLicense.get().getLicense().isEmpty()
247+
|| activeAirbyteLicense.get().getLicense().get().type() == AirbyteLicense.LicenseType.INVALID) {
248+
return LicenseStatus.INVALID;
249+
}
250+
final AirbyteLicense actualLicense = activeAirbyteLicense.get().getLicense().get();
251+
if (actualLicense.expirationDate().map(exp -> exp.toInstant().isBefore(clock.instant())).orElse(false)) {
252+
return LicenseStatus.EXPIRED;
253+
}
254+
if (actualLicense.maxEditors().map(m -> editorsUsage() > m).orElse(false)) {
255+
return LicenseStatus.EXCEEDED;
256+
}
257+
return LicenseStatus.PRO;
258+
}
259+
238260
}

airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/InstanceConfigurationHandlerTest.java

+70-2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import io.airbyte.config.AuthenticatedUser;
2929
import io.airbyte.config.Configs.AirbyteEdition;
3030
import io.airbyte.config.Organization;
31+
import io.airbyte.config.Permission;
3132
import io.airbyte.config.StandardWorkspace;
3233
import io.airbyte.config.persistence.ConfigNotFoundException;
3334
import io.airbyte.config.persistence.OrganizationPersistence;
@@ -36,9 +37,13 @@
3637
import io.airbyte.data.services.PermissionService;
3738
import io.airbyte.validation.json.JsonValidationException;
3839
import java.io.IOException;
40+
import java.time.Clock;
41+
import java.time.Instant;
42+
import java.time.ZoneId;
3943
import java.util.Date;
4044
import java.util.Optional;
4145
import java.util.UUID;
46+
import java.util.stream.Stream;
4247
import org.junit.jupiter.api.BeforeEach;
4348
import org.junit.jupiter.api.Test;
4449
import org.junit.jupiter.api.extension.ExtendWith;
@@ -159,7 +164,8 @@ void testGetInstanceConfigurationTrackingStrategy(final String envValue, final T
159164
mUserPersistence,
160165
mOrganizationPersistence,
161166
mAuthConfigs,
162-
permissionService);
167+
permissionService,
168+
Optional.empty());
163169

164170
final var result = handler.getInstanceConfiguration();
165171

@@ -280,6 +286,67 @@ void testLicenseInfo() {
280286
assertEquals(licenseInfoResponse.getMaxNodes(), MAX_NODES);
281287
}
282288

289+
@Test
290+
void testInvalidLicenseTest() {
291+
final ActiveAirbyteLicense license = new ActiveAirbyteLicense();
292+
license.setLicense(null);
293+
final InstanceConfigurationHandler handler = new InstanceConfigurationHandler(
294+
Optional.of(AIRBYTE_URL),
295+
"logging",
296+
AirbyteEdition.PRO,
297+
new AirbyteVersion("0.50.1"),
298+
Optional.of(license),
299+
mWorkspacePersistence,
300+
mWorkspacesHandler,
301+
mUserPersistence,
302+
mOrganizationPersistence,
303+
mAuthConfigs,
304+
permissionService,
305+
Optional.empty());
306+
assertEquals(handler.currentLicenseStatus(), LicenseStatus.INVALID);
307+
}
308+
309+
@Test
310+
void testExpiredLicenseTest() {
311+
final InstanceConfigurationHandler handler = new InstanceConfigurationHandler(
312+
Optional.of(AIRBYTE_URL),
313+
"logging",
314+
AirbyteEdition.PRO,
315+
new AirbyteVersion("0.50.1"),
316+
Optional.of(activeAirbyteLicense),
317+
mWorkspacePersistence,
318+
mWorkspacesHandler,
319+
mUserPersistence,
320+
mOrganizationPersistence,
321+
mAuthConfigs,
322+
permissionService,
323+
Optional.of(Clock.fixed(Instant.MAX, ZoneId.systemDefault())));
324+
assertEquals(handler.currentLicenseStatus(), LicenseStatus.EXPIRED);
325+
}
326+
327+
@Test
328+
void testExceededEditorsLicenseTest() {
329+
330+
final InstanceConfigurationHandler handler = new InstanceConfigurationHandler(
331+
Optional.of(AIRBYTE_URL),
332+
"logging",
333+
AirbyteEdition.PRO,
334+
new AirbyteVersion("0.50.1"),
335+
Optional.of(activeAirbyteLicense),
336+
mWorkspacePersistence,
337+
mWorkspacesHandler,
338+
mUserPersistence,
339+
mOrganizationPersistence,
340+
mAuthConfigs,
341+
permissionService,
342+
Optional.empty());
343+
when(permissionService.listPermissions()).thenReturn(
344+
Stream.generate(UUID::randomUUID)
345+
.map(userId -> new Permission().withUserId(userId).withPermissionType(Permission.PermissionType.ORGANIZATION_EDITOR))
346+
.limit(MAX_EDITORS + 10).toList());
347+
assertEquals(handler.currentLicenseStatus(), LicenseStatus.EXCEEDED);
348+
}
349+
283350
private void stubGetDefaultUser() throws IOException {
284351
when(mUserPersistence.getDefaultUser()).thenReturn(
285352
Optional.of(new AuthenticatedUser()
@@ -317,7 +384,8 @@ private InstanceConfigurationHandler getInstanceConfigurationHandler(final boole
317384
mUserPersistence,
318385
mOrganizationPersistence,
319386
mAuthConfigs,
320-
permissionService);
387+
permissionService,
388+
Optional.empty());
321389
}
322390

323391
}

0 commit comments

Comments
 (0)