From 4af344a9b0b3301d97d91e1ab1dabf0adb8f6e68 Mon Sep 17 00:00:00 2001
From: Thom Heymann <190132+thomheymann@users.noreply.github.com>
Date: Thu, 8 Apr 2021 19:44:57 +0100
Subject: [PATCH] Improved role management error handling for partially
authorized users (#96468)
* Role management: Gracefully handle underprivileged users
* Removed redundant condition
---
.../roles/edit_role/edit_role_page.test.tsx | 28 ++++++++++---------
.../roles/edit_role/edit_role_page.tsx | 8 ++----
2 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx
index 3002db642bc1e..5df73f7f8ec4e 100644
--- a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx
@@ -480,23 +480,25 @@ describe('', () => {
});
});
- it('can render if features are not available', async () => {
- const { http } = coreMock.createStart();
- http.get.mockImplementation(async (path: any) => {
- if (path === '/api/features') {
- const error = { response: { status: 404 } };
- throw error;
- }
+ it('registers fatal error if features endpoint fails unexpectedly', async () => {
+ const error = { response: { status: 500 } };
+ const getFeatures = jest.fn().mockRejectedValue(error);
+ const props = getProps({ action: 'edit' });
+ const wrapper = mountWithIntl();
- if (path === '/api/spaces/space') {
- return buildSpaces();
- }
- });
+ await waitForRender(wrapper);
+ expect(props.fatalErrors.add).toHaveBeenLastCalledWith(error);
+ expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(0);
+ });
- const wrapper = mountWithIntl();
+ it('can render if features call is not allowed', async () => {
+ const error = { response: { status: 403 } };
+ const getFeatures = jest.fn().mockRejectedValue(error);
+ const props = getProps({ action: 'edit' });
+ const wrapper = mountWithIntl();
await waitForRender(wrapper);
-
+ expect(props.fatalErrors.add).not.toHaveBeenCalled();
expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1);
expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0);
expectSaveFormButtons(wrapper);
diff --git a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx
index 5d6b4a1b4fdaf..f810cd2079d16 100644
--- a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx
+++ b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx
@@ -256,13 +256,12 @@ function useFeatures(
// possible that a user with `manage_security` will attempt to visit the role management page without the
// correct Kibana privileges. If that's the case, then they receive a partial view of the role, and the UI does
// not allow them to make changes to that role's kibana privileges. When this user visits the edit role page,
- // this API endpoint will throw a 404, which causes view to fail completely. So we instead attempt to detect the
- // 404 here, and respond in a way that still allows the UI to render itself.
- const unauthorizedForFeatures = err.response?.status === 404;
+ // this API endpoint will throw a 403, which causes view to fail completely. So we instead attempt to detect the
+ // 403 here, and respond in a way that still allows the UI to render itself.
+ const unauthorizedForFeatures = err.response?.status === 403;
if (unauthorizedForFeatures) {
return [] as KibanaFeature[];
}
-
fatalErrors.add(err);
})
.then((retrievedFeatures) => {
@@ -296,7 +295,6 @@ export const EditRolePage: FunctionComponent = ({
// We should keep the same mutable instance of Validator for every re-render since we'll
// eventually enable validation after the first time user tries to save a role.
const { current: validator } = useRef(new RoleValidator({ shouldValidate: false }));
-
const [formError, setFormError] = useState(null);
const runAsUsers = useRunAsUsers(userAPIClient, fatalErrors);
const indexPatternsTitles = useIndexPatternsTitles(indexPatterns, fatalErrors, notifications);