blob: 82217457f0cd49cf2baa93802d61562e7648485a [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 { HttpStatusCode, IAccount } from 'jami-web-common';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import ProcessingRequest from '../components/ProcessingRequest';
import { createOptionalContext } from '../hooks/createOptionalContext';
import { Account } from '../models/account';
import { apiUrl } from '../utils/constants';
import { WithChildren } from '../utils/utils';
interface IAuthContext {
token: string;
account: Account;
accountId: string;
logout: () => void;
axiosInstance: AxiosInstance;
}
const optionalAuthContext = createOptionalContext<IAuthContext>('AuthContext');
const AuthContext = optionalAuthContext.Context;
export const useAuthContext = optionalAuthContext.useOptionalContext;
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<IAccount>('/account').then(({ data }) => setAccount(Account.fromInterface(data)));
}, [axiosInstance, logout]);
const value = useMemo(() => {
if (!token || !account || !axiosInstance) {
return;
}
return {
token,
logout,
account,
accountId: account.id,
axiosInstance,
};
}, [token, logout, account, axiosInstance]);
if (!value) {
return <ProcessingRequest open />;
}
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
};