import { Credentials } from 'google-auth-library/build/src/auth/credentials'; import { Button, Container } from '@mui/material'; import React, { useContext, useEffect, useCallback, useState } from 'react'; import { FcGoogle } from 'react-icons/fc'; import { blueGrey } from '@mui/material/colors'; import Channels from '../electron/constants'; import { firebaseAuth } from '../firebase/connect'; import { GoogleAuthProvider, signInWithCredential, setPersistence, browserLocalPersistence, User as FirebaseUser, onAuthStateChanged, updateCurrentUser, getAuth, } from 'firebase/auth'; import { useSnackbar } from 'notistack'; import { createUser, getUserById } from '../firebase/firestore'; import CircularProgress from '@mui/material/CircularProgress'; import NirvanaLogo from '../components/NirvanaLogo'; import { User } from '@nirvana/core/src/models/user.model'; interface IAuthContext { user?: FirebaseUser; nirvanaUser?: User; logout?: () => void; } const AuthContext = React.createContext({}); export const AuthProvider = ({ children }: { children: React.ReactNode }) => { const { enqueueSnackbar } = useSnackbar(); // since auth.currentuser isn't updating const [currentUser, setCurrentUser] = useState(null); const [currentNirvanaUser, setCurrentNirvanaUser] = useState(null); // are we still waiting on initial auth to trigger? const [authIniting, setAuthIniting] = useState(true); useEffect(() => { const authListener = onAuthStateChanged(firebaseAuth, async (user) => { console.log('auth changed!!!!', user); if (user) { // getting from our data store of users let fetchedNirvanaUser = await getUserById(user.uid); if (!fetchedNirvanaUser) { await createUser(user); fetchedNirvanaUser = await getUserById(user.uid); } setCurrentNirvanaUser(fetchedNirvanaUser); setCurrentUser(user); } else { // User is signed out // ... enqueueSnackbar('Logged out'); setCurrentUser(null); } setAuthIniting(false); }); return () => authListener(); }, [setCurrentUser, enqueueSnackbar, setAuthIniting, setCurrentNirvanaUser]); useEffect(() => { const tokenListener = window.electronAPI.once( Channels.GOOGLE_AUTH_TOKENS, async (tokens: Credentials) => { setAuthIniting(true); console.log('got tokens', tokens); const credential = GoogleAuthProvider.credential(tokens.id_token); setPersistence(firebaseAuth, browserLocalPersistence) .then(() => { // Sign in with credential from the Google user. return signInWithCredential(firebaseAuth, credential).then((result) => { // This gives you a Google Access Token. You can use it to access Google APIs. const credential = GoogleAuthProvider.credentialFromResult(result); const token = credential.accessToken; // The signed-in user info. const user = result.user; console.log(user); updateCurrentUser(firebaseAuth, user); enqueueSnackbar('Signed in! All set!', { variant: 'success' }); }); }) .catch((error: any) => { setAuthIniting(false); // Handle Errors here. const errorCode = error.code; const errorMessage = error.message; // The email of the user's account used. const email = error.email; // The credential that was used. const credential = GoogleAuthProvider.credentialFromError(error); // ... enqueueSnackbar('Something went wrong', { variant: 'error' }); }); }, ); return () => tokenListener(); }, [enqueueSnackbar, setAuthIniting]); const logout = useCallback(() => firebaseAuth.signOut(), []); if (authIniting) return ( ); return ( {currentUser && currentNirvanaUser ? <>{children} : } ); }; const Login = () => { // take user to browser to complete authentication const handleLogin = useCallback(() => { // send to main process window.electronAPI.auth.initiateLogin(); }, []); return ( ); }; const useAuth = () => { return useContext(AuthContext); }; export default useAuth;