Skip to content

Commit 9a9942c

Browse files
authored
Merge pull request #18785 from mozilla/fxa-11452-user-signout-redirect
fix(next): sign out retains current location
2 parents 148601c + 26e1786 commit 9a9942c

6 files changed

Lines changed: 96 additions & 25 deletions

File tree

apps/payments/next/app/[locale]/[offeringId]/[interval]/checkout/[cartId]/layout.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import { headers } from 'next/headers';
55
import {
66
CouponForm,
7+
Header,
78
MetricsWrapper,
89
PurchaseDetails,
910
SelectTaxLocation,
@@ -22,7 +23,7 @@ import {
2223
TermsAndPrivacy,
2324
} from '@fxa/payments/ui/server';
2425
import { CartState } from '@fxa/shared/db/mysql/account';
25-
import { auth } from 'apps/payments/next/auth';
26+
import { auth, signOut } from 'apps/payments/next/auth';
2627
import { config } from 'apps/payments/next/config';
2728

2829
export interface CheckoutSearchParams {
@@ -57,6 +58,16 @@ export default async function CheckoutLayout({
5758
cms.defaultPurchase.purchaseDetails;
5859
return (
5960
<MetricsWrapper cart={cart}>
61+
<Header
62+
auth={{
63+
user: session?.user,
64+
signOut: async () => {
65+
'use server';
66+
await signOut({ redirect: false });
67+
},
68+
}}
69+
cart={cart}
70+
/>
6071
{session?.user?.email && (
6172
<div className="mb-8 tablet:hidden">
6273
<SignedIn email={session.user.email} />

apps/payments/next/app/[locale]/[offeringId]/[interval]/new/page.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,13 @@ export default async function New({
5656

5757
const fxaUid = session?.user?.id;
5858
const coupon = searchParams.coupon || undefined;
59+
const countryCode = searchParams.countryCode;
60+
const postalCode = searchParams.postalCode;
5961

60-
const taxAddress = await getTaxAddressAction(ipAddress, fxaUid);
62+
const taxAddress =
63+
countryCode && postalCode
64+
? { countryCode, postalCode }
65+
: await getTaxAddressAction(ipAddress, fxaUid);
6166

6267
// Check if the customer is in a location not supported by Subscription Platform
6368
// or whether the product is not available in the customer's location

apps/payments/next/app/[locale]/[offeringId]/[interval]/upgrade/[cartId]/(mainLayout)/layout.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

55
import { headers } from 'next/headers';
6-
import { MetricsWrapper, PurchaseDetails } from '@fxa/payments/ui';
6+
import { Header, MetricsWrapper, PurchaseDetails } from '@fxa/payments/ui';
77
import { fetchCMSData, getCartAction } from '@fxa/payments/ui/actions';
88
import {
99
getApp,
@@ -13,6 +13,7 @@ import {
1313
TermsAndPrivacy,
1414
} from '@fxa/payments/ui/server';
1515
import { config } from 'apps/payments/next/config';
16+
import { auth, signOut } from 'apps/payments/next/auth';
1617

1718
export default async function UpgradeSuccessLayout({
1819
children,
@@ -26,12 +27,27 @@ export default async function UpgradeSuccessLayout({
2627
const l10n = getApp().getL10n(acceptLanguage, locale);
2728
const cartDataPromise = getCartAction(params.cartId);
2829
const cmsDataPromise = fetchCMSData(params.offeringId, locale);
29-
const [cms, cart] = await Promise.all([cmsDataPromise, cartDataPromise]);
30+
const sessionPromise = auth();
31+
const [cms, cart, session] = await Promise.all([
32+
cmsDataPromise,
33+
cartDataPromise,
34+
sessionPromise,
35+
]);
3036
const purchaseDetails =
3137
cms.defaultPurchase.purchaseDetails.localizations.at(0) ||
3238
cms.defaultPurchase.purchaseDetails;
3339
return (
3440
<MetricsWrapper cart={cart}>
41+
<Header
42+
auth={{
43+
user: session?.user,
44+
signOut: async () => {
45+
'use server';
46+
await signOut({ redirect: false });
47+
},
48+
}}
49+
cart={cart}
50+
/>
3551
<div className="mx-7 tablet:grid tablet:grid-cols-[minmax(min-content,500px)_minmax(20rem,1fr)] tablet:grid-rows-[min-content] tablet:gap-x-8 tablet:mb-auto desktop:grid-cols-[600px_1fr]">
3652
<SubscriptionTitle cart={cart} l10n={l10n} />
3753
<section

apps/payments/next/app/[locale]/[offeringId]/[interval]/upgrade/[cartId]/(startLayout)/layout.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import assert from 'assert';
66
import { headers } from 'next/headers';
7-
import { MetricsWrapper } from '@fxa/payments/ui';
7+
import { Header, MetricsWrapper } from '@fxa/payments/ui';
88
import { fetchCMSData, getCartAction } from '@fxa/payments/ui/actions';
99
import {
1010
getApp,
@@ -14,6 +14,7 @@ import {
1414
UpgradePurchaseDetails,
1515
} from '@fxa/payments/ui/server';
1616
import { config } from 'apps/payments/next/config';
17+
import { auth, signOut } from 'apps/payments/next/auth';
1718

1819
export default async function UpgradeLayout({
1920
children,
@@ -28,7 +29,12 @@ export default async function UpgradeLayout({
2829

2930
const cartDataPromise = getCartAction(params.cartId);
3031
const cmsDataPromise = fetchCMSData(params.offeringId, locale);
31-
const [cms, cart] = await Promise.all([cmsDataPromise, cartDataPromise]);
32+
const sessionPromise = auth();
33+
const [cms, cart, session] = await Promise.all([
34+
cmsDataPromise,
35+
cartDataPromise,
36+
sessionPromise,
37+
]);
3238
const purchaseDetails =
3339
cms.defaultPurchase.purchaseDetails.localizations.at(0) ||
3440
cms.defaultPurchase.purchaseDetails;
@@ -43,6 +49,16 @@ export default async function UpgradeLayout({
4349

4450
return (
4551
<MetricsWrapper cart={cart}>
52+
<Header
53+
auth={{
54+
user: session?.user,
55+
signOut: async () => {
56+
'use server';
57+
await signOut({ redirect: false });
58+
},
59+
}}
60+
cart={cart}
61+
/>
4662
<div className="mx-7 tablet:grid tablet:grid-cols-[minmax(min-content,500px)_minmax(20rem,1fr)] tablet:grid-rows-[min-content] tablet:gap-x-8 tablet:mb-auto desktop:grid-cols-[600px_1fr]">
4763
<SubscriptionTitle cart={cart} l10n={l10n} />
4864

apps/payments/next/app/[locale]/layout.tsx

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44
import { getApp } from '@fxa/payments/ui/server';
55
import { headers } from 'next/headers';
6-
import { Header, Providers } from '@fxa/payments/ui';
6+
import { Providers } from '@fxa/payments/ui';
77
import { config } from 'apps/payments/next/config';
8-
import { auth, signOut } from '../../auth';
98

109
export default async function RootProviderLayout({
1110
params,
@@ -23,8 +22,6 @@ export default async function RootProviderLayout({
2322
params.locale
2423
);
2524

26-
const session = await auth();
27-
2825
return (
2926
<Providers
3027
config={{
@@ -37,15 +34,6 @@ export default async function RootProviderLayout({
3734
fetchedMessages={fetchedMessages}
3835
nonce={nonce}
3936
>
40-
<Header
41-
auth={{
42-
user: session?.user,
43-
signOut: async () => {
44-
'use server';
45-
await signOut({ redirect: false });
46-
},
47-
}}
48-
/>
4937
{children}
5038
</Providers>
5139
);

libs/payments/ui/src/lib/client/components/Header/index.tsx

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,54 @@ import { useEscKeydownEffect } from '../../hooks/useEscKeydownEffect';
2525
import { User } from 'next-auth';
2626
import { constructHrefWithUtm } from '../../../utils/constructHrefWithUtm';
2727
import { OFFERING_LINKS } from '../../../constants';
28-
import { useParams, useRouter } from 'next/navigation';
28+
import {
29+
ReadonlyURLSearchParams,
30+
useParams,
31+
useRouter,
32+
useSearchParams,
33+
} from 'next/navigation';
34+
35+
function buildSignOutRedirectPath(
36+
params: Record<string, string | string[]>,
37+
searchParams: ReadonlyURLSearchParams,
38+
countryCode: string,
39+
postalCode: string
40+
) {
41+
const { locale, offeringId, interval } = params;
42+
const remainingQueryParams = searchParams.toString();
43+
const basePath = `/${locale}/${offeringId}/${interval}/new?countryCode=${countryCode}&postalCode=${postalCode}`;
44+
45+
if (remainingQueryParams) {
46+
return `${basePath}&${remainingQueryParams}`;
47+
} else {
48+
return basePath;
49+
}
50+
}
2951

3052
type HeaderProps = {
3153
auth?: {
3254
user: User | undefined;
3355
signOut: () => Promise<void>;
3456
};
57+
cart: {
58+
taxAddress: {
59+
countryCode: string;
60+
postalCode: string;
61+
};
62+
};
3563
};
3664

37-
export const Header = ({ auth }: HeaderProps) => {
65+
export const Header = ({ auth, cart }: HeaderProps) => {
3866
const router = useRouter();
39-
const { locale, offeringId, interval } = useParams();
67+
const params = useParams();
68+
const searchParams = useSearchParams();
69+
70+
const signOutRedirectPath = buildSignOutRedirectPath(
71+
params,
72+
searchParams,
73+
cart.taxAddress.countryCode,
74+
cart.taxAddress.postalCode
75+
);
4076

4177
const signedIn = auth && auth.user;
4278

@@ -362,9 +398,8 @@ export const Header = ({ auth }: HeaderProps) => {
362398
// As of this commit, both router.push and direct location.href overwriting are necessary to ensure
363399
// the browser is in the correct state without any contentless flashes
364400
await auth.signOut();
365-
const redirectUrl = `/${locale}/${offeringId}/${interval}/new`;
366-
router.push(redirectUrl);
367-
window.location.href = redirectUrl;
401+
router.push(signOutRedirectPath);
402+
window.location.href = signOutRedirectPath;
368403
}}
369404
className="pl-3 group"
370405
>

0 commit comments

Comments
 (0)