🐛 fix(authGuard): remove unnecessary import statement

✨ feat(authContext): add authenticationErrorCount property to AuthContextType to keep track of authentication errors

🐛 fix(authContext): fix typo in getAuthentication function, change 'refresh_token' to 'access_token'

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(authContext): remove unnecessary whitespace

🐛 fix(auth
This commit is contained in:
Cristhian Zanforlin Lousa 2023-08-12 11:05:07 -03:00
commit 2d80efb09d
7 changed files with 62 additions and 40 deletions

View file

@ -5,7 +5,6 @@ import { AuthContext } from "../../contexts/authContext";
export const ProtectedRoute = ({ children }) => { export const ProtectedRoute = ({ children }) => {
const { isAuthenticated, logout, getAuthentication } = const { isAuthenticated, logout, getAuthentication } =
useContext(AuthContext); useContext(AuthContext);
if (!isAuthenticated && !getAuthentication()) { if (!isAuthenticated && !getAuthentication()) {
logout(); logout();
return <Navigate to="/login" replace />; return <Navigate to="/login" replace />;

View file

@ -14,6 +14,7 @@ const initialValue: AuthContextType = {
userData: null, userData: null,
setUserData: () => {}, setUserData: () => {},
getAuthentication: () => false, getAuthentication: () => false,
authenticationErrorCount: 0
}; };
export const AuthContext = createContext<AuthContextType>(initialValue); export const AuthContext = createContext<AuthContextType>(initialValue);
@ -35,7 +36,7 @@ export function AuthProvider({ children }): React.ReactElement {
function getAuthentication(){ function getAuthentication(){
const storedRefreshToken = cookies.get('refresh_token'); const storedRefreshToken = cookies.get('refresh_token');
const storedAccess = cookies.get('refresh_token'); const storedAccess = cookies.get('access_token');
const auth = storedAccess && storedRefreshToken ? true : false; const auth = storedAccess && storedRefreshToken ? true : false;
return auth; return auth;
} }
@ -49,12 +50,11 @@ export function AuthProvider({ children }): React.ReactElement {
} }
function logout() { function logout() {
cookies.remove('access_token'); cookies.remove('access_token', { path: '/' });
cookies.remove('refresh_token'); cookies.remove('refresh_token', { path: '/' });
setAccessToken(null); setAccessToken(null);
setRefreshToken(null); setRefreshToken(null);
setIsAuthenticated(false); setIsAuthenticated(false);
} }
async function refreshAccessToken(refreshToken: string) { async function refreshAccessToken(refreshToken: string) {
@ -91,7 +91,8 @@ export function AuthProvider({ children }): React.ReactElement {
refreshAccessToken, refreshAccessToken,
setUserData, setUserData,
userData, userData,
getAuthentication getAuthentication,
authenticationErrorCount: 0
}} }}
> >
{children} {children}

View file

@ -5,6 +5,7 @@ import { renewAccessToken } from ".";
import { URL_EXCLUDED_FROM_ERROR_RETRIES } from "../../constants/constants"; import { URL_EXCLUDED_FROM_ERROR_RETRIES } from "../../constants/constants";
import { alertContext } from "../../contexts/alertContext"; import { alertContext } from "../../contexts/alertContext";
import { AuthContext } from "../../contexts/authContext"; import { AuthContext } from "../../contexts/authContext";
import { Cookies } from "react-cookie";
// Create a new Axios instance // Create a new Axios instance
const api: AxiosInstance = axios.create({ const api: AxiosInstance = axios.create({
@ -13,23 +14,29 @@ const api: AxiosInstance = axios.create({
function ApiInterceptor() { function ApiInterceptor() {
const { setErrorData } = useContext(alertContext); const { setErrorData } = useContext(alertContext);
const { accessToken, login, logout } = useContext(AuthContext); let { accessToken, login, logout, authenticationErrorCount } = useContext(AuthContext);
const navigate = useNavigate(); const navigate = useNavigate();
const cookies = new Cookies();
useEffect(() => { useEffect(() => {
const interceptor = api.interceptors.response.use( const interceptor = api.interceptors.response.use(
(response) => response, (response) => response,
async (error: AxiosError) => { async (error: AxiosError) => {
if (URL_EXCLUDED_FROM_ERROR_RETRIES.includes(error.config?.url)) {
return Promise.reject(error);
}
if (error.response?.status === 401) { if (error.response?.status === 401) {
const refreshToken = localStorage.getItem("refresh_token"); const refreshToken = cookies.get('refresh_token');
if (refreshToken) { if (refreshToken) {
authenticationErrorCount = authenticationErrorCount + 1;
if(authenticationErrorCount > 3){
authenticationErrorCount = 0;
logout();
navigate("/login");
}
const res = await renewAccessToken(refreshToken); const res = await renewAccessToken(refreshToken);
login(res.data.access_token, res.data.refresh_token); login(res.data.access_token, res.data.refresh_token);
try { try {
const accessToken = localStorage.getItem("access_token"); const accessToken = cookies.get('access_token');
delete error.config.headers["Authorization"]; delete error.config.headers["Authorization"];
error.config.headers["Authorization"] = `Bearer ${accessToken}`; error.config.headers["Authorization"] = `Bearer ${accessToken}`;
const response = await axios.request(error.config); const response = await axios.request(error.config);
@ -41,30 +48,40 @@ function ApiInterceptor() {
} }
} }
} }
} else { else{
let retryCount = 0; logout();
while (retryCount < 4) { navigate("/login");
await sleep(5000); // Sleep for 5 seconds
retryCount++;
try {
const response = await axios.request(error.config);
return response;
} catch (error) {
if (retryCount === 3) {
setErrorData({
title: "There was an error on web connection, please: ",
list: [
"Refresh the page",
"Use a new flow tab",
"Check if the backend is up",
"Endpoint: " + error.config?.url,
],
});
return Promise.reject(error);
}
}
} }
}
else{
// if (URL_EXCLUDED_FROM_ERROR_RETRIES.includes(error.config?.url)) {
return Promise.reject(error);
// }
} }
// else {
// let retryCount = 0;
// while (retryCount < 4) {
// await sleep(5000); // Sleep for 5 seconds
// retryCount++;
// try {
// const response = await axios.request(error.config);
// return response;
// } catch (error) {
// if (retryCount === 3) {
// setErrorData({
// title: "There was an error on web connection, please: ",
// list: [
// "Refresh the page",
// "Use a new flow tab",
// "Check if the backend is up",
// "Endpoint: " + error.config?.url,
// ],
// });
// return Promise.reject(error);
// }
// }
// }
// }
} }
); );

View file

@ -388,7 +388,7 @@ export async function renewAccessToken(token: string) {
} }
} }
export async function getUsers(): Promise<Users> { export async function getAllUsers(): Promise<Users> {
try { try {
return await api.get(`${BASE_URL_API}user`); return await api.get(`${BASE_URL_API}user`);
} catch (error) { } catch (error) {

View file

@ -23,18 +23,16 @@ export default function UserManagementModal({
index, index,
onConfirm, onConfirm,
}: UserManagementType) { }: UserManagementType) {
const Icon: any = nodeIconsLucide[icon]; const Icon: any = nodeIconsLucide[icon];
const [pwdVisible, setPwdVisible] = useState(false); const [pwdVisible, setPwdVisible] = useState(false);
const [confirmPwdVisible, setConfirmPwdVisible] = useState(false); const [confirmPwdVisible, setConfirmPwdVisible] = useState(false);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [password, setPassword] = useState(data?.password ?? ""); const [password, setPassword] = useState(data?.password ?? "");
const [username, setUserName] = useState(data?.username ?? ""); const [username, setUserName] = useState(data?.username ?? "");
const [confirmPassword, setConfirmPassword] = useState(data?.password ?? ""); const [confirmPassword, setConfirmPassword] = useState(data?.password ?? "");
const [isDisabled, setIsDisabled] = useState(data?.is_disabled ?? false); const [isDisabled, setIsDisabled] = useState(data?.is_disabled ?? false);
const [isSuperUser, setIsSuperUser] = useState(data?.is_superuser ?? false); const [isSuperUser, setIsSuperUser] = useState(data?.is_superuser ?? false);
const [inputState, setInputState] = useState<UserInputType>(CONTROL_NEW_USER); const [inputState, setInputState] = useState<UserInputType>(CONTROL_NEW_USER);
function handleInput({ function handleInput({
@ -47,6 +45,11 @@ export default function UserManagementModal({
if (!data) { if (!data) {
resetForm(); resetForm();
} }
else{
handleInput({ target: { name: "username", value: username } });
handleInput({ target: { name: "is_disabled", value: isDisabled } });
handleInput({ target: { name: "is_superuser", value: isSuperUser } });
}
}, [open]); }, [open]);
function resetForm() { function resetForm() {
@ -149,7 +152,7 @@ export default function UserManagementModal({
}} }}
value={password} value={password}
className="primary-input" className="primary-input"
required required={data ? false : true}
type={pwdVisible ? "text" : "password"} type={pwdVisible ? "text" : "password"}
/> />
</Form.Control> </Form.Control>
@ -203,7 +206,7 @@ export default function UserManagementModal({
}} }}
value={confirmPassword} value={confirmPassword}
className="primary-input" className="primary-input"
required required={data ? false : true}
type={confirmPwdVisible ? "text" : "password"} type={confirmPwdVisible ? "text" : "password"}
/> />
</Form.Control> </Form.Control>

View file

@ -31,6 +31,7 @@ export default function AdminPage() {
const [size, setPageSize] = useState(10); const [size, setPageSize] = useState(10);
const [index, setPageIndex] = useState(0); const [index, setPageIndex] = useState(0);
const [loadingUsers, setLoadingUsers] = useState(true); const [loadingUsers, setLoadingUsers] = useState(true);
const [totalRowsCount, setTotalRowsCount] = useState(0);
const { setErrorData, setSuccessData } = useContext(alertContext); const { setErrorData, setSuccessData } = useContext(alertContext);
const userList = useRef([]); const userList = useRef([]);

View file

@ -8,6 +8,7 @@ export type AuthContextType = {
userData: userData | null; userData: userData | null;
setUserData: (userData: userData | null) => void; setUserData: (userData: userData | null) => void;
getAuthentication: () => boolean; getAuthentication: () => boolean;
authenticationErrorCount: number;
}; };
export type userData = { export type userData = {