2
0

🐛 Remove publicId and customDomain duplication on imported bots

This commit is contained in:
Baptiste Arnaud
2023-08-17 16:32:37 +02:00
parent 906845bd76
commit 304dfe2dab
17 changed files with 61 additions and 70 deletions

View File

@@ -2,6 +2,7 @@ import prisma from '@/lib/prisma'
import { authenticatedProcedure } from '@/helpers/server/trpc' import { authenticatedProcedure } from '@/helpers/server/trpc'
import { TRPCError } from '@trpc/server' import { TRPCError } from '@trpc/server'
import { z } from 'zod' import { z } from 'zod'
import { isReadWorkspaceFobidden } from '@/features/workspace/helpers/isReadWorkspaceFobidden'
export const getUsage = authenticatedProcedure export const getUsage = authenticatedProcedure
.meta({ .meta({
@@ -25,10 +26,19 @@ export const getUsage = authenticatedProcedure
const workspace = await prisma.workspace.findFirst({ const workspace = await prisma.workspace.findFirst({
where: { where: {
id: workspaceId, id: workspaceId,
members: { some: { userId: user.id } }, },
select: {
members: {
select: {
userId: true,
},
},
typebots: {
select: { id: true, results: { select: { id: true } } },
},
}, },
}) })
if (!workspace) if (!workspace || isReadWorkspaceFobidden(workspace, user))
throw new TRPCError({ throw new TRPCError({
code: 'NOT_FOUND', code: 'NOT_FOUND',
message: 'Workspace not found', message: 'Workspace not found',
@@ -36,40 +46,25 @@ export const getUsage = authenticatedProcedure
const now = new Date() const now = new Date()
const firstDayOfMonth = new Date(now.getFullYear(), now.getMonth(), 1) const firstDayOfMonth = new Date(now.getFullYear(), now.getMonth(), 1)
const [ const totalChatsUsed = await prisma.result.count({
totalChatsUsed, where: {
{ typebotId: { in: workspace.typebots.map((typebot) => typebot.id) },
_sum: { storageUsed: totalStorageUsed }, hasStarted: true,
}, createdAt: {
] = await prisma.$transaction(async (tx) => { gte: firstDayOfMonth,
const typebots = await tx.typebot.findMany({
where: {
workspace: {
id: workspaceId,
},
}, },
}) },
})
return Promise.all([ const {
prisma.result.count({ _sum: { storageUsed: totalStorageUsed },
where: { } = await prisma.answer.aggregate({
typebotId: { in: typebots.map((typebot) => typebot.id) }, where: {
hasStarted: true, storageUsed: { gt: 0 },
createdAt: { result: {
gte: firstDayOfMonth, typebotId: { in: workspace.typebots.map((typebot) => typebot.id) },
}, },
}, },
}), _sum: { storageUsed: true },
prisma.answer.aggregate({
where: {
storageUsed: { gt: 0 },
result: {
typebotId: { in: typebots.map((typebot) => typebot.id) },
},
},
_sum: { storageUsed: true },
}),
])
}) })
return { return {

View File

@@ -48,7 +48,7 @@ export const createCredentials = authenticatedProcedure
}, },
select: { id: true, members: true }, select: { id: true, members: true },
}) })
if (!workspace || (await isWriteWorkspaceForbidden(workspace, user))) if (!workspace || isWriteWorkspaceForbidden(workspace, user))
throw new TRPCError({ code: 'NOT_FOUND', message: 'Workspace not found' }) throw new TRPCError({ code: 'NOT_FOUND', message: 'Workspace not found' })
const { encryptedData, iv } = await encrypt(credentials.data) const { encryptedData, iv } = await encrypt(credentials.data)

View File

@@ -33,7 +33,7 @@ export const deleteCredentials = authenticatedProcedure
}, },
select: { id: true, members: true }, select: { id: true, members: true },
}) })
if (!workspace || (await isWriteWorkspaceForbidden(workspace, user))) if (!workspace || isWriteWorkspaceForbidden(workspace, user))
throw new TRPCError({ throw new TRPCError({
code: 'NOT_FOUND', code: 'NOT_FOUND',
message: 'Workspace not found', message: 'Workspace not found',

View File

@@ -51,7 +51,7 @@ export const listCredentials = authenticatedProcedure
}, },
}, },
}) })
if (!workspace || (await isReadWorkspaceFobidden(workspace, user))) if (!workspace || isReadWorkspaceFobidden(workspace, user))
throw new TRPCError({ code: 'NOT_FOUND', message: 'Workspace not found' }) throw new TRPCError({ code: 'NOT_FOUND', message: 'Workspace not found' })
return { credentials: workspace.credentials } return { credentials: workspace.credentials }

