cleaning hard 2
This commit is contained in:
parent
6569858fbb
commit
d2f131a142
@ -60,32 +60,7 @@ export const authOptions: NextAuthOptions = {
|
|||||||
clientSecret: process.env.KEYCLOAK_CLIENT_SECRET || "",
|
clientSecret: process.env.KEYCLOAK_CLIENT_SECRET || "",
|
||||||
issuer: process.env.KEYCLOAK_ISSUER || "",
|
issuer: process.env.KEYCLOAK_ISSUER || "",
|
||||||
profile(profile: any) {
|
profile(profile: any) {
|
||||||
console.log("Raw Keycloak profile:", JSON.stringify(profile, null, 2));
|
console.log("Raw Keycloak profile:", profile);
|
||||||
|
|
||||||
// Try to extract all possible roles from the profile
|
|
||||||
let roles: string[] = [];
|
|
||||||
|
|
||||||
// Get roles from realm_access
|
|
||||||
if (profile.realm_access && Array.isArray(profile.realm_access.roles)) {
|
|
||||||
roles = roles.concat(profile.realm_access.roles);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get roles from resource_access
|
|
||||||
if (profile.resource_access) {
|
|
||||||
for (const client in profile.resource_access) {
|
|
||||||
if (profile.resource_access[client] &&
|
|
||||||
Array.isArray(profile.resource_access[client].roles)) {
|
|
||||||
roles = roles.concat(profile.resource_access[client].roles);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get roles from groups if available
|
|
||||||
if (profile.groups && Array.isArray(profile.groups)) {
|
|
||||||
roles = roles.concat(profile.groups);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("Extracted roles from profile:", roles);
|
|
||||||
|
|
||||||
// Just return a simple profile with required fields
|
// Just return a simple profile with required fields
|
||||||
return {
|
return {
|
||||||
@ -96,7 +71,7 @@ export const authOptions: NextAuthOptions = {
|
|||||||
username: profile.preferred_username || profile.email?.split('@')[0] || '',
|
username: profile.preferred_username || profile.email?.split('@')[0] || '',
|
||||||
first_name: profile.given_name || '',
|
first_name: profile.given_name || '',
|
||||||
last_name: profile.family_name || '',
|
last_name: profile.family_name || '',
|
||||||
role: roles.length > 0 ? roles : ['user'],
|
role: profile.realm_access?.roles || ['user'],
|
||||||
// Store raw profile data for later processing
|
// Store raw profile data for later processing
|
||||||
raw_profile: profile
|
raw_profile: profile
|
||||||
};
|
};
|
||||||
@ -111,16 +86,12 @@ export const authOptions: NextAuthOptions = {
|
|||||||
async jwt({ token, account, profile, user }: any) {
|
async jwt({ token, account, profile, user }: any) {
|
||||||
// Initial sign in
|
// Initial sign in
|
||||||
if (account && account.access_token) {
|
if (account && account.access_token) {
|
||||||
console.log("FULL USER OBJECT:", JSON.stringify(user, null, 2));
|
|
||||||
console.log("FULL ACCOUNT OBJECT:", JSON.stringify(account, null, 2));
|
|
||||||
|
|
||||||
token.accessToken = account.access_token;
|
token.accessToken = account.access_token;
|
||||||
token.refreshToken = account.refresh_token;
|
token.refreshToken = account.refresh_token;
|
||||||
|
|
||||||
// Process the raw profile data if available
|
// Process the raw profile data if available
|
||||||
if (user && user.raw_profile) {
|
if (user && user.raw_profile) {
|
||||||
const rawProfile = user.raw_profile;
|
const rawProfile = user.raw_profile;
|
||||||
console.log("RAW KEYCLOAK PROFILE:", JSON.stringify(rawProfile, null, 2));
|
|
||||||
|
|
||||||
// Extract roles from all possible sources
|
// Extract roles from all possible sources
|
||||||
let roles: string[] = [];
|
let roles: string[] = [];
|
||||||
@ -134,9 +105,6 @@ export const authOptions: NextAuthOptions = {
|
|||||||
// Get roles from resource_access
|
// Get roles from resource_access
|
||||||
if (rawProfile.resource_access) {
|
if (rawProfile.resource_access) {
|
||||||
const clientId = process.env.KEYCLOAK_CLIENT_ID;
|
const clientId = process.env.KEYCLOAK_CLIENT_ID;
|
||||||
console.log("Client ID for resource access:", clientId);
|
|
||||||
console.log("Resource access object:", JSON.stringify(rawProfile.resource_access, null, 2));
|
|
||||||
|
|
||||||
if (clientId &&
|
if (clientId &&
|
||||||
rawProfile.resource_access[clientId] &&
|
rawProfile.resource_access[clientId] &&
|
||||||
Array.isArray(rawProfile.resource_access[clientId].roles)) {
|
Array.isArray(rawProfile.resource_access[clientId].roles)) {
|
||||||
@ -150,20 +118,6 @@ export const authOptions: NextAuthOptions = {
|
|||||||
roles = roles.concat(rawProfile.resource_access.account.roles);
|
roles = roles.concat(rawProfile.resource_access.account.roles);
|
||||||
console.log("Roles from resource_access.account:", rawProfile.resource_access.account.roles);
|
console.log("Roles from resource_access.account:", rawProfile.resource_access.account.roles);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for any roles in any client
|
|
||||||
for (const [clientKey, clientData] of Object.entries(rawProfile.resource_access)) {
|
|
||||||
if (clientData && Array.isArray((clientData as any).roles)) {
|
|
||||||
console.log(`Found roles in client ${clientKey}:`, (clientData as any).roles);
|
|
||||||
roles = roles.concat((clientData as any).roles);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for roles in other potential locations
|
|
||||||
if (rawProfile.groups && Array.isArray(rawProfile.groups)) {
|
|
||||||
console.log("Found groups that might contain roles:", rawProfile.groups);
|
|
||||||
roles = roles.concat(rawProfile.groups);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up roles and convert to lowercase
|
// Clean up roles and convert to lowercase
|
||||||
@ -172,24 +126,18 @@ export const authOptions: NextAuthOptions = {
|
|||||||
.map(role => role.toLowerCase());
|
.map(role => role.toLowerCase());
|
||||||
|
|
||||||
console.log("Cleaned raw Keycloak roles:", cleanedRoles);
|
console.log("Cleaned raw Keycloak roles:", cleanedRoles);
|
||||||
console.log("Directly from cleaning process:", cleanedRoles);
|
|
||||||
|
|
||||||
// Always ensure user has basic user role
|
// Always ensure user has basic user role
|
||||||
const finalRoles = [...new Set([...cleanedRoles, 'user'])];
|
const finalRoles = [...new Set([...cleanedRoles, 'user'])];
|
||||||
|
|
||||||
console.log("Input to mapping function:", finalRoles);
|
|
||||||
|
|
||||||
// Map Keycloak roles to application roles
|
// Map Keycloak roles to application roles
|
||||||
token.role = mapToApplicationRoles(finalRoles);
|
token.role = mapToApplicationRoles(finalRoles);
|
||||||
console.log("Mapped application roles:", token.role);
|
console.log("Mapped application roles:", token.role);
|
||||||
console.log("Output from mapping function:", token.role);
|
|
||||||
} else if (user && user.role) {
|
} else if (user && user.role) {
|
||||||
console.log("Using direct user.role:", user.role);
|
|
||||||
token.role = Array.isArray(user.role) ? user.role : [user.role];
|
token.role = Array.isArray(user.role) ? user.role : [user.role];
|
||||||
console.log("Using user.role directly:", token.role);
|
console.log("Using user.role directly:", token.role);
|
||||||
} else {
|
} else {
|
||||||
// Default roles if no profile data available
|
// Default roles if no profile data available
|
||||||
console.log("No role data found in user object or profile");
|
|
||||||
token.role = ['user'];
|
token.role = ['user'];
|
||||||
console.log("Using default 'user' role only");
|
console.log("Using default 'user' role only");
|
||||||
}
|
}
|
||||||
@ -207,7 +155,6 @@ export const authOptions: NextAuthOptions = {
|
|||||||
console.log("Adding default 'user' role to existing token");
|
console.log("Adding default 'user' role to existing token");
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("FINAL TOKEN:", JSON.stringify(token, null, 2));
|
|
||||||
return token;
|
return token;
|
||||||
},
|
},
|
||||||
async session({ session, token }: any) {
|
async session({ session, token }: any) {
|
||||||
@ -257,80 +204,36 @@ export const authOptions: NextAuthOptions = {
|
|||||||
* Maps Keycloak roles to application-specific roles
|
* Maps Keycloak roles to application-specific roles
|
||||||
*/
|
*/
|
||||||
function mapToApplicationRoles(keycloakRoles: string[]): string[] {
|
function mapToApplicationRoles(keycloakRoles: string[]): string[] {
|
||||||
// Debug input
|
|
||||||
console.log("Mapping input roles:", keycloakRoles);
|
|
||||||
|
|
||||||
// For development/testing, directly assign application roles based on username
|
|
||||||
// This helps in case Keycloak isn't properly configured
|
|
||||||
let appRoles: string[] = ['user']; // Always include 'user' role
|
|
||||||
|
|
||||||
// The mappings object maps Keycloak role names to application role names
|
|
||||||
const mappings: Record<string, string[]> = {
|
const mappings: Record<string, string[]> = {
|
||||||
// Map Keycloak roles to your application's role names
|
// Map Keycloak roles to your application's role names
|
||||||
'admin': ['admin', 'dataintelligence', 'coding', 'expression', 'mediation', 'entrepreneurship'],
|
'admin': ['admin', 'dataintelligence', 'coding', 'expression', 'mediation'],
|
||||||
'owner': ['admin', 'dataintelligence', 'coding', 'expression', 'mediation', 'entrepreneurship'],
|
'owner': ['admin', 'dataintelligence', 'coding', 'expression', 'mediation'],
|
||||||
'manager': ['dataintelligence', 'coding', 'expression', 'mediation', 'entrepreneurship'],
|
'cercle-admin': ['admin', 'dataintelligence', 'coding', 'expression', 'mediation'],
|
||||||
|
'manager': ['dataintelligence', 'coding', 'expression', 'mediation'],
|
||||||
'developer': ['coding', 'dataintelligence'],
|
'developer': ['coding', 'dataintelligence'],
|
||||||
'data-scientist': ['dataintelligence'],
|
'data-scientist': ['dataintelligence'],
|
||||||
'designer': ['expression'],
|
'designer': ['expression'],
|
||||||
'writer': ['expression'],
|
'writer': ['expression'],
|
||||||
'mediator': ['mediation'],
|
'mediator': ['mediation'],
|
||||||
'entrepreneur': ['entrepreneurship'],
|
|
||||||
|
|
||||||
// Support for capitalized role names from Keycloak
|
|
||||||
'Expression': ['expression'],
|
|
||||||
'Mediation': ['mediation'],
|
|
||||||
'DataIntelligence': ['dataintelligence'],
|
|
||||||
'Admin': ['admin', 'dataintelligence', 'coding', 'expression', 'mediation', 'entrepreneurship'],
|
|
||||||
|
|
||||||
// Common prefixed variants
|
|
||||||
'role_admin': ['admin', 'dataintelligence', 'coding', 'expression', 'mediation', 'entrepreneurship'],
|
|
||||||
'realm_admin': ['admin', 'dataintelligence', 'coding', 'expression', 'mediation', 'entrepreneurship'],
|
|
||||||
'app_admin': ['admin', 'dataintelligence', 'coding', 'expression', 'mediation', 'entrepreneurship'],
|
|
||||||
|
|
||||||
// Default access roles from Keycloak
|
// Default access roles from Keycloak
|
||||||
'default-roles-cercle': ['user'],
|
'default-roles-cercle': ['user'],
|
||||||
'uma_authorization': ['user'],
|
'uma_authorization': ['user'],
|
||||||
'offline_access': ['user'],
|
'offline_access': ['user'],
|
||||||
|
// Add more mappings as needed
|
||||||
// Direct mapping for flexibility
|
|
||||||
'expression': ['expression'],
|
|
||||||
'mediation': ['mediation'],
|
|
||||||
'coding': ['coding'],
|
|
||||||
'dataintelligence': ['dataintelligence'],
|
|
||||||
'entrepreneurship': ['entrepreneurship'],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Try to match each role with our mappings
|
// Map each role and flatten the result
|
||||||
|
let appRoles: string[] = ['user']; // Always include 'user' role
|
||||||
|
|
||||||
for (const role of keycloakRoles) {
|
for (const role of keycloakRoles) {
|
||||||
// Try different variations of the role name
|
const mappedRoles = mappings[role.toLowerCase()];
|
||||||
const normalizedRole = role.toLowerCase()
|
if (mappedRoles) {
|
||||||
.replace(/^role_/i, '') // Remove ROLE_ prefix
|
appRoles = [...appRoles, ...mappedRoles];
|
||||||
.replace(/^realm_/i, '') // Remove REALM_ prefix
|
|
||||||
.replace(/^app_/i, ''); // Remove APP_ prefix
|
|
||||||
|
|
||||||
console.log(`Processing role: ${role} -> normalized: ${normalizedRole}`);
|
|
||||||
|
|
||||||
// Check for direct match
|
|
||||||
if (mappings[normalizedRole]) {
|
|
||||||
appRoles = [...appRoles, ...mappings[normalizedRole]];
|
|
||||||
console.log(`Mapped ${role} to: ${mappings[normalizedRole].join(', ')}`);
|
|
||||||
}
|
|
||||||
// Check for partial matches
|
|
||||||
else {
|
|
||||||
for (const [mapKey, mapRoles] of Object.entries(mappings)) {
|
|
||||||
if (normalizedRole.includes(mapKey)) {
|
|
||||||
appRoles = [...appRoles, ...mapRoles];
|
|
||||||
console.log(`Partially matched ${role} with ${mapKey} to: ${mapRoles.join(', ')}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove duplicates and return
|
// Remove duplicates and return
|
||||||
const uniqueRoles = [...new Set(appRoles)];
|
return [...new Set(appRoles)];
|
||||||
console.log("Final mapped roles:", uniqueRoles);
|
|
||||||
return uniqueRoles;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handler = NextAuth(authOptions);
|
const handler = NextAuth(authOptions);
|
||||||
|
|||||||
@ -5,47 +5,34 @@ import { usePathname, useRouter } from "next/navigation";
|
|||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
|
||||||
export function AuthCheck({ children }: { children: React.ReactNode }) {
|
export function AuthCheck({ children }: { children: React.ReactNode }) {
|
||||||
// Wrap in try-catch to ensure it never crashes
|
const session = useSession();
|
||||||
try {
|
const pathname = usePathname();
|
||||||
const session = useSession();
|
const router = useRouter();
|
||||||
const pathname = usePathname();
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
// Safely extract status with a fallback
|
// Safely extract status with a fallback
|
||||||
const status = session?.status || "loading";
|
const status = session?.status || "loading";
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
try {
|
// Only redirect if we're certain the user is unauthenticated
|
||||||
// Only redirect if we're certain the user is unauthenticated
|
if (status === "unauthenticated" && !pathname?.includes("/signin")) {
|
||||||
if (status === "unauthenticated" && pathname && !pathname.includes("/signin")) {
|
router?.push("/signin");
|
||||||
if (router && typeof router.push === 'function') {
|
|
||||||
router.push("/signin");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error in AuthCheck useEffect:", error);
|
|
||||||
}
|
|
||||||
}, [status, router, pathname]);
|
|
||||||
|
|
||||||
// Simple loading state
|
|
||||||
if (status === "loading") {
|
|
||||||
return (
|
|
||||||
<div className="flex justify-center items-center min-h-screen">
|
|
||||||
<div className="animate-spin h-10 w-10 border-4 border-blue-500 rounded-full border-t-transparent"></div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
}, [status, router, pathname]);
|
||||||
|
|
||||||
// Don't render on unauthenticated
|
// Simple loading state
|
||||||
if (status === "unauthenticated" && pathname && !pathname.includes("/signin")) {
|
if (status === "loading") {
|
||||||
return null;
|
return (
|
||||||
}
|
<div className="flex justify-center items-center min-h-screen">
|
||||||
|
<div className="animate-spin h-10 w-10 border-4 border-blue-500 rounded-full border-t-transparent"></div>
|
||||||
// Render children if authenticated
|
</div>
|
||||||
return <>{children}</>;
|
);
|
||||||
} catch (error) {
|
|
||||||
// If anything fails, just render the children
|
|
||||||
console.error("Error in AuthCheck component:", error);
|
|
||||||
return <>{children}</>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't render on unauthenticated
|
||||||
|
if (status === "unauthenticated" && !pathname?.includes("/signin")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render children if authenticated
|
||||||
|
return <>{children}</>;
|
||||||
}
|
}
|
||||||
@ -46,50 +46,31 @@ const backgroundImages = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export function useBackgroundImage() {
|
export function useBackgroundImage() {
|
||||||
// Safety checks
|
// Initialize with a safe default in case the array is empty
|
||||||
if (!Array.isArray(backgroundImages) || backgroundImages.length === 0) {
|
const defaultBackground = backgroundImages.length > 0 ? backgroundImages[0] : '';
|
||||||
return {
|
|
||||||
currentBackground: '',
|
|
||||||
changeBackground: () => {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize with a safe default
|
|
||||||
const defaultBackground = backgroundImages[0] || '';
|
|
||||||
const [currentBackground, setCurrentBackground] = useState(defaultBackground);
|
const [currentBackground, setCurrentBackground] = useState(defaultBackground);
|
||||||
|
|
||||||
const changeBackground = () => {
|
const changeBackground = () => {
|
||||||
try {
|
// Safety check to prevent issues if the array is empty
|
||||||
// Safety check to prevent issues
|
if (backgroundImages.length === 0) return;
|
||||||
if (!Array.isArray(backgroundImages) || backgroundImages.length === 0) return;
|
|
||||||
|
|
||||||
const currentIndex = backgroundImages.indexOf(currentBackground);
|
const currentIndex = backgroundImages.indexOf(currentBackground);
|
||||||
// Handle case where current background is not in the array
|
// Handle case where current background is not in the array
|
||||||
const nextIndex = currentIndex >= 0 ?
|
const nextIndex = currentIndex >= 0 ?
|
||||||
(currentIndex + 1) % backgroundImages.length :
|
(currentIndex + 1) % backgroundImages.length :
|
||||||
0;
|
0;
|
||||||
setCurrentBackground(backgroundImages[nextIndex]);
|
setCurrentBackground(backgroundImages[nextIndex]);
|
||||||
} catch (error) {
|
|
||||||
console.error("Error changing background:", error);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
try {
|
// Set initial random background
|
||||||
// Set initial random background safely
|
if (backgroundImages.length > 0) {
|
||||||
if (Array.isArray(backgroundImages) && backgroundImages.length > 0) {
|
const randomIndex = Math.floor(Math.random() * backgroundImages.length);
|
||||||
const randomIndex = Math.floor(Math.random() * backgroundImages.length);
|
setCurrentBackground(backgroundImages[randomIndex]);
|
||||||
setCurrentBackground(backgroundImages[randomIndex] || '');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error setting initial background in useEffect:", error);
|
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return {
|
return { currentBackground, changeBackground };
|
||||||
currentBackground: currentBackground || '',
|
|
||||||
changeBackground
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BackgroundSwitcher({ children }: { children: React.ReactNode }) {
|
export function BackgroundSwitcher({ children }: { children: React.ReactNode }) {
|
||||||
|
|||||||
@ -13,37 +13,16 @@ interface LayoutWrapperProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function LayoutWrapper({ children, isSignInPage, isAuthenticated }: LayoutWrapperProps) {
|
export function LayoutWrapper({ children, isSignInPage, isAuthenticated }: LayoutWrapperProps) {
|
||||||
// Default safe values
|
// Add try-catch to handle potential errors in the hook
|
||||||
let currentBackground = '';
|
let backgroundData = { currentBackground: '', changeBackground: () => {} };
|
||||||
let changeBackground = () => {};
|
|
||||||
|
|
||||||
// Try to use the background hook if available
|
|
||||||
try {
|
try {
|
||||||
if (typeof useBackgroundImage === 'function') {
|
backgroundData = useBackgroundImage();
|
||||||
const backgroundData = useBackgroundImage();
|
|
||||||
if (backgroundData && typeof backgroundData === 'object') {
|
|
||||||
currentBackground = backgroundData.currentBackground || '';
|
|
||||||
changeBackground = typeof backgroundData.changeBackground === 'function'
|
|
||||||
? backgroundData.changeBackground
|
|
||||||
: () => {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to initialize background:", error);
|
console.error("Error initializing background:", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safely wrap the click handler to prevent errors
|
const { currentBackground, changeBackground } = backgroundData;
|
||||||
const handleBackgroundClick = (e: React.MouseEvent) => {
|
|
||||||
try {
|
|
||||||
if (!isSignInPage && typeof changeBackground === 'function') {
|
|
||||||
changeBackground();
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error in background click handler:", error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Safely render
|
|
||||||
return (
|
return (
|
||||||
<AuthCheck>
|
<AuthCheck>
|
||||||
{!isSignInPage && isAuthenticated && <MainNav />}
|
{!isSignInPage && isAuthenticated && <MainNav />}
|
||||||
@ -60,7 +39,7 @@ export function LayoutWrapper({ children, isSignInPage, isAuthenticated }: Layou
|
|||||||
transition: 'background-image 0.5s ease-in-out'
|
transition: 'background-image 0.5s ease-in-out'
|
||||||
} : {}
|
} : {}
|
||||||
}
|
}
|
||||||
onClick={handleBackgroundClick}
|
onClick={!isSignInPage && typeof changeBackground === 'function' ? changeBackground : undefined}
|
||||||
>
|
>
|
||||||
<main>{children}</main>
|
<main>{children}</main>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -9,20 +9,14 @@ interface ProvidersProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function Providers({ children, session }: ProvidersProps) {
|
export default function Providers({ children, session }: ProvidersProps) {
|
||||||
try {
|
// Ensure session is properly handled - if it's undefined, provide an empty object
|
||||||
// Ensure session is properly handled - if it's undefined, provide null
|
const safeSession = session === undefined ? null : session;
|
||||||
const safeSession = session === undefined ? null : session;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
|
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
|
||||||
<SessionProvider session={safeSession} refetchInterval={5 * 60}>
|
<SessionProvider session={safeSession} refetchInterval={5 * 60}>
|
||||||
{children}
|
{children}
|
||||||
</SessionProvider>
|
</SessionProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
);
|
);
|
||||||
} catch (error) {
|
|
||||||
// If anything goes catastrophically wrong, at least render the children
|
|
||||||
console.error("Error in Providers component:", error);
|
|
||||||
return <>{children}</>;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user