Skip to content

Instantly share code, notes, and snippets.

@RichardSPrins
Created September 7, 2022 19:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RichardSPrins/1cf7ca5f8021e8cb9422ec8d65f16c1b to your computer and use it in GitHub Desktop.
Save RichardSPrins/1cf7ca5f8021e8cb9422ec8d65f16c1b to your computer and use it in GitHub Desktop.
import React, { useState, useEffect, useContext, createContext } from 'react';
import Router from 'next/router';
import nookies from 'nookies';
import firebase from './firebase';
import { createOrUpdateUser, deleteUser, setUserStatus } from './db';
import { useCometChat } from './cometChat';
const rtdb = firebase.database();
const formatUser = async (user: firebase.User) => {
const token = await user.getIdToken();
return {
uid: user.uid,
email: user.email,
token,
};
};
function useProvideAuth() {
const { cometChat, setChatUser } = useCometChat();
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
async function handleUserPresence() {
let uid = firebase.auth().currentUser.uid;
let userDbRef = await rtdb.ref(`/status/${uid}`);
let offline = { status: 'offline' };
let online = { status: 'online' };
rtdb.ref('.info/connected').on('value', function (snapshot) {
if (snapshot.val() === false) {
return;
}
userDbRef
.onDisconnect()
.set(offline)
.then(function () {
userDbRef.set(online);
});
});
}
async function handleUser(rawUser: any) {
if (rawUser) {
let u = await formatUser(rawUser);
const { token, ...userWithoutToken } = u;
createOrUpdateUser(u.uid, userWithoutToken);
setUser(u);
handleUserPresence();
nookies.set(undefined, 'token', token, { path: '/', secure: true });
setLoading(false);
return u;
}
setUser(false);
nookies.set(undefined, 'token', '', { path: '/', secure: true });
setLoading(false);
return false;
}
async function createUserWithEmail(email: string, password: string) {
setLoading(true);
return firebase
.auth()
.createUserWithEmailAndPassword(email, password)
.then((response) => {
handleUser(response.user);
Router.push('/exchange');
});
}
async function signInWithEmail(email: string, password: string, redirect: boolean) {
setLoading(true);
return firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then((response) => {
handleUser(response.user);
if (cometChat) {
cometChat.login(response.user.uid.toLowerCase(), `${process.env.NEXT_PUBLIC_COMETCHAT_AUTH_KEY}`).then(
(user) => {
setChatUser(user);
},
(error) => {
setChatUser(null);
console.error(error);
},
);
}
if (redirect) Router.push('/exchange');
});
}
async function signOut() {
setUserStatus(user.uid, 'offline');
Router.push('/');
cometChat.logout().then(
() => {
console.log('Logout completed successfully');
},
(error) => {
console.log('Logout failed with exception:', { error });
},
);
return firebase
.auth()
.signOut()
.then(() => handleUser(false));
}
async function deleteUserAccount() {
// get the logged in user
const { currentUser } = firebase.auth();
// force refresh firebase token
await currentUser.getIdToken(true);
// delete the user in firestore
await deleteUser(currentUser.uid);
// delete the user in auth
return currentUser.delete().then(() => Router.push('/')); // go back to landing page
}
async function resetPassword(email: string) {
firebase.auth().sendPasswordResetEmail(email);
}
useEffect(() => {
const unsubscribe = firebase.auth().onIdTokenChanged(handleUser);
return () => unsubscribe();
}, []);
useEffect(() => {
const unsubscribe = firebase.auth().onAuthStateChanged(handleUser);
return () => unsubscribe();
}, []);
return {
user,
loading,
createUserWithEmail,
signInWithEmail,
signOut,
deleteUserAccount,
resetPassword,
};
}
// TODO: add better type checking here
const authContext = createContext({} as any);
type AuthProviderProps = {
children: React.ReactNode;
};
export function AuthProvider({ children }: AuthProviderProps) {
const auth = useProvideAuth();
return <authContext.Provider value={auth}>{children}</authContext.Provider>;
}
export const useAuth = () => useContext(authContext);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment