fix(team): 🛂 Improve collab permissions
This commit is contained in:
@ -1,7 +1,8 @@
|
|||||||
import { withSentry } from '@sentry/nextjs'
|
import { withSentry } from '@sentry/nextjs'
|
||||||
import { CollaborationType, Prisma, User } from 'db'
|
import { CollaborationType } from 'db'
|
||||||
import prisma from 'libs/prisma'
|
import prisma from 'libs/prisma'
|
||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
import { NextApiRequest, NextApiResponse } from 'next'
|
||||||
|
import { canReadTypebot, canWriteTypebot } from 'services/api/dbRules'
|
||||||
import { getAuthenticatedUser } from 'services/api/utils'
|
import { getAuthenticatedUser } from 'services/api/utils'
|
||||||
import { methodNotAllowed, notAuthenticated } from 'utils'
|
import { methodNotAllowed, notAuthenticated } from 'utils'
|
||||||
|
|
||||||
@ -12,7 +13,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||||||
const typebotId = req.query.typebotId.toString()
|
const typebotId = req.query.typebotId.toString()
|
||||||
if (req.method === 'GET') {
|
if (req.method === 'GET') {
|
||||||
const typebot = await prisma.typebot.findFirst({
|
const typebot = await prisma.typebot.findFirst({
|
||||||
where: parseWhereFilter(typebotId, user, 'read'),
|
where: canReadTypebot(typebotId, user),
|
||||||
include: {
|
include: {
|
||||||
publishedTypebot: true,
|
publishedTypebot: true,
|
||||||
owner: { select: { email: true, name: true, image: true } },
|
owner: { select: { email: true, name: true, image: true } },
|
||||||
@ -40,17 +41,16 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const canEditTypebot = parseWhereFilter(typebotId, user, 'write')
|
|
||||||
if (req.method === 'DELETE') {
|
if (req.method === 'DELETE') {
|
||||||
const typebots = await prisma.typebot.deleteMany({
|
const typebots = await prisma.typebot.deleteMany({
|
||||||
where: canEditTypebot,
|
where: canWriteTypebot(typebotId, user),
|
||||||
})
|
})
|
||||||
return res.send({ typebots })
|
return res.send({ typebots })
|
||||||
}
|
}
|
||||||
if (req.method === 'PUT') {
|
if (req.method === 'PUT') {
|
||||||
const data = typeof req.body === 'string' ? JSON.parse(req.body) : req.body
|
const data = typeof req.body === 'string' ? JSON.parse(req.body) : req.body
|
||||||
const typebots = await prisma.typebot.updateMany({
|
const typebots = await prisma.typebot.updateMany({
|
||||||
where: canEditTypebot,
|
where: canWriteTypebot(typebotId, user),
|
||||||
data: {
|
data: {
|
||||||
...data,
|
...data,
|
||||||
theme: data.theme ?? undefined,
|
theme: data.theme ?? undefined,
|
||||||
@ -62,7 +62,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||||||
if (req.method === 'PATCH') {
|
if (req.method === 'PATCH') {
|
||||||
const data = typeof req.body === 'string' ? JSON.parse(req.body) : req.body
|
const data = typeof req.body === 'string' ? JSON.parse(req.body) : req.body
|
||||||
const typebots = await prisma.typebot.updateMany({
|
const typebots = await prisma.typebot.updateMany({
|
||||||
where: canEditTypebot,
|
where: canWriteTypebot(typebotId, user),
|
||||||
data,
|
data,
|
||||||
})
|
})
|
||||||
return res.send({ typebots })
|
return res.send({ typebots })
|
||||||
@ -70,30 +70,4 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||||||
return methodNotAllowed(res)
|
return methodNotAllowed(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
const parseWhereFilter = (
|
|
||||||
typebotId: string,
|
|
||||||
user: User,
|
|
||||||
type: 'read' | 'write'
|
|
||||||
): Prisma.TypebotWhereInput => ({
|
|
||||||
OR: [
|
|
||||||
{
|
|
||||||
id: typebotId,
|
|
||||||
ownerId:
|
|
||||||
(type === 'read' && user.email === process.env.ADMIN_EMAIL) ||
|
|
||||||
process.env.NEXT_PUBLIC_E2E_TEST
|
|
||||||
? undefined
|
|
||||||
: user.id,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: typebotId,
|
|
||||||
collaborators: {
|
|
||||||
some: {
|
|
||||||
userId: user.id,
|
|
||||||
type: type === 'write' ? CollaborationType.WRITE : undefined,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
export default withSentry(handler)
|
export default withSentry(handler)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { withSentry } from '@sentry/nextjs'
|
import { withSentry } from '@sentry/nextjs'
|
||||||
import prisma from 'libs/prisma'
|
import prisma from 'libs/prisma'
|
||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
import { NextApiRequest, NextApiResponse } from 'next'
|
||||||
|
import { canReadTypebot } from 'services/api/dbRules'
|
||||||
import { getAuthenticatedUser } from 'services/api/utils'
|
import { getAuthenticatedUser } from 'services/api/utils'
|
||||||
import { methodNotAllowed, notAuthenticated, notFound } from 'utils'
|
import { methodNotAllowed, notAuthenticated, notFound } from 'utils'
|
||||||
|
|
||||||
@ -9,8 +10,8 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||||||
if (!user) return notAuthenticated(res)
|
if (!user) return notAuthenticated(res)
|
||||||
if (req.method === 'GET') {
|
if (req.method === 'GET') {
|
||||||
const typebotId = req.query.typebotId as string
|
const typebotId = req.query.typebotId as string
|
||||||
const typebot = await prisma.typebot.findUnique({
|
const typebot = await prisma.typebot.findFirst({
|
||||||
where: { id_ownerId: { id: typebotId, ownerId: user.id } },
|
where: canReadTypebot(typebotId, user),
|
||||||
})
|
})
|
||||||
if (!typebot) return notFound(res)
|
if (!typebot) return notFound(res)
|
||||||
return res.send({ blocks: typebot.blocks })
|
return res.send({ blocks: typebot.blocks })
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { withSentry } from '@sentry/nextjs'
|
import { withSentry } from '@sentry/nextjs'
|
||||||
import prisma from 'libs/prisma'
|
import prisma from 'libs/prisma'
|
||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
import { NextApiRequest, NextApiResponse } from 'next'
|
||||||
|
import { canReadTypebot } from 'services/api/dbRules'
|
||||||
import { getAuthenticatedUser } from 'services/api/utils'
|
import { getAuthenticatedUser } from 'services/api/utils'
|
||||||
import { methodNotAllowed, notAuthenticated } from 'utils'
|
import { methodNotAllowed, notAuthenticated } from 'utils'
|
||||||
|
|
||||||
@ -10,7 +11,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||||||
const typebotId = req.query.typebotId as string
|
const typebotId = req.query.typebotId as string
|
||||||
if (req.method === 'GET') {
|
if (req.method === 'GET') {
|
||||||
const collaborators = await prisma.collaboratorsOnTypebots.findMany({
|
const collaborators = await prisma.collaboratorsOnTypebots.findMany({
|
||||||
where: { typebotId },
|
where: { typebot: canReadTypebot(typebotId, user) },
|
||||||
include: { user: { select: { name: true, image: true, email: true } } },
|
include: { user: { select: { name: true, image: true, email: true } } },
|
||||||
})
|
})
|
||||||
return res.send({
|
return res.send({
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
import { withSentry } from '@sentry/nextjs'
|
import { withSentry } from '@sentry/nextjs'
|
||||||
import prisma from 'libs/prisma'
|
import prisma from 'libs/prisma'
|
||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
import { NextApiRequest, NextApiResponse } from 'next'
|
||||||
|
import { canWriteTypebot } from 'services/api/dbRules'
|
||||||
import { getAuthenticatedUser } from 'services/api/utils'
|
import { getAuthenticatedUser } from 'services/api/utils'
|
||||||
import { methodNotAllowed, notAuthenticated } from 'utils'
|
import { forbidden, methodNotAllowed, notAuthenticated } from 'utils'
|
||||||
|
|
||||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
const user = await getAuthenticatedUser(req)
|
const user = await getAuthenticatedUser(req)
|
||||||
if (!user) return notAuthenticated(res)
|
if (!user) return notAuthenticated(res)
|
||||||
const typebotId = req.query.typebotId as string
|
const typebotId = req.query.typebotId as string
|
||||||
const userId = req.query.userId as string
|
const userId = req.query.userId as string
|
||||||
|
const typebot = await prisma.typebot.findFirst({
|
||||||
|
where: canWriteTypebot(typebotId, user),
|
||||||
|
})
|
||||||
|
if (!typebot) return forbidden(res)
|
||||||
if (req.method === 'PUT') {
|
if (req.method === 'PUT') {
|
||||||
const data = req.body
|
const data = req.body
|
||||||
await prisma.collaboratorsOnTypebots.upsert({
|
await prisma.collaboratorsOnTypebots.upsert({
|
||||||
|
@ -3,10 +3,12 @@ import { invitationToCollaborate } from 'assets/emails/invitationToCollaborate'
|
|||||||
import { CollaborationType } from 'db'
|
import { CollaborationType } from 'db'
|
||||||
import prisma from 'libs/prisma'
|
import prisma from 'libs/prisma'
|
||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
import { NextApiRequest, NextApiResponse } from 'next'
|
||||||
|
import { canReadTypebot, canWriteTypebot } from 'services/api/dbRules'
|
||||||
import { sendEmailNotification } from 'services/api/emails'
|
import { sendEmailNotification } from 'services/api/emails'
|
||||||
import { getAuthenticatedUser } from 'services/api/utils'
|
import { getAuthenticatedUser } from 'services/api/utils'
|
||||||
import {
|
import {
|
||||||
badRequest,
|
badRequest,
|
||||||
|
forbidden,
|
||||||
isNotDefined,
|
isNotDefined,
|
||||||
methodNotAllowed,
|
methodNotAllowed,
|
||||||
notAuthenticated,
|
notAuthenticated,
|
||||||
@ -18,13 +20,17 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||||||
const typebotId = req.query.typebotId as string
|
const typebotId = req.query.typebotId as string
|
||||||
if (req.method === 'GET') {
|
if (req.method === 'GET') {
|
||||||
const invitations = await prisma.invitation.findMany({
|
const invitations = await prisma.invitation.findMany({
|
||||||
where: { typebotId },
|
where: { typebotId, typebot: canReadTypebot(typebotId, user) },
|
||||||
})
|
})
|
||||||
return res.send({
|
return res.send({
|
||||||
invitations,
|
invitations,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (req.method === 'POST') {
|
if (req.method === 'POST') {
|
||||||
|
const typebot = await prisma.typebot.findFirst({
|
||||||
|
where: canWriteTypebot(typebotId, user),
|
||||||
|
})
|
||||||
|
if (!typebot) return forbidden(res)
|
||||||
const { email, type } =
|
const { email, type } =
|
||||||
(req.body as
|
(req.body as
|
||||||
| { email: string | undefined; type: CollaborationType | undefined }
|
| { email: string | undefined; type: CollaborationType | undefined }
|
||||||
@ -36,7 +42,11 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||||||
})
|
})
|
||||||
if (existingUser)
|
if (existingUser)
|
||||||
await prisma.collaboratorsOnTypebots.create({
|
await prisma.collaboratorsOnTypebots.create({
|
||||||
data: { type, typebotId, userId: existingUser.id },
|
data: {
|
||||||
|
type,
|
||||||
|
typebotId,
|
||||||
|
userId: existingUser.id,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
else
|
else
|
||||||
await prisma.invitation.create({
|
await prisma.invitation.create({
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
import { withSentry } from '@sentry/nextjs'
|
import { withSentry } from '@sentry/nextjs'
|
||||||
import prisma from 'libs/prisma'
|
import prisma from 'libs/prisma'
|
||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
import { NextApiRequest, NextApiResponse } from 'next'
|
||||||
|
import { canWriteTypebot } from 'services/api/dbRules'
|
||||||
import { getAuthenticatedUser } from 'services/api/utils'
|
import { getAuthenticatedUser } from 'services/api/utils'
|
||||||
import { methodNotAllowed, notAuthenticated } from 'utils'
|
import { forbidden, methodNotAllowed, notAuthenticated } from 'utils'
|
||||||
|
|
||||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
const user = await getAuthenticatedUser(req)
|
const user = await getAuthenticatedUser(req)
|
||||||
if (!user) return notAuthenticated(res)
|
if (!user) return notAuthenticated(res)
|
||||||
const typebotId = req.query.typebotId as string
|
const typebotId = req.query.typebotId as string
|
||||||
const email = req.query.email as string
|
const email = req.query.email as string
|
||||||
|
const typebot = await prisma.typebot.findFirst({
|
||||||
|
where: canWriteTypebot(typebotId, user),
|
||||||
|
})
|
||||||
|
if (!typebot) return forbidden(res)
|
||||||
if (req.method === 'PUT') {
|
if (req.method === 'PUT') {
|
||||||
const data = req.body
|
const data = req.body
|
||||||
await prisma.invitation.upsert({
|
await prisma.invitation.upsert({
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { withSentry } from '@sentry/nextjs'
|
import { withSentry } from '@sentry/nextjs'
|
||||||
import prisma from 'libs/prisma'
|
import prisma from 'libs/prisma'
|
||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
import { NextApiRequest, NextApiResponse } from 'next'
|
||||||
|
import { canReadTypebot, canWriteTypebot } from 'services/api/dbRules'
|
||||||
import { getAuthenticatedUser } from 'services/api/utils'
|
import { getAuthenticatedUser } from 'services/api/utils'
|
||||||
import { isFreePlan } from 'services/user/user'
|
import { isFreePlan } from 'services/user/user'
|
||||||
import { methodNotAllowed, notAuthenticated } from 'utils'
|
import { methodNotAllowed, notAuthenticated } from 'utils'
|
||||||
@ -21,10 +22,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
where: {
|
where: {
|
||||||
typebotId,
|
typebot: canReadTypebot(typebotId, user),
|
||||||
typebot: {
|
|
||||||
ownerId: user.email === process.env.ADMIN_EMAIL ? undefined : user.id,
|
|
||||||
},
|
|
||||||
answers: { some: {} },
|
answers: { some: {} },
|
||||||
isCompleted: isFreePlan(user) ? true : undefined,
|
isCompleted: isFreePlan(user) ? true : undefined,
|
||||||
},
|
},
|
||||||
@ -39,7 +37,10 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||||||
const typebotId = req.query.typebotId.toString()
|
const typebotId = req.query.typebotId.toString()
|
||||||
const ids = req.query.ids as string[]
|
const ids = req.query.ids as string[]
|
||||||
const results = await prisma.result.deleteMany({
|
const results = await prisma.result.deleteMany({
|
||||||
where: { id: { in: ids }, typebotId, typebot: { ownerId: user.id } },
|
where: {
|
||||||
|
id: { in: ids },
|
||||||
|
typebot: canWriteTypebot(typebotId, user),
|
||||||
|
},
|
||||||
})
|
})
|
||||||
return res.status(200).send({ results })
|
return res.status(200).send({ results })
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { withSentry } from '@sentry/nextjs'
|
import { withSentry } from '@sentry/nextjs'
|
||||||
import prisma from 'libs/prisma'
|
import prisma from 'libs/prisma'
|
||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
import { NextApiRequest, NextApiResponse } from 'next'
|
||||||
|
import { canReadTypebot } from 'services/api/dbRules'
|
||||||
import { getAuthenticatedUser } from 'services/api/utils'
|
import { getAuthenticatedUser } from 'services/api/utils'
|
||||||
import { methodNotAllowed, notAuthenticated } from 'utils'
|
import { methodNotAllowed, notAuthenticated } from 'utils'
|
||||||
|
|
||||||
@ -8,8 +9,11 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||||||
const user = await getAuthenticatedUser(req)
|
const user = await getAuthenticatedUser(req)
|
||||||
if (!user) return notAuthenticated(res)
|
if (!user) return notAuthenticated(res)
|
||||||
if (req.method === 'GET') {
|
if (req.method === 'GET') {
|
||||||
|
const typebotId = req.query.typebotId as string
|
||||||
const resultId = req.query.resultId as string
|
const resultId = req.query.resultId as string
|
||||||
const logs = await prisma.log.findMany({ where: { resultId } })
|
const logs = await prisma.log.findMany({
|
||||||
|
where: { resultId, result: { typebot: canReadTypebot(typebotId, user) } },
|
||||||
|
})
|
||||||
return res.send({ logs })
|
return res.send({ logs })
|
||||||
}
|
}
|
||||||
methodNotAllowed(res)
|
methodNotAllowed(res)
|
||||||
|
@ -4,20 +4,18 @@ import { NextApiRequest, NextApiResponse } from 'next'
|
|||||||
import { methodNotAllowed, notAuthenticated } from 'utils'
|
import { methodNotAllowed, notAuthenticated } from 'utils'
|
||||||
import { withSentry } from '@sentry/nextjs'
|
import { withSentry } from '@sentry/nextjs'
|
||||||
import { getAuthenticatedUser } from 'services/api/utils'
|
import { getAuthenticatedUser } from 'services/api/utils'
|
||||||
|
import { canReadTypebot } from 'services/api/dbRules'
|
||||||
|
|
||||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
const user = await getAuthenticatedUser(req)
|
const user = await getAuthenticatedUser(req)
|
||||||
if (!user) return notAuthenticated(res)
|
if (!user) return notAuthenticated(res)
|
||||||
if (req.method === 'GET') {
|
if (req.method === 'GET') {
|
||||||
const typebotId = req.query.typebotId.toString()
|
const typebotId = req.query.typebotId.toString()
|
||||||
const typebot = await prisma.typebot.findUnique({
|
const typebot = await prisma.typebot.findFirst({
|
||||||
where: { id: typebotId },
|
where: canReadTypebot(typebotId, user),
|
||||||
include: { publishedTypebot: true },
|
include: { publishedTypebot: true },
|
||||||
})
|
})
|
||||||
if (!typebot) return res.status(404).send({ answersCounts: [] })
|
if (!typebot) return res.status(404).send({ answersCounts: [] })
|
||||||
if (typebot?.ownerId !== user.id)
|
|
||||||
return res.status(403).send({ message: 'Forbidden' })
|
|
||||||
|
|
||||||
const answersCounts: { blockId: string; totalAnswers: number }[] =
|
const answersCounts: { blockId: string; totalAnswers: number }[] =
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
(typebot.publishedTypebot as unknown as PublicTypebot).blocks.map(
|
(typebot.publishedTypebot as unknown as PublicTypebot).blocks.map(
|
||||||
|
@ -2,6 +2,7 @@ import { withSentry } from '@sentry/nextjs'
|
|||||||
import prisma from 'libs/prisma'
|
import prisma from 'libs/prisma'
|
||||||
import { Stats } from 'models'
|
import { Stats } from 'models'
|
||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
import { NextApiRequest, NextApiResponse } from 'next'
|
||||||
|
import { canReadTypebot } from 'services/api/dbRules'
|
||||||
import { getAuthenticatedUser } from 'services/api/utils'
|
import { getAuthenticatedUser } from 'services/api/utils'
|
||||||
import { methodNotAllowed, notAuthenticated } from 'utils'
|
import { methodNotAllowed, notAuthenticated } from 'utils'
|
||||||
|
|
||||||
@ -14,20 +15,20 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||||||
const totalViews = await prisma.result.count({
|
const totalViews = await prisma.result.count({
|
||||||
where: {
|
where: {
|
||||||
typebotId,
|
typebotId,
|
||||||
typebot: { ownerId: user.id },
|
typebot: canReadTypebot(typebotId, user),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const totalStarts = await prisma.result.count({
|
const totalStarts = await prisma.result.count({
|
||||||
where: {
|
where: {
|
||||||
typebotId,
|
typebotId,
|
||||||
typebot: { ownerId: user.id },
|
typebot: canReadTypebot(typebotId, user),
|
||||||
answers: { some: {} },
|
answers: { some: {} },
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const totalCompleted = await prisma.result.count({
|
const totalCompleted = await prisma.result.count({
|
||||||
where: {
|
where: {
|
||||||
typebotId,
|
typebotId,
|
||||||
typebot: { ownerId: user.id },
|
typebot: canReadTypebot(typebotId, user),
|
||||||
isCompleted: true,
|
isCompleted: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -2,14 +2,19 @@ import { withSentry } from '@sentry/nextjs'
|
|||||||
import prisma from 'libs/prisma'
|
import prisma from 'libs/prisma'
|
||||||
import { defaultWebhookAttributes } from 'models'
|
import { defaultWebhookAttributes } from 'models'
|
||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
import { NextApiRequest, NextApiResponse } from 'next'
|
||||||
|
import { canWriteTypebot } from 'services/api/dbRules'
|
||||||
import { getAuthenticatedUser } from 'services/api/utils'
|
import { getAuthenticatedUser } from 'services/api/utils'
|
||||||
import { methodNotAllowed, notAuthenticated } from 'utils'
|
import { forbidden, methodNotAllowed, notAuthenticated } from 'utils'
|
||||||
|
|
||||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
const user = await getAuthenticatedUser(req)
|
const user = await getAuthenticatedUser(req)
|
||||||
if (!user) return notAuthenticated(res)
|
if (!user) return notAuthenticated(res)
|
||||||
if (req.method === 'POST') {
|
if (req.method === 'POST') {
|
||||||
const typebotId = req.query.typebotId as string
|
const typebotId = req.query.typebotId as string
|
||||||
|
const typebot = await prisma.typebot.findFirst({
|
||||||
|
where: canWriteTypebot(typebotId, user),
|
||||||
|
})
|
||||||
|
if (!typebot) return forbidden(res)
|
||||||
const webhook = await prisma.webhook.create({
|
const webhook = await prisma.webhook.create({
|
||||||
data: { typebotId, ...defaultWebhookAttributes },
|
data: { typebotId, ...defaultWebhookAttributes },
|
||||||
})
|
})
|
||||||
|
@ -2,7 +2,11 @@ import test, { expect } from '@playwright/test'
|
|||||||
import cuid from 'cuid'
|
import cuid from 'cuid'
|
||||||
import { InputStepType, defaultTextInputOptions } from 'models'
|
import { InputStepType, defaultTextInputOptions } from 'models'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { createTypebots, parseDefaultBlockWithStep } from '../services/database'
|
import {
|
||||||
|
createResults,
|
||||||
|
createTypebots,
|
||||||
|
parseDefaultBlockWithStep,
|
||||||
|
} from '../services/database'
|
||||||
|
|
||||||
const typebotId = cuid()
|
const typebotId = cuid()
|
||||||
|
|
||||||
@ -18,6 +22,7 @@ test.beforeAll(async () => {
|
|||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
await createResults({ typebotId })
|
||||||
})
|
})
|
||||||
|
|
||||||
test.describe('Typebot owner', () => {
|
test.describe('Typebot owner', () => {
|
||||||
@ -67,5 +72,7 @@ test.describe('Collaborator', () => {
|
|||||||
await expect(page.locator('text=Free user')).toBeVisible()
|
await expect(page.locator('text=Free user')).toBeVisible()
|
||||||
await page.click('text=Block #1', { force: true })
|
await page.click('text=Block #1', { force: true })
|
||||||
await expect(page.locator('input[value="Block #1"]')).toBeHidden()
|
await expect(page.locator('input[value="Block #1"]')).toBeHidden()
|
||||||
|
await page.goto(`/typebots/${typebotId}/results`)
|
||||||
|
await expect(page.locator('text="content199"')).toBeVisible()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
33
apps/builder/services/api/dbRules.ts
Normal file
33
apps/builder/services/api/dbRules.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { CollaborationType, Prisma, User } from 'db'
|
||||||
|
|
||||||
|
const parseWhereFilter = (
|
||||||
|
typebotId: string,
|
||||||
|
user: User,
|
||||||
|
type: 'read' | 'write'
|
||||||
|
): Prisma.TypebotWhereInput => ({
|
||||||
|
OR: [
|
||||||
|
{
|
||||||
|
id: typebotId,
|
||||||
|
ownerId:
|
||||||
|
(type === 'read' && user.email === process.env.ADMIN_EMAIL) ||
|
||||||
|
process.env.NEXT_PUBLIC_E2E_TEST
|
||||||
|
? undefined
|
||||||
|
: user.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: typebotId,
|
||||||
|
collaborators: {
|
||||||
|
some: {
|
||||||
|
userId: user.id,
|
||||||
|
type: type === 'write' ? CollaborationType.WRITE : undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
export const canReadTypebot = (typebotId: string, user: User) =>
|
||||||
|
parseWhereFilter(typebotId, user, 'read')
|
||||||
|
|
||||||
|
export const canWriteTypebot = (typebotId: string, user: User) =>
|
||||||
|
parseWhereFilter(typebotId, user, 'write')
|
@ -161,7 +161,7 @@ export const ChatBlock = ({
|
|||||||
return onBlockEnd(currentStep.outgoingEdgeId)
|
return onBlockEnd(currentStep.outgoingEdgeId)
|
||||||
}
|
}
|
||||||
const nextStep = steps[processedSteps.length + startStepIndex]
|
const nextStep = steps[processedSteps.length + startStepIndex]
|
||||||
if (nextStep) insertStepInStack(nextStep)
|
nextStep ? insertStepInStack(nextStep) : onBlockEnd()
|
||||||
}
|
}
|
||||||
|
|
||||||
const avatarSrc = typebot.theme.chat.hostAvatar?.url
|
const avatarSrc = typebot.theme.chat.hostAvatar?.url
|
||||||
|
Reference in New Issue
Block a user