You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by hu...@apache.org on 2021/08/31 18:54:16 UTC

[superset] branch hugh/rbac-2 created (now 7b8ffaf)

This is an automated email from the ASF dual-hosted git repository.

hugh pushed a change to branch hugh/rbac-2
in repository https://gitbox.apache.org/repos/asf/superset.git.


      at 7b8ffaf  fix test

This branch includes the following new commits:

     new 70c3033  user into dumb components
     new 7b8ffaf  fix test

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


[superset] 01/02: user into dumb components

Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

hugh pushed a commit to branch hugh/rbac-2
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 70c3033393db7edf64331362de5a17876b3a308d
Author: hughhhh <hu...@gmail.com>
AuthorDate: Tue Aug 31 11:04:34 2021 -0700

    user into dumb components
---
 superset-frontend/src/components/Menu/Menu.tsx     |   5 +-
 .../src/components/Menu/MenuRight.tsx              | 255 +++++++++++----------
 superset-frontend/src/views/App.tsx                |   2 +-
 3 files changed, 142 insertions(+), 120 deletions(-)

diff --git a/superset-frontend/src/components/Menu/Menu.tsx b/superset-frontend/src/components/Menu/Menu.tsx
index 098aa3a..10baa91 100644
--- a/superset-frontend/src/components/Menu/Menu.tsx
+++ b/superset-frontend/src/components/Menu/Menu.tsx
@@ -61,6 +61,7 @@ export interface MenuProps {
     brand: BrandProps;
     navbar_right: NavBarProps;
     settings: MenuObjectProps[];
+    user: object;
   };
   isFrontendRoute?: (path?: string) => boolean;
 }
