mirror of
https://github.com/formbricks/formbricks.git
synced 2026-01-06 13:49:54 -06:00
Merge branch 'main' of https://github.com/formbricks/formbricks into feat-advanced-logic-editor
This commit is contained in:
@@ -4,7 +4,7 @@ import { z } from "zod";
|
||||
import { createActionClass } from "@formbricks/lib/actionClass/service";
|
||||
import { actionClient, authenticatedActionClient } from "@formbricks/lib/actionClient";
|
||||
import { checkAuthorization } from "@formbricks/lib/actionClient/utils";
|
||||
import { UNSPLASH_ACCESS_KEY } from "@formbricks/lib/constants";
|
||||
import { UNSPLASH_ACCESS_KEY, UNSPLASH_ALLOWED_DOMAINS } from "@formbricks/lib/constants";
|
||||
import {
|
||||
getOrganizationIdFromEnvironmentId,
|
||||
getOrganizationIdFromProductId,
|
||||
@@ -227,13 +227,26 @@ export const getImagesFromUnsplashAction = actionClient
|
||||
});
|
||||
});
|
||||
|
||||
const isValidUnsplashUrl = (url: string): boolean => {
|
||||
try {
|
||||
const parsedUrl = new URL(url);
|
||||
return parsedUrl.protocol === "https:" && UNSPLASH_ALLOWED_DOMAINS.includes(parsedUrl.hostname);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const ZTriggerDownloadUnsplashImageAction = z.object({
|
||||
downloadUrl: z.string(),
|
||||
downloadUrl: z.string().url(),
|
||||
});
|
||||
|
||||
export const triggerDownloadUnsplashImageAction = actionClient
|
||||
.schema(ZTriggerDownloadUnsplashImageAction)
|
||||
.action(async ({ parsedInput }) => {
|
||||
if (!isValidUnsplashUrl(parsedInput.downloadUrl)) {
|
||||
throw new Error("Invalid Unsplash URL");
|
||||
}
|
||||
|
||||
const response = await fetch(`${parsedInput.downloadUrl}/?client_id=${UNSPLASH_ACCESS_KEY}`, {
|
||||
method: "GET",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
|
||||
@@ -168,6 +168,7 @@ export const RATE_LIMITING_DISABLED = env.RATE_LIMITING_DISABLED === "1";
|
||||
export const CUSTOMER_IO_SITE_ID = env.CUSTOMER_IO_SITE_ID;
|
||||
export const CUSTOMER_IO_API_KEY = env.CUSTOMER_IO_API_KEY;
|
||||
export const UNSPLASH_ACCESS_KEY = env.UNSPLASH_ACCESS_KEY;
|
||||
export const UNSPLASH_ALLOWED_DOMAINS = ["api.unsplash.com"];
|
||||
|
||||
export const STRIPE_API_VERSION = "2024-06-20";
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
ZResponseInput,
|
||||
ZResponseUpdateInput,
|
||||
} from "@formbricks/types/responses";
|
||||
import { TSurveySummary } from "@formbricks/types/surveys/types";
|
||||
import { TSurvey, TSurveyQuestionTypeEnum, TSurveySummary } from "@formbricks/types/surveys/types";
|
||||
import { TTag } from "@formbricks/types/tags";
|
||||
import { getAttributes } from "../attribute/service";
|
||||
import { cache } from "../cache";
|
||||
@@ -28,7 +28,7 @@ import { createPerson, getPersonByUserId } from "../person/service";
|
||||
import { sendPlanLimitsReachedEventToPosthogWeekly } from "../posthogServer";
|
||||
import { responseNoteCache } from "../responseNote/cache";
|
||||
import { getResponseNotes } from "../responseNote/service";
|
||||
import { putFile } from "../storage/service";
|
||||
import { deleteFile, putFile } from "../storage/service";
|
||||
import { getSurvey } from "../survey/service";
|
||||
import { captureTelemetry } from "../telemetry";
|
||||
import { convertToCsv, convertToXlsxBuffer } from "../utils/fileConversion";
|
||||
@@ -706,6 +706,35 @@ export const updateResponse = async (
|
||||
}
|
||||
};
|
||||
|
||||
const findAndDeleteUploadedFilesInResponse = async (response: TResponse, survey: TSurvey): Promise<void> => {
|
||||
const fileUploadQuestions = new Set(
|
||||
survey.questions
|
||||
.filter((question) => question.type === TSurveyQuestionTypeEnum.FileUpload)
|
||||
.map((q) => q.id)
|
||||
);
|
||||
|
||||
const fileUrls = Object.entries(response.data)
|
||||
.filter(([questionId]) => fileUploadQuestions.has(questionId))
|
||||
.flatMap(([, questionResponse]) => questionResponse as string[]);
|
||||
|
||||
const deletionPromises = fileUrls.map(async (fileUrl) => {
|
||||
try {
|
||||
const { pathname } = new URL(fileUrl);
|
||||
const [, environmentId, accessType, fileName] = pathname.split("/").filter(Boolean);
|
||||
|
||||
if (!environmentId || !accessType || !fileName) {
|
||||
throw new Error(`Invalid file path: ${pathname}`);
|
||||
}
|
||||
|
||||
return deleteFile(environmentId, accessType as "private" | "public", fileName);
|
||||
} catch (error) {
|
||||
console.error(`Failed to delete file ${fileUrl}:`, error);
|
||||
}
|
||||
});
|
||||
|
||||
await Promise.all(deletionPromises);
|
||||
};
|
||||
|
||||
export const deleteResponse = async (responseId: string): Promise<TResponse> => {
|
||||
validateInputs([responseId, ZId]);
|
||||
try {
|
||||
@@ -727,6 +756,16 @@ export const deleteResponse = async (responseId: string): Promise<TResponse> =>
|
||||
|
||||
const survey = await getSurvey(response.surveyId);
|
||||
|
||||
if (survey) {
|
||||
await findAndDeleteUploadedFilesInResponse(
|
||||
{
|
||||
...responsePrisma,
|
||||
tags: responsePrisma.tags.map((tag) => tag.tag),
|
||||
},
|
||||
survey
|
||||
);
|
||||
}
|
||||
|
||||
responseCache.revalidate({
|
||||
environmentId: survey?.environmentId,
|
||||
id: response.id,
|
||||
|
||||
@@ -571,7 +571,42 @@ export const updateSurvey = async (updatedSurvey: TSurvey): Promise<TSurvey> =>
|
||||
id: segment.id,
|
||||
environmentId: segment.environmentId,
|
||||
});
|
||||
} else if (type === "app") {
|
||||
if (!currentSurvey.segment) {
|
||||
await prisma.survey.update({
|
||||
where: {
|
||||
id: surveyId,
|
||||
},
|
||||
data: {
|
||||
segment: {
|
||||
connectOrCreate: {
|
||||
where: {
|
||||
environmentId_title: {
|
||||
environmentId,
|
||||
title: surveyId,
|
||||
},
|
||||
},
|
||||
create: {
|
||||
title: surveyId,
|
||||
isPrivate: true,
|
||||
filters: [],
|
||||
environment: {
|
||||
connect: {
|
||||
id: environmentId,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
segmentCache.revalidate({
|
||||
environmentId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
data.questions = questions.map((question) => {
|
||||
const { isDraft, ...rest } = question;
|
||||
return rest;
|
||||
|
||||
Reference in New Issue
Block a user