diff --git a/public/apps/configuration/panels/audit-logging/audit-logging-edit-settings.tsx b/public/apps/configuration/panels/audit-logging/audit-logging-edit-settings.tsx
index 8e89d62a7..05f705e24 100644
--- a/public/apps/configuration/panels/audit-logging/audit-logging-edit-settings.tsx
+++ b/public/apps/configuration/panels/audit-logging/audit-logging-edit-settings.tsx
@@ -76,7 +76,7 @@ export function AuditLoggingEditSettings(props: AuditLoggingEditSettingProps) {
};
fetchConfig();
- }, [props.coreStart.http, dataSource.id]);
+ }, [props.coreStart.http, dataSource]);
const renderSaveAndCancel = () => {
return (
diff --git a/public/apps/configuration/panels/audit-logging/audit-logging.tsx b/public/apps/configuration/panels/audit-logging/audit-logging.tsx
index c89acdd12..1895d529c 100644
--- a/public/apps/configuration/panels/audit-logging/audit-logging.tsx
+++ b/public/apps/configuration/panels/audit-logging/audit-logging.tsx
@@ -30,6 +30,7 @@ import {
} from '@elastic/eui';
import React, { useContext } from 'react';
import { FormattedMessage } from '@osd/i18n/react';
+import { DataSourceOption } from 'src/plugins/data_source_management/public';
import { AppDependencies } from '../../../types';
import { ResourceType } from '../../../../../common';
import { getAuditLogging, updateAuditLogging } from '../../utils/audit-logging-utils';
@@ -94,6 +95,18 @@ function renderStatusPanel(onSwitchChange: () => void, auditLoggingEnabled: bool
);
}
+function renderAccessErrorPanel(dataSource: DataSourceOption) {
+ return (
+
+
+ Audit logging
+
+
+
+
+ );
+}
+
export function renderGeneralSettings(config: AuditLoggingSettings) {
return (
<>
@@ -167,13 +180,15 @@ export function AuditLogging(props: AuditLoggingProps) {
};
fetchData();
- }, [props.coreStart.http, props.fromType, dataSource.id]);
+ }, [props.coreStart.http, props.fromType, dataSource]);
const statusPanel = renderStatusPanel(onSwitchChange, configuration.enabled || false);
let content;
- if (!configuration.enabled) {
+ if (errorFlag) {
+ content = renderAccessErrorPanel(dataSource);
+ } else if (!configuration.enabled) {
content = statusPanel;
} else {
content = (
@@ -241,11 +256,7 @@ export function AuditLogging(props: AuditLoggingProps) {
setDataSource={setDataSource}
selectedDataSource={dataSource}
/>
- {errorFlag ? (
-
- ) : (
- content
- )}
+ {content}
);
}
diff --git a/public/apps/configuration/panels/auth-view/auth-view.tsx b/public/apps/configuration/panels/auth-view/auth-view.tsx
index bb01793a5..246fe9828 100644
--- a/public/apps/configuration/panels/auth-view/auth-view.tsx
+++ b/public/apps/configuration/panels/auth-view/auth-view.tsx
@@ -52,7 +52,7 @@ export function AuthView(props: AppDependencies) {
};
fetchData();
- }, [props.coreStart.http, dataSource.id]);
+ }, [props.coreStart.http, dataSource]);
if (isEmpty(authentication)) {
return (
diff --git a/public/apps/configuration/panels/internal-user-edit/internal-user-edit.tsx b/public/apps/configuration/panels/internal-user-edit/internal-user-edit.tsx
index 70ba39be8..986ff8e05 100644
--- a/public/apps/configuration/panels/internal-user-edit/internal-user-edit.tsx
+++ b/public/apps/configuration/panels/internal-user-edit/internal-user-edit.tsx
@@ -98,7 +98,7 @@ export function InternalUserEdit(props: InternalUserEditDeps) {
fetchData();
}
- }, [addToast, props.action, props.coreStart.http, props.sourceUserName, dataSource.id]);
+ }, [addToast, props.action, props.coreStart.http, props.sourceUserName, dataSource]);
const updateUserHandler = async () => {
try {
diff --git a/public/apps/configuration/panels/permission-list/permission-list.tsx b/public/apps/configuration/panels/permission-list/permission-list.tsx
index 41cf84a22..8d0fd6bb7 100644
--- a/public/apps/configuration/panels/permission-list/permission-list.tsx
+++ b/public/apps/configuration/panels/permission-list/permission-list.tsx
@@ -217,11 +217,11 @@ export function PermissionList(props: AppDependencies) {
} finally {
setLoading(false);
}
- }, [props.coreStart.http, dataSource.id]);
+ }, [props.coreStart.http, dataSource]);
React.useEffect(() => {
fetchData();
- }, [props.coreStart.http, fetchData, dataSource.id]);
+ }, [props.coreStart.http, fetchData, dataSource]);
const handleDelete = async () => {
const groupsToDelete: string[] = selection.map((r) => r.name);
diff --git a/public/apps/configuration/panels/role-edit/role-edit.tsx b/public/apps/configuration/panels/role-edit/role-edit.tsx
index 42fb8c2a9..384a2e95c 100644
--- a/public/apps/configuration/panels/role-edit/role-edit.tsx
+++ b/public/apps/configuration/panels/role-edit/role-edit.tsx
@@ -114,7 +114,7 @@ export function RoleEdit(props: RoleEditDeps) {
fetchData();
}
- }, [addToast, props.action, props.coreStart.http, props.sourceRoleName, dataSource.id]);
+ }, [addToast, props.action, props.coreStart.http, props.sourceRoleName, dataSource]);
const [actionGroups, setActionGroups] = useState>([]);
React.useEffect(() => {
@@ -129,7 +129,7 @@ export function RoleEdit(props: RoleEditDeps) {
};
fetchActionGroupNames();
- }, [addToast, props.coreStart.http, dataSource.id]);
+ }, [addToast, props.coreStart.http, dataSource]);
const [tenantNames, setTenantNames] = React.useState([]);
React.useEffect(() => {
@@ -143,7 +143,7 @@ export function RoleEdit(props: RoleEditDeps) {
};
fetchTenantNames();
- }, [addToast, props.coreStart.http, dataSource.id]);
+ }, [addToast, props.coreStart.http, dataSource]);
const updateRoleHandler = async () => {
try {
diff --git a/public/apps/configuration/panels/role-list.tsx b/public/apps/configuration/panels/role-list.tsx
index 2d7b46e5b..4b4ff9751 100644
--- a/public/apps/configuration/panels/role-list.tsx
+++ b/public/apps/configuration/panels/role-list.tsx
@@ -120,7 +120,6 @@ export function RoleList(props: AppDependencies) {
setRoleData(processedData);
setErrorFlag(false);
} catch (e) {
- console.log(e);
setErrorFlag(true);
} finally {
setLoading(false);
@@ -128,7 +127,7 @@ export function RoleList(props: AppDependencies) {
};
fetchData();
- }, [props.coreStart.http, dataSource.id]);
+ }, [props.coreStart.http, dataSource]);
const handleDelete = async () => {
const rolesToDelete: string[] = selection.map((r) => r.roleName);
diff --git a/public/apps/configuration/panels/role-mapping/role-edit-mapped-user.tsx b/public/apps/configuration/panels/role-mapping/role-edit-mapped-user.tsx
index 8bfc51b01..65e384275 100644
--- a/public/apps/configuration/panels/role-mapping/role-edit-mapped-user.tsx
+++ b/public/apps/configuration/panels/role-mapping/role-edit-mapped-user.tsx
@@ -86,7 +86,7 @@ export function RoleEditMappedUser(props: RoleEditMappedUserProps) {
};
fetchData();
- }, [addToast, props.coreStart.http, props.roleName, dataSource.id]);
+ }, [addToast, props.coreStart.http, props.roleName, dataSource]);
React.useEffect(() => {
const fetchInternalUserNames = async () => {
@@ -101,7 +101,7 @@ export function RoleEditMappedUser(props: RoleEditMappedUserProps) {
};
fetchInternalUserNames();
- }, [addToast, props.coreStart.http, dataSource.id]);
+ }, [addToast, props.coreStart.http, dataSource]);
const internalUserOptions = userNames.map(stringToComboBoxOption);
const updateRoleMappingHandler = async () => {
diff --git a/public/apps/configuration/panels/role-view/role-view.tsx b/public/apps/configuration/panels/role-view/role-view.tsx
index caac1bfd7..0b29c3469 100644
--- a/public/apps/configuration/panels/role-view/role-view.tsx
+++ b/public/apps/configuration/panels/role-view/role-view.tsx
@@ -147,7 +147,7 @@ export function RoleView(props: RoleViewProps) {
};
fetchData();
- }, [addToast, props.coreStart.http, props.roleName, props.prevAction, dataSource.id]);
+ }, [addToast, props.coreStart.http, props.roleName, props.prevAction, dataSource]);
const handleRoleMappingDelete = async () => {
try {
diff --git a/public/apps/configuration/panels/tenant-list/test/__snapshots__/tenant-list.test.tsx.snap b/public/apps/configuration/panels/tenant-list/test/__snapshots__/tenant-list.test.tsx.snap
index c817212aa..47f814978 100644
--- a/public/apps/configuration/panels/tenant-list/test/__snapshots__/tenant-list.test.tsx.snap
+++ b/public/apps/configuration/panels/tenant-list/test/__snapshots__/tenant-list.test.tsx.snap
@@ -138,7 +138,7 @@ exports[`Tenant list Action menu click Duplicate click 1`] = `
},
]
}
- error="Load data failed, please check console log for more detail."
+ error=""
itemId="tenant"
items={
Array [
@@ -326,7 +326,7 @@ exports[`Tenant list Action menu click Edit click 1`] = `
},
]
}
- error="Load data failed, please check console log for more detail."
+ error=""
itemId="tenant"
items={
Array [
diff --git a/public/apps/configuration/panels/tenant-list/test/tenant-list.test.tsx b/public/apps/configuration/panels/tenant-list/test/tenant-list.test.tsx
index fa72caf09..0805d51d5 100644
--- a/public/apps/configuration/panels/tenant-list/test/tenant-list.test.tsx
+++ b/public/apps/configuration/panels/tenant-list/test/tenant-list.test.tsx
@@ -75,12 +75,7 @@ describe('Tenant list', () => {
};
beforeEach(() => {
- // jest.spyOn(React, 'useState').mockImplementation((initialValue) => [initialValue, setState]);
- jest.spyOn(React, 'useState').mockRestore();
- jest
- .spyOn(React, 'useState')
- .mockImplementationOnce(() => [false, jest.fn()])
- .mockImplementationOnce(() => ['', jest.fn()]);
+ jest.spyOn(React, 'useState').mockImplementation((initialValue) => [initialValue, setState]);
});
it('Render empty', () => {
@@ -272,7 +267,21 @@ describe('Tenant list', () => {
};
it('edit and delete should be disabled when selected tenant is reserved', () => {
- jest.spyOn(React, 'useState').mockImplementation(() => [[sampleReservedTenant], jest.fn()]);
+ jest.spyOn(React, 'useState').mockRestore();
+ jest
+ .spyOn(React, 'useState')
+ .mockImplementationOnce(() => [[sampleReservedTenant], jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()])
+ .mockImplementationOnce(() => [[sampleReservedTenant], jest.fn()])
+ .mockImplementationOnce(() => ['', jest.fn()])
+ .mockImplementationOnce(() => ['', jest.fn()])
+ .mockImplementationOnce(() => [null, jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()])
+ .mockImplementationOnce(() => [null, jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()])
+ .mockImplementationOnce(() => ['', jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()]);
const component = shallow(
{
});
it('All menues should be disabled when there is multiple tenant selected including reserved tenant', () => {
+ jest.spyOn(React, 'useState').mockRestore();
jest
.spyOn(React, 'useState')
- .mockImplementation(() => [[sampleReservedTenant, sampleCustomTenant1], jest.fn()]);
+ .mockImplementationOnce(() => [[sampleReservedTenant, sampleCustomTenant1], jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()])
+ .mockImplementationOnce(() => [[sampleReservedTenant, sampleReservedTenant], jest.fn()])
+ .mockImplementationOnce(() => ['', jest.fn()])
+ .mockImplementationOnce(() => ['', jest.fn()])
+ .mockImplementationOnce(() => [null, jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()])
+ .mockImplementationOnce(() => [null, jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()])
+ .mockImplementationOnce(() => ['', jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()]);
const component = shallow(
{
expect(component.find('#delete').prop('disabled')).toBe(true);
});
- it('All menues should be disabled except delete when there is multiple custom tenant selected', () => {
+ it('All menus should be disabled except delete when there is multiple custom tenant selected', () => {
+ jest.spyOn(React, 'useState').mockRestore();
jest
.spyOn(React, 'useState')
- .mockImplementation(() => [[sampleCustomTenant1, sampleCustomTenant2], jest.fn()]);
+ .mockImplementationOnce(() => [[sampleCustomTenant1, sampleCustomTenant2], jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()])
+ .mockImplementationOnce(() => [[sampleCustomTenant1, sampleCustomTenant2], jest.fn()])
+ .mockImplementationOnce(() => ['', jest.fn()])
+ .mockImplementationOnce(() => ['', jest.fn()])
+ .mockImplementationOnce(() => [null, jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()])
+ .mockImplementationOnce(() => [null, jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()])
+ .mockImplementationOnce(() => ['', jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()]);
const component = shallow(
{
};
beforeEach(() => {
- // jest.spyOn(React, 'useState').mockImplementation(() => [[sampleCustomTenant1], jest.fn()]);
jest.spyOn(React, 'useState').mockRestore();
jest
.spyOn(React, 'useState')
@@ -370,11 +402,41 @@ describe('Tenant list', () => {
});
it('Edit click', () => {
+ jest.spyOn(React, 'useState').mockRestore();
+ jest
+ .spyOn(React, 'useState')
+ .mockImplementationOnce(() => [[sampleCustomTenant1], jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()])
+ .mockImplementationOnce(() => [[sampleCustomTenant1], jest.fn()])
+ .mockImplementationOnce(() => ['', jest.fn()])
+ .mockImplementationOnce(() => ['', jest.fn()])
+ .mockImplementationOnce(() => [null, jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()])
+ .mockImplementationOnce(() => [null, jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()])
+ .mockImplementationOnce(() => ['', jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()]);
component.find('#edit').simulate('click');
expect(component).toMatchSnapshot();
});
it('Duplicate click', () => {
+ jest.spyOn(React, 'useState').mockRestore();
+ jest
+ .spyOn(React, 'useState')
+ .mockImplementationOnce(() => [[sampleCustomTenant1], jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()])
+ .mockImplementationOnce(() => [[sampleCustomTenant1], jest.fn()])
+ .mockImplementationOnce(() => ['', jest.fn()])
+ .mockImplementationOnce(() => ['', jest.fn()])
+ .mockImplementationOnce(() => [null, jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()])
+ .mockImplementationOnce(() => [null, jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()])
+ .mockImplementationOnce(() => ['', jest.fn()])
+ .mockImplementationOnce(() => [false, jest.fn()]);
component.find('#duplicate').simulate('click');
expect(component).toMatchSnapshot();
});
diff --git a/public/apps/configuration/panels/user-list.tsx b/public/apps/configuration/panels/user-list.tsx
index cf3f6c832..636edb0fd 100644
--- a/public/apps/configuration/panels/user-list.tsx
+++ b/public/apps/configuration/panels/user-list.tsx
@@ -129,7 +129,7 @@ export function UserList(props: AppDependencies) {
};
fetchData();
- }, [props.coreStart.http, dataSource.id]);
+ }, [props.coreStart.http, dataSource]);
const handleDelete = async () => {
const usersToDelete: string[] = selection.map((r) => r.username);
diff --git a/public/apps/configuration/top-nav-menu.tsx b/public/apps/configuration/top-nav-menu.tsx
index 669a6d805..5e5e51893 100644
--- a/public/apps/configuration/top-nav-menu.tsx
+++ b/public/apps/configuration/top-nav-menu.tsx
@@ -54,14 +54,21 @@ export const SecurityPluginTopNavMenu = React.memo(
savedObjects: coreStart.savedObjects.client,
notifications: coreStart.notifications,
activeOption:
- selectedDataSource.id || selectedDataSource.label ? [selectedDataSource] : undefined,
+ selectedDataSource && (selectedDataSource.id || selectedDataSource.label)
+ ? [selectedDataSource]
+ : undefined,
onSelectedDataSources: wrapSetDataSourceWithUpdateUrl,
fullWidth: true,
}}
/>
) : null;
},
- (prevProps, newProps) =>
- prevProps.selectedDataSource.id === newProps.selectedDataSource.id &&
- prevProps.dataSourcePickerReadOnly === newProps.dataSourcePickerReadOnly
+ (prevProps, newProps) => {
+ return (
+ prevProps.selectedDataSource &&
+ newProps.selectedDataSource &&
+ prevProps.selectedDataSource.id === newProps.selectedDataSource.id &&
+ prevProps.dataSourcePickerReadOnly === newProps.dataSourcePickerReadOnly
+ );
+ }
);