feat: add usage data to license and vendor detail endpoints
Add getAppCount() to ServerApiClient, include usage counts (agents, environments, apps, users) in tenant license and vendor detail responses so the frontend can render progress bars against license limits. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -157,6 +157,22 @@ public class ServerApiClient {
|
||||
}
|
||||
}
|
||||
|
||||
/** Fetch app count from a tenant's server. */
|
||||
public int getAppCount(String serverEndpoint) {
|
||||
try {
|
||||
var resp = RestClient.create().get()
|
||||
.uri(serverEndpoint + "/api/v1/admin/apps")
|
||||
.header("Authorization", "Bearer " + getAccessToken())
|
||||
.header("X-Cameleer-Protocol-Version", "1")
|
||||
.retrieve()
|
||||
.body(java.util.List.class);
|
||||
return resp != null ? resp.size() : 0;
|
||||
} catch (Exception e) {
|
||||
log.warn("App count fetch failed for {}: {}", serverEndpoint, e.getMessage());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Reset the built-in admin password on a tenant's server. */
|
||||
public void resetServerAdminPassword(String serverEndpoint, String newPassword) {
|
||||
RestClient.create(serverEndpoint)
|
||||
|
||||
@@ -68,7 +68,8 @@ public class TenantPortalService {
|
||||
public record LicenseData(
|
||||
UUID id, String tier, String label, Map<String, Object> limits,
|
||||
int gracePeriodDays, Instant issuedAt, Instant expiresAt,
|
||||
String token, long daysRemaining
|
||||
String token, long daysRemaining,
|
||||
Map<String, Integer> usage
|
||||
) {}
|
||||
|
||||
public record TenantSettingsData(
|
||||
@@ -140,16 +141,36 @@ public class TenantPortalService {
|
||||
public LicenseData getLicense() {
|
||||
TenantEntity tenant = resolveTenant();
|
||||
return licenseService.getActiveLicense(tenant.getId())
|
||||
.map(lic -> new LicenseData(
|
||||
lic.getId(), lic.getTier(), lic.getLabel(),
|
||||
lic.getLimits() != null ? lic.getLimits() : Map.of(),
|
||||
lic.getGracePeriodDays(),
|
||||
lic.getIssuedAt(), lic.getExpiresAt(),
|
||||
lic.getToken(), daysUntil(lic.getExpiresAt())
|
||||
))
|
||||
.map(lic -> {
|
||||
Map<String, Integer> usage = fetchUsage(tenant);
|
||||
return new LicenseData(
|
||||
lic.getId(), lic.getTier(), lic.getLabel(),
|
||||
lic.getLimits() != null ? lic.getLimits() : Map.of(),
|
||||
lic.getGracePeriodDays(),
|
||||
lic.getIssuedAt(), lic.getExpiresAt(),
|
||||
lic.getToken(), daysUntil(lic.getExpiresAt()),
|
||||
usage
|
||||
);
|
||||
})
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
private Map<String, Integer> fetchUsage(TenantEntity tenant) {
|
||||
Map<String, Integer> usage = new HashMap<>();
|
||||
String endpoint = tenant.getServerEndpoint();
|
||||
if (endpoint != null && !endpoint.isBlank()) {
|
||||
usage.put("agents", serverApiClient.getAgentCount(endpoint));
|
||||
usage.put("environments", serverApiClient.getEnvironmentCount(endpoint));
|
||||
usage.put("apps", serverApiClient.getAppCount(endpoint));
|
||||
}
|
||||
// User count from Logto org membership
|
||||
String orgId = tenant.getLogtoOrgId();
|
||||
if (orgId != null && !orgId.isBlank()) {
|
||||
usage.put("users", logtoClient.listOrganizationMembers(orgId).size());
|
||||
}
|
||||
return usage;
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> listTeamMembers() {
|
||||
TenantEntity tenant = resolveTenant();
|
||||
String orgId = tenant.getLogtoOrgId();
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@RestController
|
||||
@@ -57,7 +58,8 @@ public class VendorTenantController {
|
||||
String serverState,
|
||||
boolean serverHealthy,
|
||||
String serverStatus,
|
||||
LicenseResponse license
|
||||
LicenseResponse license,
|
||||
Map<String, Integer> usage
|
||||
) {}
|
||||
|
||||
// --- Endpoints ---
|
||||
@@ -123,12 +125,23 @@ public class VendorTenantController {
|
||||
.getLicenseForTenant(id)
|
||||
.map(LicenseResponse::from)
|
||||
.orElse(null);
|
||||
|
||||
Map<String, Integer> usage = new java.util.HashMap<>();
|
||||
String endpoint = tenant.getServerEndpoint();
|
||||
if (health.healthy() && endpoint != null && !endpoint.isBlank()) {
|
||||
var serverApi = vendorTenantService.getServerApiClient();
|
||||
usage.put("agents", serverApi.getAgentCount(endpoint));
|
||||
usage.put("environments", serverApi.getEnvironmentCount(endpoint));
|
||||
usage.put("apps", serverApi.getAppCount(endpoint));
|
||||
}
|
||||
|
||||
return ResponseEntity.ok(new VendorTenantDetail(
|
||||
TenantResponse.from(tenant),
|
||||
serverStatus.state().name(),
|
||||
health.healthy(),
|
||||
health.status(),
|
||||
license
|
||||
license,
|
||||
usage
|
||||
));
|
||||
})
|
||||
.orElse(ResponseEntity.notFound().build());
|
||||
|
||||
Reference in New Issue
Block a user