View File

@@ -25,6 +25,7 @@ import { useScopedI18n } from '@/locales'
import { TypebotInDashboard } from '@/features/dashboard/types' import { TypebotInDashboard } from '@/features/dashboard/types'
import { isMobile } from '@/helpers/isMobile' import { isMobile } from '@/helpers/isMobile'
import { trpc, trpcVanilla } from '@/lib/trpc' import { trpc, trpcVanilla } from '@/lib/trpc'
import { duplicateName } from '@/features/typebot/helpers/duplicateName'
type Props = { type Props = {
typebot: TypebotInDashboard typebot: TypebotInDashboard
@@ -221,10 +222,3 @@ export const TypebotButton = ({
</Button> </Button>
) )
} }
const duplicateName = (name: string | `${string} (${number})`) => {
const match = name.match(/^(.*) \((\d+)\)$/)
if (!match) return `${name} (1)`
const [, nameWithoutNumber, number] = match
return `${nameWithoutNumber} (${Number(number) + 1})`
}

View File

@@ -56,7 +56,13 @@ export const CreateNewTypebotButtons = () => {
mutate({ mutate({
workspaceId: workspace.id, workspaceId: workspace.id,
typebot: { typebot: {
...(typebot ? { ...typebot } : {}), ...(typebot
? {
...typebot,
publicId: undefined,
customDomain: undefined,
}
: {}),
folderId, folderId,
}, },
}) })

View File

@@ -19,13 +19,12 @@ export const ImportTypebotFromFileButton = ({
const file = e.target.files[0] const file = e.target.files[0]
const fileContent = await readFile(file) const fileContent = await readFile(file)
try { try {
const typebot = parseInvalidTypebot(JSON.parse(fileContent)) const typebot = typebotSchema
typebotSchema
.omit({ .omit({
createdAt: true, createdAt: true,
updatedAt: true, updatedAt: true,
}) })
.parse(typebot) .parse(parseInvalidTypebot(JSON.parse(fileContent)))
onNewTypebot(typebot as Typebot) onNewTypebot(typebot as Typebot)
} catch (err) { } catch (err) {
console.error(err) console.error(err)

View File

@@ -0,0 +1,6 @@
export const duplicateName = (name: string | `${string} (${number})`) => {
const match = name.match(/^(.*) \((\d+)\)$/)
if (!match) return `${name} (1)`
const [, nameWithoutNumber, number] = match
return `${nameWithoutNumber} (${Number(number) + 1})`
}

View File

@@ -30,7 +30,7 @@ export const deleteWorkspace = authenticatedProcedure
include: { members: true }, include: { members: true },
}) })
if (!workspace || (await isAdminWriteWorkspaceForbidden(workspace, user))) if (!workspace || isAdminWriteWorkspaceForbidden(workspace, user))
throw new TRPCError({ code: 'NOT_FOUND', message: 'No workspaces found' }) throw new TRPCError({ code: 'NOT_FOUND', message: 'No workspaces found' })
await prisma.workspace.deleteMany({ await prisma.workspace.deleteMany({

View File

@@ -31,7 +31,7 @@ export const getWorkspace = authenticatedProcedure
include: { members: true }, include: { members: true },
}) })
if (!workspace || (await isReadWorkspaceFobidden(workspace, user))) if (!workspace || isReadWorkspaceFobidden(workspace, user))
throw new TRPCError({ code: 'NOT_FOUND', message: 'No workspaces found' }) throw new TRPCError({ code: 'NOT_FOUND', message: 'No workspaces found' })
return { return {

View File

@@ -31,7 +31,7 @@ export const listInvitationsInWorkspace = authenticatedProcedure
include: { members: true, invitations: true }, include: { members: true, invitations: true },
}) })
if (!workspace || (await isReadWorkspaceFobidden(workspace, user))) if (!workspace || isReadWorkspaceFobidden(workspace, user))
throw new TRPCError({ code: 'NOT_FOUND', message: 'No workspaces found' }) throw new TRPCError({ code: 'NOT_FOUND', message: 'No workspaces found' })
return { invitations: workspace.invitations } return { invitations: workspace.invitations }

