From 223937adcc435653e3e7ba898452efc4e5bc5908 Mon Sep 17 00:00:00 2001 From: Anshuman Pandey <54475686+pandeymangg@users.noreply.github.com> Date: Thu, 23 May 2024 19:46:57 +0530 Subject: [PATCH] feat: adds a POST endpoint for response creation in management apis (#2652) Co-authored-by: Matthias Nannt --- .../app/api/v1/management/responses/route.ts | 81 ++++++++++++++++++- packages/lib/response/service.ts | 41 +++++----- packages/types/responses.ts | 2 + 3 files changed, 102 insertions(+), 22 deletions(-) diff --git a/apps/web/app/api/v1/management/responses/route.ts b/apps/web/app/api/v1/management/responses/route.ts index 3dd69912a6..1f8e068699 100644 --- a/apps/web/app/api/v1/management/responses/route.ts +++ b/apps/web/app/api/v1/management/responses/route.ts @@ -1,10 +1,12 @@ import { authenticateRequest } from "@/app/api/v1/auth"; import { responses } from "@/app/lib/api/response"; +import { transformErrorToDetails } from "@/app/lib/api/validator"; import { NextRequest } from "next/server"; -import { getResponses, getResponsesByEnvironmentId } from "@formbricks/lib/response/service"; -import { DatabaseError } from "@formbricks/types/errors"; -import { TResponse } from "@formbricks/types/responses"; +import { createResponse, getResponses, getResponsesByEnvironmentId } from "@formbricks/lib/response/service"; +import { getSurvey } from "@formbricks/lib/survey/service"; +import { DatabaseError, InvalidInputError } from "@formbricks/types/errors"; +import { TResponse, ZResponseInput } from "@formbricks/types/responses"; export const GET = async (request: NextRequest) => { const searchParams = request.nextUrl.searchParams; @@ -30,3 +32,76 @@ export const GET = async (request: NextRequest) => { throw error; } }; + +export const POST = async (request: Request): Promise => { + try { + const authentication = await authenticateRequest(request); + if (!authentication) return responses.notAuthenticatedResponse(); + + const environmentId = authentication.environmentId; + + let jsonInput; + + try { + jsonInput = await request.json(); + } catch (err) { + console.error(`Error parsing JSON input: ${err}`); + return responses.badRequestResponse("Malformed JSON input, please check your request body"); + } + + // add environmentId to response + jsonInput.environmentId = environmentId; + + const inputValidation = ZResponseInput.safeParse(jsonInput); + + if (!inputValidation.success) { + return responses.badRequestResponse( + "Fields are missing or incorrectly formatted", + transformErrorToDetails(inputValidation.error), + true + ); + } + + const responseInput = inputValidation.data; + + // get and check survey + const survey = await getSurvey(responseInput.surveyId); + if (!survey) { + return responses.notFoundResponse("Survey", responseInput.surveyId, true); + } + if (survey.environmentId !== environmentId) { + return responses.badRequestResponse( + "Survey is part of another environment", + { + "survey.environmentId": survey.environmentId, + environmentId, + }, + true + ); + } + + // if there is a createdAt but no updatedAt, set updatedAt to createdAt + if (responseInput.createdAt && !responseInput.updatedAt) { + responseInput.updatedAt = responseInput.createdAt; + } + + let response: TResponse; + try { + response = await createResponse(inputValidation.data); + } catch (error) { + if (error instanceof InvalidInputError) { + return responses.badRequestResponse(error.message); + } else { + console.error(error); + return responses.internalServerErrorResponse(error.message); + } + } + + return responses.successResponse(response, true); + } catch (error) { + if (error instanceof DatabaseError) { + return responses.badRequestResponse(error.message); + } + throw error; + } +}; diff --git a/packages/lib/response/service.ts b/packages/lib/response/service.ts index 3115806a7c..266eec00b9 100644 --- a/packages/lib/response/service.ts +++ b/packages/lib/response/service.ts @@ -203,6 +203,7 @@ export const createResponse = async (responseInput: TResponseInput): Promise; export const ZResponseInput = z.object({ + createdAt: z.coerce.date().optional(), + updatedAt: z.coerce.date().optional(), environmentId: z.string().cuid2(), surveyId: z.string().cuid2(), userId: z.string().nullish(),