Skip to content

Commit

Permalink
Merge pull request #8 from nichitaa/dev
Browse files Browse the repository at this point in the history
fix flickering for first check/validation of user role
  • Loading branch information
nichitaa authored May 12, 2022
2 parents a984572 + eb81ee9 commit 5c17f82
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 46 deletions.
2 changes: 1 addition & 1 deletion example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ const App = () => {
</Link>
</li>
</ul>
<fieldset>
<fieldset style={{minHeight: 100}}>
<legend>pages wrapper</legend>
<Routes />
</fieldset>
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "0.4.1",
"version": "0.4.2",
"license": "MIT",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
Expand Down
85 changes: 45 additions & 40 deletions src/hooks/use-role.hook.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {useContext, useEffect, useState} from 'react';
import {RouterContext} from "../context/context";
import { useContext, useEffect, useState } from 'react';
import { RouterContext } from '../context/context';

/**
* Custom hook that returns a boolean value if the user can access the specified route path,
Expand All @@ -17,50 +17,55 @@ export const useRole = (
) => {
const ctx = useContext(RouterContext);
if (!ctx) {
throw new Error(
`useRole hook must be used inside AppRouter provider!`,
);
throw new Error(`useRole hook must be used inside AppRouter provider!`);
}
const [userHasRequiredRole, setUserHasRequiredRole] = useState(false);
const { userRole } = ctx;

const [userHasRequiredRole, setUserHasRequiredRole] = useState(() =>
checkRole(path, routeRoles, userRole, allRolesRequired),
);

useEffect(() => {
/** the route has some roles */
if (routeRoles && routeRoles.length) {
if (!userRole) {
/** but user has no role */
const errorMsg = `The path ${path} has some required roles: ${JSON.stringify(
routeRoles,
)}, but current user does not have a role!`;
console.error(errorMsg);
// throw new Error(errorMsg);
} else {
/** check against user role/s */
const canAccess = checkRole(path, routeRoles, userRole, allRolesRequired);
if (canAccess !== userHasRequiredRole) setUserHasRequiredRole(canAccess);
}, [userRole, routeRoles]);

return [userHasRequiredRole];
};

if (Array.isArray(userRole)) {
/** user has multiple roles */
if (allRolesRequired) {
/** and all roles must be required */
const hasAllRoles = routeRoles.every((r) => userRole.includes(r));
setUserHasRequiredRole(hasAllRoles);
} else {
/** user must have at least one role */
const hasAtLeastOneRole = userRole.some((r) =>
routeRoles.includes(r),
);
setUserHasRequiredRole(hasAtLeastOneRole);
}
} else {
/** user has a single role */
const roleIsIncluded = routeRoles.includes(userRole);
setUserHasRequiredRole(roleIsIncluded);
const checkRole = (
path: string,
routeRoles?: string[],
userRole?: string[] | string,
allRolesRequired?: boolean,
): boolean => {
/** the route has some roles */
if (routeRoles && routeRoles.length) {
if (!userRole) {
/** but user has no role */
const errorMsg = `The path ${path} has some required roles: ${JSON.stringify(
routeRoles,
)}, but current user does not have a role!`;
console.error(errorMsg);
// throw new Error(errorMsg);
} else {
/** check against user role/s */
if (Array.isArray(userRole)) {
/** user has multiple roles */
if (allRolesRequired) {
/** and all roles must be required */
const hasAllRoles = routeRoles.every((r) => userRole.includes(r));
return hasAllRoles;
}
/** user must have at least one role */
const hasAtLeastOneRole = userRole.some((r) => routeRoles.includes(r));
return hasAtLeastOneRole;
}
} else {
/** the route has no roles */
setUserHasRequiredRole(true);
/** user has a single role */
const roleIsIncluded = routeRoles.includes(userRole);
return roleIsIncluded;
}
}, [userRole, routeRoles]);

return [userHasRequiredRole];
}
/** the route has no roles */
return true;
};
2 changes: 1 addition & 1 deletion src/route/common.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const Common: FC<IRoute> = (props): ReactElement => {
? defaultFallback
: null;

if (userHasRequiredRole === false) {
if (!userHasRequiredRole) {
return InvalidUserRoleFallback ? (
<InvalidUserRoleFallback
currentUserRole={userRole}
Expand Down
2 changes: 1 addition & 1 deletion src/route/private.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const Private: FC<IRoute> = (props): ReactElement => {
}

/** user must have the required role that matches a route role */
if (userHasRequiredRole === false) {
if (!userHasRequiredRole) {
return InvalidUserRoleFallback ? (
<InvalidUserRoleFallback
currentUserRole={userRole}
Expand Down
2 changes: 1 addition & 1 deletion src/route/public.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const Public: FC<IRoute> = (props): ReactElement => {
}

/** user must have the required role that matches a route role */
if (userHasRequiredRole === false) {
if (!userHasRequiredRole) {
return InvalidUserRoleFallback ? (
<InvalidUserRoleFallback
currentUserRole={userRole}
Expand Down
2 changes: 1 addition & 1 deletion src/shared/invalid-user-default-fallback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const InvalidUserDefaultFallback: FC<MainProps> = ({
</p>
<br />
<p>
Route required roles:{' '}
Route required roles:&nbsp;
<strong>{JSON.stringify(routeRequiredRoles)}</strong>
</p>
</>
Expand Down

0 comments on commit 5c17f82

Please sign in to comment.