in public/apps/configuration/panels/role-edit/role-edit.tsx [74:250]
export function RoleEdit(props: RoleEditDeps) {
const [roleName, setRoleName] = React.useState('');
const [roleClusterPermission, setRoleClusterPermission] = useState<ComboBoxOptions>([]);
const [roleIndexPermission, setRoleIndexPermission] = useState<RoleIndexPermissionStateClass[]>(
[]
);
const [roleTenantPermission, setRoleTenantPermission] = useState<
RoleTenantPermissionStateClass[]
>([]);
const [toasts, addToast, removeToast] = useToastState();
const [isFormValid, setIsFormValid] = useState<boolean>(true);
React.useEffect(() => {
const action = props.action;
if (action === 'edit' || action === 'duplicate') {
const fetchData = async () => {
try {
const roleData = await getRoleDetail(props.coreStart.http, props.sourceRoleName);
setRoleClusterPermission(roleData.cluster_permissions.map(stringToComboBoxOption));
setRoleIndexPermission(buildIndexPermissionState(roleData.index_permissions));
setRoleTenantPermission(buildTenantPermissionState(roleData.tenant_permissions));
setRoleName(generateResourceName(action, props.sourceRoleName));
} catch (e) {
addToast(createUnknownErrorToast('fetchRole', 'load data'));
console.error(e);
}
};
fetchData();
}
}, [addToast, props.action, props.coreStart.http, props.sourceRoleName]);
const [actionGroups, setActionGroups] = useState<string[]>([]);
React.useEffect(() => {
const fetchActionGroupNames = async () => {
try {
const actionGroupsObject = await fetchActionGroups(props.coreStart.http);
setActionGroups(Object.keys(actionGroupsObject));
} catch (e) {
addToast(createUnknownErrorToast('actionGroup', 'load data'));
console.error(e);
}
};
fetchActionGroupNames();
}, [addToast, props.coreStart.http]);
const [tenantNames, setTenantNames] = React.useState<string[]>([]);
React.useEffect(() => {
const fetchTenantNames = async () => {
try {
setTenantNames(await fetchTenantNameList(props.coreStart.http));
} catch (e) {
addToast(createUnknownErrorToast('tenant', 'load data'));
console.error(e);
}
};
fetchTenantNames();
}, [addToast, props.coreStart.http]);
const updateRoleHandler = async () => {
try {
// Remove index/tenant permissions with empty patterns.
const validIndexPermission = roleIndexPermission.filter(
(v: RoleIndexPermissionStateClass) => !isEmpty(v.indexPatterns)
);
const validTenantPermission = roleTenantPermission.filter(
(v: RoleTenantPermissionStateClass) => !isEmpty(v.tenantPatterns)
);
await updateRole(props.coreStart.http, roleName, {
cluster_permissions: roleClusterPermission.map(comboBoxOptionToString),
index_permissions: unbuildIndexPermissionState(validIndexPermission),
tenant_permissions: unbuildTenantPermissionState(validTenantPermission),
});
setCrossPageToast(buildUrl(ResourceType.roles, Action.view, roleName), {
id: 'updateRoleSucceeded',
color: 'success',
title: getSuccessToastMessage('Role', props.action, roleName),
});
// Redirect to role view
window.location.href = buildHashUrl(ResourceType.roles, Action.view, roleName);
} catch (e) {
addToast(createUnknownErrorToast('updateRole', `${props.action} role`));
console.error(e);
}
};
const clusterWisePermissionOptions = [
{
label: 'Permission groups',
options: actionGroups.map(stringToComboBoxOption),
},
{
label: 'Cluster permissions',
options: CLUSTER_PERMISSIONS.map(stringToComboBoxOption),
},
{
label: 'Index permissions',
options: INDEX_PERMISSIONS.map(stringToComboBoxOption),
},
];
const tenantOptions = tenantNames.map(stringToComboBoxOption);
return (
<>
{props.buildBreadcrumbs(TITLE_TEXT_DICT[props.action])}
<EuiPageHeader>
<EuiText size="xs" color="subdued" className="panel-header-subtext">
<EuiTitle size="m">
<h1>{TITLE_TEXT_DICT[props.action]}</h1>
</EuiTitle>
Roles are the core way of controlling access to your cluster. Roles contain any
combination of cluster-wide permission, index-specific permissions, document- and
field-level security, and tenants. Once you've created the role, you can map users to
the roles so that users gain those permissions.{' '}
<ExternalLink href={DocLinks.UsersAndRolesDoc} />
</EuiText>
</EuiPageHeader>
<PanelWithHeader headerText="Name">
<EuiForm>
<NameRow
headerText="Name"
headerSubText="Specify a descriptive and unique role name. You cannot edit the name once the role is created."
resourceName={roleName}
resourceType="role"
action={props.action}
setNameState={setRoleName}
setIsFormValid={setIsFormValid}
/>
</EuiForm>
</PanelWithHeader>
<EuiSpacer size="m" />
<ClusterPermissionPanel
state={roleClusterPermission}
setState={setRoleClusterPermission}
optionUniverse={clusterWisePermissionOptions}
/>
<EuiSpacer size="m" />
<IndexPermissionPanel
state={roleIndexPermission}
setState={setRoleIndexPermission}
optionUniverse={clusterWisePermissionOptions}
/>
<EuiSpacer size="m" />
<TenantPanel
state={roleTenantPermission}
setState={setRoleTenantPermission}
optionUniverse={tenantOptions}
/>
<EuiSpacer size="m" />
<EuiFlexGroup justifyContent="flexEnd">
<EuiFlexItem grow={false}>
<EuiButton
onClick={() => {
window.location.href = buildHashUrl(ResourceType.roles);
}}
>
Cancel
</EuiButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton fill onClick={updateRoleHandler} disabled={!isFormValid}>
{props.action === 'edit' ? 'Update' : 'Create'}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
<EuiGlobalToastList toasts={toasts} toastLifeTimeMs={10000} dismissToast={removeToast} />
</>
);
}