2
0

🛂 Reset isQuarantined when upgrading workspace

This commit is contained in:
Baptiste Arnaud
2023-04-23 21:03:14 +02:00
parent 69e1c4f20d
commit c6983c952c
5 changed files with 9 additions and 278 deletions

View File

@@ -1,7 +1,6 @@
import { publicProcedure } from '@/helpers/server/trpc'
import prisma from '@/lib/prisma'
import { TRPCError } from '@trpc/server'
import { getStorageLimit } from '@typebot.io/lib/pricing'
import {
FileInputBlock,
InputBlockType,
@@ -9,16 +8,9 @@ import {
PublicTypebot,
TypebotLinkBlock,
} from '@typebot.io/schemas'
import { byId, env, isDefined } from '@typebot.io/lib'
import { byId, isDefined } from '@typebot.io/lib'
import { z } from 'zod'
import { generatePresignedUrl } from '@typebot.io/lib/api/storage'
import {
sendAlmostReachedStorageLimitEmail,
sendReachedStorageLimitEmail,
} from '@typebot.io/emails'
import { WorkspaceRole } from '@typebot.io/prisma'
const LIMIT_EMAIL_TRIGGER_PERCENT = 0.8
export const getUploadUrl = publicProcedure
.meta({
@@ -58,7 +50,6 @@ export const getUploadUrl = publicProcedure
'S3 not properly configured. Missing one of those variables: S3_ENDPOINT, S3_ACCESS_KEY, S3_SECRET_KEY',
})
await checkIfStorageLimitReached(typebotId)
const publicTypebot = (await prisma.publicTypebot.findFirst({
where: { typebotId },
select: {
@@ -118,111 +109,3 @@ const getFileUploadBlock = async (
return fileUploadBlockFromLinkedTypebots
return null
}
const checkIfStorageLimitReached = async (
typebotId: string
): Promise<boolean> => {
const typebot = await prisma.typebot.findUnique({
where: { id: typebotId },
select: {
workspace: {
select: {
id: true,
additionalStorageIndex: true,
plan: true,
storageLimitFirstEmailSentAt: true,
storageLimitSecondEmailSentAt: true,
customStorageLimit: true,
},
},
},
})
if (!typebot?.workspace) throw new Error('Workspace not found')
const { workspace } = typebot
const {
_sum: { storageUsed: totalStorageUsed },
} = await prisma.answer.aggregate({
where: {
storageUsed: { gt: 0 },
result: {
typebot: {
workspaceId: typebot.workspace.id,
},
},
},
_sum: { storageUsed: true },
})
if (!totalStorageUsed) return false
const hasSentFirstEmail = workspace.storageLimitFirstEmailSentAt !== null
const hasSentSecondEmail = workspace.storageLimitSecondEmailSentAt !== null
const storageLimit = getStorageLimit(typebot.workspace)
if (storageLimit === -1) return false
const storageLimitBytes = storageLimit * 1024 * 1024 * 1024
if (
totalStorageUsed >= storageLimitBytes * LIMIT_EMAIL_TRIGGER_PERCENT &&
!hasSentFirstEmail &&
env('E2E_TEST') !== 'true'
)
await sendAlmostReachStorageLimitNotification({
workspaceId: workspace.id,
storageLimit,
})
if (
totalStorageUsed >= storageLimitBytes &&
!hasSentSecondEmail &&
env('E2E_TEST') !== 'true'
)
await sendReachStorageLimitNotification({
workspaceId: workspace.id,
storageLimit,
})
return totalStorageUsed >= storageLimitBytes
}
const sendAlmostReachStorageLimitNotification = async ({
workspaceId,
storageLimit,
}: {
workspaceId: string
storageLimit: number
}) => {
const members = await prisma.memberInWorkspace.findMany({
where: { role: WorkspaceRole.ADMIN, workspaceId },
include: { user: { select: { email: true } } },
})
await sendAlmostReachedStorageLimitEmail({
to: members.map((member) => member.user.email).filter(isDefined),
storageLimit,
url: `${process.env.NEXTAUTH_URL}/typebots?workspaceId=${workspaceId}`,
})
await prisma.workspace.update({
where: { id: workspaceId },
data: { storageLimitFirstEmailSentAt: new Date() },
})
}
const sendReachStorageLimitNotification = async ({
workspaceId,
storageLimit,
}: {
workspaceId: string
storageLimit: number
}) => {
const members = await prisma.memberInWorkspace.findMany({
where: { role: WorkspaceRole.ADMIN, workspaceId },
include: { user: { select: { email: true } } },
})
await sendReachedStorageLimitEmail({
to: members.map((member) => member.user.email).filter(isDefined),
storageLimit,
url: `${process.env.NEXTAUTH_URL}/typebots?workspaceId=${workspaceId}`,
})
await prisma.workspace.update({
where: { id: workspaceId },
data: { storageLimitSecondEmailSentAt: new Date() },
})
}

View File

@@ -1,145 +0,0 @@
import prisma from '@/lib/prisma'
import { WorkspaceRole } from '@typebot.io/prisma'
import {
sendAlmostReachedChatsLimitEmail,
sendReachedChatsLimitEmail,
} from '@typebot.io/emails'
import { Workspace } from '@typebot.io/schemas'
import { env, isDefined } from '@typebot.io/lib'
import { getChatsLimit } from '@typebot.io/lib/pricing'
const LIMIT_EMAIL_TRIGGER_PERCENT = 0.8
export const checkChatsUsage = async (props: {
typebotId: string
workspace?: Pick<
Workspace,
| 'id'
| 'plan'
| 'additionalChatsIndex'
| 'chatsLimitFirstEmailSentAt'
| 'chatsLimitSecondEmailSentAt'
| 'customChatsLimit'
>
}) => {
const typebot = props.workspace
? null
: await prisma.typebot.findUnique({
where: {
id: props.typebotId,
},
include: {
workspace: {
select: {
id: true,
plan: true,
additionalChatsIndex: true,
chatsLimitFirstEmailSentAt: true,
chatsLimitSecondEmailSentAt: true,
customChatsLimit: true,
},
},
},
})
const workspace = props.workspace || typebot?.workspace
if (!workspace) return false
const chatsLimit = getChatsLimit(workspace)
if (chatsLimit === -1) return
const now = new Date()
const firstDayOfMonth = new Date(now.getFullYear(), now.getMonth(), 1)
const firstDayOfNextMonth = new Date(now.getFullYear(), now.getMonth() + 1, 1)
const chatsCount = await prisma.$transaction(async (tx) => {
const typebotIds = await tx.typebot.findMany({
where: {
workspaceId: workspace.id,
},
select: { id: true },
})
return tx.result.count({
where: {
typebotId: { in: typebotIds.map((typebot) => typebot.id) },
hasStarted: true,
createdAt: { gte: firstDayOfMonth, lte: firstDayOfNextMonth },
},
})
})
const hasSentFirstEmail =
workspace.chatsLimitFirstEmailSentAt !== null &&
workspace.chatsLimitFirstEmailSentAt < firstDayOfNextMonth &&
workspace.chatsLimitFirstEmailSentAt > firstDayOfMonth
const hasSentSecondEmail =
workspace.chatsLimitSecondEmailSentAt !== null &&
workspace.chatsLimitSecondEmailSentAt < firstDayOfNextMonth &&
workspace.chatsLimitSecondEmailSentAt > firstDayOfMonth
if (
chatsCount >= chatsLimit * LIMIT_EMAIL_TRIGGER_PERCENT &&
!hasSentFirstEmail &&
env('E2E_TEST') !== 'true'
)
await sendAlmostReachChatsLimitNotification({
workspaceId: workspace.id,
chatsLimit,
})
if (
chatsCount >= chatsLimit &&
!hasSentSecondEmail &&
env('E2E_TEST') !== 'true'
)
await sendReachedAlertNotification({
workspaceId: workspace.id,
chatsLimit,
})
return chatsCount >= chatsLimit
}
const sendAlmostReachChatsLimitNotification = async ({
workspaceId,
chatsLimit,
}: {
workspaceId: string
chatsLimit: number
}) => {
const members = await prisma.memberInWorkspace.findMany({
where: { role: WorkspaceRole.ADMIN, workspaceId },
include: { user: { select: { email: true } } },
})
await sendAlmostReachedChatsLimitEmail({
to: members.map((member) => member.user.email).filter(isDefined),
chatsLimit,
url: `${process.env.NEXTAUTH_URL}/typebots?workspaceId=${workspaceId}`,
})
await prisma.workspace.update({
where: { id: workspaceId },
data: { chatsLimitFirstEmailSentAt: new Date() },
})
}
const sendReachedAlertNotification = async ({
workspaceId,
chatsLimit,
}: {
workspaceId: string
chatsLimit: number
}) => {
const members = await prisma.memberInWorkspace.findMany({
where: { role: WorkspaceRole.ADMIN, workspaceId },
include: { user: { select: { email: true } } },
})
await sendReachedChatsLimitEmail({
to: members.map((member) => member.user.email).filter(isDefined),
chatsLimit,
url: `${process.env.NEXTAUTH_URL}/typebots?workspaceId=${workspaceId}`,
})
await prisma.workspace.update({
where: { id: workspaceId },
data: { chatsLimitSecondEmailSentAt: new Date() },
})
}

View File

@@ -3,7 +3,6 @@ import prisma from '@/lib/prisma'
import { ResultWithAnswers } from '@typebot.io/schemas'
import { NextApiRequest, NextApiResponse } from 'next'
import { methodNotAllowed } from '@typebot.io/lib/api'
import { checkChatsUsage } from '@/features/usage/checkChatsUsage'
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
if (req.method === 'GET') {
@@ -26,8 +25,12 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
}
if (req.method === 'POST') {
const typebotId = req.query.typebotId as string
const hasReachedLimit = await checkChatsUsage({ typebotId })
if (hasReachedLimit) return res.send({ result: null, hasReachedLimit })
const typebot = await prisma.typebot.findFirst({
where: { id: typebotId },
select: { workspace: { select: { isQuarantined: true } } },
})
if (typebot?.workspace.isQuarantined)
return res.send({ result: null, hasReachedLimit: true })
const result = await prisma.result.create({
data: {
typebotId,