fix(results): 🔒️ Improve delete security checks
This commit is contained in:
@ -4,7 +4,6 @@ import { SubmissionsTable } from 'components/results/SubmissionsTable'
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
import {
|
||||
convertResultsToTableData,
|
||||
deleteAllResults,
|
||||
deleteResults,
|
||||
getAllResults,
|
||||
useResults,
|
||||
@ -70,10 +69,11 @@ export const SubmissionsContent = ({
|
||||
const selectedIds = (results ?? [])
|
||||
.filter((_, idx) => selectedIndices.includes(idx))
|
||||
.map((result) => result.id)
|
||||
const { error } =
|
||||
totalSelected === totalResults
|
||||
? await deleteAllResults(typebotId)
|
||||
: await deleteResults(typebotId, selectedIds)
|
||||
const { error } = await deleteResults(
|
||||
workspaceId,
|
||||
typebotId,
|
||||
totalSelected === totalResults ? [] : selectedIds
|
||||
)
|
||||
if (error) showToast({ description: error.message, title: error.name })
|
||||
else {
|
||||
mutate(
|
||||
|
@ -2,7 +2,7 @@ import { rest, setupWorker } from 'msw'
|
||||
import { setupServer } from 'msw/node'
|
||||
|
||||
const handlers = () => [
|
||||
rest.get('/api/auth/session', (req, res, ctx) => {
|
||||
rest.get('http://localhost:3000/api/auth/session', (req, res, ctx) => {
|
||||
const authenticatedUser = JSON.parse(
|
||||
typeof localStorage !== 'undefined'
|
||||
? (localStorage.getItem('authenticatedUser') as string)
|
||||
|
@ -15,13 +15,13 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const user = await getAuthenticatedUser(req)
|
||||
if (!user) return notAuthenticated(res)
|
||||
const workspaceId = req.query.workspaceId as string | undefined
|
||||
if (!workspaceId) return badRequest(res, 'workspaceId is required')
|
||||
const workspace = await prisma.workspace.findFirst({
|
||||
where: { id: workspaceId, members: { some: { userId: user.id } } },
|
||||
select: { plan: true },
|
||||
})
|
||||
if (!workspace) return forbidden(res)
|
||||
if (req.method === 'GET') {
|
||||
if (!workspaceId) return badRequest(res, 'workspaceId is required')
|
||||
const workspace = await prisma.workspace.findFirst({
|
||||
where: { id: workspaceId, members: { some: { userId: user.id } } },
|
||||
select: { plan: true },
|
||||
})
|
||||
if (!workspace) return forbidden(res)
|
||||
const typebotId = req.query.typebotId.toString()
|
||||
const lastResultId = req.query.lastResultId?.toString()
|
||||
const take = parseInt(req.query.limit?.toString())
|
||||
@ -46,7 +46,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
return res.status(200).send({ results })
|
||||
}
|
||||
if (req.method === 'DELETE') {
|
||||
const typebotId = req.query.typebotId.toString()
|
||||
const typebotId = req.query.typebotId as string
|
||||
const ids = req.query.ids as string[]
|
||||
const results = await prisma.result.deleteMany({
|
||||
where: {
|
||||
|
@ -57,10 +57,12 @@ test.describe('Results page', () => {
|
||||
await deleteButtonInConfirmDialog(page).click()
|
||||
await expect(page.locator('text=content199')).toBeHidden()
|
||||
await expect(page.locator('text=content198')).toBeHidden()
|
||||
await page.waitForTimeout(1000)
|
||||
await page.click('[data-testid="checkbox"] >> nth=0')
|
||||
await page.click('button:has-text("Delete198")')
|
||||
await deleteButtonInConfirmDialog(page).click()
|
||||
await expect(page.locator(':nth-match(tr, 2)')).toBeHidden()
|
||||
await page.waitForTimeout(1000)
|
||||
expect(await page.locator('tr').count()).toBe(1)
|
||||
})
|
||||
|
||||
test('submissions table should have infinite scroll', async ({ page }) => {
|
||||
|
@ -76,10 +76,15 @@ export const useResults = ({
|
||||
}
|
||||
}
|
||||
|
||||
export const deleteResults = async (typebotId: string, ids: string[]) => {
|
||||
export const deleteResults = async (
|
||||
workspaceId: string,
|
||||
typebotId: string,
|
||||
ids: string[]
|
||||
) => {
|
||||
const params = stringify(
|
||||
{
|
||||
ids,
|
||||
workspaceId,
|
||||
},
|
||||
{ indices: false }
|
||||
)
|
||||
@ -89,12 +94,6 @@ export const deleteResults = async (typebotId: string, ids: string[]) => {
|
||||
})
|
||||
}
|
||||
|
||||
export const deleteAllResults = async (typebotId: string) =>
|
||||
sendRequest({
|
||||
url: `/api/typebots/${typebotId}/results`,
|
||||
method: 'DELETE',
|
||||
})
|
||||
|
||||
export const getAllResults = async (workspaceId: string, typebotId: string) => {
|
||||
const results = []
|
||||
let hasMore = true
|
||||
|
@ -3604,9 +3604,9 @@
|
||||
set-cookie-parser "^2.4.6"
|
||||
|
||||
"@mswjs/interceptors@^0.15.1":
|
||||
version "0.15.1"
|
||||
resolved "https://registry.yarnpkg.com/@mswjs/interceptors/-/interceptors-0.15.1.tgz#4a0009f56e51bc2cd3176f1507065c7d2f6c0d5e"
|
||||
integrity sha512-D5B+ZJNlfvBm6ZctAfRBdNJdCHYAe2Ix4My5qfbHV5WH+3lkt3mmsjiWJzEh5ZwGDauzY487TldI275If7DJVw==
|
||||
version "0.15.3"
|
||||
resolved "https://registry.yarnpkg.com/@mswjs/interceptors/-/interceptors-0.15.3.tgz#bcd17b5d7558d4f598007a4bb383b42dc9264f8d"
|
||||
integrity sha512-GJ1qzBq82EQ3bwhsvw5nScbrLzOSI5H/TyB2CGd1K7dDqX58DJDLJHexiN+S5Ucvl6/84FjRdIysz0RxE/L8MA==
|
||||
dependencies:
|
||||
"@open-draft/until" "^1.0.3"
|
||||
"@xmldom/xmldom" "^0.7.5"
|
||||
|
Reference in New Issue
Block a user