From 95917837e37b3536f46128e90f4b31dd550863cf Mon Sep 17 00:00:00 2001 From: Jared Scheib Date: Wed, 25 Oct 2017 16:22:00 -0700 Subject: [PATCH] Render Admin NavBlock based on authorization Require location prop as propType in SideNav to prevent silent fail. Add guard clause on isUsingAuth to prevent DOM break in Authorized. Consolidate return on Authorized render. Clean up Authorized. Signed-off-by: Alex Paxton --- ui/src/auth/Authorized.js | 25 +++++++++++++++++-------- ui/src/side_nav/components/NavItems.js | 11 ++++++----- ui/src/side_nav/containers/SideNav.js | 10 +++++++--- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/ui/src/auth/Authorized.js b/ui/src/auth/Authorized.js index 6a2d2ac283..f0dddd7c41 100644 --- a/ui/src/auth/Authorized.js +++ b/ui/src/auth/Authorized.js @@ -33,19 +33,28 @@ export const isUserAuthorized = (meRole, requiredRole) => { const getRoleName = ({roles: [{name}, ..._]}) => name -const Authorized = ({children, me, isUsingAuth, requiredRole, replaceWith}) => { - if (!isUsingAuth) { - return React.isValidElement(children) ? children : children[0] +const Authorized = ({ + children, + me, + isUsingAuth, + requiredRole, + replaceWith, + ...additionalProps +}) => { + // if me response has not been received yet, render nothing + if (typeof isUsingAuth !== 'boolean') { + return null } const meRole = getRoleName(me) - if (isUserAuthorized(meRole, requiredRole)) { + if (!isUsingAuth || isUserAuthorized(meRole, requiredRole)) { return React.cloneElement( - React.isValidElement(children) ? children : children[0] - ) + React.isValidElement(children) ? children : children[0], + {...additionalProps} + ) // guards against multiple children wrapped by Authorized } - return replaceWith ? React.cloneElement(replaceWith) : null + return replaceWith ? replaceWith : null // if you want elements to be disabled instead of hidden: // return React.cloneElement(clonedElement, {disabled: !isAuthorized}) @@ -54,7 +63,7 @@ const Authorized = ({children, me, isUsingAuth, requiredRole, replaceWith}) => { const {arrayOf, bool, node, shape, string} = PropTypes Authorized.propTypes = { - isUsingAuth: bool.isRequired, + isUsingAuth: bool, replaceWith: node, children: node.isRequired, me: shape({ diff --git a/ui/src/side_nav/components/NavItems.js b/ui/src/side_nav/components/NavItems.js index 4977b4b35f..e5871f12dc 100644 --- a/ui/src/side_nav/components/NavItems.js +++ b/ui/src/side_nav/components/NavItems.js @@ -2,13 +2,15 @@ import React, {PropTypes} from 'react' import {Link} from 'react-router' import classnames from 'classnames' +import Authorized from 'src/auth/Authorized' + const {bool, node, string} = PropTypes const NavListItem = React.createClass({ propTypes: { link: string.isRequired, children: node, - location: string, + location: string.isRequired, useAnchor: bool, isExternal: bool, }, @@ -60,15 +62,14 @@ const NavBlock = React.createClass({ children: node, link: string, icon: string.isRequired, - location: string, + location: string.isRequired, className: string, }, render() { const {location, className} = this.props - const isActive = React.Children.toArray(this.props.children).find(child => { - return location.startsWith(child.props.link) + return location.startsWith(child.props.link) // if location is undefined, this will fail silently }) const children = React.Children.map(this.props.children, child => { @@ -119,7 +120,7 @@ const NavBar = React.createClass({ render() { const children = React.Children.map(this.props.children, child => { - if (child && child.type === NavBlock) { + if (child && (child.type === NavBlock || child.type === Authorized)) { return React.cloneElement(child, { location: this.props.location, }) diff --git a/ui/src/side_nav/containers/SideNav.js b/ui/src/side_nav/containers/SideNav.js index 113b4727f3..8280a00527 100644 --- a/ui/src/side_nav/containers/SideNav.js +++ b/ui/src/side_nav/containers/SideNav.js @@ -2,6 +2,8 @@ import React, {PropTypes} from 'react' import {withRouter, Link} from 'react-router' import {connect} from 'react-redux' +import Authorized, {ADMIN_ROLE} from 'src/auth/Authorized' + import { NavBar, NavBlock, @@ -108,9 +110,11 @@ const SideNav = React.createClass({ Create - - - + + + + +