Auth
This document provides a detailed overview of the Intecode Common Auth Module, which is responsible for handling user authentication and authorization.
Last updated
const { token, logout, fetchUser, currentUser } = useAuth();import { createContext, useCallback, useContext, useState } from 'react';
import { useLocalStorage } from '../common/hooks/useLocalStorage';
import { useNavigate } from 'react-router-dom';
import { useUserService } from '../services/userService';
import { REFRESH_TOKEN, TOKEN, USER_ROLES } from '../common/constants/localStorage';
import { updateToken } from '../services/tokenService';
import { useAuthService } from '../services/authService';
import globalNotification from '../common/hooks/globalNotification';
import { useTeamService } from '../services/teamService';
export const AuthContext = createContext(null);
export const AuthProvider = ({ children }) => {
const [token, setToken] = useLocalStorage(TOKEN, null);
const [refreshToken, setRefreshToken] = useLocalStorage(REFRESH_TOKEN, null);
const [currentUser, setCurrentUser] = useState();
const [isUserLoading, setIsUserLoading] = useState(true);
const navigate = useNavigate();
const userService = useUserService();
const authService = useAuthService();
const { updateMembership, findUserMembership } = useTeamService();
const fetchUser = useCallback(async () => {
try {
if (token) {
setIsUserLoading(true);
const { data } = await userService.getUser();
setCurrentUser(data);
updateToken(USER_ROLES, data.userRoleNames);
setTimeout(() => {
setIsUserLoading(false);
}, 1000);
if (!data.teamId) {
navigate('/create-team');
}
}
} catch (e) {
logout();
console.error(e);
}
}, []);
const setAuth = (token, refreshToken) => {
setToken(token);
setRefreshToken(refreshToken);
};
const logout = async () => {
try {
if (!currentUser) {
throw new Error();
}
const { data } = await findUserMembership(currentUser.id);
if (!data) {
throw new Error();
}
await updateMembership({ id: data.id, isActive: false });
} catch (e) {
console.log(e);
} finally {
updateToken(TOKEN, null);
updateToken(REFRESH_TOKEN, null);
updateToken(USER_ROLES, null);
navigate('/auth/sign-in');
}
};
const changeTeam = async teamId => {
try {
const { data } = await authService.changeTeam(teamId);
setAuth(data.accessToken, data.refreshToken || data.accessToken);
} catch (error) {
globalNotification.open({ message: 'This membership is not valid' });
} finally {
await fetchUser();
}
};
return (
<AuthContext.Provider
value={{
token,
setAuth,
logout,
fetchUser,
currentUser,
isUserLoading,
changeTeam,
}}
>
{children}
</AuthContext.Provider>
);
};
export const useAuth = () => {
return useContext(AuthContext);
};import { useLocation } from 'react-router-dom';
import { Navigate } from 'react-router-dom';
import { routesPath } from '../../common/constants/routesPath';
import { TOKEN, REFRESH_TOKEN } from '../../common/constants/localStorage';
function AuthGuard({ children }) {
const location = useLocation();
const isAuth = location.pathname.split('/')[1] === 'auth';
if (isAuth) {
return getToken(TOKEN) && getToken(REFRESH_TOKEN) ? <Navigate to={routesPath.ROOT.DASHBOARD} /> : children;
} else {
return getToken(TOKEN) && getToken(REFRESH_TOKEN) ? children : <Navigate to={'auth/sign-in'} />;
}
}
const getToken = tokenName => {
const token = localStorage.getItem(tokenName);
if (token === null || token === 'undefined') {
return null;
}
return JSON.parse(localStorage.getItem(tokenName));
};
export default AuthGuard;import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { JwtUserPayload } from 'src/common/interfaces/jwt-user-payload.interface';
export const GetUser = createParamDecorator((data, ctx: ExecutionContext): JwtUserPayload => {
const req = ctx.switchToHttp().getRequest();
return req.user;
});