From 4fa45287718fff8e80fc7e840842a6a281cfa195 Mon Sep 17 00:00:00 2001 From: Piyush Gupta Date: Fri, 12 Apr 2024 15:02:07 +0530 Subject: [PATCH] adds enterprise license check --- .../(peopleAndSegments)/segments/layout.tsx | 2 +- .../(peopleAndSegments)/segments/page.tsx | 2 +- .../components/EnvironmentsNavbar.tsx | 2 +- .../settings/enterprise/page.tsx | 2 +- .../settings/language/page.tsx | 2 +- .../[environmentId]/settings/layout.tsx | 2 +- .../EditMemberships/EditMemberships.tsx | 2 +- .../[environmentId]/settings/members/page.tsx | 2 +- .../surveys/[surveyId]/edit/page.tsx | 4 +- apps/web/app/s/[surveyId]/page.tsx | 2 +- packages/ee/lib/service.ts | 55 ++++++++++++++++--- 11 files changed, 58 insertions(+), 19 deletions(-) diff --git a/apps/web/app/(app)/environments/[environmentId]/(peopleAndSegments)/segments/layout.tsx b/apps/web/app/(app)/environments/[environmentId]/(peopleAndSegments)/segments/layout.tsx index bc0c622461..e24da73bb8 100644 --- a/apps/web/app/(app)/environments/[environmentId]/(peopleAndSegments)/segments/layout.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/(peopleAndSegments)/segments/layout.tsx @@ -16,7 +16,7 @@ export default async function PeopleLayout({ params, children }) { throw new Error("Team not found"); } - const isUserTargetingAllowed = getAdvancedTargetingPermission(team); + const isUserTargetingAllowed = await getAdvancedTargetingPermission(team); return ( <> diff --git a/apps/web/app/(app)/environments/[environmentId]/(peopleAndSegments)/segments/page.tsx b/apps/web/app/(app)/environments/[environmentId]/(peopleAndSegments)/segments/page.tsx index 2dc6120c38..cdfca24083 100644 --- a/apps/web/app/(app)/environments/[environmentId]/(peopleAndSegments)/segments/page.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/(peopleAndSegments)/segments/page.tsx @@ -31,7 +31,7 @@ export default async function SegmentsPage({ params }) { throw new Error("Team not found"); } - const isAdvancedTargetingAllowed = getAdvancedTargetingPermission(team); + const isAdvancedTargetingAllowed = await getAdvancedTargetingPermission(team); if (!segments) { throw new Error("Failed to fetch segments"); diff --git a/apps/web/app/(app)/environments/[environmentId]/components/EnvironmentsNavbar.tsx b/apps/web/app/(app)/environments/[environmentId]/components/EnvironmentsNavbar.tsx index 1c4ec18d14..205d17d7d4 100644 --- a/apps/web/app/(app)/environments/[environmentId]/components/EnvironmentsNavbar.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/components/EnvironmentsNavbar.tsx @@ -25,7 +25,7 @@ export default async function EnvironmentsNavbar({ environmentId, session }: Env return ; } - const isMultiLanguageAllowed = getMultiLanguagePermission(team); + const isMultiLanguageAllowed = await getMultiLanguagePermission(team); const [products, environments] = await Promise.all([ getProducts(team.id), diff --git a/apps/web/app/(app)/environments/[environmentId]/settings/enterprise/page.tsx b/apps/web/app/(app)/environments/[environmentId]/settings/enterprise/page.tsx index e937a1fec3..f0a4f68c21 100644 --- a/apps/web/app/(app)/environments/[environmentId]/settings/enterprise/page.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/settings/enterprise/page.tsx @@ -37,7 +37,7 @@ export default async function EnterpriseLicensePage({ params }) { notFound(); } - const isEnterpriseEdition = getIsEnterpriseEdition(); + const isEnterpriseEdition = await getIsEnterpriseEdition(); const paidFeatures = [ { diff --git a/apps/web/app/(app)/environments/[environmentId]/settings/language/page.tsx b/apps/web/app/(app)/environments/[environmentId]/settings/language/page.tsx index 7e00152690..fd437f46a5 100644 --- a/apps/web/app/(app)/environments/[environmentId]/settings/language/page.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/settings/language/page.tsx @@ -20,7 +20,7 @@ export default async function LanguageSettingsPage({ params }: { params: { envir throw new Error("Team not found"); } - const isMultiLanguageAllowed = getMultiLanguagePermission(team); + const isMultiLanguageAllowed = await getMultiLanguagePermission(team); if (!isMultiLanguageAllowed) { notFound(); diff --git a/apps/web/app/(app)/environments/[environmentId]/settings/layout.tsx b/apps/web/app/(app)/environments/[environmentId]/settings/layout.tsx index a959f67a6c..4dcdac2509 100644 --- a/apps/web/app/(app)/environments/[environmentId]/settings/layout.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/settings/layout.tsx @@ -33,7 +33,7 @@ export default async function SettingsLayout({ children, params }) { throw new Error("Unauthenticated"); } - const isMultiLanguageAllowed = getMultiLanguagePermission(team); + const isMultiLanguageAllowed = await getMultiLanguagePermission(team); const currentUserMembership = await getMembershipByUserIdTeamId(session?.user.id, team.id); diff --git a/apps/web/app/(app)/environments/[environmentId]/settings/members/components/EditMemberships/EditMemberships.tsx b/apps/web/app/(app)/environments/[environmentId]/settings/members/components/EditMemberships/EditMemberships.tsx index a00da73cf2..bd1f241c0e 100644 --- a/apps/web/app/(app)/environments/[environmentId]/settings/members/components/EditMemberships/EditMemberships.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/settings/members/components/EditMemberships/EditMemberships.tsx @@ -23,7 +23,7 @@ export async function EditMemberships({ const currentUserRole = membership?.role; const isUserAdminOrOwner = membership?.role === "admin" || membership?.role === "owner"; - const canDoRoleManagement = getRoleManagementPermission(team); + const canDoRoleManagement = await getRoleManagementPermission(team); return (
diff --git a/apps/web/app/(app)/environments/[environmentId]/settings/members/page.tsx b/apps/web/app/(app)/environments/[environmentId]/settings/members/page.tsx index 34aab3f774..9095f8b570 100644 --- a/apps/web/app/(app)/environments/[environmentId]/settings/members/page.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/settings/members/page.tsx @@ -51,7 +51,7 @@ export default async function MembersSettingsPage({ params }: { params: { enviro if (!team) { throw new Error("Team not found"); } - const canDoRoleManagement = getRoleManagementPermission(team); + const canDoRoleManagement = await getRoleManagementPermission(team); const currentUserMembership = await getMembershipByUserIdTeamId(session?.user.id, team.id); const { isOwner, isAdmin } = getAccessFlags(currentUserMembership?.role); diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/page.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/page.tsx index f9c6b041fe..289056b107 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/page.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/page.tsx @@ -59,8 +59,8 @@ export default async function SurveysEditPage({ params }) { const { isViewer } = getAccessFlags(currentUserMembership?.role); const isSurveyCreationDeletionDisabled = isViewer; - const isUserTargetingAllowed = getAdvancedTargetingPermission(team); - const isMultiLanguageAllowed = getMultiLanguagePermission(team); + const isUserTargetingAllowed = await getAdvancedTargetingPermission(team); + const isMultiLanguageAllowed = await getMultiLanguagePermission(team); if ( !survey || diff --git a/apps/web/app/s/[surveyId]/page.tsx b/apps/web/app/s/[surveyId]/page.tsx index 598937cd3d..ab275c1a2b 100644 --- a/apps/web/app/s/[surveyId]/page.tsx +++ b/apps/web/app/s/[surveyId]/page.tsx @@ -62,7 +62,7 @@ export default async function LinkSurveyPage({ params, searchParams }: LinkSurve if (!team) { throw new Error("Team not found"); } - const isMultiLanguageAllowed = getMultiLanguagePermission(team); + const isMultiLanguageAllowed = await getMultiLanguagePermission(team); if (survey && survey.status !== "inProgress") { return ( diff --git a/packages/ee/lib/service.ts b/packages/ee/lib/service.ts index 790419c971..9f110a92ce 100644 --- a/packages/ee/lib/service.ts +++ b/packages/ee/lib/service.ts @@ -3,9 +3,48 @@ import "server-only"; import { ENTERPRISE_LICENSE_KEY, IS_FORMBRICKS_CLOUD } from "@formbricks/lib/constants"; import { TTeam } from "@formbricks/types/teams"; -export const getIsEnterpriseEdition = (): boolean => { - if (ENTERPRISE_LICENSE_KEY) { - return ENTERPRISE_LICENSE_KEY.length > 0; +const licenseDetails: { + isValid: boolean | null; + lastChecked: Date; +} = { + isValid: null, + lastChecked: new Date(0), // Initialize with an old date +}; + +export const getIsEnterpriseEdition = async (): Promise => { + if (ENTERPRISE_LICENSE_KEY && ENTERPRISE_LICENSE_KEY.length > 0) { + const currentTime = new Date(); + const timeSinceLastChecked = currentTime.getTime() - licenseDetails.lastChecked.getTime(); // Difference in milliseconds + + // Check if the lastChecked time is within the last 24 hours + if ( + licenseDetails.isValid !== null && + timeSinceLastChecked < 1000 * 60 * 60 * 24 // 1000ms * 60s * 60min * 24hrs + ) { + return licenseDetails.isValid; + } + + try { + const res = await fetch("https://ee.formbricks.com/api/licenses/check", { + body: JSON.stringify({ licenseKey: ENTERPRISE_LICENSE_KEY }), + headers: { "Content-Type": "application/json" }, + method: "POST", + }); + + let isValid = false; + + if (res.ok) { + const responseJson = await res.json(); + isValid = responseJson.data.status === "active"; + } + + licenseDetails.isValid = isValid; + licenseDetails.lastChecked = new Date(); // Update the last checked time + + return isValid; + } catch (error) { + console.error("Error while checking license", error); + } } return false; }; @@ -22,20 +61,20 @@ export const getRemoveLinkBrandingPermission = (team: TTeam): boolean => { else return false; }; -export const getRoleManagementPermission = (team: TTeam): boolean => { +export const getRoleManagementPermission = async (team: TTeam): Promise => { if (IS_FORMBRICKS_CLOUD) return team.billing.features.inAppSurvey.status !== "inactive"; else if (!IS_FORMBRICKS_CLOUD) return getIsEnterpriseEdition(); else return false; }; -export const getAdvancedTargetingPermission = (team: TTeam): boolean => { +export const getAdvancedTargetingPermission = async (team: TTeam): Promise => { if (IS_FORMBRICKS_CLOUD) return team.billing.features.userTargeting.status !== "inactive"; - else if (!IS_FORMBRICKS_CLOUD) return getIsEnterpriseEdition(); + else if (!IS_FORMBRICKS_CLOUD) return await getIsEnterpriseEdition(); else return false; }; -export const getMultiLanguagePermission = (team: TTeam): boolean => { +export const getMultiLanguagePermission = async (team: TTeam): Promise => { if (IS_FORMBRICKS_CLOUD) return team.billing.features.inAppSurvey.status !== "inactive"; - else if (!IS_FORMBRICKS_CLOUD) return getIsEnterpriseEdition(); + else if (!IS_FORMBRICKS_CLOUD) return await getIsEnterpriseEdition(); else return false; };