feat: add mau limit to web-app survey (#828)

This commit is contained in:
Matti Nannt
2023-09-17 22:57:47 +09:00
committed by GitHub
parent ac11537e07
commit 9d1ea819c5
4 changed files with 57 additions and 2 deletions
+24 -1
View File
@@ -1,7 +1,8 @@
import { getSurveysCached } from "@/app/api/v1/js/surveys";
import { MAU_LIMIT } from "@formbricks/lib/constants";
import { getActionClassesCached } from "@formbricks/lib/services/actionClass";
import { getEnvironmentCached } from "@formbricks/lib/services/environment";
import { createPerson, getPersonCached } from "@formbricks/lib/services/person";
import { createPerson, getMonthlyActivePeopleCount, getPersonCached } from "@formbricks/lib/services/person";
import { getProductByEnvironmentIdCached } from "@formbricks/lib/services/product";
import { createSession, extendSession, getSessionCached } from "@formbricks/lib/services/session";
import { captureTelemetry } from "@formbricks/lib/telemetry";
@@ -31,6 +32,28 @@ export const getUpdatedState = async (
throw new Error("Environment does not exist");
}
// check if Monthly Active Users limit is reached
const currentMau = await getMonthlyActivePeopleCount(environmentId);
const isMauLimitReached = currentMau >= MAU_LIMIT;
if (isMauLimitReached) {
const errorMessage = `Monthly Active Users limit reached in ${environmentId} (${currentMau}/${MAU_LIMIT})`;
if (!personId || !sessionId) {
// don't allow new people or sessions
throw new Error(errorMessage);
}
const session = await getSessionCached(sessionId);
if (!session) {
// don't allow new sessions
throw new Error(errorMessage);
}
// check if session was created this month (user already active this month)
const now = new Date();
const firstDayOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
if (new Date(session.createdAt) < firstDayOfMonth) {
throw new Error(errorMessage);
}
}
if (!personId) {
// create a new person
person = await createPerson(environmentId);
+1 -1
View File
@@ -29,7 +29,7 @@ export async function POST(req: Request): Promise<NextResponse> {
return responses.successResponse({ ...state }, true);
} catch (error) {
console.error(error);
console.error(error.message);
return responses.internalServerErrorResponse(
"Unable to complete response. See server logs for details.",
true
+1
View File
@@ -1,6 +1,7 @@
export const RESPONSES_LIMIT_FREE = 100;
export const IS_FORMBRICKS_CLOUD = process.env.NEXT_PUBLIC_IS_FORMBRICKS_CLOUD === "1";
export const REVALIDATION_INTERVAL = 0; //TODO: find a good way to cache and revalidate data when it changes
export const MAU_LIMIT = IS_FORMBRICKS_CLOUD ? 5000 : 1000000;
// URLs
const VERCEL_URL = process.env.NEXT_PUBLIC_VERCEL_URL ? `https://${process.env.NEXT_PUBLIC_VERCEL_URL}` : "";
+31
View File
@@ -237,3 +237,34 @@ export const getOrCreatePersonByUserId = async (userId: string, environmentId: s
return transformPrismaPerson(personPrisma);
}
};
export const getMonthlyActivePeopleCount = async (environmentId: string): Promise<number> =>
await unstable_cache(
async () => {
const now = new Date();
const firstDayOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
const aggregations = await prisma.person.aggregate({
_count: {
id: true,
},
where: {
environmentId,
sessions: {
some: {
createdAt: {
gte: firstDayOfMonth,
},
},
},
},
});
return aggregations._count.id;
},
[`env-${environmentId}-mau`],
{
tags: [`env-${environmentId}-mau`],
revalidate: 60 * 60 * 6, // 6 hours
}
)();