diff --git a/app/contexts/Authentication/Authentication.tsx b/app/contexts/Authentication/Authentication.tsx deleted file mode 100644 index a0da3f27bc..0000000000 --- a/app/contexts/Authentication/Authentication.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import { - createContext, - useCallback, - useEffect, - useState, - ReactNode, - Dispatch, - SetStateAction -} from "react"; - -import { - SessionResponse, - AuthState, - STORAGE_KEYS -} from "./types"; - -import { CreateSession, DestroySession, GetSession } from "./utilities"; - -export const AuthenticationContext = createContext<{ - authState: AuthState, - setAuthState?: Dispatch>, - loginAndGetUserInfo?: ( - usernameOrEmail: string, - password:string, - failureCallback?:()=>void - )=>void; - logout?: ()=>void; -}>({ - authState:{} -}); - -export const AuthenticationProvider = ({children}:{children:ReactNode})=>{ - // console.log('auth provider rerender'); - // const [, setAuthCookie, removeAuthCookie] = useCookies([STORAGE_KEYS.USER_INFO]); - const [authState, setAuthState] = useState({}); - - const loginAndGetUserInfo = useCallback(( - usernameOrEmail: string, - password:string, - failureCallback?:()=>void - )=>{ - CreateSession({usernameOrEmail, password}) - .then((respond)=>{ - GetSession().then(( - res: SessionResponse - )=>{ - if(res.success && res.user && setAuthState){ - setAuthState({ - isLoggedIn: true, - sessionData: JSON.stringify(res.user), - userInfo: res.user - }); - }else{ - if(failureCallback) failureCallback(); - } - }); - }); - },[]); - - const setLogoutState = useCallback(()=>{ - setAuthState({ - isLoggedIn: false, - sessionData: null, - userInfo: undefined - }); - },[]); - - const logout = useCallback(()=>{ - DestroySession().then((res)=>{ - if (res) setLogoutState(); - }); - },[]); - - //Set Session upon Auth State Changes - useEffect(()=>{ - //On First Load - if(authState.isLoggedIn === undefined){ - //Persist Login if Session Data exist - const sessionData = localStorage.getItem(STORAGE_KEYS.USER_INFO); - // console.log(`Session Data: ${sessionData?.substring(0, 30)}${sessionData ? '...':''}`); - if (sessionData !== null){ - // console.log('Getting session to persist login'); - GetSession().then(( - res: SessionResponse - )=>{ - // console.log('Session Returned'); - // console.log(res); - if(res.success && res.user){ - // console.log('Setting Auth State'); - setAuthState({ - isLoggedIn: true, - sessionData: JSON.stringify(res.user), - userInfo: res.user - }); - }else{ - // console.log('Session expired, setting State'); - setLogoutState(); - } - }); - }else{ - setLogoutState(); - } - } - - // Propagate session data to localstorage - if(authState.sessionData !== null && authState.sessionData !== undefined){ - localStorage.setItem(STORAGE_KEYS.USER_INFO, authState.sessionData); - // setAuthCookie(STORAGE_KEYS.USER_INFO, authState.userInfo); - } - // Propagate Logout - else if (authState.sessionData === null){ - localStorage.removeItem(STORAGE_KEYS.USER_INFO); - // removeAuthCookie(STORAGE_KEYS.USER_INFO); - } - },[authState]); - - return( - - {children} - - ) -} - \ No newline at end of file diff --git a/app/contexts/Authentication/AuthenticationContext.tsx b/app/contexts/Authentication/AuthenticationContext.tsx new file mode 100644 index 0000000000..821bb92c1b --- /dev/null +++ b/app/contexts/Authentication/AuthenticationContext.tsx @@ -0,0 +1,18 @@ +import { createContext, Dispatch, SetStateAction } from "react"; +import { AuthState, AUTH_STATUS } from "./types"; + +export const AuthenticationContext = createContext<{ + authState: AuthState, + setAuthState?: Dispatch>, + login?: ( + usernameOrEmail: string, + password:string, + failureCallback?:()=>void + )=>void; + logout?: ()=>void; +}>({ + authState:{ + authStatus: AUTH_STATUS.INIT + } +}); + diff --git a/app/contexts/Authentication/AuthenticationProvider.tsx b/app/contexts/Authentication/AuthenticationProvider.tsx new file mode 100644 index 0000000000..c09239fe66 --- /dev/null +++ b/app/contexts/Authentication/AuthenticationProvider.tsx @@ -0,0 +1,123 @@ +import { useCallback, useEffect, useState, ReactNode} from "react"; +import { SessionResponse, AuthState, STORAGE_KEYS, AUTH_STATUS, UserInfo} from "./types"; +import { CreateSession, DestroySession, GetSession } from "./utilities"; +import { AuthenticationContext } from "./AuthenticationContext"; + +export const AuthenticationProvider = ({children}:{children:ReactNode})=>{ + console.log('auth provider rerender'); + + const [authState, setAuthState] = useState({ + authStatus: AUTH_STATUS.INIT + }); + + const startLoggingState = useCallback(()=>{ + setAuthState({ + authStatus: AUTH_STATUS.LOGGING, + sessionToken: undefined, + userInfo: undefined + }); + }, []); + + const updateLoggingState = useCallback((sessionToken: string)=>{ + setAuthState({ + authStatus: AUTH_STATUS.LOGGING, + sessionToken: sessionToken, + userInfo: undefined + }); + }, []); + + const setLoginState = useCallback((userInfo: UserInfo)=>{ + setAuthState((curr)=>({ + ...curr, + authStatus: AUTH_STATUS.LOGGED_IN, + userInfo: userInfo, + })); + }, []) + + const setLogoutState = useCallback(()=>{ + setAuthState({ + authStatus: AUTH_STATUS.LOGGED_OUT, + sessionToken: undefined, + userInfo: undefined + }); + },[]); + + const login = useCallback(( + usernameOrEmail: string, + password:string, + failureCallback?:()=>void + )=>{ + console.log('CreateSession'); + startLoggingState(); + CreateSession({usernameOrEmail, password}) + .then((loginResponse)=>{ + updateLoggingState(loginResponse.signed_session); + GetSession().then(( + sessionResponse: SessionResponse + )=>{ + if(sessionResponse.success && sessionResponse.user && sessionResponse.user !== null){ + setLoginState(sessionResponse.user); + }else{ + if(failureCallback) failureCallback(); + setLogoutState(); + } + }); + }); + },[]); + + const logout = useCallback(()=>{ + DestroySession().then((res)=>{ + if (res) setLogoutState(); + }); + },[]); + + //Set Session upon Auth State Changes + useEffect(()=>{ + //On First Load + if(authState.authStatus === AUTH_STATUS.INIT){ + //Persist Login if Session Data exist + const sessionData = localStorage.getItem(STORAGE_KEYS.SESSION_TOKEN); + console.log(`Session Data: ${sessionData?.substring(0, 30)}${sessionData ? '...':''}`); + if (sessionData !== null){ + console.log('Getting session to persist login'); + updateLoggingState(sessionData); + GetSession().then(( + sessionResponse: SessionResponse + )=>{ + console.log('Session Returned'); + console.log(sessionResponse); + if(sessionResponse.success && sessionResponse.user && sessionResponse.user !== null){ + console.log('Setting Auth State'); + setLoginState(sessionResponse.user) + }else{ + console.log('Session expired, setting State'); + setLogoutState(); + } + }); + }else{ + setLogoutState(); + } + } + + // Propagate session data to localstorage + if(authState.sessionToken !== null && authState.sessionToken !== undefined){ + localStorage.setItem(STORAGE_KEYS.SESSION_TOKEN, authState.sessionToken); + } + // Propagate Logout + else if (authState.sessionToken === null){ + localStorage.removeItem(STORAGE_KEYS.SESSION_TOKEN); + } + },[authState]); + + return( + + {children} + + ) +} + \ No newline at end of file diff --git a/app/contexts/Authentication/index.tsx b/app/contexts/Authentication/index.tsx index 0074994891..d8182c97c6 100644 --- a/app/contexts/Authentication/index.tsx +++ b/app/contexts/Authentication/index.tsx @@ -1,4 +1,5 @@ -import { AuthenticationContext, AuthenticationProvider } from "./Authentication"; +import { AuthenticationContext, } from "./AuthenticationContext"; +import { AuthenticationProvider } from "./AuthenticationProvider"; import { UserInfo, AUTH_STATUS } from "./types"; diff --git a/app/contexts/Authentication/types.tsx b/app/contexts/Authentication/types.tsx index b1e05ae494..7666c58134 100644 --- a/app/contexts/Authentication/types.tsx +++ b/app/contexts/Authentication/types.tsx @@ -1,15 +1,17 @@ export enum STORAGE_KEYS{ - USER_INFO = "user_info", + SESSION_TOKEN = "session_token", } + export enum AUTH_STATUS { + INIT = "INIT", LOGGED_IN = "logged_in", LOGGING = "logging", LOGGED_OUT = "logged_out", } export type AuthState = { - isLoggedIn?: boolean; - sessionData?: string | null; + authStatus: AUTH_STATUS; + sessionToken?: string | null; userInfo?: UserInfo; } export interface UserInfo { diff --git a/app/contexts/Authentication/utilities.tsx b/app/contexts/Authentication/utilities.tsx index 0cc54b8f46..78a11ee0bd 100644 --- a/app/contexts/Authentication/utilities.tsx +++ b/app/contexts/Authentication/utilities.tsx @@ -21,7 +21,7 @@ export const CreateSession = async ({ "Accept": "application/json", "Content-Type": "application/json", }, - credentials: 'include', + // credentials: 'include', body: JSON.stringify(request) }) .then(res => res.json()) @@ -39,7 +39,7 @@ export const GetSession = async () => { headers: { 'Accept': 'application/json', }, - credentials: 'include', + // credentials: 'include', }) .then(res => res.json()) .then(res => { @@ -59,7 +59,7 @@ export async function DestroySession() : Promise { headers: { 'Accept': 'application/json', }, - credentials: 'include', + // credentials: 'include', }) .then(res => res.json()) .then(res => { diff --git a/app/hooks/useInferenceJobManager/useInferenceJobManager.tsx b/app/hooks/useInferenceJobManager/useInferenceJobManager.tsx index 89c5206542..f107143d55 100644 --- a/app/hooks/useInferenceJobManager/useInferenceJobManager.tsx +++ b/app/hooks/useInferenceJobManager/useInferenceJobManager.tsx @@ -59,7 +59,7 @@ export async function GetInferenceJobStatus(jobToken:string) : Promise res.json()) .then(res => { diff --git a/app/modules/TopBar/AuthButtons.tsx b/app/modules/TopBar/AuthButtons.tsx index 1f7474667a..fc7ed8a14c 100644 --- a/app/modules/TopBar/AuthButtons.tsx +++ b/app/modules/TopBar/AuthButtons.tsx @@ -1,10 +1,9 @@ import { useContext, } from "react"; import { useSignals } from "@preact/signals-react/runtime"; -import { AuthenticationContext } from "~/contexts/Authentication"; +import { AUTH_STATUS, AuthenticationContext } from "~/contexts/Authentication"; import { Button, ButtonLink } from "~/components"; import { DialogueInference } from "../DialogueInference"; -import { inferenceJobs } from "~/pages/PageEnigma/store/inferenceJobs"; export const AuthButtons = ()=>{ useSignals(); @@ -13,7 +12,7 @@ export const AuthButtons = ()=>{ const handleLogout = ()=>{ if(logout)logout(); } - if ( authState && authState.isLoggedIn ) { + if ( authState && authState.authStatus === AUTH_STATUS.LOGGED_IN ) { return( <> diff --git a/app/modules/withProtectedRoute/index.tsx b/app/modules/withProtectedRoute/index.tsx index 1278e11b6f..aff5cb6a75 100644 --- a/app/modules/withProtectedRoute/index.tsx +++ b/app/modules/withProtectedRoute/index.tsx @@ -1,25 +1,33 @@ import { useContext, useEffect, ComponentType } from "react"; import { useNavigate, useLocation } from "@remix-run/react"; -import { AuthenticationContext } from "~/contexts/Authentication"; +import { AUTH_STATUS, AuthenticationContext } from "~/contexts/Authentication"; +import { LoadingDots } from "~/components"; export const withProtectionRoute =

(Component: ComponentType

) => (rest:P) => { const { authState } = useContext(AuthenticationContext); - if (authState.isLoggedIn === undefined ) { - return <>waiting; - } - if (authState.isLoggedIn === false) { + if (authState.authStatus === AUTH_STATUS.LOGGED_OUT) { return } - return ( - - ); + else if (authState.authStatus === AUTH_STATUS.LOGGED_IN ) { + return (); + }else { + return( +

+ +
+ ); + } } const RedirectToLogin = ()=>{ const navigate = useNavigate(); const {pathname} = useLocation(); useEffect(()=>{ - navigate(`/login?redirect=${pathname}`); + setTimeout(()=>navigate(`/login?redirect=${pathname}`), 2000); },[]); - return <>redirecting + return ( +
+ +
+ ); } \ No newline at end of file diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/AudioTabComponent/listAudioByUser.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/AudioTabComponent/listAudioByUser.tsx index b277c03941..19e0d23c3e 100644 --- a/app/pages/PageEnigma/comps/SidePanelTabs/AudioTabComponent/listAudioByUser.tsx +++ b/app/pages/PageEnigma/comps/SidePanelTabs/AudioTabComponent/listAudioByUser.tsx @@ -40,7 +40,7 @@ export const ListAudioByUser = async(username:string) => { headers: { "Accept": "application/json", }, - credentials: 'include' + // credentials: 'include' }) .then(res => res.json()) .then(res => { diff --git a/app/pages/PageEnigma/js/api_manager.ts b/app/pages/PageEnigma/js/api_manager.ts index 8657109208..14d6f554e7 100644 --- a/app/pages/PageEnigma/js/api_manager.ts +++ b/app/pages/PageEnigma/js/api_manager.ts @@ -238,7 +238,7 @@ export class APIManager { const response = await fetch(url, { method: "POST", - credentials: "include", + // credentials: "include", headers: { Accept: "application/json", }, @@ -291,7 +291,7 @@ export class APIManager { const response = await fetch(url, { method: "POST", - credentials: "include", + // credentials: "include", headers: { Accept: "application/json", }, @@ -325,7 +325,7 @@ export class APIManager { const response = await fetch(url, { method: "POST", - credentials: "include", + // credentials: "include", headers: { Accept: "application/json", }, @@ -362,7 +362,7 @@ export class APIManager { const response = await fetch(url, { method: "POST", - credentials: "include", + // credentials: "include", headers: { Accept: "application/json", }, @@ -421,7 +421,7 @@ export class APIManager { const response = await fetch(`${this.baseUrl}/v1/video/enqueue_vst`, { method: "POST", - credentials: "include", + // credentials: "include", headers: { Accept: "application/json", "Content-Type": "application/json", diff --git a/app/routes/Login.tsx b/app/routes/Login.tsx index eb1205dcf3..db398880d7 100644 --- a/app/routes/Login.tsx +++ b/app/routes/Login.tsx @@ -1,7 +1,7 @@ import { useContext, useEffect, useState, useRef } from "react"; import { useNavigate, useSearchParams } from "@remix-run/react"; import { faKey, faUser } from "@fortawesome/pro-solid-svg-icons"; -import { AuthenticationContext } from "~/contexts/Authentication"; +import { AUTH_STATUS, AuthenticationContext } from "~/contexts/Authentication"; import { Button,H1,Input,Link,P } from '~/components'; import { LoadingDots } from "~/components"; @@ -12,7 +12,7 @@ export default function LoginScreen() { const [showLoader, setShowLoader] = useState(undefined); const formRef = useRef(null); - const {authState, loginAndGetUserInfo} = useContext(AuthenticationContext); + const {authState, login} = useContext(AuthenticationContext); const handleOnSumbit = (ev: React.FormEvent)=>{ ev.preventDefault(); @@ -20,9 +20,9 @@ export default function LoginScreen() { const form = new FormData(formRef.current); const usernameOrEmail = form.get("usernameOrEmail")?.toString(); const password = form.get("password")?.toString(); - if( usernameOrEmail && password && loginAndGetUserInfo){ + if( usernameOrEmail && password && login){ setShowLoader("Authenticating"); - loginAndGetUserInfo( + login( usernameOrEmail, password, ()=>{ @@ -34,7 +34,7 @@ export default function LoginScreen() { useEffect(()=>{ const redirectPath = searchParams.get('redirect'); - if(authState && authState.isLoggedIn) + if(authState && authState.authStatus === AUTH_STATUS.LOGGED_IN) navigate(redirectPath ? redirectPath:'/'); },[authState]);