fix: added checks on unauthorized server actions (#2218)

Co-authored-by: Matthias Nannt <mail@matthiasnannt.com>
This commit is contained in:
Piyush Gupta
2024-03-11 19:46:47 +05:30
committed by GitHub
parent 2e83adc846
commit 2089b339b4
6 changed files with 33 additions and 24 deletions

View File

@@ -4,7 +4,7 @@ import { useResponseFilter } from "@/app/(app)/environments/[environmentId]/comp
import { getFormattedFilters } from "@/app/lib/surveys/surveys";
import SurveyResultsTabs from "@/app/share/[sharingKey]/(analysis)/components/SurveyResultsTabs";
import ResponseTimeline from "@/app/share/[sharingKey]/(analysis)/responses/components/ResponseTimeline";
import { getResponsesUnauthorizedAction } from "@/app/share/[sharingKey]/action";
import { getResponsesBySurveySharingKeyAction } from "@/app/share/[sharingKey]/action";
import CustomFilter from "@/app/share/[sharingKey]/components/CustomFilter";
import SummaryHeader from "@/app/share/[sharingKey]/components/SummaryHeader";
import { useSearchParams } from "next/navigation";
@@ -65,24 +65,29 @@ const ResponsePage = ({
useEffect(() => {
const fetchInitialResponses = async () => {
const responses = await getResponsesUnauthorizedAction(surveyId, 1, responsesPerPage, filters);
const responses = await getResponsesBySurveySharingKeyAction(sharingKey, 1, responsesPerPage, filters);
if (responses.length < responsesPerPage) {
setHasMore(false);
}
setResponses(responses);
};
fetchInitialResponses();
}, [surveyId, filters, responsesPerPage]);
}, [filters, responsesPerPage, sharingKey]);
const fetchNextPage = useCallback(async () => {
const newPage = page + 1;
const newResponses = await getResponsesUnauthorizedAction(surveyId, newPage, responsesPerPage, filters);
const newResponses = await getResponsesBySurveySharingKeyAction(
sharingKey,
newPage,
responsesPerPage,
filters
);
if (newResponses.length === 0 || newResponses.length < responsesPerPage) {
setHasMore(false);
}
setResponses([...responses, ...newResponses]);
setPage(newPage);
}, [filters, page, responses, responsesPerPage, surveyId]);
}, [filters, page, responses, responsesPerPage, sharingKey]);
return (
<ContentWrapper>

View File

@@ -1,18 +1,17 @@
import ResponsePage from "@/app/share/[sharingKey]/(analysis)/responses/components/ResponsePage";
import { getResultShareUrlSurveyAction } from "@/app/share/[sharingKey]/action";
import { notFound } from "next/navigation";
import { RESPONSES_PER_PAGE, REVALIDATION_INTERVAL, WEBAPP_URL } from "@formbricks/lib/constants";
import { getEnvironment } from "@formbricks/lib/environment/service";
import { getProductByEnvironmentId } from "@formbricks/lib/product/service";
import { getResponsePersonAttributes } from "@formbricks/lib/response/service";
import { getSurvey } from "@formbricks/lib/survey/service";
import { getSurvey, getSurveyIdByResultShareKey } from "@formbricks/lib/survey/service";
import { getTagsByEnvironmentId } from "@formbricks/lib/tag/service";
export const revalidate = REVALIDATION_INTERVAL;
export default async function Page({ params }) {
const surveyId = await getResultShareUrlSurveyAction(params.sharingKey);
const surveyId = await getSurveyIdByResultShareKey(params.sharingKey);
if (!surveyId) {
return notFound();

View File

@@ -6,7 +6,7 @@ import SummaryList from "@/app/(app)/environments/[environmentId]/surveys/[surve
import SummaryMetadata from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryMetadata";
import { getFormattedFilters } from "@/app/lib/surveys/surveys";
import SurveyResultsTabs from "@/app/share/[sharingKey]/(analysis)/components/SurveyResultsTabs";
import { getSurveySummaryUnauthorizedAction } from "@/app/share/[sharingKey]/action";
import { getSummaryBySurveySharingKeyAction } from "@/app/share/[sharingKey]/action";
import CustomFilter from "@/app/share/[sharingKey]/components/CustomFilter";
import SummaryHeader from "@/app/share/[sharingKey]/components/SummaryHeader";
import { useSearchParams } from "next/navigation";
@@ -65,11 +65,11 @@ const SummaryPage = ({
useEffect(() => {
const fetchSurveySummary = async () => {
const response = await getSurveySummaryUnauthorizedAction(surveyId, filters);
const response = await getSummaryBySurveySharingKeyAction(sharingKey, filters);
setSurveySummary(response);
};
fetchSurveySummary();
}, [filters, surveyId]);
}, [filters, sharingKey]);
survey = useMemo(() => {
return checkForRecallInHeadline(survey);

View File

@@ -1,19 +1,18 @@
import { getAnalysisData } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/data";
import SummaryPage from "@/app/share/[sharingKey]/(analysis)/summary/components/SummaryPage";
import { getResultShareUrlSurveyAction } from "@/app/share/[sharingKey]/action";
import { notFound } from "next/navigation";
import { REVALIDATION_INTERVAL } from "@formbricks/lib/constants";
import { getEnvironment } from "@formbricks/lib/environment/service";
import { getProductByEnvironmentId } from "@formbricks/lib/product/service";
import { getResponsePersonAttributes } from "@formbricks/lib/response/service";
import { getSurvey } from "@formbricks/lib/survey/service";
import { getSurvey, getSurveyIdByResultShareKey } from "@formbricks/lib/survey/service";
import { getTagsByEnvironmentId } from "@formbricks/lib/tag/service";
export const revalidate = REVALIDATION_INTERVAL;
export default async function Page({ params }) {
const surveyId = await getResultShareUrlSurveyAction(params.sharingKey);
const surveyId = await getSurveyIdByResultShareKey(params.sharingKey);
if (!surveyId) {
return notFound();

View File

@@ -1,27 +1,30 @@
"use server";
import { getResponses, getSurveySummary } from "@formbricks/lib/response/service";
import { getSurveyByResultShareKey } from "@formbricks/lib/survey/service";
import { getSurveyIdByResultShareKey } from "@formbricks/lib/survey/service";
import { AuthorizationError } from "@formbricks/types/errors";
import { TResponse, TResponseFilterCriteria, TSurveySummary } from "@formbricks/types/responses";
export async function getResultShareUrlSurveyAction(key: string): Promise<string | null> {
return getSurveyByResultShareKey(key);
}
export async function getResponsesUnauthorizedAction(
surveyId: string,
export async function getResponsesBySurveySharingKeyAction(
sharingKey: string,
page: number,
batchSize?: number,
filterCriteria?: TResponseFilterCriteria
): Promise<TResponse[]> {
const surveyId = await getSurveyIdByResultShareKey(sharingKey);
if (!surveyId) throw new AuthorizationError("Not authorized");
batchSize = batchSize ?? 10;
const responses = await getResponses(surveyId, page, batchSize, filterCriteria);
return responses;
}
export const getSurveySummaryUnauthorizedAction = async (
surveyId: string,
export const getSummaryBySurveySharingKeyAction = async (
sharingKey: string,
filterCriteria?: TResponseFilterCriteria
): Promise<TSurveySummary> => {
const surveyId = await getSurveyIdByResultShareKey(sharingKey);
if (!surveyId) throw new AuthorizationError("Not authorized");
return await getSurveySummary(surveyId, filterCriteria);
};

View File

@@ -775,12 +775,15 @@ export const getSyncSurveys = async (
return surveys.map((survey) => formatDateFields(survey, ZSurvey));
};
export const getSurveyByResultShareKey = async (resultShareKey: string): Promise<string | null> => {
export const getSurveyIdByResultShareKey = async (resultShareKey: string): Promise<string | null> => {
try {
const survey = await prisma.survey.findFirst({
where: {
resultShareKey,
},
select: {
id: true,
},
});
if (!survey) {