Skip to content

Commit

Permalink
Fix: all permissions show as required (#797)
Browse files Browse the repository at this point in the history
* add token to notify state when panel/tab

* prevent display of permissions in tab when panel open

* show message when panel and tab open

* fix linting errors
  • Loading branch information
thewahome authored Jan 15, 2021
1 parent 07db101 commit ed6815a
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 61 deletions.
6 changes: 5 additions & 1 deletion src/app/services/actions/permissions-action-creator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -47,6 +48,7 @@ export function fetchScopes(query?: IQuery): Function {
}

permissionsUrl = `${permissionsUrl}?requesturl=/${requestUrl}&method=${query.selectedVerb}`;
hasUrl = true;
}

const headers = {
Expand All @@ -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) {
Expand Down
15 changes: 13 additions & 2 deletions src/app/services/reducers/permissions-reducer.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
48 changes: 39 additions & 9 deletions src/app/views/query-runner/request/permissions/PanelList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<>
Expand All @@ -55,7 +74,7 @@ const PanelList = ({ messages, permissions,
searchValueChanged(event, newValue)}
styles={{ field: { paddingLeft: 10 } }}
/>
<Announced message={`${permissions.length} search results available.`}/>
<Announced message={`${permissions.length} search results available.`} />
<hr />
<DetailsList
onShouldVirtualize={() => false}
Expand All @@ -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 &&
<Label style={{
display: 'flex',
width: '100%',
minHeight: '200px',
justifyContent: 'center',
alignItems: 'center'
}}>
<FormattedMessage id='permissions not found' />
</Label>
}
</>
);
};
Expand Down
44 changes: 1 addition & 43 deletions src/app/views/query-runner/request/permissions/Permission.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,13 @@ 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';
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<IPermissionProps, IPermissionState> {

Expand Down Expand Up @@ -67,23 +65,6 @@ export class Permission extends Component<IPermissionProps, IPermissionState> {
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);
Expand Down Expand Up @@ -227,25 +208,18 @@ export class Permission extends Component<IPermissionProps, IPermissionState> {
}
);
}

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;
Expand All @@ -268,43 +242,27 @@ export class Permission extends Component<IPermissionProps, IPermissionState> {
{!loading &&
<div className={classes.permissions}>
{!panel && <TabList
permissions={permissions}
columns={this.getColumns()}
classes={classes}
renderItemColumn={(item?: any, index?: number, column?: IColumn) =>
this.renderItemColumn(item, index, column)}
renderDetailsHeader={this.renderDetailsHeader}

/>}
{panel &&
<div data-is-scrollable={true}>
<PanelList
classes={classes}
permissions={permissions}
messages={messages}
selection={selection}
columns={this.getColumns()}
renderItemColumn={(item?: any, index?: number, column?: IColumn) =>
this.renderItemColumn(item, index, column)}
searchValueChanged={(event?: React.ChangeEvent<HTMLInputElement>, value?: string) =>
this.searchValueChanged(event, value)}
renderDetailsHeader={this.renderDetailsHeader}
/>
</div>
}
</div>
}
{permissions && permissions.length === 0 && !loading &&
<Label style={{
display: 'flex',
width: '100%',
minHeight: '200px',
justifyContent: 'center',
alignItems: 'center'
}}>
<FormattedMessage id='permissions not found' />
</Label>
}
</div>
);
}
Expand Down
39 changes: 33 additions & 6 deletions src/app/views/query-runner/request/permissions/TabList.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
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;
renderDetailsHeader: Function;
}


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 (
<>
<Label className={classes.permissionLength}>
Expand All @@ -32,8 +44,23 @@ const TabList = ({ permissions, columns, classes, renderItemColumn, renderDetail
selectionMode={SelectionMode.none}
layoutMode={DetailsListLayoutMode.justified}
onRenderDetailsHeader={(props?: any, defaultRender?: any) => renderDetailsHeader(props, defaultRender)} />
{permissions && permissions.length === 0 &&
displayNoPermissionsFoundMessage()
}
</>
);
};

export default TabList;
export default TabList;

function displayNoPermissionsFoundMessage() {
return (<Label style={{
display: 'flex',
width: '100%',
minHeight: '200px',
justifyContent: 'center',
alignItems: 'center'
}}>
<FormattedMessage id='permissions not found' />
</Label>);
}

0 comments on commit ed6815a

Please sign in to comment.