add isActive field to dev, checks for user existance on sign up to not overwrite inactive profiles

This commit is contained in:
Ruidy Nemausat 2020-05-16 13:40:07 +02:00
parent de6790168c
commit c988143921
6 changed files with 38 additions and 17 deletions

View file

@ -10,8 +10,9 @@ import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {faCode, faSignOutAlt, faUser} from '@fortawesome/free-solid-svg-icons'; import {faCode, faSignOutAlt, faUser} from '@fortawesome/free-solid-svg-icons';
// Typing // Typing
import User from '../models/User'; import User from '../models/User';
import Dev from '../models/Dev';
interface IProps extends WithFirebaseProps<User> { interface IProps extends Dev, WithFirebaseProps<User> {
isEmpty: boolean; isEmpty: boolean;
isLoaded: boolean; isLoaded: boolean;
} }
@ -19,7 +20,7 @@ interface IProps extends WithFirebaseProps<User> {
/** /**
* Main Navbar serves navigation Routes. * Main Navbar serves navigation Routes.
*/ */
const NavBar: FC<IProps> = ({firebase, isEmpty, isLoaded}) => { const NavBar: FC<IProps> = ({firebase, isEmpty, isLoaded, isActive}) => {
const publicLinks = ( const publicLinks = (
<ul data-testid="publicLinks"> <ul data-testid="publicLinks">
<li> <li>
@ -72,7 +73,8 @@ const NavBar: FC<IProps> = ({firebase, isEmpty, isLoaded}) => {
); );
/** Display appropriated links after loading given authenticated prop */ /** Display appropriated links after loading given authenticated prop */
const RenderLinks = isLoaded && !isEmpty ? privateLinks : publicLinks; const RenderLinks =
isLoaded && !isEmpty && isActive ? privateLinks : publicLinks;
return ( return (
<nav className="navbar bg-dark"> <nav className="navbar bg-dark">

View file

@ -13,13 +13,14 @@ import Alert from '../components/Alert';
import User from '../models/User'; import User from '../models/User';
// Form // Form
import useForm from '../hooks'; import useForm from '../hooks';
import Dev from '../models/Dev';
interface InitFormData { interface InitFormData {
email: string; email: string;
password: string; password: string;
} }
interface IProps extends WithFirebaseProps<User> { interface IProps extends Dev, WithFirebaseProps<User> {
isEmpty: boolean; isEmpty: boolean;
isLoaded: boolean; isLoaded: boolean;
} }
@ -27,7 +28,7 @@ interface IProps extends WithFirebaseProps<User> {
/** /**
* Sign in form * Sign in form
*/ */
const SignIn: FC<IProps> = ({firebase, isEmpty, isLoaded}) => { const SignIn: FC<IProps> = ({firebase, isEmpty, isLoaded, isActive}) => {
const [error, setError] = useState<any>(null); const [error, setError] = useState<any>(null);
// handle form data // handle form data
@ -57,7 +58,7 @@ const SignIn: FC<IProps> = ({firebase, isEmpty, isLoaded}) => {
firebase.login({provider: 'google', type: 'popup'}); firebase.login({provider: 'google', type: 'popup'});
// redirect to dashboard if connected // redirect to dashboard if connected
if (isLoaded && !isEmpty) { if (isLoaded && !isEmpty && isActive) {
return <Redirect to={Routes.DASHBOARD} />; return <Redirect to={Routes.DASHBOARD} />;
} }

View file

@ -12,10 +12,10 @@ import Alert from '../components/Alert';
import Header from '../components/Header'; import Header from '../components/Header';
// Form // Form
import useForm from '../hooks'; import useForm from '../hooks';
import {blankDev} from '../models/Dev'; import Dev, {blankDev} from '../models/Dev';
// extends withFirebaseProps type to ad profile info // extends withFirebaseProps type to ad profile info
interface IProps extends WithFirebaseProps<User> { interface IProps extends Dev, WithFirebaseProps<User> {
isEmpty: boolean; isEmpty: boolean;
isLoaded: boolean; isLoaded: boolean;
} }
@ -30,7 +30,7 @@ interface InitFormData {
/** /**
* Sign up form recieves firebase from withFirebase HOC * Sign up form recieves firebase from withFirebase HOC
*/ */
const SignUp: FC<IProps> = ({firebase, isEmpty, isLoaded}) => { const SignUp: FC<IProps> = ({firebase, isEmpty, isLoaded, isActive}) => {
const [error, setError] = useState<any>(null); const [error, setError] = useState<any>(null);
// handle form data // handle form data
@ -66,11 +66,29 @@ const SignUp: FC<IProps> = ({firebase, isEmpty, isLoaded}) => {
const loginWithGoogle = () => const loginWithGoogle = () =>
firebase firebase
.login({provider: 'google', type: 'popup'}) .login({provider: 'google', type: 'popup'})
.then(() => firebase.updateProfile(blankDev, {useSet: true, merge: true})) .then(() => {
// updateProfile only if user does not already exists in db
const email = firebase.auth().currentUser?.email;
let exists: boolean = false;
firebase
.firestore()
.collection('users/')
.where('email', '==', email)
.get()
.then(docs =>
docs.forEach(doc => {
exists = doc.data().isActive !== undefined;
}),
)
.then(() => {
if (!exists)
firebase.updateProfile(blankDev, {useSet: true, merge: true});
});
})
.catch(err => setError(err)); .catch(err => setError(err));
// redirect to dashboard if connected // redirect to dashboard if connected
if (isLoaded && !isEmpty) { if (isLoaded && !isEmpty && isActive) {
return <Redirect to={Routes.DASHBOARD} />; return <Redirect to={Routes.DASHBOARD} />;
} }

View file

@ -23,13 +23,15 @@ const PrivateRoute: FC<IProps> = ({
...rest ...rest
}) => { }) => {
const auth = useSelector((state: RootState) => state.firebase.auth); const auth = useSelector((state: RootState) => state.firebase.auth);
const profile = useSelector((state: RootState) => state.firebase.profile);
const isActive = profile.isActive;
return ( return (
<Route <Route
exact={exact} exact={exact}
path={path} path={path}
{...rest} {...rest}
render={({location, ...rest}) => render={({location, ...rest}) =>
isLoaded(auth) && !isEmpty(auth) ? ( isLoaded(auth) && !isEmpty(auth) && isActive ? (
<Component {...rest} /> <Component {...rest} />
) : ( ) : (
<Redirect <Redirect

View file

@ -19,7 +19,7 @@ const rrfProps = {
createFirestoreInstance, createFirestoreInstance,
}; };
// Firestore SChema // Firestore Schema
export interface Schema { export interface Schema {
devs: Dev; devs: Dev;
} }

View file

@ -1,16 +1,14 @@
// Redux // Redux
import {configureStore} from '@reduxjs/toolkit'; import {configureStore} from '@reduxjs/toolkit';
// import authReducer from './auth/';
// Firebase // Firebase
import {firebaseReducer, FirebaseReducer} from 'react-redux-firebase'; import {firebaseReducer, FirebaseReducer} from 'react-redux-firebase';
import {firestoreReducer} from 'redux-firestore'; import {firestoreReducer} from 'redux-firestore';
// Typing // Typing
import User from '../models/User';
import {Schema} from './firebase/config'; import {Schema} from './firebase/config';
import Dev from '../models/Dev';
const store = configureStore({ const store = configureStore({
reducer: { reducer: {
// auth: authReducer,
firebase: firebaseReducer, firebase: firebaseReducer,
firestore: firestoreReducer, firestore: firestoreReducer,
}, },
@ -18,7 +16,7 @@ const store = configureStore({
// State type // State type
export interface RootState { export interface RootState {
firebase: FirebaseReducer.Reducer<User, Schema>; firebase: FirebaseReducer.Reducer<Dev, Schema>;
} }
export default store; export default store;