diff --git a/src/app/services/actions/permissions-action-creator.ts b/src/app/services/actions/permissions-action-creator.ts index 97fd62357..3a97a6461 100644 --- a/src/app/services/actions/permissions-action-creator.ts +++ b/src/app/services/actions/permissions-action-creator.ts @@ -37,6 +37,7 @@ export function fetchScopes(query?: IQuery): Function { try { const { devxApi } = getState(); let permissionsUrl = `${devxApi}/permissions`; + let hasUrl = false; // whether permissions are for a specific url if (query) { const signature = sanitizeQueryUrl(query.sampleUrl); @@ -47,6 +48,7 @@ export function fetchScopes(query?: IQuery): Function { } permissionsUrl = `${permissionsUrl}?requesturl=/${requestUrl}&method=${query.selectedVerb}`; + hasUrl = true; } const headers = { @@ -61,7 +63,9 @@ export function fetchScopes(query?: IQuery): Function { const response = await fetch(permissionsUrl, options); if (response.ok) { const scopes = await response.json(); - return dispatch(fetchScopesSuccess(scopes)); + return dispatch(fetchScopesSuccess({ + hasUrl, scopes + })); } throw (response); } catch (error) { diff --git a/src/app/services/reducers/permissions-reducer.ts b/src/app/services/reducers/permissions-reducer.ts index d7ac1a3f8..5925fcd25 100644 --- a/src/app/services/reducers/permissions-reducer.ts +++ b/src/app/services/reducers/permissions-reducer.ts @@ -1,31 +1,42 @@ import { IAction } from '../../../types/action'; +import { IPermission } from '../../../types/permissions'; import { FETCH_SCOPES_ERROR, FETCH_SCOPES_PENDING, FETCH_SCOPES_SUCCESS } from '../redux-constants'; const initialState = { pending: false, data: [], + hasUrl: false, error: null }; +interface IPermissionsResponse { + hasUrl: boolean; + scopes: IPermission[]; +} + export function scopes(state = initialState, action: IAction): any { switch (action.type) { case FETCH_SCOPES_SUCCESS: + const response: IPermissionsResponse = { ...action.response as IPermissionsResponse }; return { pending: false, - data: action.response, + data: response.scopes, + hasUrl: response.hasUrl, error: null }; case FETCH_SCOPES_ERROR: return { pending: false, error: action.response, + hasUrl: false, data: [] }; case FETCH_SCOPES_PENDING: return { pending: true, data: [], - error: null + error: null, + hasUrl: false }; default: return state; diff --git a/src/app/views/query-runner/request/permissions/PanelList.tsx b/src/app/views/query-runner/request/permissions/PanelList.tsx index 95f751e31..f2abcfc7e 100644 --- a/src/app/views/query-runner/request/permissions/PanelList.tsx +++ b/src/app/views/query-runner/request/permissions/PanelList.tsx @@ -7,40 +7,59 @@ import { SearchBox, SelectionMode } from 'office-ui-fabric-react'; -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { FormattedMessage } from 'react-intl'; +import { useSelector } from 'react-redux'; import { SortOrder } from '../../../../../types/enums'; import { IPermission } from '../../../../../types/permissions'; import { dynamicSort } from '../../../../utils/dynamic-sort'; import { generateGroupsFromList } from '../../../../utils/generate-groups'; +import { setConsentedStatus } from './util'; interface IPanelList { messages: any; - permissions: IPermission[]; columns: any[]; classes: any; selection: any; renderItemColumn: any; - searchValueChanged: Function; renderDetailsHeader: Function; } -const PanelList = ({ messages, permissions, +const PanelList = ({ messages, columns, classes, selection, - renderItemColumn, searchValueChanged, renderDetailsHeader }: IPanelList) => { + renderItemColumn, renderDetailsHeader }: IPanelList) => { + const { consentedScopes, scopes, tokenPresent } = useSelector((state: any) => state); + const [permissions, setPermissions] = useState(scopes.data.sort(dynamicSort('value', SortOrder.ASC))); const permissionsList: any[] = []; - permissions.forEach(perm => { - const permission: any = {...perm}; + + useEffect(() => { + setConsentedStatus(tokenPresent, permissions, consentedScopes); + }, [scopes, consentedScopes]); + + permissions.forEach((perm: any) => { + const permission: any = { ...perm }; const permissionValue = permission.value; const groupName = permissionValue.split('.')[0]; permission.groupName = groupName; permissionsList.push(permission); }); + const searchValueChanged = (event: any, value?: string): void => { + let filteredPermissions = scopes.data; + if (value) { + const keyword = value.toLowerCase(); + + filteredPermissions = scopes.data.filter((permission: IPermission) => { + const name = permission.value.toLowerCase(); + return name.includes(keyword); + }); + } + setPermissions(filteredPermissions); + }; + const groups = generateGroupsFromList(permissionsList, 'groupName'); - permissions = permissions.sort(dynamicSort('value', SortOrder.ASC)); return ( <> @@ -55,7 +74,7 @@ const PanelList = ({ messages, permissions, searchValueChanged(event, newValue)} styles={{ field: { paddingLeft: 10 } }} /> - +
false} @@ -75,6 +94,17 @@ const PanelList = ({ messages, permissions, checkButtonAriaLabel={messages['Row checkbox'] || 'Row checkbox'} onRenderDetailsHeader={(props?: any, defaultRender?: any) => renderDetailsHeader(props, defaultRender)} /> + {permissions && permissions.length === 0 && + + } ); }; diff --git a/src/app/views/query-runner/request/permissions/Permission.tsx b/src/app/views/query-runner/request/permissions/Permission.tsx index e0f821a5f..8d8c8cbce 100644 --- a/src/app/views/query-runner/request/permissions/Permission.tsx +++ b/src/app/views/query-runner/request/permissions/Permission.tsx @@ -14,7 +14,6 @@ import { FormattedMessage, injectIntl } from 'react-intl'; import { connect } from 'react-redux'; import { bindActionCreators, Dispatch } from 'redux'; -import { telemetry } from '../../../../../telemetry'; import { IPermission, IPermissionProps, IPermissionState } from '../../../../../types/permissions'; import * as permissionActionCreators from '../../../../services/actions/permissions-action-creator'; import { translateMessage } from '../../../../utils/translate-messages'; @@ -22,7 +21,6 @@ import { classNames } from '../../../classnames'; import PanelList from './PanelList'; import { permissionStyles } from './Permission.styles'; import TabList from './TabList'; -import { setConsentedStatus } from './util'; export class Permission extends Component { @@ -67,23 +65,6 @@ export class Permission extends Component { return shouldUpdate; } - public searchValueChanged = (event: any, value?: string): void => { - const { scopes } = this.props; - let filteredPermissions = scopes.data; - if (value) { - const keyword = value.toLowerCase(); - - filteredPermissions = scopes.data.filter((permission: IPermission) => { - const name = permission.value.toLowerCase(); - return name.includes(keyword); - }); - } - - this.setState({ - permissions: filteredPermissions - }); - } - public handleConsent = async (permission: IPermission) => { const consentScopes = [permission.value]; this.props.actions!.consentToScopes(consentScopes); @@ -227,25 +208,18 @@ export class Permission extends Component { } ); } - return columns; } - - - public render() { const classes = classNames(this.props); - const { panel, scopes, tokenPresent, consentedScopes } = this.props; + const { panel, scopes } = this.props; const { pending: loading } = scopes; - const { permissions } = this.state; const { intl: { messages }, }: any = this.props; - setConsentedStatus(tokenPresent, permissions, consentedScopes); - const selection = new Selection({ onSelectionChanged: () => { const selected = selection.getSelection() as any; @@ -268,43 +242,27 @@ export class Permission extends Component { {!loading &&
{!panel && this.renderItemColumn(item, index, column)} renderDetailsHeader={this.renderDetailsHeader} - />} {panel &&
this.renderItemColumn(item, index, column)} - searchValueChanged={(event?: React.ChangeEvent, value?: string) => - this.searchValueChanged(event, value)} renderDetailsHeader={this.renderDetailsHeader} />
}
} - {permissions && permissions.length === 0 && !loading && - - } ); } diff --git a/src/app/views/query-runner/request/permissions/TabList.tsx b/src/app/views/query-runner/request/permissions/TabList.tsx index dc2073d25..1c067b53f 100644 --- a/src/app/views/query-runner/request/permissions/TabList.tsx +++ b/src/app/views/query-runner/request/permissions/TabList.tsx @@ -1,12 +1,11 @@ import { DetailsList, DetailsListLayoutMode, IColumn, Label, SelectionMode } from 'office-ui-fabric-react'; -import React from 'react'; +import React, { useEffect } from 'react'; import { FormattedMessage } from 'react-intl'; import { useSelector } from 'react-redux'; -import { IPermission } from '../../../../../types/permissions'; +import { setConsentedStatus } from './util'; interface ITabList { - permissions: IPermission[]; columns: any[]; classes: any; renderItemColumn: Function; @@ -14,8 +13,21 @@ interface ITabList { } -const TabList = ({ permissions, columns, classes, renderItemColumn, renderDetailsHeader }: ITabList) => { - const tokenPresent = useSelector((state: any) => state.authToken); +const TabList = ({ columns, classes, renderItemColumn, renderDetailsHeader }: ITabList) => { + let permissions: any[] = []; + const { consentedScopes, scopes, tokenPresent } = useSelector((state: any) => state); + + if (scopes.hasUrl) { + permissions = scopes.data; + } + useEffect(() => { + setConsentedStatus(tokenPresent, permissions, consentedScopes); + }, [scopes.data, consentedScopes]); + + if (!scopes.hasUrl) { + return displayNoPermissionsFoundMessage(); + } + return ( <>