2
0

fix(results): 🔒️ Improve delete security checks

This commit is contained in:
Baptiste Arnaud
2022-06-18 09:41:23 +02:00
parent 4e6217597c
commit 9352587298
6 changed files with 25 additions and 24 deletions

View File

@ -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(

View File

@ -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)

View File

@ -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: {

View File

@ -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 }) => {

View File

@ -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