diff --git a/messages/en-US.json b/messages/en-US.json index 37d1390e6..f7f4c05f6 100644 --- a/messages/en-US.json +++ b/messages/en-US.json @@ -576,10 +576,10 @@ "licenseQuestionRemove": "Are you sure you want to delete the license key ?", "licenseKeyDelete": "Delete License Key", "licenseKeyDeleteConfirm": "Confirm Delete License Key", - "licenseTitle": "Manage License Status", + "licenseTitle": "Manage Licenses", "licenseTitleDescription": "View and manage license keys in the system", - "licenseHost": "Host License", - "licenseHostDescription": "Manage the main license key for the host.", + "licenseHost": "License", + "licenseHostDescription": "See the license tier and host information", "licensedNot": "Not Licensed", "hostId": "Host ID", "licenseReckeckAll": "Recheck All Keys", @@ -589,15 +589,16 @@ "licensePurchase": "Purchase License", "licensePurchaseSites": "Purchase Additional Sites", "licenseSitesUsedMax": "{usedSites} of {maxSites} sites used", - "licenseSitesUsed": "{count, plural, =0 {# sites} one {# site} other {# sites}} in system.", - "licenseUsage": "License Usage", - "licenseUsageDescription": "View the number of users and sites licensed for this host.", + "licenseSitesUsed": "{count, plural, =0 {# sites} one {# site} other {# sites}}", + "licenseUsage": "Usage", + "licenseUsageDescription": "View the number of users and sites licensed for this host", "licenseUsageSites": "Sites", "licenseUsageUsers": "Users", - "licenseNoUserLimit": "There is no limit on the number of users using an unlicensed host.", + "licenseNoUserLimit": "There is no limit on the number of users using an unlicensed hot", "licenseUsersUsedMax": "{usedUsers} of {maxUsers} users used", - "licenseUsersUsed": "{count, plural, =0 {# users} one {# user} other {# users}} in system.", + "licenseUsersUsed": "{count, plural, =0 {# users} one {# user} other {# users}}", "licenseUnlimited": "Unlimited", + "licenseTierLabel": "Tier", "licensePurchaseDescription": "Choose how many sites you want to {selectedMode, select, license {purchase a license for. You can always add more sites later.} other {add to your existing license.}}", "licenseFee": "License fee", "licensePriceSite": "Price per site", diff --git a/server/private/license/license.ts b/server/private/license/license.ts index 0ff77bc4f..25eac8bc5 100644 --- a/server/private/license/license.ts +++ b/server/private/license/license.ts @@ -297,6 +297,11 @@ LQIDAQAB if (!apiResponse?.success) { throw new Error(apiResponse?.error); } + + logger.debug( + `License server response: ${JSON.stringify(apiResponse)}` + ); + // Reset failure count on success this.phoneHomeFailureCount = 0; } catch (e) { @@ -359,6 +364,11 @@ LQIDAQAB licenseKeyRes, this.publicKey ); + + logger.debug( + `Decoded license key ${key.licenseKey}: ${JSON.stringify(payload)}` + ); + cached.valid = payload.valid; cached.type = payload.type; cached.tier = payload.tier; @@ -451,6 +461,8 @@ LQIDAQAB this.checkInProgress = false; } + logger.debug(`Computed license status: ${JSON.stringify(status)}`); + this.statusCache.set(this.statusKey, status, 0); return status; } diff --git a/src/app/admin/license/page.tsx b/src/app/admin/license/page.tsx index 33cf86d96..8ed2d697d 100644 --- a/src/app/admin/license/page.tsx +++ b/src/app/admin/license/page.tsx @@ -1,7 +1,7 @@ "use client"; import { useState, useEffect } from "react"; -import { LicenseKeyCache } from "@server/license/license"; +import { LicenseKeyCache, LicenseKeyTier } from "@server/license/license"; import { createApiClient } from "@app/lib/api"; import { useEnvContext } from "@app/hooks/useEnvContext"; import { toast } from "@app/hooks/useToast"; @@ -65,6 +65,23 @@ const ENTERPRISE_DOCS_URL = "https://docs.pangolin.net/self-host/enterprise-edition"; const ENTERPRISE_PRICING_URL = "https://pangolin.net/pricing#Self-Hosted"; +function getTierLabel( + tier: LicenseKeyTier | undefined, + t: (key: string) => string +): string { + switch (tier) { + case "enterprise": + return t("licenseTierEnterprise"); + case "tier1": + return t("licenseTierTier1"); + case "tier2": + return t("licenseTierTier2"); + case "personal": + default: + return t("licenseTierPersonal"); + } +} + export default function LicensePage() { const api = createApiClient(useEnvContext()); const [rows, setRows] = useState([]); @@ -514,6 +531,14 @@ export default function LicensePage() { )} +
+
+ {t("licenseTierLabel")} +
+
+ {getTierLabel(licenseStatus?.tier, t)} +
+
{licenseStatus?.hostId && (