Skip to content
Snippets Groups Projects
auth.provider.tsx 3.53 KiB
Newer Older
  • Learn to ignore specific revisions
  • import { AuthServiceLoginApiArg, AuthServiceLoginApiResponse, useAuthServiceLoginMutation } from "@api/api";
    
    import { getCookieValue } from "@helper/coookie";
    
    Matthias Feyll's avatar
    Matthias Feyll committed
    import { BasicProp } from "@helper/interfaces";
    
    import { useAppDispatch, useAppSelector } from "@hooks";
    
    import { DEVICE_URL, LOGIN_URL } from "@routes";
    
    import { jwtDecode } from "jwt-decode";
    import { createContext, useContext, useEffect, useMemo } from "react";
    import { useNavigate } from "react-router-dom";
    
    import { setToken } from "../reducer/user.reducer";
    
    
    interface AuthProviderType {
        login: (username: string, password: string) => void,
        logout: () => void,
        // todo figure out the type of loginProperties
    
    Matthias Feyll's avatar
    Matthias Feyll committed
        loginProperties: any,
    
        isAuthenticated: () => boolean
    
    }
    
    const AuthContext = createContext<AuthProviderType>({
        login: () => { throw new Error("login function not implemented"); },
        logout: () => { throw new Error("logout function not implemented"); },
        loginProperties: undefined,
    
        isAuthenticated: () => { throw new Error("login function not implemented"); },
    
    Matthias Feyll's avatar
    Matthias Feyll committed
    export const AuthProvider: React.FC<BasicProp> = ({ children }) => {
    
        const dispatch = useAppDispatch()
        const navigate = useNavigate()
        const { username } = useAppSelector(state => state.user)
    
    
        useEffect(() => {
    
            const token = getCookieValue('token');
    
                navigate(LOGIN_URL)
    
    
        }, [username, navigate]);
    
    
        const [
            sendLogin,
            loginProperties,
        ] = useAuthServiceLoginMutation()
    
    
        /**
         * Returns the /login payload 
         */
        const getAuthPayload = (username: string, password: string): AuthServiceLoginApiArg => {
            const payload: AuthServiceLoginApiArg = {
                rbacLoginRequest: {
                    username,
                    pwd: password,
                    timestamp: new Date().getTime().toString(),
                },
            }
    
            return payload;
        }
    
        const executeLogin = (username: string, password: string) => {
            const authPayload = getAuthPayload(username, password);
    
            sendLogin(authPayload).unwrap().then((response: AuthServiceLoginApiResponse) => {
                if (!response.token) {
                    // reset the action by calling the reset hook
                    throw Error("Response is successful but no token was provided. Expected response {token: '<jwt-token>'}");
                }
    
    
                dispatch(setToken({ token: response.token, username }));
    
                navigate(DEVICE_URL);
    
    Matthias Feyll's avatar
    Matthias Feyll committed
            }).catch(() => {
    
                // determine whether 500 or 401 err
            });
        }
    
    
        const isAuthenticated = () => {
    
            const token = getCookieValue('token');
    
            if (!token) {
                return false;
            }
    
            const { exp } = jwtDecode(token);
            const currentTime = new Date().getTime() / 1000;
    
            // TODO this is currently a workaround for the never expiring token
            if (process.env.NODE_ENV === 'development') {
                return !!token;
    
            } else {
    
                return !!token && exp! > currentTime;
            }
        }
    
    
            // TODO: purge other information
    
    Matthias Feyll's avatar
    Matthias Feyll committed
        const value = useMemo<AuthProviderType>(
    
                login: executeLogin,
    
                isAuthenticated,
    
    Matthias Feyll's avatar
    Matthias Feyll committed
            [executeLogin, loginProperties, logout]
    
        );
    
        return (
            <AuthContext.Provider value={value}>
                {children}
            </AuthContext.Provider>
        )
    }
    
    export const useAuth = () => {
        return useContext(AuthContext);
    }