mirror of
https://github.com/grafana/grafana.git
synced 2024-12-02 05:29:42 -06:00
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:
parent
61533a3cb4
commit
3cf31451ec
@ -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
|
||||
|
@ -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
|
||||
|
@ -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}
|
||||
/>
|
||||
|
@ -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}
|
||||
/>
|
||||
) : (
|
||||
|
@ -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">
|
||||
|
@ -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)}
|
||||
/>
|
||||
) : (
|
||||
|
Loading…
Reference in New Issue
Block a user