View File

@@ -37,7 +37,7 @@ export const listMembersInWorkspace = authenticatedProcedure
}, },
}) })
if (!workspace || (await isReadWorkspaceFobidden(workspace, user))) if (!workspace || isReadWorkspaceFobidden(workspace, user))
throw new TRPCError({ code: 'NOT_FOUND', message: 'No workspaces found' }) throw new TRPCError({ code: 'NOT_FOUND', message: 'No workspaces found' })
return { return {

View File

@@ -41,7 +41,7 @@ export const updateWorkspace = authenticatedProcedure
if (!workspace) if (!workspace)
throw new TRPCError({ code: 'NOT_FOUND', message: 'Workspace not found' }) throw new TRPCError({ code: 'NOT_FOUND', message: 'Workspace not found' })
if (await isAdminWriteWorkspaceForbidden(workspace, user)) if (isAdminWriteWorkspaceForbidden(workspace, user))
throw new TRPCError({ throw new TRPCError({
code: 'FORBIDDEN', code: 'FORBIDDEN',
message: 'You are not allowed to update this workspace', message: 'You are not allowed to update this workspace',

View File

@@ -1,6 +1,6 @@
import { MemberInWorkspace, User } from '@typebot.io/prisma' import { MemberInWorkspace, User } from '@typebot.io/prisma'
export const isAdminWriteWorkspaceForbidden = async ( export const isAdminWriteWorkspaceForbidden = (
workspace: { workspace: {
members: MemberInWorkspace[] members: MemberInWorkspace[]
}, },

View File

@@ -1,8 +1,8 @@
import { MemberInWorkspace, User } from '@typebot.io/prisma' import { MemberInWorkspace, User } from '@typebot.io/prisma'
export const isReadWorkspaceFobidden = async ( export const isReadWorkspaceFobidden = (
workspace: { workspace: {
members: MemberInWorkspace[] members: Pick<MemberInWorkspace, 'userId'>[]
}, },
user: Pick<User, 'email' | 'id'> user: Pick<User, 'email' | 'id'>
) => { ) => {

View File

@@ -1,6 +1,6 @@
import { MemberInWorkspace, User } from '@typebot.io/prisma' import { MemberInWorkspace, User } from '@typebot.io/prisma'
export const isWriteWorkspaceForbidden = async ( export const isWriteWorkspaceForbidden = (
workspace: { workspace: {
members: MemberInWorkspace[] members: MemberInWorkspace[]
}, },

View File

@@ -426,7 +426,7 @@
} }
} }
}, },
"/linkedTypebots": { "/typebots/{typebotId}/linkedTypebots": {
"get": { "get": {
"operationId": "getLinkedTypebots", "operationId": "getLinkedTypebots",
"summary": "Get linked typebots", "summary": "Get linked typebots",
@@ -440,21 +440,12 @@
], ],
"parameters": [ "parameters": [
{ {
"name": "workspaceId", "name": "typebotId",
"in": "query", "in": "path",
"required": true, "required": true,
"schema": { "schema": {
"type": "string" "type": "string"
} }
},
{
"name": "typebotIds",
"in": "query",
"required": true,
"schema": {
"type": "string"
},
"description": "Comma separated list of typebot ids"
} }
], ],
"responses": { "responses": {