Merged PR 2318: auth stabilisation: extract shared myportal auth guard helper
auth stabilisation: extract shared myportal auth guard helper ntroduces a small shared SSR helper (resolveMyPortalAuthContext) to standardize common myportal auth/session guards (session presence, session user identity, and pinsUser cookie) with preserved reason-coded diagnostics and signin redirect behavior. Migrates exactly two loaders (pages/myportal/searchresults.js, pages/myportal/addresssearchresults.js) to use the helper while keeping loader-specific UPSTREAM_FAILURE and CONTACT_LOOKUP_FAILED logic unchanged. Related work items: #23020
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
import { getSession } from "next-auth/react";
|
||||
import { consoleLogger } from "../../actions/core/logger";
|
||||
|
||||
const signinRedirect = {
|
||||
destination: "/auth/signin",
|
||||
permanent: false
|
||||
};
|
||||
|
||||
const buildSigninRedirectResult = () => ({ redirect: signinRedirect });
|
||||
|
||||
export async function resolveMyPortalAuthContext(ctx, options = {}) {
|
||||
const {
|
||||
loggerName = "MyPortalAuthGuard",
|
||||
noSessionMessage = "myportal loader missing session; redirecting to signin",
|
||||
noSessionUserMessage = "myportal loader missing session user identity; redirecting to signin",
|
||||
noPinsUserMessage = "myportal loader missing pinsUser cookie; redirecting to signin"
|
||||
} = options;
|
||||
|
||||
const session = await getSession(ctx);
|
||||
|
||||
if (!session) {
|
||||
consoleLogger({
|
||||
name: loggerName,
|
||||
reasonCode: "NO_SESSION",
|
||||
message: noSessionMessage
|
||||
});
|
||||
return { ok: false, redirect: buildSigninRedirectResult().redirect };
|
||||
}
|
||||
|
||||
if (!session?.user?.id || !session?.user?.email) {
|
||||
consoleLogger({
|
||||
name: loggerName,
|
||||
reasonCode: "NO_SESSION_USER",
|
||||
message: noSessionUserMessage,
|
||||
hasSessionUserId: !!session?.user?.id,
|
||||
hasSessionUserEmail: !!session?.user?.email
|
||||
});
|
||||
return { ok: false, redirect: buildSigninRedirectResult().redirect };
|
||||
}
|
||||
|
||||
const pinsUser = ctx?.req?.cookies?.pinsUser;
|
||||
if (!pinsUser) {
|
||||
consoleLogger({
|
||||
name: loggerName,
|
||||
reasonCode: "NO_PINSUSER_COOKIE",
|
||||
message: noPinsUserMessage
|
||||
});
|
||||
return { ok: false, redirect: buildSigninRedirectResult().redirect };
|
||||
}
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
session,
|
||||
sessionUserId: session.user.id,
|
||||
sessionUserEmail: session.user.email,
|
||||
pinsUser
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
import { getSession } from "next-auth/react";
|
||||
import useTranslation from "next-translate/useTranslation";
|
||||
import Head from "next/head";
|
||||
import { useRouter } from "next/router";
|
||||
@@ -39,6 +38,7 @@ import {
|
||||
import { wrapper } from "../../store/store";
|
||||
import ServiceBanner from "../../components/myportal/servicebanner";
|
||||
import TimeOut from "../../components/timeout";
|
||||
import { resolveMyPortalAuthContext } from "../../lib/auth/resolveMyPortalAuthContext";
|
||||
|
||||
const Home = (props) => {
|
||||
const { footerLinks, pages } = props;
|
||||
@@ -147,57 +147,23 @@ export const getServerSideProps = wrapper.getServerSideProps(
|
||||
store.dispatch(setShowReps(showReps, showLoginCheck));
|
||||
store.dispatch(setSearch(Object.entries(query)));
|
||||
|
||||
const { cookies } = req;
|
||||
|
||||
let loggedInUser = cookies.pinsUser;
|
||||
let thisSession = await getSession(ctx);
|
||||
|
||||
if (!thisSession) {
|
||||
consoleLogger({
|
||||
name: "MyPortalAddressSearchResultsAuthGuard",
|
||||
reasonCode: "NO_SESSION",
|
||||
message:
|
||||
"myportal addresssearchresults loader missing session; redirecting to signin"
|
||||
});
|
||||
return {
|
||||
redirect: {
|
||||
destination: "/auth/signin",
|
||||
permanent: false
|
||||
}
|
||||
};
|
||||
} else {
|
||||
if (!thisSession?.user?.id || !thisSession?.user?.email) {
|
||||
consoleLogger({
|
||||
name: "MyPortalAddressSearchResultsAuthGuard",
|
||||
reasonCode: "NO_SESSION_USER",
|
||||
message:
|
||||
const authContext = await resolveMyPortalAuthContext(ctx, {
|
||||
loggerName: "MyPortalAddressSearchResultsAuthGuard",
|
||||
noSessionMessage:
|
||||
"myportal addresssearchresults loader missing session; redirecting to signin",
|
||||
noSessionUserMessage:
|
||||
"myportal addresssearchresults loader missing session user identity; redirecting to signin",
|
||||
hasSessionUserId: !!thisSession?.user?.id,
|
||||
hasSessionUserEmail: !!thisSession?.user?.email
|
||||
});
|
||||
return {
|
||||
redirect: {
|
||||
destination: "/auth/signin",
|
||||
permanent: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (!loggedInUser) {
|
||||
consoleLogger({
|
||||
name: "MyPortalAddressSearchResultsAuthGuard",
|
||||
reasonCode: "NO_PINSUSER_COOKIE",
|
||||
message:
|
||||
noPinsUserMessage:
|
||||
"myportal addresssearchresults loader missing pinsUser cookie; redirecting to signin"
|
||||
});
|
||||
return {
|
||||
redirect: {
|
||||
destination: "/auth/signin",
|
||||
permanent: false
|
||||
}
|
||||
};
|
||||
|
||||
if (!authContext.ok) {
|
||||
return { redirect: authContext.redirect };
|
||||
}
|
||||
|
||||
const thisSession = authContext.session;
|
||||
const loggedInUser = authContext.pinsUser;
|
||||
|
||||
thisSession != false &&
|
||||
store.dispatch(setContainerID(thisSession.user.id));
|
||||
|
||||
@@ -259,7 +225,6 @@ export const getServerSideProps = wrapper.getServerSideProps(
|
||||
store.dispatch(setWatchedCasesDetails(watchedCasesDetails));
|
||||
store.dispatch(setSearch(Object.entries(query)));
|
||||
store.dispatch(setLoggedInUserId(loggedInUser));
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
|
||||
@@ -31,8 +31,8 @@ import {
|
||||
setWatchedCasesDetails
|
||||
} from "../../store/watchedCases/action";
|
||||
|
||||
import { getSession } from "next-auth/react";
|
||||
import TimeOut from "../../components/timeout";
|
||||
import { resolveMyPortalAuthContext } from "../../lib/auth/resolveMyPortalAuthContext";
|
||||
import {
|
||||
setAccountDetails,
|
||||
setContainerID,
|
||||
@@ -81,65 +81,29 @@ export const getServerSideProps = wrapper.getServerSideProps(
|
||||
getIP(req);
|
||||
console.log("query-", query);
|
||||
|
||||
const { cookies } = req;
|
||||
|
||||
let thisSession = await getSession(ctx);
|
||||
|
||||
const showReps = process.env.SHOWREPRESENTATIONS || false;
|
||||
const showLoginCheck = process.env.SHOWLOGIN || false;
|
||||
store.dispatch(setShowReps(showReps, showLoginCheck));
|
||||
|
||||
if (!thisSession) {
|
||||
consoleLogger({
|
||||
name: "MyPortalSearchResultsAuthGuard",
|
||||
reasonCode: "NO_SESSION",
|
||||
message:
|
||||
"myportal searchresults loader missing session; redirecting to signin"
|
||||
});
|
||||
return {
|
||||
redirect: {
|
||||
destination: "/auth/signin",
|
||||
permanent: false
|
||||
}
|
||||
};
|
||||
} else {
|
||||
if (!thisSession?.user?.id || !thisSession?.user?.email) {
|
||||
consoleLogger({
|
||||
name: "MyPortalSearchResultsAuthGuard",
|
||||
reasonCode: "NO_SESSION_USER",
|
||||
message:
|
||||
const authContext = await resolveMyPortalAuthContext(ctx, {
|
||||
loggerName: "MyPortalSearchResultsAuthGuard",
|
||||
noSessionMessage:
|
||||
"myportal searchresults loader missing session; redirecting to signin",
|
||||
noSessionUserMessage:
|
||||
"myportal searchresults loader missing session user identity; redirecting to signin",
|
||||
hasSessionUserId: !!thisSession?.user?.id,
|
||||
hasSessionUserEmail: !!thisSession?.user?.email
|
||||
});
|
||||
return {
|
||||
redirect: {
|
||||
destination: "/auth/signin",
|
||||
permanent: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (!cookies?.pinsUser) {
|
||||
consoleLogger({
|
||||
name: "MyPortalSearchResultsAuthGuard",
|
||||
reasonCode: "NO_PINSUSER_COOKIE",
|
||||
message:
|
||||
noPinsUserMessage:
|
||||
"myportal searchresults loader missing pinsUser cookie; redirecting to signin"
|
||||
});
|
||||
return {
|
||||
redirect: {
|
||||
destination: "/auth/signin",
|
||||
permanent: false
|
||||
}
|
||||
};
|
||||
|
||||
if (!authContext.ok) {
|
||||
return { redirect: authContext.redirect };
|
||||
}
|
||||
|
||||
const thisSession = authContext.session;
|
||||
|
||||
let loggedInUser;
|
||||
try {
|
||||
const portalLogin = await getPortalLogin(
|
||||
thisSession.user.email
|
||||
);
|
||||
const portalLogin = await getPortalLogin(thisSession.user.email);
|
||||
loggedInUser = portalLogin?.value?.[0]?.contactid;
|
||||
} catch (error) {
|
||||
consoleLogger({
|
||||
@@ -190,7 +154,7 @@ export const getServerSideProps = wrapper.getServerSideProps(
|
||||
|
||||
thisSession != false &&
|
||||
store.dispatch(setContainerID(thisSession.user.id));
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
showLoginCheck: showLoginCheck
|
||||
|
||||
@@ -48,6 +48,11 @@ const loadMyPortalAddressSearchResultsPage = (overrides = {}) => {
|
||||
setWatchedCases: () => ({}),
|
||||
setWatchedCasesDetails: () => ({}),
|
||||
setLoggedInUserId: () => ({}),
|
||||
resolveMyPortalAuthContext: async (ctx) => ({
|
||||
ok: true,
|
||||
session: { user: { id: "u-1", email: "x@y.z" } },
|
||||
pinsUser: ctx?.req?.cookies?.pinsUser
|
||||
}),
|
||||
wrapper: {
|
||||
getServerSideProps: (factory) => async (ctx) => {
|
||||
const store = { dispatch: () => {} };
|
||||
@@ -65,7 +70,10 @@ const loadMyPortalAddressSearchResultsPage = (overrides = {}) => {
|
||||
|
||||
test("addresssearchresults redirects to signin when session is missing", async () => {
|
||||
const mod = loadMyPortalAddressSearchResultsPage({
|
||||
getSession: async () => null
|
||||
resolveMyPortalAuthContext: async () => ({
|
||||
ok: false,
|
||||
redirect: { destination: "/auth/signin", permanent: false }
|
||||
})
|
||||
});
|
||||
const result = await mod.getServerSideProps({
|
||||
query: { q: "CAS" },
|
||||
@@ -76,7 +84,10 @@ test("addresssearchresults redirects to signin when session is missing", async (
|
||||
|
||||
test("addresssearchresults redirects to signin when session user identity is missing", async () => {
|
||||
const mod = loadMyPortalAddressSearchResultsPage({
|
||||
getSession: async () => ({ user: { id: "u-1" } })
|
||||
resolveMyPortalAuthContext: async () => ({
|
||||
ok: false,
|
||||
redirect: { destination: "/auth/signin", permanent: false }
|
||||
})
|
||||
});
|
||||
const result = await mod.getServerSideProps({
|
||||
query: { q: "CAS" },
|
||||
@@ -86,7 +97,12 @@ test("addresssearchresults redirects to signin when session user identity is mis
|
||||
});
|
||||
|
||||
test("addresssearchresults redirects to signin when pinsUser cookie is missing", async () => {
|
||||
const mod = loadMyPortalAddressSearchResultsPage();
|
||||
const mod = loadMyPortalAddressSearchResultsPage({
|
||||
resolveMyPortalAuthContext: async () => ({
|
||||
ok: false,
|
||||
redirect: { destination: "/auth/signin", permanent: false }
|
||||
})
|
||||
});
|
||||
const result = await mod.getServerSideProps({
|
||||
query: { q: "CAS" },
|
||||
req: { cookies: {} }
|
||||
|
||||
@@ -46,6 +46,11 @@ const loadMyPortalSearchResultsPage = (overrides = {}) => {
|
||||
setWatchedCasesDetails: () => ({}),
|
||||
setLoggedInUserId: () => ({}),
|
||||
setContainerID: () => ({}),
|
||||
resolveMyPortalAuthContext: async (ctx) => ({
|
||||
ok: true,
|
||||
session: { user: { id: "u-1", email: "test@example.com" } },
|
||||
pinsUser: ctx?.req?.cookies?.pinsUser
|
||||
}),
|
||||
wrapper: {
|
||||
getServerSideProps: (factory) => async (ctx) => {
|
||||
const store = { dispatch: () => {} };
|
||||
@@ -62,7 +67,12 @@ const loadMyPortalSearchResultsPage = (overrides = {}) => {
|
||||
};
|
||||
|
||||
test("myportal searchresults redirects to signin when session is missing", async () => {
|
||||
const mod = loadMyPortalSearchResultsPage({ getSession: async () => null });
|
||||
const mod = loadMyPortalSearchResultsPage({
|
||||
resolveMyPortalAuthContext: async () => ({
|
||||
ok: false,
|
||||
redirect: { destination: "/auth/signin", permanent: false }
|
||||
})
|
||||
});
|
||||
const result = await mod.getServerSideProps({
|
||||
query: { q: "CAS" },
|
||||
req: { cookies: { pinsUser: "contact-1" } }
|
||||
@@ -72,7 +82,10 @@ test("myportal searchresults redirects to signin when session is missing", async
|
||||
|
||||
test("myportal searchresults redirects to signin when session user identity is missing", async () => {
|
||||
const mod = loadMyPortalSearchResultsPage({
|
||||
getSession: async () => ({ user: { id: "u-1" } })
|
||||
resolveMyPortalAuthContext: async () => ({
|
||||
ok: false,
|
||||
redirect: { destination: "/auth/signin", permanent: false }
|
||||
})
|
||||
});
|
||||
const result = await mod.getServerSideProps({
|
||||
query: { q: "CAS" },
|
||||
@@ -82,7 +95,12 @@ test("myportal searchresults redirects to signin when session user identity is m
|
||||
});
|
||||
|
||||
test("myportal searchresults redirects to signin when pinsUser cookie is missing", async () => {
|
||||
const mod = loadMyPortalSearchResultsPage();
|
||||
const mod = loadMyPortalSearchResultsPage({
|
||||
resolveMyPortalAuthContext: async () => ({
|
||||
ok: false,
|
||||
redirect: { destination: "/auth/signin", permanent: false }
|
||||
})
|
||||
});
|
||||
const result = await mod.getServerSideProps({
|
||||
query: { q: "CAS" },
|
||||
req: { cookies: {} }
|
||||
|
||||
Reference in New Issue
Block a user