diff --git a/changes/issue-3061-no-access-user-view b/changes/issue-3061-no-access-user-view new file mode 100644 index 0000000000..f98951ed26 --- /dev/null +++ b/changes/issue-3061-no-access-user-view @@ -0,0 +1 @@ +* No access users are presented with a 403 "Access denied" page for all user routes \ No newline at end of file diff --git a/frontend/components/AccessRoutes/AccessRoutes.tsx b/frontend/components/AccessRoutes/AccessRoutes.tsx new file mode 100644 index 0000000000..9ac328ad7d --- /dev/null +++ b/frontend/components/AccessRoutes/AccessRoutes.tsx @@ -0,0 +1,38 @@ +import React from "react"; +import { useDispatch, useSelector } from "react-redux"; +import { push } from "react-router-redux"; + +import { IUser } from "interfaces/user"; +import permissionUtils from "utilities/permissions"; +import paths from "router/paths"; + +interface IAccessRoutes { + children: JSX.Element; +} + +interface IRootState { + auth: { + user: IUser; + }; +} + +const { FLEET_403 } = paths; + +const AccessRoutes = ({ children }: IAccessRoutes): JSX.Element | null => { + const dispatch = useDispatch(); + const user = useSelector((state: IRootState) => state.auth.user); + + // user is an empty object here. The API result has not come back + // so render nothing. + if (Object.keys(user).length === 0) { + return null; + } + + if (permissionUtils.isNoAccess(user)) { + dispatch(push(FLEET_403)); + return null; + } + return <>{children}; +}; + +export default AccessRoutes; diff --git a/frontend/components/AccessRoutes/index.ts b/frontend/components/AccessRoutes/index.ts new file mode 100644 index 0000000000..77be8369f5 --- /dev/null +++ b/frontend/components/AccessRoutes/index.ts @@ -0,0 +1 @@ +export { default } from "./AccessRoutes"; diff --git a/frontend/components/side_panels/SiteTopNav/navItems.js b/frontend/components/side_panels/SiteTopNav/navItems.js index 5d7473c7e6..a26aede8fc 100644 --- a/frontend/components/side_panels/SiteTopNav/navItems.js +++ b/frontend/components/side_panels/SiteTopNav/navItems.js @@ -3,7 +3,7 @@ import URL_PREFIX from "router/url_prefix"; import permissionUtils from "utilities/permissions"; export default (currentUser) => { - const userNavItems = [ + const logo = [ { icon: "logo", name: "Home", @@ -13,6 +13,9 @@ export default (currentUser) => { pathname: PATHS.HOME, }, }, + ]; + + const userNavItems = [ { icon: "hosts", name: "Hosts", @@ -79,6 +82,7 @@ export default (currentUser) => { }, ]; return [ + ...logo, ...userNavItems, ...teamMaintainerNavItems, ...policiesTab, @@ -90,8 +94,16 @@ export default (currentUser) => { permissionUtils.isGlobalMaintainer(currentUser) || permissionUtils.isAnyTeamMaintainer(currentUser) ) { - return [...userNavItems, ...teamMaintainerNavItems, ...policiesTab]; + return [ + ...logo, + ...userNavItems, + ...teamMaintainerNavItems, + ...policiesTab, + ]; } - return [...userNavItems, ...policiesTab]; + if (permissionUtils.isNoAccess(currentUser)) { + return [...logo]; + } + return [...logo, ...userNavItems, ...policiesTab]; }; diff --git a/frontend/router/index.tsx b/frontend/router/index.tsx index b828b916e6..1d104fd537 100644 --- a/frontend/router/index.tsx +++ b/frontend/router/index.tsx @@ -16,6 +16,7 @@ import AdminUserManagementPage from "pages/admin/UserManagementPage"; import AdminTeamManagementPage from "pages/admin/TeamManagementPage"; import TeamDetailsWrapper from "pages/admin/TeamManagementPage/TeamDetailsWrapper"; import App from "components/App"; +import AccessRoutes from "components/AccessRoutes"; import AuthenticatedAdminRoutes from "components/AuthenticatedAdminRoutes"; import AuthAnyAdminRoutes from "components/AuthAnyAdminRoutes"; import AuthenticatedRoutes from "components/AuthenticatedRoutes"; @@ -85,71 +86,79 @@ const routes = ( - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + - - - - - + + + + + + - - - - - + + - + - - - - diff --git a/frontend/utilities/permissions/permissions.ts b/frontend/utilities/permissions/permissions.ts index 93d054ccb1..d1e199d963 100644 --- a/frontend/utilities/permissions/permissions.ts +++ b/frontend/utilities/permissions/permissions.ts @@ -94,6 +94,10 @@ const isOnlyObserver = (user: IUser): boolean => { return false; }; +const isNoAccess = (user: IUser): boolean => { + return user.global_role === null && user.teams.length === 0; +}; + export default { isFreeTier, isPremiumTier, @@ -109,4 +113,5 @@ export default { isTeamAdmin, isAnyTeamAdmin, isOnlyObserver, + isNoAccess, };