oktopus/frontend/src/contexts/auth-context.js

241 lines
5.0 KiB
JavaScript

import { createContext, useContext, useEffect, useReducer, useRef } from 'react';
import PropTypes from 'prop-types';
import { useRouter } from 'next/router';
const HANDLERS = {
INITIALIZE: 'INITIALIZE',
SIGN_IN: 'SIGN_IN',
SIGN_OUT: 'SIGN_OUT'
};
const initialState = {
isAuthenticated: false,
isLoading: true,
user: null
};
const handlers = {
[HANDLERS.INITIALIZE]: (state, action) => {
const user = action.payload;
return {
...state,
...(
// if payload (user) is provided, then is authenticated
user
? ({
isAuthenticated: true,
isLoading: false,
user
})
: ({
isLoading: false
})
)
};
},
[HANDLERS.SIGN_IN]: (state, action) => {
const user = action.payload;
return {
...state,
isAuthenticated: true,
user
};
},
[HANDLERS.SIGN_OUT]: (state) => {
return {
...state,
isAuthenticated: false,
user: null
};
}
};
const reducer = (state, action) => (
handlers[action.type] ? handlers[action.type](state, action) : state
);
// The role of this context is to propagate authentication state through the App tree.
export const AuthContext = createContext({ undefined });
export const AuthProvider = (props) => {
const { children } = props;
const [state, dispatch] = useReducer(reducer, initialState);
const initialized = useRef(false);
const router = useRouter();
const initialize = async () => {
// Prevent from calling twice in development mode with React.StrictMode enabled
if (initialized.current) {
return;
}
initialized.current = true;
let isAuthenticated = false;
try {
isAuthenticated = window.sessionStorage.getItem('authenticated') === 'true';
} catch (err) {
console.error(err);
}
console.log("isAuthenticated: ", isAuthenticated)
if (isAuthenticated) {
const user = {
id: '5e86809283e28b96d2d38537',
avatar: '/assets/avatars/default-avatar.png',
name: 'Oktopus',
email: 'anika.visser@devias.io',
token: localStorage.getItem("token")
};
dispatch({
type: HANDLERS.INITIALIZE,
payload: user
});
console.log("AUTH CONTEXT --> auth.user.token:", user.token)
} else {
dispatch({
type: HANDLERS.INITIALIZE
});
}
};
useEffect(
() => {
initialize();
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
);
const skip = () => {
try {
window.sessionStorage.setItem('authenticated', 'true');
} catch (err) {
console.error(err);
}
const user = {
id: '5e86809283e28b96d2d38537',
avatar: '/assets/avatars/default-avatar.png',
name: 'Oktopus',
email: 'anika.visser@devias.io',
};
dispatch({
type: HANDLERS.SIGN_IN,
payload: user
});
};
const signIn = async (email, password) => {
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
var raw = JSON.stringify({
"email": email,
"password": password
});
var requestOptions = {
method: 'PUT',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
let result = await fetch(process.env.NEXT_PUBLIC_REST_ENDPOINT+"/auth/login", requestOptions)
if (result.status != 200) {
throw new Error('Please check your email and password');
}
const token = await result.json()
try {
window.sessionStorage.setItem('authenticated', 'true');
window.sessionStorage.setItem('email',email)
} catch (err) {
console.error(err);
}
const user = {
id: '5e86809283e28b96d2d38537',
avatar: '/assets/avatars/default-avatar.png',
name: 'Oktopus',
email: email,
token: token
};
localStorage.setItem("token", token)
dispatch({
type: HANDLERS.SIGN_IN,
payload: user
});
};
const signUp = async (email, name, password) => {
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
var raw = JSON.stringify({
"email": email,
"password": password,
"name": name
});
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
let result = await fetch(process.env.NEXT_PUBLIC_REST_ENDPOINT+"/auth/admin/register", requestOptions)
if (result.status == 200) {
router.push("/auth/login")
}else{
const content = await result.json()
throw new Error(content);
}
};
const signOut = () => {
dispatch({
type: HANDLERS.SIGN_OUT
});
};
return (
<AuthContext.Provider
value={{
...state,
skip,
signIn,
signUp,
signOut,
}}
>
{children}
</AuthContext.Provider>
);
};
AuthProvider.propTypes = {
children: PropTypes.node
};
export const AuthConsumer = AuthContext.Consumer;
export const useAuthContext = () => useContext(AuthContext);