Files
klz-cables.com/.pnpm-store/v10/files/f6/03f9d05b696bdcc979683badc9da85fa14811b120583a103526c7ac705fe60d7541816244e257834103e422148a44b2fefeada14092fb15857990d641303a8
Marc Mintel 5397309103
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
fix(products): fix breadcrumbs and product filtering (backport from main)
2026-02-24 16:04:21 +01:00

271 lines
8.5 KiB
Plaintext

'use client';
import { jsx as _jsx } from "react/jsx-runtime";
import { useModal } from '@faceless-ui/modal';
import { usePathname, useRouter } from 'next/navigation.js';
import { formatAdminURL } from 'payload/shared';
import * as qs from 'qs-esm';
import React, { createContext, use, useCallback, useEffect, useState } from 'react';
import { toast } from 'sonner';
import { stayLoggedInModalSlug } from '../../elements/StayLoggedIn/index.js';
import { useEffectEvent } from '../../hooks/useEffectEvent.js';
import { useTranslation } from '../../providers/Translation/index.js';
import { requests } from '../../utilities/api.js';
import { useConfig } from '../Config/index.js';
import { useRouteTransition } from '../RouteTransition/index.js';
const Context = /*#__PURE__*/createContext({});
const maxTimeoutMs = 2147483647;
export function AuthProvider({
children,
permissions: initialPermissions,
user: initialUser
}) {
const pathname = usePathname();
const router = useRouter();
const {
config
} = useConfig();
const {
admin: {
autoLogin,
autoRefresh,
routes: {
inactivity: logoutInactivityRoute
},
user: userSlug
},
routes: {
admin: adminRoute,
api: apiRoute
}
} = config;
const {
i18n
} = useTranslation();
const {
closeAllModals,
openModal
} = useModal();
const {
startRouteTransition
} = useRouteTransition();
const [user, setUserInMemory] = useState(initialUser);
const [tokenInMemory, setTokenInMemory] = useState();
const [tokenExpirationMs, setTokenExpirationMs] = useState();
const [permissions, setPermissions] = useState(initialPermissions);
const [forceLogoutBufferMs, setForceLogoutBufferMs] = useState(120_000);
const [fetchedUserOnMount, setFetchedUserOnMount] = useState(false);
const refreshTokenTimeoutRef = React.useRef(null);
const reminderTimeoutRef = React.useRef(null);
const forceLogOutTimeoutRef = React.useRef(null);
const id = user?.id;
const redirectToInactivityRoute = useCallback(() => {
const baseAdminRoute = formatAdminURL({
adminRoute,
path: ''
});
startRouteTransition(() => router.replace(formatAdminURL({
adminRoute,
path: `${logoutInactivityRoute}${window.location.pathname.startsWith(baseAdminRoute) ? `?redirect=${encodeURIComponent(window.location.pathname)}` : ''}`
})));
closeAllModals();
}, [router, adminRoute, logoutInactivityRoute, closeAllModals, startRouteTransition]);
const revokeTokenAndExpire = useCallback(() => {
setUserInMemory(null);
setTokenInMemory(undefined);
setTokenExpirationMs(undefined);
clearTimeout(refreshTokenTimeoutRef.current);
}, []);
// Handler for reminder timeout - uses useEffectEvent to capture latest autoRefresh value
const handleReminderTimeout = useEffectEvent(() => {
if (autoRefresh) {
refreshCookieEvent();
} else {
openModal(stayLoggedInModalSlug);
}
});
const setNewUser = useCallback(userResponse => {
clearTimeout(reminderTimeoutRef.current);
clearTimeout(forceLogOutTimeoutRef.current);
if (userResponse?.user) {
setUserInMemory(userResponse.user);
setTokenInMemory(userResponse.token);
setTokenExpirationMs(userResponse.exp * 1000);
const expiresInMs = Math.max(0, Math.min((userResponse.exp ?? 0) * 1000 - Date.now(), maxTimeoutMs));
if (expiresInMs) {
const nextForceLogoutBufferMs = Math.min(60_000, expiresInMs / 2);
setForceLogoutBufferMs(nextForceLogoutBufferMs);
reminderTimeoutRef.current = setTimeout(handleReminderTimeout, Math.max(expiresInMs - nextForceLogoutBufferMs, 0));
forceLogOutTimeoutRef.current = setTimeout(() => {
revokeTokenAndExpire();
redirectToInactivityRoute();
}, expiresInMs);
}
} else {
revokeTokenAndExpire();
}
}, [redirectToInactivityRoute, revokeTokenAndExpire]);
const refreshCookie = useCallback(forceRefresh => {
if (!id) {
return;
}
const expiresInMs_0 = Math.max(0, (tokenExpirationMs ?? 0) - Date.now());
if (forceRefresh || tokenExpirationMs && expiresInMs_0 < forceLogoutBufferMs * 2) {
clearTimeout(refreshTokenTimeoutRef.current);
refreshTokenTimeoutRef.current = setTimeout(async () => {
try {
const request = await requests.post(formatAdminURL({
apiRoute,
path: `/${userSlug}/refresh-token?refresh`
}), {
headers: {
'Accept-Language': i18n.language
}
});
if (request.status === 200) {
const json = await request.json();
setNewUser(json);
} else {
setNewUser(null);
redirectToInactivityRoute();
}
} catch (e) {
toast.error(e.message);
}
}, 1000);
}
}, [apiRoute, i18n.language, redirectToInactivityRoute, setNewUser, tokenExpirationMs, userSlug, forceLogoutBufferMs, id]);
const refreshCookieAsync = useCallback(async skipSetUser => {
try {
const request_0 = await requests.post(formatAdminURL({
apiRoute,
path: `/${userSlug}/refresh-token`
}), {
headers: {
'Accept-Language': i18n.language
}
});
if (request_0.status === 200) {
const json_0 = await request_0.json();
if (!skipSetUser) {
setNewUser(json_0);
}
return json_0.user;
}
if (user) {
setNewUser(null);
redirectToInactivityRoute();
}
} catch (e_0) {
toast.error(`Refreshing token failed: ${e_0.message}`);
}
return null;
}, [apiRoute, i18n.language, redirectToInactivityRoute, setNewUser, userSlug, user]);
const logOut = useCallback(async () => {
try {
if (user && user.collection) {
setNewUser(null);
await requests.post(formatAdminURL({
apiRoute,
path: `/${user.collection}/logout`
}));
}
} catch (_) {
// fail silently and log the user out in state
}
return true;
}, [apiRoute, setNewUser, user]);
const refreshPermissions = useCallback(async ({
locale
} = {}) => {
const params = qs.stringify({
locale
}, {
addQueryPrefix: true
});
try {
const request_1 = await requests.get(formatAdminURL({
apiRoute,
path: `/access${params}`
}), {
headers: {
'Accept-Language': i18n.language
}
});
if (request_1.status === 200) {
const json_1 = await request_1.json();
setPermissions(json_1);
} else {
throw new Error(`Fetching permissions failed with status code ${request_1.status}`);
}
} catch (e_1) {
toast.error(`Refreshing permissions failed: ${e_1.message}`);
}
}, [apiRoute, i18n]);
const fetchFullUser = React.useCallback(async () => {
try {
const request_2 = await requests.get(formatAdminURL({
apiRoute,
path: `/${userSlug}/me`
}), {
credentials: 'include',
headers: {
'Accept-Language': i18n.language
}
});
if (request_2.status === 200) {
const json_2 = await request_2.json();
setNewUser(json_2);
return json_2?.user || null;
}
} catch (e_2) {
toast.error(`Fetching user failed: ${e_2.message}`);
}
return null;
}, [apiRoute, userSlug, i18n.language, setNewUser]);
const refreshCookieEvent = useEffectEvent(refreshCookie);
useEffect(() => {
// when location changes, refresh cookie
refreshCookieEvent();
}, [pathname]);
const fetchFullUserEvent = useEffectEvent(fetchFullUser);
useEffect(() => {
async function fetchUserOnMount() {
await fetchFullUserEvent();
setFetchedUserOnMount(true);
}
void fetchUserOnMount();
}, []);
useEffect(() => {
if (!user && autoLogin && !autoLogin.prefillOnly) {
void fetchFullUserEvent();
}
}, [user, autoLogin]);
useEffect(() => () => {
// remove all timeouts on unmount
clearTimeout(refreshTokenTimeoutRef.current);
clearTimeout(reminderTimeoutRef.current);
clearTimeout(forceLogOutTimeoutRef.current);
}, []);
if (!user && !fetchedUserOnMount) {
return null;
}
return /*#__PURE__*/_jsx(Context, {
value: {
fetchFullUser,
logOut,
permissions,
refreshCookie,
refreshCookieAsync,
refreshPermissions,
setPermissions,
setUser: setNewUser,
token: tokenInMemory,
tokenExpirationMs,
user
},
children: children
});
}
export const useAuth = () => use(Context);
//# sourceMappingURL=index.js.map