@@ -171,7 +172,7 @@ const { SubMenu } = DropdownMenu;
 const { useBreakpoint } = Grid;
 
 export function Menu({
-  data: { menu, brand, navbar_right: navbarRight, settings },
+  data: { menu, brand, navbar_right: navbarRight, settings, user },
   isFrontendRoute = () => false,
 }: MenuProps) {
   const [showMenu, setMenu] = useState<MenuMode>('horizontal');
@@ -283,7 +284,6 @@ export function Menu({
                   if (typeof c === 'string') {
                     return c;
                   }
-
                   return {
                     ...c,
                     isFrontendRoute: isFrontendRoute(c.url),
@@ -301,6 +301,7 @@ export function Menu({
             settings={settings}
             navbarRight={navbarRight}
             isFrontendRoute={isFrontendRoute}
+            user={user}
           />
         </Col>
       </Row>
diff --git a/superset-frontend/src/components/Menu/MenuRight.tsx b/superset-frontend/src/components/Menu/MenuRight.tsx
index 35d2cb0..a9f1456 100644
--- a/superset-frontend/src/components/Menu/MenuRight.tsx
+++ b/superset-frontend/src/components/Menu/MenuRight.tsx
@@ -21,6 +21,7 @@ import { MainNav as Menu } from 'src/common/components';
 import { t, styled, css, SupersetTheme } from '@superset-ui/core';
 import { Link } from 'react-router-dom';
 import Icons from 'src/components/Icons';
+import findPermission from 'src/dashboard/util/findPermission';
 import LanguagePicker from './LanguagePicker';
 import { NavBarProps, MenuObjectProps } from './Menu';
 
@@ -29,16 +30,22 @@ export const dropdownItems = [
     label: t('SQL query'),
     url: '/superset/sqllab?new=true',
     icon: 'fa-fw fa-search',
+    perm: 'can_sqllab',
+    view: 'Superset',
   },
   {
     label: t('Chart'),
     url: '/chart/add',
     icon: 'fa-fw fa-bar-chart',
+    perm: 'can_write',
+    view: 'Dashboard',
   },
   {
     label: t('Dashboard'),
     url: '/dashboard/new',
     icon: 'fa-fw fa-dashboard',
+    perm: 'can_write',
+    view: 'Chart',
   },
 ];
 
@@ -76,6 +83,7 @@ interface RightMenuProps {
   settings: MenuObjectProps[];
   navbarRight: NavBarProps;
   isFrontendRoute: (path?: string) => boolean;
+  user: any;
 }
 
 const RightMenu = ({
@@ -83,127 +91,140 @@ const RightMenu = ({
   settings,
   navbarRight,
   isFrontendRoute,
-}: RightMenuProps) => (
-  <StyledDiv align={align}>
-    <Menu mode="horizontal">
-      {!navbarRight.user_is_anonymous && (
-        <SubMenu
-          data-test="new-dropdown"
-          title={
-            <StyledI data-test="new-dropdown-icon" className="fa fa-plus" />
-          }
-          icon={<Icons.TriangleDown />}
-        >
-          {dropdownItems.map(menu => (
-            <Menu.Item key={menu.label}>
-              <a href={menu.url}>
-                <i
-                  data-test={`menu-item-${menu.label}`}
-                  className={`fa ${menu.icon}`}
-                />{' '}
-                {menu.label}
-              </a>
-            </Menu.Item>
-          ))}
-        </SubMenu>
-      )}
-      <SubMenu title="Settings" icon={<Icons.TriangleDown iconSize="xl" />}>
-        {settings.map((section, index) => [
-          <Menu.ItemGroup key={`${section.label}`} title={section.label}>
-            {section.childs?.map(child => {
-              if (typeof child !== 'string') {
-                return (
-                  <Menu.Item key={`${child.label}`}>
-                    {isFrontendRoute(child.url) ? (
-                      <Link to={child.url || ''}>{child.label}</Link>
-                    ) : (
-                      <a href={child.url}>{child.label}</a>
-                    )}
-                  </Menu.Item>
-                );
-              }
-              return null;
-            })}
-          </Menu.ItemGroup>,
-          index < settings.length - 1 && <Menu.Divider />,
-        ])}
+  user,
+}: RightMenuProps) => {
+  const { roles } = user;
 
-        {!navbarRight.user_is_anonymous && [
-          <Menu.Divider key="user-divider" />,
-          <Menu.ItemGroup key="user-section" title={t('User')}>
-            {navbarRight.user_profile_url && (
-              <Menu.Item key="profile">
-                <a href={navbarRight.user_profile_url}>{t('Profile')}</a>
-              </Menu.Item>
-            )}
-            {navbarRight.user_info_url && (
-              <Menu.Item key="info">
-                <a href={navbarRight.user_info_url}>{t('Info')}</a>
-              </Menu.Item>
+  // if user has any of these roles the dropdown will appear
+  const canSql = findPermission('can_sqllab', 'Superset', roles);
+  const canDashboard = findPermission('can_write', 'Dashboard', roles);
+  const canChart = findPermission('can_write', 'Chart', roles);
+  const showActionDropdown = canSql || canChart || canDashboard;
+  return (
+    <StyledDiv align={align}>
+      <Menu mode="horizontal">
+        {!navbarRight.user_is_anonymous && showActionDropdown && (
+          <SubMenu
+            data-test="new-dropdown"
+            title={
+              <StyledI data-test="new-dropdown-icon" className="fa fa-plus" />
+            }
+            icon={<Icons.TriangleDown />}
+          >
+            {dropdownItems.map(
+              menu =>
+                findPermission(menu.perm, menu.view, roles) && (
+                  <Menu.Item key={menu.label}>
+                    <a href={menu.url}>
+                      <i
+                        data-test={`menu-item-${menu.label}`}
+                        className={`fa ${menu.icon}`}
+                      />{' '}
+                      {menu.label}
+                    </a>
+                  </Menu.Item>
+                ),
             )}
-            <Menu.Item key="logout">
-              <a href={navbarRight.user_logout_url}>{t('Logout')}</a>
-            </Menu.Item>
-          </Menu.ItemGroup>,
-        ]}
-        {(navbarRight.version_string || navbarRight.version_sha) && [
-          <Menu.Divider key="version-info-divider" />,
-          <Menu.ItemGroup key="about-section" title={t('About')}>
-            <div className="about-section">
-              {navbarRight.show_watermark && (
-                <div css={versionInfoStyles}>
-                  {t('Powered by Apache Superset')}
-                </div>
-              )}
-              {navbarRight.version_string && (
-                <div css={versionInfoStyles}>
-                  Version: {navbarRight.version_string}
-                </div>
+          </SubMenu>
+        )}
+        <SubMenu title="Settings" icon={<Icons.TriangleDown iconSize="xl" />}>
+          {settings.map((section, index) => [
+            <Menu.ItemGroup key={`${section.label}`} title={section.label}>
+              {section.childs?.map(child => {
+                if (typeof child !== 'string') {
+                  return (
+                    <Menu.Item key={`${child.label}`}>
+                      {isFrontendRoute(child.url) ? (
+                        <Link to={child.url || ''}>{child.label}</Link>
+                      ) : (
+                        <a href={child.url}>{child.label}</a>
+                      )}
+                    </Menu.Item>
+                  );
+                }
+                return null;
+              })}
+            </Menu.ItemGroup>,
+            index < settings.length - 1 && <Menu.Divider />,
+          ])}
+
+          {!navbarRight.user_is_anonymous && [
+            <Menu.Divider key="user-divider" />,
+            <Menu.ItemGroup key="user-section" title={t('User')}>
+              {navbarRight.user_profile_url && (
+                <Menu.Item key="profile">
+                  <a href={navbarRight.user_profile_url}>{t('Profile')}</a>
+                </Menu.Item>
               )}
-              {navbarRight.version_sha && (
-                <div css={versionInfoStyles}>
-                  SHA: {navbarRight.version_sha}
-                </div>
+              {navbarRight.user_info_url && (
+                <Menu.Item key="info">
+                  <a href={navbarRight.user_info_url}>{t('Info')}</a>
+                </Menu.Item>
               )}
-            </div>
-          </Menu.ItemGroup>,
-        ]}
-      </SubMenu>
-      {navbarRight.show_language_picker && (
-        <LanguagePicker
-          locale={navbarRight.locale}
-          languages={navbarRight.languages}
-        />
+              <Menu.Item key="logout">
+                <a href={navbarRight.user_logout_url}>{t('Logout')}</a>
+              </Menu.Item>
+            </Menu.ItemGroup>,
+          ]}
+          {(navbarRight.version_string || navbarRight.version_sha) && [
+            <Menu.Divider key="version-info-divider" />,
+            <Menu.ItemGroup key="about-section" title={t('About')}>
+              <div className="about-section">
+                {navbarRight.show_watermark && (
+                  <div css={versionInfoStyles}>
+                    {t('Powered by Apache Superset')}
+                  </div>
+                )}
+                {navbarRight.version_string && (
+                  <div css={versionInfoStyles}>
+                    Version: {navbarRight.version_string}
+                  </div>
+                )}
+                {navbarRight.version_sha && (
+                  <div css={versionInfoStyles}>
+                    SHA: {navbarRight.version_sha}
+                  </div>
+                )}
+              </div>
+            </Menu.ItemGroup>,
+          ]}
+        </SubMenu>
+        {navbarRight.show_language_picker && (
+          <LanguagePicker
+            locale={navbarRight.locale}
+            languages={navbarRight.languages}
+          />
+        )}
+      </Menu>
+      {navbarRight.documentation_url && (
+        <StyledAnchor
+          href={navbarRight.documentation_url}
+          target="_blank"
+          rel="noreferrer"
+          title={t('Documentation')}
+        >
+          <i className="fa fa-question" />
+          &nbsp;
+        </StyledAnchor>
+      )}
+      {navbarRight.bug_report_url && (
+        <StyledAnchor
+          href={navbarRight.bug_report_url}
+          target="_blank"
+          rel="noreferrer"
+          title={t('Report a bug')}
+        >
+          <i className="fa fa-bug" />
+        </StyledAnchor>
+      )}
+      {navbarRight.user_is_anonymous && (
+        <StyledAnchor href={navbarRight.user_login_url}>
+          <i className="fa fa-fw fa-sign-in" />
+          {t('Login')}
+        </StyledAnchor>
       )}
-    </Menu>
-    {navbarRight.documentation_url && (
-      <StyledAnchor
-        href={navbarRight.documentation_url}
-        target="_blank"
-        rel="noreferrer"
-        title={t('Documentation')}
-      >
-        <i className="fa fa-question" />
-        &nbsp;
-      </StyledAnchor>
-    )}
-    {navbarRight.bug_report_url && (
-      <StyledAnchor
-        href={navbarRight.bug_report_url}
-        target="_blank"
-        rel="noreferrer"
-        title={t('Report a bug')}
-      >
-        <i className="fa fa-bug" />
-      </StyledAnchor>
-    )}
-    {navbarRight.user_is_anonymous && (
-      <StyledAnchor href={navbarRight.user_login_url}>
-        <i className="fa fa-fw fa-sign-in" />
-        {t('Login')}
-      </StyledAnchor>
-    )}
-  </StyledDiv>
-);
+    </StyledDiv>
+  );
+};
 
 export default RightMenu;
diff --git a/superset-frontend/src/views/App.tsx b/superset-frontend/src/views/App.tsx
index 445a875..b4a2d19 100644
--- a/superset-frontend/src/views/App.tsx
+++ b/superset-frontend/src/views/App.tsx
@@ -41,7 +41,7 @@ setupApp();
 const container = document.getElementById('app');
 const bootstrap = JSON.parse(container?.getAttribute('data-bootstrap') ?? '{}');
 const user = { ...bootstrap.user };
-const menu = { ...bootstrap.common.menu_data };
+const menu = { ...bootstrap.common.menu_data, user };
 const common = { ...bootstrap.common };
 initFeatureFlags(bootstrap.common.feature_flags);
 

[superset] 02/02: fix test

Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

hugh pushed a commit to branch hugh/rbac-2
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 7b8ffaf948e3a608c27848d578a9f54dffa8610c
Author: hughhhh <hu...@gmail.com>
AuthorDate: Tue Aug 31 11:47:28 2021 -0700

    fix test
---
 superset-frontend/src/components/Menu/Menu.test.tsx | 9 +++++++++
 superset-frontend/src/components/Menu/Menu.tsx      | 4 +++-
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/superset-frontend/src/components/Menu/Menu.test.tsx b/superset-frontend/src/components/Menu/Menu.test.tsx
index 212521b..92c5e7d 100644
--- a/superset-frontend/src/components/Menu/Menu.test.tsx
+++ b/superset-frontend/src/components/Menu/Menu.test.tsx
@@ -24,6 +24,15 @@ import { dropdownItems } from './MenuRight';
 
 const mockedProps = {
   data: {
+    user: {
+      roles: {
+        Admin: [
+          ['can_sqllab', 'Superset'],
+          ['can_write', 'Chart'],
+          ['can_write', 'Dashboard'],
+        ],
+      },
+    },
     menu: [
       {
         name: 'Home',
diff --git a/superset-frontend/src/components/Menu/Menu.tsx b/superset-frontend/src/components/Menu/Menu.tsx
index 10baa91..769f8c9 100644
--- a/superset-frontend/src/components/Menu/Menu.tsx
+++ b/superset-frontend/src/components/Menu/Menu.tsx
@@ -61,7 +61,9 @@ export interface MenuProps {
     brand: BrandProps;
     navbar_right: NavBarProps;
     settings: MenuObjectProps[];
-    user: object;
+    user: {
+      roles: { [key: string]: string[][] };
+    };
   };
   isFrontendRoute?: (path?: string) => boolean;
 }