Skip to content

Commit e008245

Browse files
[UI] Added LoginByGoogle (#2852)
1 parent 7fed232 commit e008245

File tree

11 files changed

+167
-1
lines changed

11 files changed

+167
-1
lines changed

frontend/src/App/Login/EnterpriseLogin/index.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ import { Box, NavigateLink, SpaceBetween } from 'components';
66
import { UnauthorizedLayout } from 'layouts/UnauthorizedLayout';
77

88
import { ROUTES } from 'routes';
9-
import { useGetEntraInfoQuery, useGetOktaInfoQuery } from 'services/auth';
9+
import { useGetEntraInfoQuery, useGetOktaInfoQuery, useGetGoogleInfoQuery } from 'services/auth';
1010

1111
import { LoginByEntraID } from '../EntraID/LoginByEntraID';
1212
import { LoginByOkta } from '../LoginByOkta';
13+
import { LoginByGoogle } from '../LoginByGoogle';
1314
import { LoginByTokenForm } from '../LoginByTokenForm';
1415

1516
import styles from './styles.module.scss';
@@ -18,9 +19,11 @@ export const EnterpriseLogin: React.FC = () => {
1819
const { t } = useTranslation();
1920
const { data: oktaData, isLoading: isLoadingOkta } = useGetOktaInfoQuery();
2021
const { data: entraData, isLoading: isLoadingEntra } = useGetEntraInfoQuery();
22+
const { data: googleData, isLoading: isLoadingGoogle } = useGetGoogleInfoQuery();
2123

2224
const oktaEnabled = oktaData?.enabled;
2325
const entraEnabled = entraData?.enabled;
26+
const googleEnabled = googleData?.enabled;
2427

2528
const isLoading = isLoadingOkta || isLoadingEntra;
2629
const isShowTokenForm = !oktaEnabled && !entraEnabled;
@@ -36,6 +39,7 @@ export const EnterpriseLogin: React.FC = () => {
3639
{!isLoading && isShowTokenForm && <LoginByTokenForm />}
3740
{!isLoadingOkta && oktaEnabled && <LoginByOkta className={styles.okta} />}
3841
{!isLoadingEntra && entraEnabled && <LoginByEntraID className={styles.entra} />}
42+
{!isLoadingGoogle && googleEnabled && <LoginByGoogle className={styles.google} />}
3943

4044
{!isLoading && !isShowTokenForm && (
4145
<Box color="text-body-secondary">
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import React from 'react';
2+
import { useTranslation } from 'react-i18next';
3+
import cn from 'classnames';
4+
5+
import { Button } from 'components';
6+
7+
import { goToUrl } from 'libs';
8+
import { useGoogleAuthorizeMutation } from 'services/auth';
9+
10+
import { ReactComponent as GoogleIcon } from 'assets/icons/google.svg';
11+
import styles from './styles.module.scss';
12+
13+
export const LoginByGoogle: React.FC<{ className?: string }> = ({ className }) => {
14+
const { t } = useTranslation();
15+
16+
const [googleAuthorize, { isLoading }] = useGoogleAuthorizeMutation();
17+
18+
const signInClick = () => {
19+
googleAuthorize()
20+
.unwrap()
21+
.then((data) => {
22+
goToUrl(data.authorization_url);
23+
})
24+
.catch(console.log);
25+
};
26+
27+
return (
28+
<div className={cn(styles.signIn, className)}>
29+
<Button onClick={signInClick} disabled={isLoading} loading={isLoading} variant="normal">
30+
<span className={styles.loginButtonInner}>
31+
<GoogleIcon />
32+
<span className={styles.loginButtonLabel}>{t('common.login_google')}</span>
33+
</span>
34+
</Button>
35+
</div>
36+
);
37+
};
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
@use '@cloudscape-design/design-tokens/index' as awsui;
2+
3+
.signIn {
4+
display: flex;
5+
justify-content: center;
6+
7+
button {
8+
.loginButtonInner {
9+
display: inline-flex;
10+
align-items: center;
11+
justify-content: center;
12+
gap: 8px;
13+
}
14+
15+
.loginButtonLabel {
16+
height: 20px;
17+
line-height: 21px;
18+
}
19+
}
20+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import React, { useEffect, useState } from 'react';
2+
import { useTranslation } from 'react-i18next';
3+
import { useNavigate, useSearchParams } from 'react-router-dom';
4+
5+
import { NavigateLink } from 'components';
6+
import { UnauthorizedLayout } from 'layouts/UnauthorizedLayout';
7+
8+
import { useAppDispatch } from 'hooks';
9+
import { ROUTES } from 'routes';
10+
import { useGoogleCallbackMutation } from 'services/auth';
11+
12+
import { AuthErrorMessage } from 'App/AuthErrorMessage';
13+
import { Loading } from 'App/Loading';
14+
import { setAuthData } from 'App/slice';
15+
16+
export const LoginByGoogleCallback: React.FC = () => {
17+
const { t } = useTranslation();
18+
const [searchParams] = useSearchParams();
19+
const navigate = useNavigate();
20+
const code = searchParams.get('code');
21+
const state = searchParams.get('state');
22+
const [isInvalidCode, setIsInvalidCode] = useState(false);
23+
const dispatch = useAppDispatch();
24+
25+
const [googleCallback] = useGoogleCallbackMutation();
26+
27+
const checkCode = () => {
28+
if (code && state) {
29+
googleCallback({ code, state })
30+
.unwrap()
31+
.then(({ creds: { token } }) => {
32+
dispatch(setAuthData({ token }));
33+
navigate('/');
34+
})
35+
.catch(() => {
36+
setIsInvalidCode(true);
37+
});
38+
}
39+
};
40+
41+
useEffect(() => {
42+
if (code && state) {
43+
checkCode();
44+
} else {
45+
setIsInvalidCode(true);
46+
}
47+
}, []);
48+
49+
if (isInvalidCode)
50+
return (
51+
<UnauthorizedLayout>
52+
<AuthErrorMessage title={t('auth.authorization_failed')}>
53+
<NavigateLink href={ROUTES.BASE}>{t('auth.try_again')}</NavigateLink>
54+
</AuthErrorMessage>
55+
</UnauthorizedLayout>
56+
);
57+
58+
return (
59+
<UnauthorizedLayout>
60+
<Loading />;
61+
</UnauthorizedLayout>
62+
);
63+
};

frontend/src/App/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const IGNORED_AUTH_PATHS = [
1919
ROUTES.AUTH.GITHUB_CALLBACK,
2020
ROUTES.AUTH.OKTA_CALLBACK,
2121
ROUTES.AUTH.ENTRA_CALLBACK,
22+
ROUTES.AUTH.GOOGLE_CALLBACK,
2223
ROUTES.AUTH.TOKEN,
2324
];
2425

frontend/src/api.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ export const API = {
2222
AUTHORIZE: () => `${API.AUTH.ENTRA.BASE()}/authorize`,
2323
CALLBACK: () => `${API.AUTH.ENTRA.BASE()}/callback`,
2424
},
25+
GOOGLE: {
26+
BASE: () => `${API.AUTH.BASE()}/google`,
27+
INFO: () => `${API.AUTH.GOOGLE.BASE()}/info`,
28+
AUTHORIZE: () => `${API.AUTH.GOOGLE.BASE()}/authorize`,
29+
CALLBACK: () => `${API.AUTH.GOOGLE.BASE()}/callback`,
30+
},
2531
},
2632

2733
USERS: {
Lines changed: 1 addition & 0 deletions
Loading

frontend/src/locale/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"login_github": "Sign in with GitHub",
3333
"login_okta": "Sign in with Okta",
3434
"login_entra": "Sign in with EntraID",
35+
"login_google": "Sign in with Google",
3536
"general": "General",
3637
"test": "Test",
3738
"local_storage_unavailable": "Local Storage is unavailable",

frontend/src/router.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import App from 'App';
77
import { LoginByEntraIDCallback } from 'App/Login/EntraID/LoginByEntraIDCallback';
88
import { LoginByGithubCallback } from 'App/Login/LoginByGithubCallback';
99
import { LoginByOktaCallback } from 'App/Login/LoginByOktaCallback';
10+
import { LoginByGoogleCallback } from 'App/Login/LoginByGoogleCallback';
1011
import { TokenLogin } from 'App/Login/TokenLogin';
1112
import { Logout } from 'App/Logout';
1213
import { FleetDetails, FleetList } from 'pages/Fleets';
@@ -45,6 +46,10 @@ export const router = createBrowserRouter([
4546
path: ROUTES.AUTH.ENTRA_CALLBACK,
4647
element: <LoginByEntraIDCallback />,
4748
},
49+
{
50+
path: ROUTES.AUTH.GOOGLE_CALLBACK,
51+
element: <LoginByGoogleCallback />,
52+
},
4853
{
4954
path: ROUTES.AUTH.TOKEN,
5055
element: <TokenLogin />,

frontend/src/routes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export const ROUTES = {
88
GITHUB_CALLBACK: `/auth/github/callback`,
99
OKTA_CALLBACK: `/auth/okta/callback`,
1010
ENTRA_CALLBACK: `/auth/entra/callback`,
11+
GOOGLE_CALLBACK: `/auth/google/callback`,
1112
TOKEN: `/auth/token`,
1213
},
1314

0 commit comments

Comments
 (0)