🐛 fix(App.tsx): add autoLogin function to handle automatic login on page refresh

🐛 fix(authLoginGuard/index.tsx): change condition to check autoLogin flag instead of LOCALHOST_JWT flag
🐛 fix(headerComponent/index.tsx): change condition to check autoLogin flag instead of LOCALHOST_JWT flag
🐛 fix(constants.ts): remove unused LOCALHOST_JWT variable
✨ feat(authContext.tsx): add autoLogin and setAutoLogin functions to AuthContext
🐛 fix(API/api.tsx): add auto_login endpoint to the list of excluded endpoints from Authorization header
✨ feat(API/index.ts): add autoLogin function to handle automatic login
🐛 fix(AdminPage/index.tsx): change handleDisableUser function parameter from user.is_superuser to user.is_active
🐛 fix(types/contexts/auth.ts): add autoLogin and setAutoLogin to AuthContextType
This commit is contained in:
Cristhian Zanforlin Lousa 2023-08-16 08:38:49 -03:00
commit d320ddd30a
10 changed files with 56 additions and 70 deletions

View file

@ -14,10 +14,8 @@ import { alertContext } from "./contexts/alertContext";
import { AuthContext } from "./contexts/authContext"; import { AuthContext } from "./contexts/authContext";
import { locationContext } from "./contexts/locationContext"; import { locationContext } from "./contexts/locationContext";
import { TabsContext } from "./contexts/tabsContext"; import { TabsContext } from "./contexts/tabsContext";
import { getLoggedUser, onLogin } from "./controllers/API"; import { autoLogin, getLoggedUser, onLogin } from "./controllers/API";
import Router from "./routes"; import Router from "./routes";
import { LOCALHOST_JWT } from "./constants/constants";
import { LoginType } from "./types/api";
export default function App() { export default function App() {
let { setCurrent, setShowSideBar, setIsStackedOpen } = let { setCurrent, setShowSideBar, setIsStackedOpen } =
@ -133,52 +131,32 @@ export default function App() {
}; };
//this function is to get the user logged in when the page is refreshed //this function is to get the user logged in when the page is refreshed
const { setUserData, getAuthentication, login } = useContext(AuthContext); const { setUserData, getAuthentication, login, setAutoLogin } = useContext(AuthContext);
useEffect(() => { useEffect(() => {
setTimeout(() => { setTimeout(() => {
if (getAuthentication && !isLoginPage) { autoLogin().then((user) => {
getLoggedUser() if(user && user['access_token']){
.then((user) => { user['refresh_token'] = "auto";
setUserData(user); login(user['access_token'], user['refresh_token']);
}) setAutoLogin(true);
.catch((error) => {}); }
} }).catch((error) => {
}, 1000); setAutoLogin(false);
if (getAuthentication && !isLoginPage) {
getLoggedUser()
.then((user) => {
setUserData(user);
})
.catch((error) => {});
}
else{
navigate("/login");
}
});
}, 500);
}, []); }, []);
useEffect(() => {
if(LOCALHOST_JWT === true && isLocalHost === true){
const user: LoginType = {
username: "superuser",
password: "12345",
};
onLogin(user)
.then((user) => {
login(user.access_token, user.refresh_token);
getUser();
navigate("/");
})
.catch((error) => {
setErrorData({
title: "Error signing in",
list: [error["response"]["data"]["detail"]],
});
});
}
}, [])
function getUser() {
if (getAuthentication) {
setTimeout(() => {
getLoggedUser()
.then((user) => {
setUserData(user);
})
.catch((error) => {});
}, 1000);
}
}
return ( return (
//need parent component with width and height //need parent component with width and height

View file

@ -65,10 +65,6 @@ export default function PaginatorComponent({
<span className="sr-only">Go to first page</span> <span className="sr-only">Go to first page</span>
<IconComponent name="ChevronsLeft" className="h-4 w-4" /> <IconComponent name="ChevronsLeft" className="h-4 w-4" />
</Button> </Button>
<Button <Button
disabled={index <= 0} disabled={index <= 0}
onClick={() => { onClick={() => {
@ -85,10 +81,6 @@ export default function PaginatorComponent({
<span className="sr-only">Go to previous page</span> <span className="sr-only">Go to previous page</span>
<IconComponent name="ChevronLeft" className="h-4 w-4" /> <IconComponent name="ChevronLeft" className="h-4 w-4" />
</Button> </Button>
<Button <Button
disabled={currentPage === maxIndex} disabled={currentPage === maxIndex}
onClick={() => { onClick={() => {
@ -103,10 +95,6 @@ export default function PaginatorComponent({
<span className="sr-only">Go to next page</span> <span className="sr-only">Go to next page</span>
<IconComponent name="ChevronRight" className="h-4 w-4" /> <IconComponent name="ChevronRight" className="h-4 w-4" />
</Button> </Button>
<Button <Button
disabled={currentPage === maxIndex} disabled={currentPage === maxIndex}
variant="outline" variant="outline"

View file

@ -1,14 +1,11 @@
import { useContext } from "react"; import { useContext } from "react";
import { Navigate } from "react-router-dom"; import { Navigate } from "react-router-dom";
import { AuthContext } from "../../contexts/authContext"; import { AuthContext } from "../../contexts/authContext";
import { LOCALHOST_JWT } from "../../constants/constants";
export const ProtectedLoginRoute = ({ children }) => { export const ProtectedLoginRoute = ({ children }) => {
const { getAuthentication } = useContext(AuthContext); const { getAuthentication, autoLogin } = useContext(AuthContext);
const isLocalHost = window.location.href.includes("localhost"); if(autoLogin === true){
if(isLocalHost && LOCALHOST_JWT){
window.location.replace("/"); window.location.replace("/");
return <Navigate to="/" replace />; return <Navigate to="/" replace />;
} }

View file

@ -2,7 +2,7 @@ import { useContext, useEffect, useState } from "react";
import { FaDiscord, FaGithub, FaTwitter } from "react-icons/fa"; import { FaDiscord, FaGithub, FaTwitter } from "react-icons/fa";
import { Link, useLocation, useNavigate } from "react-router-dom"; import { Link, useLocation, useNavigate } from "react-router-dom";
import AlertDropdown from "../../alerts/alertDropDown"; import AlertDropdown from "../../alerts/alertDropDown";
import { LOCALHOST_JWT, USER_PROJECTS_HEADER } from "../../constants/constants"; import { USER_PROJECTS_HEADER } from "../../constants/constants";
import { alertContext } from "../../contexts/alertContext"; import { alertContext } from "../../contexts/alertContext";
import { AuthContext } from "../../contexts/authContext"; import { AuthContext } from "../../contexts/authContext";
import { darkContext } from "../../contexts/darkContext"; import { darkContext } from "../../contexts/darkContext";
@ -18,11 +18,10 @@ export default function Header() {
const { dark, setDark } = useContext(darkContext); const { dark, setDark } = useContext(darkContext);
const { notificationCenter } = useContext(alertContext); const { notificationCenter } = useContext(alertContext);
const location = useLocation(); const location = useLocation();
const { logout } = useContext(AuthContext); const { logout, autoLogin } = useContext(AuthContext);
const navigate = useNavigate(); const navigate = useNavigate();
const [stars, setStars] = useState(null); const [stars, setStars] = useState(null);
const isLocalHost = window.location.href.includes("localhost");
// Get and set numbers of stars on header // Get and set numbers of stars on header
useEffect(() => { useEffect(() => {
@ -38,7 +37,7 @@ export default function Header() {
<Link to="/"> <Link to="/">
<span className="ml-4 text-2xl">⛓️</span> <span className="ml-4 text-2xl">⛓️</span>
</Link> </Link>
{!isLocalHost || !LOCALHOST_JWT && ( {autoLogin === false && (
<Button <Button
onClick={() => { onClick={() => {
logout(); logout();

View file

@ -610,5 +610,3 @@ export function tabsArray(codes: string[], method: number) {
} }
export const BASE_URL_API = "http://localhost:7860/"; export const BASE_URL_API = "http://localhost:7860/";
export let LOCALHOST_JWT = false;

View file

@ -14,6 +14,8 @@ const initialValue: AuthContextType = {
setUserData: () => {}, setUserData: () => {},
getAuthentication: () => false, getAuthentication: () => false,
authenticationErrorCount: 0, authenticationErrorCount: 0,
autoLogin: false,
setAutoLogin: () => {},
}; };
export const AuthContext = createContext<AuthContextType>(initialValue); export const AuthContext = createContext<AuthContextType>(initialValue);
@ -23,6 +25,7 @@ export function AuthProvider({ children }): React.ReactElement {
const [refreshToken, setRefreshToken] = useState<string | null>(null); const [refreshToken, setRefreshToken] = useState<string | null>(null);
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(false); const [isAuthenticated, setIsAuthenticated] = useState<boolean>(false);
const [userData, setUserData] = useState<Users>(null); const [userData, setUserData] = useState<Users>(null);
const [autoLogin, setAutoLogin] = useState<boolean>(false);
const cookies = new Cookies(); const cookies = new Cookies();
useEffect(() => { useEffect(() => {
@ -91,6 +94,8 @@ export function AuthProvider({ children }): React.ReactElement {
userData, userData,
getAuthentication, getAuthentication,
authenticationErrorCount: 0, authenticationErrorCount: 0,
setAutoLogin,
autoLogin
}} }}
> >
{children} {children}

View file

@ -80,6 +80,10 @@ function ApiInterceptor() {
config?.url?.includes( config?.url?.includes(
"https://api.github.com/repos/logspace-ai/langflow" "https://api.github.com/repos/logspace-ai/langflow"
) )
||
config?.url?.includes(
"auto_login"
)
) { ) {
delete config.headers["Authorization"]; delete config.headers["Authorization"];
} }

View file

@ -378,6 +378,21 @@ export async function onLogin(user: LoginType) {
} }
} }
export async function autoLogin() {
try {
const response = await api.get(
`${BASE_URL_API}auto_login`
);
if (response.status === 200) {
const data = response.data;
return data;
}
} catch (error) {
throw error;
}
}
export async function renewAccessToken(token: string) { export async function renewAccessToken(token: string) {
try { try {
return await api.post(`${BASE_URL_API}refresh?token=${token}`); return await api.post(`${BASE_URL_API}refresh?token=${token}`);

View file

@ -266,7 +266,7 @@ export default function AdminPage() {
<TableRow> <TableRow>
<TableHead className="h-10">Id</TableHead> <TableHead className="h-10">Id</TableHead>
<TableHead className="h-10">Username</TableHead> <TableHead className="h-10">Username</TableHead>
<TableHead className="h-10">Disabled</TableHead> <TableHead className="h-10">Active</TableHead>
<TableHead className="h-10">Superuser</TableHead> <TableHead className="h-10">Superuser</TableHead>
<TableHead className="h-10">Created At</TableHead> <TableHead className="h-10">Created At</TableHead>
<TableHead className="h-10">Updated At</TableHead> <TableHead className="h-10">Updated At</TableHead>
@ -304,7 +304,7 @@ export default function AdminPage() {
index={index} index={index}
onConfirm={(index, user) => { onConfirm={(index, user) => {
handleDisableUser( handleDisableUser(
user.is_superuser, user.is_active,
user.id, user.id,
user user
); );

View file

@ -11,4 +11,6 @@ export type AuthContextType = {
setUserData: (userData: Users | null) => void; setUserData: (userData: Users | null) => void;
getAuthentication: () => boolean; getAuthentication: () => boolean;
authenticationErrorCount: number; authenticationErrorCount: number;
autoLogin: boolean;
setAutoLogin: (autoLogin: boolean) => void
}; };