Integrate new server authentication to client
Changes:
- Use server authentication REST API
- Log in automatically after registration
- Store token in localStorage
- Give feedback to user if registration or login fails
GitLab: #75
Change-Id: Ib90e5b911621567c6825af5e275920d703cdfe88
diff --git a/client/src/pages/AccountSettings.tsx b/client/src/pages/AccountSettings.tsx
index fe98277..b09fb65 100644
--- a/client/src/pages/AccountSettings.tsx
+++ b/client/src/pages/AccountSettings.tsx
@@ -15,62 +15,68 @@
* License along with this program. If not, see
* <https://www.gnu.org/licenses/>.
*/
-import { CircularProgress, Container } from '@mui/material';
-import { Account } from 'jami-web-common';
-import { useEffect, useState } from 'react';
-import { useParams } from 'react-router';
+import { Container } from '@mui/material';
+import { Account, HttpStatusCode } from 'jami-web-common';
+import { useEffect } from 'react';
+import { useNavigate } from 'react-router-dom';
-import authManager from '../AuthManager';
import AccountPreferences from '../components/AccountPreferences';
import Header from '../components/Header';
-import { setAccountId, setAccountObject } from '../redux/appSlice';
-import { useAppDispatch } from '../redux/hooks';
+import ProcessingRequest from '../components/ProcessingRequest';
+import { setAccount } from '../redux/appSlice';
+import { useAppDispatch, useAppSelector } from '../redux/hooks';
+import { getAccessToken, setAccessToken } from '../utils/auth';
+import { apiUrl } from '../utils/constants';
-type AccountSettingsProps = {
- accountId?: string;
- account?: Account;
-};
-
-const AccountSettings = (props: AccountSettingsProps) => {
- console.log('ACCOUNT SETTINGS', props.account);
- const params = useParams();
- const accountId = props.accountId || params.accountId;
-
- if (accountId == null) {
- throw new Error('Missing accountId');
- }
-
+export default function AccountSettings() {
const dispatch = useAppDispatch();
+ const navigate = useNavigate();
- const [account, setAccount] = useState<Account | null>(null);
+ const { account } = useAppSelector((state) => state.userInfo);
+ const accessToken = getAccessToken();
useEffect(() => {
- dispatch(setAccountId(accountId));
+ if (accessToken) {
+ const getAccount = async () => {
+ const url = new URL('/account', apiUrl);
+ let response: Response;
- const controller = new AbortController();
- authManager
- .fetch(`/api/accounts/${accountId}`, { signal: controller.signal })
- .then((res) => res.json())
- .then((result) => {
- const account = Account.from(result);
- account.setDevices(result.devices);
- dispatch(setAccountObject(account));
- setAccount(account);
- })
- .catch((e) => console.log(e));
- // return () => controller.abort() // crash on React18
- }, [accountId, dispatch]);
+ try {
+ response = await fetch(url, {
+ method: 'GET',
+ mode: 'cors',
+ headers: {
+ Authorization: `Bearer ${accessToken}`,
+ },
+ referrerPolicy: 'no-referrer',
+ });
+ } catch (err) {
+ setAccessToken('');
+ dispatch(setAccount(undefined));
+ navigate('/', { replace: true });
+ return;
+ }
+ if (response.status === HttpStatusCode.Ok) {
+ const serializedAccount = await response.json();
+ const account = Account.from(serializedAccount);
+ dispatch(setAccount(account));
+ } else if (response.status === HttpStatusCode.Unauthorized) {
+ setAccessToken('');
+ dispatch(setAccount(undefined));
+ navigate('/', { replace: true });
+ }
+ };
+
+ getAccount();
+ }
+ }, [accessToken, dispatch, navigate]);
+
+ // TODO: Improve component and sub-components UI.
return (
<Container maxWidth="sm">
<Header />
- {account != null ? (
- <AccountPreferences account={account} onAccountChanged={(account: Account) => setAccount(account)} />
- ) : (
- <CircularProgress />
- )}
+ {account ? <AccountPreferences account={account} /> : <ProcessingRequest open={true} />}
</Container>
);
-};
-
-export default AccountSettings;
+}