|
2 | 2 | * Authentication
|
3 | 3 | *
|
4 | 4 | * wrap component for authentication
|
| 5 | + * |
| 6 | + * - checks if user is logged-in, and if not, then redirects to the login page |
| 7 | + * |
| 8 | + * Also, this component load important data for `hasPermission` method: |
| 9 | + * - decodes user token and set in Redux Store `authUser.userId, handle, roles` |
| 10 | + * - we need to know user `roles` to check if user user has Topcoder Roles |
| 11 | + * - load team (project) members if current route has `:teamId` param |
| 12 | + * - we need to know members of the team to check user users Project Roles |
5 | 13 | */
|
6 |
| -import React, { useState, useEffect } from "react"; |
| 14 | +import React, { useEffect } from "react"; |
7 | 15 | import _ from "lodash";
|
8 | 16 | import { getAuthUserTokens, login } from "@topcoder/micro-frontends-navbar-app";
|
9 | 17 | import LoadingIndicator from "../../components/LoadingIndicator";
|
10 |
| -import { authUserSuccess, authUserError } from "./actions"; |
| 18 | +import { |
| 19 | + authUserSuccess, |
| 20 | + authUserError, |
| 21 | + authLoadTeamMembers, |
| 22 | + authClearTeamMembers, |
| 23 | +} from "./actions"; |
11 | 24 | import { decodeToken } from "tc-auth-lib";
|
12 | 25 | import { useDispatch, useSelector } from "react-redux";
|
| 26 | +import { useParams } from "@reach/router"; |
13 | 27 |
|
14 | 28 | export default function withAuthentication(Component) {
|
15 | 29 | const AuthenticatedComponent = (props) => {
|
16 | 30 | const dispatch = useDispatch();
|
17 |
| - const { isLoggedIn, authError } = useSelector((state) => state.authUser); |
| 31 | + const { isLoggedIn, authError, teamId, teamMembersLoaded, teamMembersLoadingError } = useSelector( |
| 32 | + (state) => state.authUser |
| 33 | + ); |
| 34 | + const params = useParams(); |
18 | 35 |
|
| 36 | + /* |
| 37 | + Check if user is logged-in or redirect ot the login page |
| 38 | + */ |
19 | 39 | useEffect(() => {
|
20 | 40 | // prevent page redirecting to login page when unmount
|
21 | 41 | let isUnmount = false;
|
22 |
| - getAuthUserTokens() |
23 |
| - .then(({ tokenV3 }) => { |
24 |
| - if (!!tokenV3) { |
25 |
| - const tokenData = decodeToken(tokenV3); |
26 |
| - dispatch( |
27 |
| - authUserSuccess(_.pick(tokenData, ["userId", "handle", "roles"])) |
28 |
| - ); |
29 |
| - } else if (!isUnmount) { |
30 |
| - login(); |
31 |
| - } |
32 |
| - }) |
33 |
| - .catch((error) => dispatch(authUserError(error))); |
| 42 | + |
| 43 | + if (!isLoggedIn) { |
| 44 | + getAuthUserTokens() |
| 45 | + .then(({ tokenV3 }) => { |
| 46 | + if (!!tokenV3) { |
| 47 | + const tokenData = decodeToken(tokenV3); |
| 48 | + dispatch( |
| 49 | + authUserSuccess( |
| 50 | + _.pick(tokenData, ["userId", "handle", "roles"]) |
| 51 | + ) |
| 52 | + ); |
| 53 | + } else if (!isUnmount) { |
| 54 | + login(); |
| 55 | + } |
| 56 | + }) |
| 57 | + .catch((error) => dispatch(authUserError(error))); |
| 58 | + } |
34 | 59 |
|
35 | 60 | return () => {
|
36 | 61 | isUnmount = true;
|
37 | 62 | };
|
38 |
| - }, [dispatch]); |
| 63 | + }, [dispatch, isLoggedIn]); |
| 64 | + |
| 65 | + /* |
| 66 | + Load team (project) members if current URL has `:teamId` param |
| 67 | + */ |
| 68 | + useEffect(() => { |
| 69 | + // if we haven't loaded team members yet, or we if we've moved to a page for another team |
| 70 | + // we have to load team members which we would use for checking permissions |
| 71 | + if ( |
| 72 | + isLoggedIn && |
| 73 | + params.teamId && |
| 74 | + (!teamId || params.teamId !== teamId) |
| 75 | + ) { |
| 76 | + dispatch(authLoadTeamMembers(params.teamId)); |
| 77 | + |
| 78 | + // if we are going to some page without `teamId` then we have to clear team members |
| 79 | + // if we had some |
| 80 | + } else if (teamId && !params.teamId) { |
| 81 | + dispatch(authClearTeamMembers()); |
| 82 | + } |
| 83 | + }, [params.teamId, teamId, dispatch, isLoggedIn]); |
39 | 84 |
|
40 | 85 | return (
|
41 | 86 | <>
|
42 | 87 | {/* Show loading indicator until we know if user is logged-in or no.
|
| 88 | + Also, show loading indicator if we need to know team members but haven't loaded them yet. |
43 | 89 | In we got error during this process, show error */}
|
44 |
| - {isLoggedIn === null && <LoadingIndicator error={authError} />} |
| 90 | + {isLoggedIn === null || (params.teamId && !teamMembersLoaded) && <LoadingIndicator error={authError || teamMembersLoadingError} />} |
45 | 91 |
|
46 |
| - {/* Show component only if user is logged-in */} |
47 |
| - {isLoggedIn === true ? <Component {...props} /> : null} |
| 92 | + {/* Show component only if user is logged-in and if we don't need team members or we already loaded them */} |
| 93 | + {isLoggedIn === true && (!params.teamId || teamMembersLoaded) ? <Component {...props} /> : null} |
48 | 94 | </>
|
49 | 95 | );
|
50 | 96 | };
|
|
0 commit comments