Skip to content

Commit 6d81159

Browse files
authored
[DOP-21436] add Keycloak auth (#128)
* [DOP-21436] add Keycloak auth * [DOP-21436] fix after review
1 parent b4eb0e5 commit 6d81159

File tree

47 files changed

+328
-52
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+328
-52
lines changed

.env.example

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
API_URL="http://localhost:8000/v1/"
1+
API_URL=http://localhost:8000
2+
AUTH_PROVIDER=dummyAuthProvider

docker/Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ COPY --from=build /app/dist /usr/share/nginx/html
2323
COPY ./docker/entrypoint.sh /entrypoint.sh
2424
RUN chmod +x /entrypoint.sh
2525

26-
ARG API_URL=http://localhost:8000/v1
26+
ARG API_URL=http://localhost:8000
27+
ARG AUTH_PROVIDER=dummyAuthProvider
2728
ENV SYNCMASTER__UI__API_BROWSER_URL=${API_URL}
29+
ENV SYNCMASTER__UI__AUTH_PROVIDER=${AUTH_PROVIDER}
2830

2931
ENTRYPOINT ["/entrypoint.sh"]
3032
CMD ["nginx", "-g", "daemon off;"]

docker/entrypoint.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
cat <<EOF > /usr/share/nginx/html/env-config.js
44
window.env = {
55
API_URL: "${SYNCMASTER__UI__API_BROWSER_URL}",
6+
AUTH_PROVIDER: "${SYNCMASTER__UI__AUTH_PROVIDER}",
67
};
78
EOF
89

src/app/config/errorBoundary/Fallback.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
import React from 'react';
22
import { FallbackProps } from 'react-error-boundary';
33
import { ErrorLayout } from '@app/layouts';
4-
import { Error } from '@shared/config';
4+
import { ErrorStatusCode } from '@shared/config';
5+
import { AUTH_PROVIDER, AuthProviderType } from '@shared/constants';
56

6-
import { AccessError, AuthError, NotFoundError, ServerError } from './errors';
7+
import { AccessError, AuthError, KeycloakAuthError, NotFoundError, ServerError } from './errors';
78
import { ErrorBoundaryContext } from './constants';
89

910
export const Fallback = ({ error, resetErrorBoundary }: FallbackProps) => {
1011
const renderError = () => {
1112
if ('status' in error) {
1213
switch (error.status) {
13-
case Error.AUTH:
14-
return <AuthError />;
15-
case Error.ACCESS:
14+
case ErrorStatusCode.AUTH:
15+
if (AUTH_PROVIDER === AuthProviderType.DUMMY) {
16+
return <AuthError />;
17+
}
18+
return <KeycloakAuthError />;
19+
case ErrorStatusCode.ACCESS:
1620
return <AccessError />;
17-
case Error.NOT_FOUND:
21+
case ErrorStatusCode.NOT_FOUND:
1822
return <NotFoundError />;
1923
default:
2024
return <ServerError />;
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { useEffect } from 'react';
1+
import React, { useLayoutEffect } from 'react';
22
import { useLogout } from '@entities/auth';
33
import { useSelectedGroup } from '@entities/group';
4+
import { SpinOverlay } from '@shared/ui';
45

56
import { useErrorBoundaryContext } from '../hooks';
67

@@ -9,11 +10,11 @@ export const AuthError = () => {
910
const { cleanGroup } = useSelectedGroup();
1011
const { resetErrorBoundary } = useErrorBoundaryContext();
1112

12-
useEffect(() => {
13+
useLayoutEffect(() => {
1314
resetErrorBoundary();
1415
cleanGroup();
1516
logout();
1617
}, [logout, cleanGroup, resetErrorBoundary]);
1718

18-
return null;
19+
return <SpinOverlay />;
1920
};
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React, { useEffect } from 'react';
2+
import { useKeycloakLogout } from '@entities/auth';
3+
import { SpinOverlay } from '@shared/ui';
4+
5+
import { AuthError } from './AuthError';
6+
7+
export const KeycloakAuthError = () => {
8+
const { mutate: logout, isSuccess } = useKeycloakLogout();
9+
10+
useEffect(() => {
11+
logout(null);
12+
}, [logout]);
13+
14+
if (!isSuccess) {
15+
return <SpinOverlay />;
16+
}
17+
18+
return <AuthError />;
19+
};

src/app/config/errorBoundary/errors/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export * from './NotFoundError';
22
export * from './ServerError';
33
export * from './AuthError';
44
export * from './AccessError';
5+
export * from './KeycloakAuthError';

src/app/config/router/instance.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
22
import { createBrowserRouter, Navigate } from 'react-router-dom';
3-
import { LoginPage } from '@pages/auth';
3+
import { KeycloakCallbackPage, LoginPage } from '@pages/auth';
44
import { AuthLayout, ErrorLayout, PrivateLayout } from '@app/layouts';
55
import { CreateGroupPage, GroupDetailPage, GroupListPage, UpdateGroupPage } from '@pages/group';
66
import { AuthProvider } from '@entities/auth';
@@ -33,6 +33,10 @@ export const router = createBrowserRouter([
3333
path: '/login',
3434
element: <LoginPage />,
3535
},
36+
{
37+
path: '/auth/callback',
38+
element: <KeycloakCallbackPage />,
39+
},
3640
],
3741
},
3842
{
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1-
import { Storage } from '@shared/constants';
1+
import { AUTH_PROVIDER, AuthProviderType, Storage } from '@shared/constants';
22

3-
export const isAuthenticated = () => !!localStorage.getItem(Storage.ACCESS_TOKEN);
3+
export const isAuthenticated = () => {
4+
if (AUTH_PROVIDER === AuthProviderType.DUMMY) {
5+
return !!localStorage.getItem(Storage.ACCESS_TOKEN);
6+
}
7+
8+
return !!localStorage.getItem(Storage.IS_KEYCLOAK_AUTH);
9+
};

src/app/layouts/PrivateLayout/index.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import React, { Suspense } from 'react';
1+
import React from 'react';
22
import { Layout } from 'antd';
33
import { Outlet } from 'react-router-dom';
44
import { Header, Sidebar } from '@widgets/layout';
5-
import { SpinOverlay } from '@shared/ui';
5+
import { SpinOverlay, Suspense } from '@shared/ui';
66
import { useSelectedGroup } from '@entities/group';
77

88
import classes from './styles.module.less';
@@ -23,7 +23,7 @@ export const PrivateLayout = () => {
2323
<Sidebar />
2424
<Layout>
2525
<Content className={classes.layout__content}>
26-
<Suspense fallback={<SpinOverlay />}>
26+
<Suspense>
2727
<Outlet />
2828
</Suspense>
2929
</Content>

0 commit comments

Comments
 (0)