|
|
import React, { createContext, useState, useContext, useEffect } from 'react';
|
|
|
import { base44 } from '@/api/base44Client';
|
|
|
import { appParams } from '@/lib/app-params';
|
|
|
import { createAxiosClient } from '@base44/sdk/dist/utils/axios-client';
|
|
|
|
|
|
const AuthContext = createContext();
|
|
|
|
|
|
export const AuthProvider = ({ children }) => {
|
|
|
const [user, setUser] = useState(null);
|
|
|
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
|
|
const [isLoadingAuth, setIsLoadingAuth] = useState(true);
|
|
|
const [isLoadingPublicSettings, setIsLoadingPublicSettings] = useState(true);
|
|
|
const [authError, setAuthError] = useState(null);
|
|
|
const [appPublicSettings, setAppPublicSettings] = useState(null);
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
setIsLoadingAuth(false);
|
|
|
setIsLoadingPublicSettings(false);
|
|
|
}, []);
|
|
|
|
|
|
const checkAppState = async () => {
|
|
|
try {
|
|
|
setIsLoadingPublicSettings(true);
|
|
|
setAuthError(null);
|
|
|
|
|
|
|
|
|
|
|
|
const appClient = createAxiosClient({
|
|
|
baseURL: `/api/apps/public`,
|
|
|
headers: {
|
|
|
'X-App-Id': appParams.appId
|
|
|
},
|
|
|
token: appParams.token,
|
|
|
interceptResponses: true
|
|
|
});
|
|
|
|
|
|
try {
|
|
|
const publicSettings = await appClient.get(`/prod/public-settings/by-id/${appParams.appId}`);
|
|
|
setAppPublicSettings(publicSettings);
|
|
|
|
|
|
|
|
|
if (appParams.token) {
|
|
|
await checkUserAuth();
|
|
|
} else {
|
|
|
setIsLoadingAuth(false);
|
|
|
setIsAuthenticated(false);
|
|
|
}
|
|
|
setIsLoadingPublicSettings(false);
|
|
|
} catch (appError) {
|
|
|
console.error('App state check failed:', appError);
|
|
|
|
|
|
|
|
|
if (appError.status === 403 && appError.data?.extra_data?.reason) {
|
|
|
const reason = appError.data.extra_data.reason;
|
|
|
if (reason === 'auth_required') {
|
|
|
setAuthError({
|
|
|
type: 'auth_required',
|
|
|
message: 'Authentication required'
|
|
|
});
|
|
|
} else if (reason === 'user_not_registered') {
|
|
|
setAuthError({
|
|
|
type: 'user_not_registered',
|
|
|
message: 'User not registered for this app'
|
|
|
});
|
|
|
} else {
|
|
|
setAuthError({
|
|
|
type: reason,
|
|
|
message: appError.message
|
|
|
});
|
|
|
}
|
|
|
} else {
|
|
|
setAuthError({
|
|
|
type: 'unknown',
|
|
|
message: appError.message || 'Failed to load app'
|
|
|
});
|
|
|
}
|
|
|
setIsLoadingPublicSettings(false);
|
|
|
setIsLoadingAuth(false);
|
|
|
}
|
|
|
} catch (error) {
|
|
|
console.error('Unexpected error:', error);
|
|
|
setAuthError({
|
|
|
type: 'unknown',
|
|
|
message: error.message || 'An unexpected error occurred'
|
|
|
});
|
|
|
setIsLoadingPublicSettings(false);
|
|
|
setIsLoadingAuth(false);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
const checkUserAuth = async () => {
|
|
|
try {
|
|
|
|
|
|
setIsLoadingAuth(true);
|
|
|
const currentUser = await base44.auth.me();
|
|
|
setUser(currentUser);
|
|
|
setIsAuthenticated(true);
|
|
|
setIsLoadingAuth(false);
|
|
|
} catch (error) {
|
|
|
console.error('User auth check failed:', error);
|
|
|
setIsLoadingAuth(false);
|
|
|
setIsAuthenticated(false);
|
|
|
|
|
|
|
|
|
if (error.status === 401 || error.status === 403) {
|
|
|
setAuthError({
|
|
|
type: 'auth_required',
|
|
|
message: 'Authentication required'
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
|
|
|
const logout = (shouldRedirect = true) => {
|
|
|
setUser(null);
|
|
|
setIsAuthenticated(false);
|
|
|
|
|
|
if (shouldRedirect) {
|
|
|
|
|
|
base44.auth.logout(window.location.href);
|
|
|
} else {
|
|
|
|
|
|
base44.auth.logout();
|
|
|
}
|
|
|
};
|
|
|
|
|
|
const navigateToLogin = () => {
|
|
|
|
|
|
base44.auth.redirectToLogin(window.location.href);
|
|
|
};
|
|
|
|
|
|
return (
|
|
|
<AuthContext.Provider value={{
|
|
|
user,
|
|
|
isAuthenticated,
|
|
|
isLoadingAuth,
|
|
|
isLoadingPublicSettings,
|
|
|
authError,
|
|
|
appPublicSettings,
|
|
|
logout,
|
|
|
navigateToLogin,
|
|
|
checkAppState
|
|
|
}}>
|
|
|
{children}
|
|
|
</AuthContext.Provider>
|
|
|
);
|
|
|
};
|
|
|
|
|
|
export const useAuth = () => {
|
|
|
const context = useContext(AuthContext);
|
|
|
if (!context) {
|
|
|
throw new Error('useAuth must be used within an AuthProvider');
|
|
|
}
|
|
|
return context;
|
|
|
};
|
|
|
|