blob: 440c4dc401cedbab677ab5d62888044b6b6b9e9e [file] [log] [blame]
/*
* Copyright (C) 2022 Savoir-faire Linux Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see
* <https://www.gnu.org/licenses/>.
*/
import axios, { AxiosInstance } from 'axios';
import { Account } from 'jami-web-common/dist/Account';
import { HttpStatusCode } from 'jami-web-common/dist/enums/http-status-code';
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import ProcessingRequest from '../components/ProcessingRequest';
import { apiUrl } from '../utils/constants';
import { WithChildren } from '../utils/utils';
interface IAuthContext {
token: string;
account: Account;
logout: () => void;
axiosInstance: AxiosInstance;
}
const AuthContext = createContext<IAuthContext | undefined>(undefined);
export default ({ children }: WithChildren) => {
const [token, setToken] = useState<string | undefined>();
const [account, setAccount] = useState<Account | undefined>();
const navigate = useNavigate();
const logout = useCallback(() => {
localStorage.removeItem('accessToken');
navigate('/login');
}, [navigate]);
const axiosInstance = useMemo(() => {
if (!token) {
return;
}
const instance = axios.create({
baseURL: apiUrl,
headers: {
Authorization: `Bearer ${token}`,
},
});
instance.interceptors.response.use(
(res) => res,
(e) => {
switch (e.response?.status) {
case HttpStatusCode.Unauthorized:
logout();
break;
}
throw e;
}
);
return instance;
}, [token, logout]);
useEffect(() => {
const accessToken = localStorage.getItem('accessToken');
if (!accessToken) {
console.warn('Missing authentication JWT. Redirecting to login page...');
logout();
} else {
setToken(accessToken);
}
}, [logout]);
useEffect(() => {
if (!axiosInstance) {
return;
}
axiosInstance.get('/account').then(({ data }) => setAccount(Account.from(data)));
}, [axiosInstance, logout]);
if (!token || !account || !axiosInstance) {
return <ProcessingRequest open />;
}
return (
<AuthContext.Provider
value={{
token,
logout,
account,
axiosInstance,
}}
>
{children}
</AuthContext.Provider>
);
};
export function useAuthContext(dontThrowIfUndefined: true): IAuthContext | undefined;
export function useAuthContext(): IAuthContext;
export function useAuthContext(dontThrowIfUndefined?: true) {
const authContext = useContext(AuthContext);
if (!authContext && !dontThrowIfUndefined) {
throw new Error('AuthContext is not provided');
}
return authContext;
}