keanacobarde / FEDuo

0 stars 0 forks source link

SETUP - Authentication/Register #3

Open keanacobarde opened 2 months ago

keanacobarde commented 2 months ago

User Story

I, as the user, should be able to login and utilize the application, if I have previously logged in and registered. If not, I should be redirected to a registration form.

Acceptance Criteria

As laid out by MVP:

User Authentication: Staff will log in securely using Firebase Authentication, ensuring a reliable and secure access system.

Dependecies

Dev Notes

Authentication utilities pulled from previous full-stack projects. Compare and contrast and ensure API calls align with backend.

const checkUser = (uid) => new Promise((resolve, reject) => { fetch(${clientCredentials.databaseURL}/api/checkuser, { method: 'POST', body: JSON.stringify({ uid }), headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, }) .then((resp) => { if (resp.ok) { resolve(resp.json()); } else { resolve({}); } }) .catch(reject); });

const registerUser = (userInfo) => new Promise((resolve, reject) => { fetch(${clientCredentials.databaseURL}/api/register, { method: 'POST', body: JSON.stringify(userInfo), headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, }) .then((resp) => resolve(resp.json())) .catch(reject); });

const signIn = () => { const provider = new firebase.auth.GoogleAuthProvider(); firebase.auth().signInWithPopup(provider); };

const signOut = () => { firebase.auth().signOut(); };

export { signIn, // signOut, checkUser, registerUser, };


- authContext.js

// Context API Docs: https://beta.reactjs.org/learn/passing-data-deeply-with-context

import React, { createContext, // useContext, useEffect, useMemo, useState, } from 'react'; import { checkUser } from '../auth'; import { firebase } from '../client';

const AuthContext = createContext();

AuthContext.displayName = 'AuthContext'; // Context object accepts a displayName string property. React DevTools uses this string to determine what to display for the context. https://reactjs.org/docs/context.html#contextdisplayname

const AuthProvider = (props) => { const [user, setUser] = useState(null); const [oAuthUser, setOAuthUser] = useState(null);

// there are 3 states for the user: // null = application initial state, not yet loaded // false = user is not logged in, but the app has loaded // an object/value = user is logged in

const updateUser = useMemo( () => (uid) => checkUser(uid).then((gamerInfo) => { setUser({ fbUser: oAuthUser, ...gamerInfo }); }), [oAuthUser], );

useEffect(() => { firebase.auth().onAuthStateChanged((fbUser) => { if (fbUser) { setOAuthUser(fbUser); checkUser(fbUser.uid).then((gamerInfo) => { let userObj = {}; if ('null' in gamerInfo) { userObj = gamerInfo; } else { userObj = { fbUser, uid: fbUser.uid, ...gamerInfo }; } setUser(userObj); }); } else { setOAuthUser(false); setUser(false); } }); // creates a single global listener for auth state changed }, []);

const value = useMemo( // https://reactjs.org/docs/hooks-reference.html#usememo () => ({ user, updateUser, userLoading: user === null || oAuthUser === null, // as long as user === null, will be true // As soon as the user value !== null, value will be false }), [user, oAuthUser, updateUser], );

return <AuthContext.Provider value={value} {...props} />; }; const AuthConsumer = AuthContext.Consumer;

const useAuth = () => { const context = useContext(AuthContext);

if (context === undefined) { throw new Error('useAuth must be used within an AuthProvider'); } return context; };

export { AuthProvider, useAuth, AuthConsumer };