From 2a212cbc84e4037a4cdf83c027fe80d85105929a Mon Sep 17 00:00:00 2001 From: Vincent Date: Wed, 23 Oct 2024 17:03:43 +0200 Subject: [PATCH] Don't derive FxA auth code from session --- .../(authenticated)/admin/fxa/actions.tsx | 14 +++++++-- .../user/(dashboard)/settings/actions.ts | 30 +++++++++++++++++-- src/app/functions/server/applyCoupon.ts | 4 +-- src/app/functions/server/deleteAccount.ts | 5 +--- src/app/functions/server/user.ts | 10 +++++-- 5 files changed, 50 insertions(+), 13 deletions(-) diff --git a/src/app/(proper_react)/(redesign)/(authenticated)/admin/fxa/actions.tsx b/src/app/(proper_react)/(redesign)/(authenticated)/admin/fxa/actions.tsx index afe06de11ac..dbb002176e8 100644 --- a/src/app/(proper_react)/(redesign)/(authenticated)/admin/fxa/actions.tsx +++ b/src/app/(proper_react)/(redesign)/(authenticated)/admin/fxa/actions.tsx @@ -10,6 +10,7 @@ import { getServerSession } from "../../../../../functions/server/getServerSessi import { isAdmin } from "../../../../../api/utils/auth"; import { logger } from "@sentry/utils"; import { captureException } from "@sentry/node"; +import { getSubscriberByFxaUid } from "../../../../../../db/tables/subscribers"; export async function getAttachedClientsAction() { const session = await getServerSession(); @@ -17,14 +18,23 @@ export async function getAttachedClientsAction() { if ( !session?.user?.email || !isAdmin(session.user.email) || - process.env.APP_ENV === "production" + process.env.APP_ENV === "production" || + typeof session?.user?.subscriber?.fxa_uid !== "string" ) { return notFound(); } + const subscriber = await getSubscriberByFxaUid( + session.user.subscriber.fxa_uid, + ); + if (!subscriber) { + logger.error("admin_fxa_no_subscriber_found"); + return notFound(); + } + try { const attachedClients = await getAttachedClients( - session?.user.subscriber?.fxa_access_token ?? "", + subscriber.fxa_access_token ?? "", ); return attachedClients; } catch (error) { diff --git a/src/app/(proper_react)/(redesign)/(authenticated)/user/(dashboard)/settings/actions.ts b/src/app/(proper_react)/(redesign)/(authenticated)/user/(dashboard)/settings/actions.ts index ee268fbc96a..f0007b3c02c 100644 --- a/src/app/(proper_react)/(redesign)/(authenticated)/user/(dashboard)/settings/actions.ts +++ b/src/app/(proper_react)/(redesign)/(authenticated)/user/(dashboard)/settings/actions.ts @@ -176,7 +176,20 @@ export async function onDeleteAccount() { }; } - await deleteAccount(session.user.subscriber); + const subscriber = await getSubscriberByFxaUid( + session.user.subscriber.fxa_uid, + ); + if (!subscriber) { + logger.error( + `Tried to delete an account with a session that could not be linked to a subscriber.`, + ); + return { + success: false, + error: "delete-account-with-invalid-session", + errorMessage: `User tried to delete their account, but we could not find it.`, + }; + } + await deleteAccount(subscriber); // Tell the front page to display an "account deleted" notification: cookies().set("justDeletedAccount", "justDeletedAccount", { @@ -202,7 +215,20 @@ export async function onApplyCouponCode() { }; } - const result = await applyCurrentCouponCode(session.user.subscriber); + const subscriber = await getSubscriberByFxaUid( + session.user.subscriber.fxa_uid, + ); + if (!subscriber) { + logger.error( + `Tried to apply a coupon code with a session that could not be linked to a subscriber.`, + ); + return { + success: false, + error: "apply-coupon-code-with-invalid-session", + errorMessage: `User tried to apply a coupon code, but we could not find their account.`, + }; + } + const result = await applyCurrentCouponCode(subscriber); return result; } diff --git a/src/app/functions/server/applyCoupon.ts b/src/app/functions/server/applyCoupon.ts index d337ac75ca7..9731976260a 100644 --- a/src/app/functions/server/applyCoupon.ts +++ b/src/app/functions/server/applyCoupon.ts @@ -11,9 +11,7 @@ import { } from "../../../db/tables/subscriber_coupons"; import { applyCoupon } from "../../../utils/fxa"; -export async function applyCurrentCouponCode( - subscriber: SubscriberRow | SerializedSubscriber, -) { +export async function applyCurrentCouponCode(subscriber: SubscriberRow) { logger.info("fxa_apply_coupon_code", { subscriber: subscriber.id, }); diff --git a/src/app/functions/server/deleteAccount.ts b/src/app/functions/server/deleteAccount.ts index 4ac9229b8f7..634fc122320 100644 --- a/src/app/functions/server/deleteAccount.ts +++ b/src/app/functions/server/deleteAccount.ts @@ -9,13 +9,10 @@ import { getOnerepProfileId, } from "../../../db/tables/subscribers"; import { deactivateProfile } from "./onerep"; -import { SerializedSubscriber } from "../../../next-auth"; import { deleteSubscription } from "../../../utils/fxa"; import { record } from "./glean"; -export async function deleteAccount( - subscriber: SubscriberRow | SerializedSubscriber, -) { +export async function deleteAccount(subscriber: SubscriberRow) { logger.info("fxa_delete_user", { subscriber: subscriber.id, }); diff --git a/src/app/functions/server/user.ts b/src/app/functions/server/user.ts index ee4bd38d12a..108ab78ccf3 100644 --- a/src/app/functions/server/user.ts +++ b/src/app/functions/server/user.ts @@ -4,10 +4,16 @@ import { Session } from "next-auth"; import { getBillingAndSubscriptions } from "../../../utils/fxa"; +import { getSubscriberByFxaUid } from "../../../db/tables/subscribers"; /* c8 ignore start */ export async function checkUserHasMonthlySubscription(user: Session["user"]) { - if (!user.subscriber?.fxa_access_token) { + if (!user.subscriber?.fxa_uid) { + console.error("FXA UID not set"); + return false; + } + const subscriber = await getSubscriberByFxaUid(user.subscriber.fxa_uid); + if (!subscriber || !subscriber.fxa_access_token) { console.error("FXA token not set"); return false; } @@ -18,7 +24,7 @@ export async function checkUserHasMonthlySubscription(user: Session["user"]) { } const billingAndSubscriptionInfo = await getBillingAndSubscriptions( - user.subscriber.fxa_access_token, + subscriber.fxa_access_token, ); if (billingAndSubscriptionInfo === null) {