Skip to content

Commit

Permalink
refactor(session): rename & smaller interfaces
Browse files Browse the repository at this point in the history
Renames:
* userDataFromRedis -> userData
* cookieId -> cookieHeader
* sessionContext -> sessionManager
* updateSessionInHeader -> updateMainSession
* sessionId -> debugId
* updateSessionWithCsrfToken -> createSessionWithCsrf

Refactor(csrf): pass cookieHeader instead of whole request

Co-Authored-By: Pram Gurusinga <[email protected]>
Co-Authored-By: Rafael Falk <[email protected]>
  • Loading branch information
3 people committed Mar 1, 2024
1 parent 5fb8358 commit 9700d0e
Show file tree
Hide file tree
Showing 15 changed files with 142 additions and 136 deletions.
7 changes: 5 additions & 2 deletions app/models/flows/fluggastrechte/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { guards as fluggastrechteVorabcheckGuards } from "~/models/flows/fluggastrechte/guards";
import fluggastrechteVorabcheckFlow from "~/models/flows/fluggastrechte/config.json";
import type { Context } from "../contexts";

export const fluggastrechteVorabcheck = {
cmsSlug: "vorab-check-pages",
Expand All @@ -19,5 +20,7 @@ export const partnerCourtAirports = {

type PartnerAirport = keyof typeof partnerCourtAirports;

export const isPartnerAirport = (airport: string): airport is PartnerAirport =>
airport in partnerCourtAirports;
export const isPartnerAirport = (
airport: Context[string],
): airport is PartnerAirport =>
typeof airport === "string" && airport in partnerCourtAirports;
4 changes: 2 additions & 2 deletions app/routes/action.send-rating.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ActionFunctionArgs } from "@remix-run/node";
import { json, redirect } from "@remix-run/node";
import { BannerState } from "~/components/UserFeedback";
import { userRatingFieldname } from "~/components/UserFeedback/RatingBox";
import { getSessionForContext } from "~/services/session.server";
import { getSessionManager } from "~/services/session.server";
import { bannerStateName } from "~/services/feedback/handleFeedback";
import { sendCustomEvent } from "~/services/analytics/customEvent";

Expand All @@ -16,7 +16,7 @@ export const action = async ({ request }: ActionFunctionArgs) => {
const formData = await request.formData();

const cookie = request.headers.get("Cookie");
const { getSession, commitSession } = getSessionForContext("main");
const { getSession, commitSession } = getSessionManager("main");
const session = await getSession(cookie);

const userRatings =
Expand Down
16 changes: 6 additions & 10 deletions app/routes/beratungshilfe.antrag.pdf.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
import { redirect, type LoaderFunctionArgs } from "@remix-run/node";
import _ from "lodash";
import type { BeratungshilfeFormularContext } from "~/models/flows/beratungshilfeFormular";
import { getBeratungshilfePdfFromContext } from "~/services/pdf/beratungshilfe/beratungshilfe.server";
import { getSessionForContext } from "~/services/session.server";
import { getSessionData } from "~/services/session.server";

export const loader = async ({ request }: LoaderFunctionArgs) => {
const cookieId = request.headers.get("Cookie");
const { data } = await getSessionForContext(
"beratungshilfe/antrag",
).getSession(cookieId);
const cookieHeader = request.headers.get("Cookie");
const flowId = "beratungshilfe/antrag";
const { userData } = await getSessionData(flowId, cookieHeader);

const context: BeratungshilfeFormularContext = data; // Recast for now to get type safety

if (_.isEmpty(context)) {
if (_.isEmpty(userData)) {
return redirect("/beratungshilfe/antrag");
}

return new Response(await getBeratungshilfePdfFromContext(context), {
return new Response(await getBeratungshilfePdfFromContext(userData), {
headers: {
"Content-Type": "application/pdf",
},
Expand Down
4 changes: 2 additions & 2 deletions app/routes/beratungshilfe.zustaendiges-gericht.suche.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
} from "~/services/cms/index.server";
import CourtFinderHeader from "~/components/CourtFinderHeader";
import PageContent from "~/components/PageContent";
import { getSessionForContext } from "~/services/session.server";
import { getSessionManager } from "~/services/session.server";
import { getReturnToURL } from "~/services/routing/getReturnToURL";
import { ButtonNavigation } from "~/components/form/ButtonNavigation";
import { postcodeSchema } from "~/services/validation/postcode";
Expand All @@ -30,7 +30,7 @@ const validatorServer = withZod(serverSchema);

export async function loader({ request }: LoaderFunctionArgs) {
const slug = new URL(request.url).pathname;
const sessionContext = getSessionForContext("beratungshilfe/vorabcheck");
const sessionContext = getSessionManager("beratungshilfe/vorabcheck");

const [common, { form, meta }] = await Promise.all([
fetchSingleEntry("amtsgericht-common"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
} from "~/services/gerichtsfinder/amtsgerichtData.server";
import { flowIDFromPathname } from "~/models/flows/contexts";
import { splatFromParams } from "~/services/params";
import { getSessionForContext } from "~/services/session.server";
import { getSessionManager } from "~/services/session.server";
import type { GeldEinklagenVorabcheckContext } from "~/models/flows/geldEinklagen/context";
import Heading from "~/components/Heading";
import type { ReactElement } from "react";
Expand All @@ -32,9 +32,10 @@ export const loader = async ({
}: LoaderFunctionArgs) => {
const { pathname } = new URL(request.url);
const flowId = flowIDFromPathname(pathname);
const cookieId = request.headers.get("Cookie");
const { data, id } = await getSessionForContext(flowId).getSession(cookieId);
context.sessionId = getSessionForContext(flowId).getSessionId(id); // For showing in errors
const cookieHeader = request.headers.get("Cookie");
const sessionManager = getSessionManager(flowId);
const { data, id } = await sessionManager.getSession(cookieHeader);
context.debugId = sessionManager.getDebugId(id); // For showing in errors

const contextData = data as GeldEinklagenVorabcheckContext;
const zipCodes = [
Expand Down
39 changes: 16 additions & 23 deletions app/routes/shared/formular.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { json, redirectDocument } from "@remix-run/node";
import { validationError } from "remix-validated-form";
import {
getSessionData,
getSessionForContext,
getSessionManager,
updateSession,
} from "~/services/session.server";
import {
Expand Down Expand Up @@ -36,7 +36,7 @@ import {
} from "~/services/session.server/arrayDeletion";
import { interpolateDeep } from "~/util/fillTemplate";
import { stepMeta } from "~/services/meta/formStepMeta";
import { updateSessionInHeader } from "~/services/session.server/updateSessionInHeader";
import { updateMainSession } from "~/services/session.server/updateSessionInHeader";

const structureCmsContent = (
formPageContent: z.infer<CollectionSchemas["form-flow-pages"]>,
Expand Down Expand Up @@ -86,19 +86,16 @@ export const loader = async ({
const { pathname, searchParams } = new URL(request.url);
const returnTo = searchParams.get("returnTo") ?? undefined;
const { flowId, stepId, arrayIndex } = parsePathname(pathname);
const cookieId = request.headers.get("Cookie");
const cookieHeader = request.headers.get("Cookie");

const { userDataFromRedis, sessionId } = await getSessionData(
flowId,
cookieId,
);
context.sessionId = sessionId; // For showing in errors
const { userData, debugId } = await getSessionData(flowId, cookieHeader);
context.debugId = debugId; // For showing in errors

// get flow controller
const currentFlow = flows[flowId];
const flowController = buildFlowController({
config: currentFlow.config,
data: userDataFromRedis,
data: userData,
guards: currentFlow.guards,
});

Expand Down Expand Up @@ -129,7 +126,7 @@ export const loader = async ({
const cmsContent = interpolateDeep(
structureCmsContent(formPageContent),
"stringReplacements" in currentFlow
? currentFlow.stringReplacements(userDataFromRedis)
? currentFlow.stringReplacements(userData)
: {},
);

Expand All @@ -150,25 +147,21 @@ export const loader = async ({

// filter user data for current step
const fieldNames = formPageContent.form.map((entry) => entry.name);
const stepData = stepDataFromFieldNames(
fieldNames,
userDataFromRedis,
arrayIndex,
);
const stepData = stepDataFromFieldNames(fieldNames, userData, arrayIndex);

// get array data to display in ArraySummary -> Formular + Vorabcheck?
const arrayData = Object.fromEntries(
formPageContent.pre_form.filter(isStrapiArraySummary).map((entry) => {
const possibleArray = userDataFromRedis[entry.arrayKey];
const possibleArray = userData[entry.arrayKey];
return [
entry.arrayKey,
Array.isArray(possibleArray) ? possibleArray : [],
];
}),
);

const { headers, csrf } = await updateSessionInHeader({
request,
const { headers, csrf } = await updateMainSession({
cookieHeader,
flowId,
stepId,
});
Expand All @@ -193,7 +186,7 @@ export const loader = async ({
stepId,
flowId,
currentFlow,
cookieId,
cookieHeader,
);

return json(
Expand Down Expand Up @@ -226,9 +219,9 @@ export const action = async ({ request }: ActionFunctionArgs) => {
}
const { pathname } = new URL(request.url);
const { flowId, stepId, arrayIndex } = parsePathname(pathname);
const { getSession, commitSession } = getSessionForContext(flowId);
const cookieId = request.headers.get("Cookie");
const flowSession = await getSession(cookieId);
const { getSession, commitSession } = getSessionManager(flowId);
const cookieHeader = request.headers.get("Cookie");
const flowSession = await getSession(cookieHeader);

const formData = await request.formData();
const currentFlow = flows[flowId];
Expand Down Expand Up @@ -263,7 +256,7 @@ export const action = async ({ request }: ActionFunctionArgs) => {
stepId,
flowId,
currentFlow,
cookieId,
cookieHeader,
);
if (migrationData && validationResult.data["doMigration"] === "yes") {
updateSession(flowSession, migrationData);
Expand Down
59 changes: 34 additions & 25 deletions app/routes/shared/result.server.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import type { ActionFunction, LoaderFunctionArgs } from "@remix-run/node";
import { json, redirect } from "@remix-run/node";
import { getSessionForContext, updateSession } from "~/services/session.server";
import {
getSessionData,
getSessionManager,
mainSessionFromCookieHeader,
updateSession,

Check warning on line 7 in app/routes/shared/result.server.ts

View workflow job for this annotation

GitHub Actions / code-quality / npm run eslint:check

'updateSession' is defined but never used
} from "~/services/session.server";
import {
fetchCollectionEntry,
fetchMeta,
Expand All @@ -12,7 +17,6 @@ import { parsePathname } from "~/models/flows/contexts";
import { flows } from "~/models/flows/flows.server";
import { BannerState } from "~/components/UserFeedback";
import { throw404IfFeatureFlagEnabled } from "~/services/errorPages/throw404";
import { lastStepKey } from "~/services/flow/constants";
import {
getFeedbackBannerState,
handleFeedback,
Expand All @@ -24,19 +28,29 @@ import {
} from "~/models/flows/fluggastrechte";
import { findCourt } from "~/services/gerichtsfinder/amtsgerichtData.server";
import type { Jmtd14VTErwerberGerbeh } from "~/services/gerichtsfinder/types";
import { updateMainSession } from "~/services/session.server/updateSessionInHeader";

export const loader = async ({ request, context }: LoaderFunctionArgs) => {
await throw404IfFeatureFlagEnabled(request);

// get data from request
const { pathname } = new URL(request.url);
const { flowId, stepId } = parsePathname(pathname);
const cookieId = request.headers.get("Cookie");
const flowSession = await getSessionForContext(flowId).getSession(cookieId);
const { data, id } = flowSession;
context.sessionId = getSessionForContext(flowId).getSessionId(id); // For showing in errors
const cookieHeader = request.headers.get("Cookie");

const sessionManager = getSessionManager(flowId);
const { userData, debugId } = await getSessionData(flowId, cookieHeader);
context.debugId = debugId; // For showing in errors

const flowController = buildFlowController({
config: flows[flowId].config,
data: userData,
guards: flows[flowId].guards,
});

if (!flowController.isReachable(stepId))
return redirect(flowController.getInitial());

const courts = [data.startAirport, data.endAirport]
const courts = [userData.startAirport, userData.endAirport]
.filter(isPartnerAirport)
.map((airport) => findCourt({ zipCode: partnerCourtAirports[airport] }))
.filter(Boolean) as Jmtd14VTErwerberGerbeh[];
Expand All @@ -49,18 +63,11 @@ export const loader = async ({ request, context }: LoaderFunctionArgs) => {
}));

if (zustaendigesAmtsgericht.length > 0) {
updateSession(flowSession, {
zustaendigesAmtsgericht: zustaendigesAmtsgericht[0],
});
await getSessionForContext(flowId).commitSession(flowSession);
const session = await sessionManager.getSession(cookieHeader);
session.set("zustaendigesAmtsgericht", zustaendigesAmtsgericht[0]);
await sessionManager.commitSession(session);
}

const { config, guards } = flows[flowId];
const flowController = buildFlowController({ config, data, guards });

if (!flowController.isReachable(stepId))
return redirect(flowController.getInitial());

// Slug change to keep Strapi slugs without ergebnis/
const slug = pathname.replace(/ergebnis\//, "");
const [common, cmsData, parentMeta, amtsgerichtCommon] = await Promise.all([
Expand All @@ -84,9 +91,12 @@ export const loader = async ({ request, context }: LoaderFunctionArgs) => {
label: cmsData.nextLink?.text ?? common.nextButtonDefaultLabel,
};

const { getSession, commitSession } = getSessionForContext("main");
const userDataFromRedis = await getSession(cookieId);
userDataFromRedis.set(lastStepKey, { [flowId]: stepId });
const mainSession = await mainSessionFromCookieHeader(cookieHeader);
const { headers } = await updateMainSession({
cookieHeader,
flowId,
stepId,
});

return json(
{
Expand All @@ -96,7 +106,7 @@ export const loader = async ({ request, context }: LoaderFunctionArgs) => {
content: cmsData.freeZone,
meta: { ...cmsData.meta, breadcrumbTitle: parentMeta?.title ?? "" },
reasons: reasonElementsWithID.filter((reason) =>
Boolean(getReasonsToDisplay(data)[reason.elementId]),
Boolean(getReasonsToDisplay(userData)[reason.elementId]),
),
progress: flowController.getProgress(stepId),
nextButton,
Expand All @@ -105,12 +115,11 @@ export const loader = async ({ request, context }: LoaderFunctionArgs) => {
label: common.backButtonDefaultLabel,
},
bannerState:
getFeedbackBannerState(userDataFromRedis, pathname) ??
BannerState.ShowRating,
getFeedbackBannerState(mainSession, pathname) ?? BannerState.ShowRating,
amtsgerichtCommon,
courts: cmsData.pageType === "success" && courts,
},
{ headers: { "Set-Cookie": await commitSession(userDataFromRedis) } },
{ headers },
);
};

Expand Down
Loading

0 comments on commit 9700d0e

Please sign in to comment.