2
0

🐛 (share) Restrict public ID to non-existant only

This commit is contained in:
Baptiste Arnaud
2022-11-04 13:53:54 +01:00
parent 4d38726eae
commit 63845effaf
5 changed files with 70 additions and 3 deletions

View File

@ -22,16 +22,22 @@ import { getViewerUrl, isDefined, isNotDefined } from 'utils'
import { CustomDomainsDropdown } from './customDomain/CustomDomainsDropdown' import { CustomDomainsDropdown } from './customDomain/CustomDomainsDropdown'
import { EditableUrl } from './EditableUrl' import { EditableUrl } from './EditableUrl'
import { integrationsList } from './integrations/EmbedButton' import { integrationsList } from './integrations/EmbedButton'
import { isPublicDomainAvailableQuery } from './queries/isPublicDomainAvailableQuery'
export const ShareContent = () => { export const ShareContent = () => {
const { workspace } = useWorkspace() const { workspace } = useWorkspace()
const { typebot, updateTypebot } = useTypebot() const { typebot, updateTypebot } = useTypebot()
const { showToast } = useToast() const { showToast } = useToast()
const handlePublicIdChange = (publicId: string) => { const handlePublicIdChange = async (publicId: string) => {
if (publicId === typebot?.publicId) return if (publicId === typebot?.publicId) return
if (publicId.length < 4) if (publicId.length < 4)
return showToast({ description: 'ID must be longer than 4 characters' }) return showToast({ description: 'ID must be longer than 4 characters' })
const { data } = await isPublicDomainAvailableQuery(publicId)
if (!data?.isAvailable)
return showToast({ description: 'ID is already taken' })
updateTypebot({ publicId }) updateTypebot({ publicId })
} }

View File

@ -0,0 +1,7 @@
import { sendRequest } from 'utils'
export const isPublicDomainAvailableQuery = (publicId: string) =>
sendRequest<{ isAvailable: boolean }>({
method: 'GET',
url: `/api/publicIdAvailable?publicId=${publicId}`,
})

View File

@ -0,0 +1,19 @@
import { withSentry } from '@sentry/nextjs'
import prisma from 'libs/prisma'
import { NextApiRequest, NextApiResponse } from 'next'
import { getAuthenticatedUser } from 'services/api/utils'
import { badRequest, methodNotAllowed, notAuthenticated } from 'utils/api'
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const user = await getAuthenticatedUser(req)
if (!user) return notAuthenticated(res)
if (req.method === 'GET') {
const publicId = req.query.publicId as string | undefined
if (!publicId) return badRequest(res, 'publicId is required')
const exists = await prisma.typebot.count({ where: { publicId } })
return res.send({ isAvailable: Boolean(!exists) })
}
return methodNotAllowed(res)
}
export default withSentry(handler)

View File

@ -0,0 +1,35 @@
import test, { expect } from '@playwright/test'
import cuid from 'cuid'
import { defaultTextInputOptions, InputBlockType } from 'models'
import { createTypebots } from 'utils/playwright/databaseActions'
import { parseDefaultGroupWithBlock } from 'utils/playwright/databaseHelpers'
test('should not be able to submit taken url ID', async ({ page }) => {
const takenTypebotId = cuid()
const typebotId = cuid()
await createTypebots([
{
id: takenTypebotId,
...parseDefaultGroupWithBlock({
type: InputBlockType.TEXT,
options: defaultTextInputOptions,
}),
publicId: 'taken-url-id',
},
])
await createTypebots([
{
id: typebotId,
...parseDefaultGroupWithBlock({
type: InputBlockType.TEXT,
options: defaultTextInputOptions,
}),
publicId: typebotId + '-public',
},
])
await page.goto(`/typebots/${typebotId}/share`)
await page.getByText(`${typebotId}-public`).click()
await page.getByRole('textbox').fill('taken-url-id')
await page.getByRole('textbox').press('Enter')
await expect(page.getByText('ID is already taken').nth(0)).toBeVisible()
})

View File

@ -159,7 +159,7 @@ export const createTypebots = async (partialTypebots: Partial<Typebot>[]) => {
return { return {
...typebot, ...typebot,
id: typebotId, id: typebotId,
publicId: typebotId + '-public', publicId: typebot.publicId ?? typebotId + '-public',
} }
}) })
await prisma.typebot.createMany({ await prisma.typebot.createMany({
@ -167,7 +167,7 @@ export const createTypebots = async (partialTypebots: Partial<Typebot>[]) => {
}) })
return prisma.publicTypebot.createMany({ return prisma.publicTypebot.createMany({
data: typebotsWithId.map((t) => data: typebotsWithId.map((t) =>
parseTypebotToPublicTypebot(t.id + '-public', parseTestTypebot(t)) parseTypebotToPublicTypebot(t.publicId, parseTestTypebot(t))
), ),
}) })
} }