Skip to content
Snippets Groups Projects
Authorization.tsx 1.73 KiB
Newer Older
Defendi Alberto's avatar
Defendi Alberto committed
import React, { ComponentType, FC, useContext } from 'react';
import { BlurCircular } from '@material-ui/icons';
import { NonAuthRoutes } from 'api/routes';
import { Redirect } from 'react-router-dom';
import { Unauthorized } from 'components/Unauthorized/Unauthorized';
import { AuthContext } from 'components/Auth/AuthContext';
Defendi Alberto's avatar
Defendi Alberto committed

const HandleIsAuth: FC<{ isAuth: boolean }> = ({ isAuth }) =>
  isAuth ? (
    <Unauthorized />
  ) : (
    <Redirect
      to={{ pathname: `${NonAuthRoutes.auth}${NonAuthRoutes.signIn}` }}
    />
  );
Defendi Alberto's avatar
Defendi Alberto committed

interface WithAuthProps {
  allowedRoles: string[];
}

Defendi Alberto's avatar
Defendi Alberto committed
interface Props extends WithAuthProps {
Defendi Alberto's avatar
Defendi Alberto committed
  children: React.ReactNode;
}

/* eslint-disable react/jsx-props-no-spreading */
Defendi Alberto's avatar
Defendi Alberto committed
/**
 *
 * @param WrappedComponent component to be wrapped by the authentication control.
 * This creates a "personal area" in the working implementation.
 * @returns {FC<T>} wrapped component.
 */
Defendi Alberto's avatar
Defendi Alberto committed
export const withAuthorization = <T extends WithAuthProps = WithAuthProps>(
  WrappedComponent: React.ComponentType<T>,
): FC<T> => {
  // Creating the inner component. The calculated Props type here is the where the magic happens.
  const ComponentWithAuthorization: FC<T> = (
    props: Omit<T, keyof WithAuthProps>,
  ) => {
    const { allowedRoles } = props as T;

Defendi Alberto's avatar
Defendi Alberto committed
    const { role, isAuth } = useContext(AuthContext);
    console.log(`ROLE ${role} AUTH ${isAuth}`);
Defendi Alberto's avatar
Defendi Alberto committed

    /* eslint-disable no-nested-ternary */
    return typeof isAuth === null || role === null ? (
      <BlurCircular />
    ) : // props comes afterwards so the can override the default ones.
    allowedRoles.includes(role) && isAuth ? (
Defendi Alberto's avatar
Defendi Alberto committed
      <WrappedComponent {...(props as T)} />
    ) : (
      <HandleIsAuth isAuth={!!isAuth} />
Defendi Alberto's avatar
Defendi Alberto committed
    );
  };

  return ComponentWithAuthorization;
};