Access control: Reduce number of API calls for role picker (#44905)

* Restucture state for TeamRolePicker and UserRolePicker

Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
This commit is contained in:
Karl Persson 2022-02-04 14:54:42 +01:00 committed by GitHub
parent 61533a3cb4
commit 3cf31451ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 46 additions and 56 deletions

View File

@ -1,38 +1,29 @@
import React, { FC, useState } from 'react';
import { useAsync } from 'react-use';
import { contextSrv } from 'app/core/core';
import { AccessControlAction, Role } from 'app/types';
import { Role } from 'app/types';
import { RolePicker } from './RolePicker';
import { fetchRoleOptions, fetchTeamRoles, updateTeamRoles } from './api';
import { fetchTeamRoles, updateTeamRoles } from './api';
export interface Props {
teamId: number;
orgId?: number;
getRoleOptions?: () => Promise<Role[]>;
roleOptions: Role[];
disabled?: boolean;
builtinRolesDisabled?: boolean;
}
export const TeamRolePicker: FC<Props> = ({ teamId, orgId, getRoleOptions, disabled, builtinRolesDisabled }) => {
const [roleOptions, setRoleOptions] = useState<Role[]>([]);
export const TeamRolePicker: FC<Props> = ({ teamId, orgId, roleOptions, disabled, builtinRolesDisabled }) => {
const [appliedRoles, setAppliedRoles] = useState<Role[]>([]);
const { loading } = useAsync(async () => {
try {
if (contextSrv.hasPermission(AccessControlAction.ActionRolesList)) {
let options = await (getRoleOptions ? getRoleOptions() : fetchRoleOptions(orgId));
setRoleOptions(options.filter((option) => !option.name?.startsWith('managed:')));
} else {
setRoleOptions([]);
}
const teamRoles = await fetchTeamRoles(teamId, orgId);
setAppliedRoles(teamRoles);
} catch (e) {
// TODO handle error
console.error('Error loading options');
}
}, [getRoleOptions, orgId, teamId]);
}, [orgId, teamId]);
return (
<RolePicker

View File

@ -3,15 +3,15 @@ import { useAsync } from 'react-use';
import { contextSrv } from 'app/core/core';
import { Role, OrgRole, AccessControlAction } from 'app/types';
import { RolePicker } from './RolePicker';
import { fetchBuiltinRoles, fetchRoleOptions, fetchUserRoles, updateUserRoles } from './api';
import { fetchUserRoles, updateUserRoles } from './api';
export interface Props {
builtInRole: OrgRole;
userId: number;
orgId?: number;
onBuiltinRoleChange: (newRole: OrgRole) => void;
getRoleOptions?: () => Promise<Role[]>;
getBuiltinRoles?: () => Promise<{ [key: string]: Role[] }>;
roleOptions: Role[];
builtInRoles?: { [key: string]: Role[] };
disabled?: boolean;
builtinRolesDisabled?: boolean;
}
@ -21,31 +21,15 @@ export const UserRolePicker: FC<Props> = ({
userId,
orgId,
onBuiltinRoleChange,
getRoleOptions,
getBuiltinRoles,
roleOptions,
builtInRoles,
disabled,
builtinRolesDisabled,
}) => {
const [roleOptions, setRoleOptions] = useState<Role[]>([]);
const [appliedRoles, setAppliedRoles] = useState<Role[]>([]);
const [builtInRoles, setBuiltinRoles] = useState<Record<string, Role[]>>({});
const { loading } = useAsync(async () => {
try {
if (contextSrv.hasPermission(AccessControlAction.ActionRolesList)) {
let options = await (getRoleOptions ? getRoleOptions() : fetchRoleOptions(orgId));
setRoleOptions(options.filter((option) => !option.name?.startsWith('managed:')));
} else {
setRoleOptions([]);
}
if (contextSrv.hasPermission(AccessControlAction.ActionBuiltinRolesList)) {
const builtInRoles = await (getBuiltinRoles ? getBuiltinRoles() : fetchBuiltinRoles(orgId));
setBuiltinRoles(builtInRoles);
} else {
setBuiltinRoles({});
}
if (contextSrv.hasPermission(AccessControlAction.ActionUserRolesList)) {
const userRoles = await fetchUserRoles(userId, orgId);
setAppliedRoles(userRoles);
@ -56,7 +40,7 @@ export const UserRolePicker: FC<Props> = ({
// TODO handle error
console.error('Error loading options');
}
}, [getBuiltinRoles, getRoleOptions, orgId, userId]);
}, [orgId, userId]);
return (
<RolePicker

View File

@ -20,6 +20,7 @@ import { OrgPicker, OrgSelectItem } from 'app/core/components/Select/OrgPicker';
import { OrgRolePicker } from './OrgRolePicker';
import { contextSrv } from 'app/core/core';
import { UserRolePicker } from 'app/core/components/RolePicker/UserRolePicker';
import { fetchRoleOptions } from 'app/core/components/RolePicker/api';
interface Props {
orgs: UserOrg[];
@ -133,8 +134,25 @@ class UnThemedOrgRow extends PureComponent<OrgRowProps> {
state = {
currentRole: this.props.org.role,
isChangingRole: false,
roleOptions: [],
builtInRoles: {},
};
componentDidMount() {
if (contextSrv.licensedAccessControlEnabled()) {
if (contextSrv.hasPermission(AccessControlAction.ActionRolesList)) {
fetchRoleOptions(this.props.org.orgId)
.then((roles) => this.setState({ roleOptions: roles }))
.catch((e) => console.error(e));
}
if (contextSrv.hasPermission(AccessControlAction.ActionBuiltinRolesList)) {
fetchRoleOptions(this.props.org.orgId)
.then((roles) => this.setState({ builtInRoles: roles }))
.catch((e) => console.error(e));
}
}
}
onOrgRemove = () => {
const { org } = this.props;
this.props.onOrgRemove(org.orgId);
@ -184,6 +202,8 @@ class UnThemedOrgRow extends PureComponent<OrgRowProps> {
userId={user?.id || 0}
orgId={org.orgId}
builtInRole={org.role}
roleOptions={this.state.roleOptions}
builtInRoles={this.state.builtInRoles}
onBuiltinRoleChange={this.onBuiltinRoleChange}
builtinRolesDisabled={rolePickerDisabled}
/>

View File

@ -28,10 +28,15 @@ const ServiceAccountsTable: FC<Props> = (props) => {
useEffect(() => {
async function fetchOptions() {
try {
let options = await fetchRoleOptions(orgId);
setRoleOptions(options);
const builtInRoles = await fetchBuiltinRoles(orgId);
setBuiltinRoles(builtInRoles);
if (contextSrv.hasPermission(AccessControlAction.ActionRolesList)) {
let options = await fetchRoleOptions(orgId);
setRoleOptions(options);
}
if (contextSrv.hasPermission(AccessControlAction.ActionBuiltinRolesList)) {
const builtInRoles = await fetchBuiltinRoles(orgId);
setBuiltinRoles(builtInRoles);
}
} catch (e) {
console.error('Error loading options');
}
@ -41,9 +46,6 @@ const ServiceAccountsTable: FC<Props> = (props) => {
}
}, [orgId]);
const getRoleOptions = async () => roleOptions;
const getBuiltinRoles = async () => builtinRoles;
return (
<>
<table className="filter-table form-inline">
@ -89,8 +91,8 @@ const ServiceAccountsTable: FC<Props> = (props) => {
orgId={orgId}
builtInRole={serviceAccount.role}
onBuiltinRoleChange={(newRole) => onRoleChange(newRole, serviceAccount)}
getRoleOptions={getRoleOptions}
getBuiltinRoles={getBuiltinRoles}
roleOptions={roleOptions}
builtInRoles={builtinRoles}
disabled={rolePickerDisabled}
/>
) : (

View File

@ -43,7 +43,7 @@ export class TeamList extends PureComponent<Props, State> {
componentDidMount() {
this.fetchTeams();
if (contextSrv.licensedAccessControlEnabled()) {
if (contextSrv.licensedAccessControlEnabled() && contextSrv.hasPermission(AccessControlAction.ActionRolesList)) {
this.fetchRoleOptions();
}
}
@ -95,7 +95,7 @@ export class TeamList extends PureComponent<Props, State> {
</td>
{contextSrv.licensedAccessControlEnabled() && (
<td>
<TeamRolePicker teamId={team.id} getRoleOptions={async () => this.state.roleOptions} />
<TeamRolePicker teamId={team.id} roleOptions={this.state.roleOptions} />
</td>
)}
<td className="text-right">

View File

@ -26,15 +26,11 @@ const UsersTable: FC<Props> = (props) => {
if (contextSrv.hasPermission(AccessControlAction.ActionRolesList)) {
let options = await fetchRoleOptions(orgId);
setRoleOptions(options);
} else {
setRoleOptions([]);
}
if (contextSrv.hasPermission(AccessControlAction.ActionBuiltinRolesList)) {
const builtInRoles = await fetchBuiltinRoles(orgId);
setBuiltinRoles(builtInRoles);
} else {
setBuiltinRoles({});
}
} catch (e) {
console.error('Error loading options');
@ -45,9 +41,6 @@ const UsersTable: FC<Props> = (props) => {
}
}, [orgId]);
const getRoleOptions = async () => roleOptions;
const getBuiltinRoles = async () => builtinRoles;
return (
<>
<table className="filter-table form-inline">
@ -94,8 +87,8 @@ const UsersTable: FC<Props> = (props) => {
orgId={orgId}
builtInRole={user.role}
onBuiltinRoleChange={(newRole) => onRoleChange(newRole, user)}
getRoleOptions={getRoleOptions}
getBuiltinRoles={getBuiltinRoles}
roleOptions={roleOptions}
builtInRoles={builtinRoles}
disabled={!contextSrv.hasPermissionInMetadata(AccessControlAction.OrgUsersRoleUpdate, user)}
/>
) : (