From 6a7b66aaaa0e87522e006545177f8330c1ceb7cd Mon Sep 17 00:00:00 2001 From: Matti Nannt Date: Fri, 15 Dec 2023 15:08:25 +0100 Subject: [PATCH] fix: add response limitations to sync endpoint (#1785) --- .../in-app/sync/[userId]/route.ts | 27 +++++++++++++++---- .../[environmentId]/in-app/sync/route.ts | 24 ++++++++++++++++- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/apps/web/app/api/v1/client/[environmentId]/in-app/sync/[userId]/route.ts b/apps/web/app/api/v1/client/[environmentId]/in-app/sync/[userId]/route.ts index e8fe273a0f..8da3c3a322 100644 --- a/apps/web/app/api/v1/client/[environmentId]/in-app/sync/[userId]/route.ts +++ b/apps/web/app/api/v1/client/[environmentId]/in-app/sync/[userId]/route.ts @@ -4,12 +4,20 @@ import { NextResponse } from "next/server"; import { getLatestActionByPersonId } from "@formbricks/lib/action/service"; import { getActionClasses } from "@formbricks/lib/actionClass/service"; -import { IS_FORMBRICKS_CLOUD, PRICING_USERTARGETING_FREE_MTU } from "@formbricks/lib/constants"; +import { + IS_FORMBRICKS_CLOUD, + PRICING_APPSURVEYS_FREE_RESPONSES, + PRICING_USERTARGETING_FREE_MTU, +} from "@formbricks/lib/constants"; import { getEnvironment, updateEnvironment } from "@formbricks/lib/environment/service"; import { createPerson, getPersonByUserId } from "@formbricks/lib/person/service"; import { getProductByEnvironmentId } from "@formbricks/lib/product/service"; import { getSyncSurveys } from "@formbricks/lib/survey/service"; -import { getMonthlyActiveTeamPeopleCount, getTeamByEnvironmentId } from "@formbricks/lib/team/service"; +import { + getMonthlyActiveTeamPeopleCount, + getMonthlyTeamResponseCount, + getTeamByEnvironmentId, +} from "@formbricks/lib/team/service"; import { TEnvironment } from "@formbricks/types/environment"; import { TJsStateSync, ZJsPeopleUserIdInput } from "@formbricks/types/js"; @@ -58,6 +66,7 @@ export async function GET( // check if MAU limit is reached let isMauLimitReached = false; + let isInAppSurveyLimitReached = false; if (IS_FORMBRICKS_CLOUD) { // check team subscriptons const team = await getTeamByEnvironmentId(environmentId); @@ -65,11 +74,19 @@ export async function GET( if (!team) { throw new Error("Team does not exist"); } + // check userTargeting subscription const hasUserTargetingSubscription = - team?.billing?.features.userTargeting.status && - ["active", "canceled"].includes(team?.billing?.features.userTargeting.status); + team.billing.features.userTargeting.status && + ["active", "canceled"].includes(team.billing.features.userTargeting.status); const currentMau = await getMonthlyActiveTeamPeopleCount(team.id); isMauLimitReached = !hasUserTargetingSubscription && currentMau >= PRICING_USERTARGETING_FREE_MTU; + // check inAppSurvey subscription + const hasInAppSurveySubscription = + team.billing.features.inAppSurvey.status && + ["active", "canceled"].includes(team.billing.features.inAppSurvey.status); + const currentResponseCount = await getMonthlyTeamResponseCount(team.id); + isInAppSurveyLimitReached = + !hasInAppSurveySubscription && currentResponseCount >= PRICING_APPSURVEYS_FREE_RESPONSES; } let person = await getPersonByUserId(environmentId, userId); @@ -104,7 +121,7 @@ export async function GET( // return state const state: TJsStateSync = { person: { id: person.id, userId: person.userId }, - surveys, + surveys: !isInAppSurveyLimitReached ? surveys : [], noCodeActionClasses: noCodeActionClasses.filter((actionClass) => actionClass.type === "noCode"), product, }; diff --git a/apps/web/app/api/v1/client/[environmentId]/in-app/sync/route.ts b/apps/web/app/api/v1/client/[environmentId]/in-app/sync/route.ts index 3197bf03e5..2273548ec4 100644 --- a/apps/web/app/api/v1/client/[environmentId]/in-app/sync/route.ts +++ b/apps/web/app/api/v1/client/[environmentId]/in-app/sync/route.ts @@ -3,9 +3,11 @@ import { transformErrorToDetails } from "@/app/lib/api/validator"; import { NextRequest, NextResponse } from "next/server"; import { getActionClasses } from "@formbricks/lib/actionClass/service"; +import { IS_FORMBRICKS_CLOUD, PRICING_APPSURVEYS_FREE_RESPONSES } from "@formbricks/lib/constants"; import { getEnvironment, updateEnvironment } from "@formbricks/lib/environment/service"; import { getProductByEnvironmentId } from "@formbricks/lib/product/service"; import { getSurveys } from "@formbricks/lib/survey/service"; +import { getMonthlyTeamResponseCount, getTeamByEnvironmentId } from "@formbricks/lib/team/service"; import { TJsStateSync, ZJsPublicSyncInput } from "@formbricks/types/js"; export async function OPTIONS(): Promise { @@ -38,6 +40,24 @@ export async function GET( throw new Error("Environment does not exist"); } + // check if MAU limit is reached + let isInAppSurveyLimitReached = false; + if (IS_FORMBRICKS_CLOUD) { + // check team subscriptons + const team = await getTeamByEnvironmentId(environmentId); + + if (!team) { + throw new Error("Team does not exist"); + } + // check inAppSurvey subscription + const hasInAppSurveySubscription = + team.billing.features.inAppSurvey.status && + ["active", "canceled"].includes(team.billing.features.inAppSurvey.status); + const currentResponseCount = await getMonthlyTeamResponseCount(team.id); + isInAppSurveyLimitReached = + !hasInAppSurveySubscription && currentResponseCount >= PRICING_APPSURVEYS_FREE_RESPONSES; + } + if (!environment?.widgetSetupCompleted) { await updateEnvironment(environment.id, { widgetSetupCompleted: true }); } @@ -52,7 +72,9 @@ export async function GET( } const state: TJsStateSync = { - surveys: surveys.filter((survey) => survey.status === "inProgress" && survey.type === "web"), + surveys: !isInAppSurveyLimitReached + ? surveys.filter((survey) => survey.status === "inProgress" && survey.type === "web") + : [], noCodeActionClasses: noCodeActionClasses.filter((actionClass) => actionClass.type === "noCode"), product, person: null,