mirror of
https://github.com/formbricks/formbricks.git
synced 2026-04-23 14:08:42 -05:00
feat: add mau limit to web-app survey (#828)
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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,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}` : "";
|
||||
|
||||
@@ -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
|
||||
}
|
||||
)();
|
||||
|
||||
Reference in New Issue
Block a user