Skip to content

Commit

Permalink
[Synthetic] Show monitors from all permitted spaces !! (#196109)
Browse files Browse the repository at this point in the history
## Summary

Fixes #194760 !!
Fixes #169753 !!

Added an options to list monitors from all spaces which user has
permission for , user can either select default option which is to get
monitors from current space or all permitted spaces !!

### Testing

Create monitors in 3 spaces, assign 2 spaces to a role, and create a
user. Make sure monitors only appears to which user have space
permission.

<img width="1727" alt="image"
src="https://github.com/user-attachments/assets/972d213a-ee00-4950-be9f-a209393cb69a">

---------

Co-authored-by: Justin Kambic <jk@elastic.co>
  • Loading branch information
shahzad31 and justinkambic authored Oct 16, 2024
1 parent 35bc785 commit 2f67874
Show file tree
Hide file tree
Showing 59 changed files with 584 additions and 128 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const FetchMonitorManagementListQueryArgsCodec = t.partial({
schedules: t.array(t.string),
monitorQueryIds: t.array(t.string),
internal: t.boolean,
showFromAllSpaces: t.boolean,
});

export type FetchMonitorManagementListQueryArgs = t.TypeOf<
Expand All @@ -38,6 +39,7 @@ export const FetchMonitorOverviewQueryArgsCodec = t.partial({
monitorQueryIds: t.array(t.string),
sortField: t.string,
sortOrder: t.string,
showFromAllSpaces: t.boolean,
});

export type FetchMonitorOverviewQueryArgs = t.TypeOf<typeof FetchMonitorOverviewQueryArgsCodec>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export const OverviewStatusMetaDataCodec = t.intersection([
updated_at: t.string,
ping: OverviewPingCodec,
timestamp: t.string,
spaceId: t.string,
}),
]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ export const recordVideo = (page: Page, postfix = '') => {
after(async () => {
try {
const videoFilePath = await page.video()?.path();
const pathToVideo = videoFilePath?.replace('.journeys/videos/', '').replace('.webm', '');
const newVideoPath = videoFilePath?.replace(
pathToVideo!,
postfix ? runner.currentJourney!.name + `-${postfix}` : runner.currentJourney!.name
);
const fileName = videoFilePath?.split('/').pop();
const fName = fileName?.split('.').shift();

const name = postfix
? runner.currentJourney!.name + `-${postfix}`
: runner.currentJourney!.name;

const newVideoPath = videoFilePath?.replace(fName!, name);
fs.renameSync(videoFilePath!, newVideoPath!);
} catch (e) {
// eslint-disable-next-line no-console
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ journey(`CustomStatusAlert`, async ({ page, params }) => {

step('should create status rule', async () => {
await page.getByTestId('syntheticsRefreshButtonButton').click();
await page.waitForTimeout(5000);
await page.getByTestId('syntheticsAlertsRulesButton').click();
await page.getByTestId('manageStatusRuleName').click();
await page.getByTestId('createNewStatusRule').click();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

import { syntheticsEditMonitorLocatorID } from '@kbn/observability-plugin/common';

async function navigate({ configId }: { configId: string }) {
async function navigate({ configId, spaceId }: { configId: string; spaceId?: string }) {
return {
app: 'synthetics',
path: `/edit-monitor/${configId}`,
path: `/edit-monitor/${configId}` + (spaceId ? `?spaceId=${spaceId}` : ''),
state: {},
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,24 @@

import { syntheticsMonitorDetailLocatorID } from '@kbn/observability-plugin/common';

async function navigate({ configId, locationId }: { configId: string; locationId?: string }) {
const locationUrlQueryParam = locationId ? `?locationId=${locationId}` : '';
async function navigate({
configId,
locationId,
spaceId,
}: {
configId: string;
locationId?: string;
spaceId?: string;
}) {
let queryParam = locationId ? `?locationId=${locationId}` : '';

if (spaceId) {
queryParam += queryParam ? `&spaceId=${spaceId}` : `?spaceId=${spaceId}`;
}

return {
app: 'synthetics',
path: `/monitor/${configId}${locationUrlQueryParam}`,
path: `/monitor/${configId}${queryParam}`,
state: {},
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,13 @@ describe('AlertingCallout', () => {
const { getByText, queryByText } = render(<AlertingCallout />, {
state: {
dynamicSettings: {
...(shouldShowCallout ? { settings: {} } : {}),
...(shouldShowCallout
? {
settings: {
defaultTLSRuleEnabled: true,
},
}
: {}),
},
defaultAlerting: {
data: {
Expand Down Expand Up @@ -85,7 +91,13 @@ describe('AlertingCallout', () => {
{
state: {
dynamicSettings: {
...(shouldShowCallout ? { settings: {} } : {}),
...(shouldShowCallout
? {
settings: {
defaultTLSRuleEnabled: true,
},
}
: {}),
},
defaultAlerting: {
data: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const AlertingCallout = ({ isAlertingEnabled }: { isAlertingEnabled?: boo
const { settings } = useSelector(selectDynamicSettings);

const hasDefaultConnector = !settings || !isEmpty(settings?.defaultConnectors);
const defaultRuleEnabled = settings?.defaultTLSRuleEnabled || settings?.defaultStatusRuleEnabled;

const { canSave } = useSyntheticsSettingsContext();

Expand All @@ -55,7 +56,7 @@ export const AlertingCallout = ({ isAlertingEnabled }: { isAlertingEnabled?: boo
(monitorsLoaded &&
monitors.some((monitor) => monitor[ConfigKey.ALERT_CONFIG]?.status?.enabled));

const showCallout = !hasDefaultConnector && hasAlertingConfigured;
const showCallout = !hasDefaultConnector && hasAlertingConfigured && defaultRuleEnabled;
const hasDefaultRules =
!rulesLoaded || Boolean(defaultRules?.statusRule && defaultRules?.tlsRule);
const missingRules = !hasDefaultRules && !canSave;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { i18n } from '@kbn/i18n';
import { useDispatch } from 'react-redux';
import { TagsList } from '@kbn/observability-shared-plugin/public';
import { isEmpty } from 'lodash';
import { useKibanaSpace } from '../../../../../hooks/use_kibana_space';
import { PanelWithTitle } from './panel_with_title';
import { MonitorEnabled } from '../../monitors_page/management/monitor_list_table/monitor_enabled';
import { getMonitorAction } from '../../../state';
Expand All @@ -32,6 +33,7 @@ import {
} from '../../../../../../common/runtime_types';
import { MonitorTypeBadge } from './monitor_type_badge';
import { useDateFormat } from '../../../../../hooks/use_date_format';
import { useGetUrlParams } from '../../../hooks';

export interface MonitorDetailsPanelProps {
latestPing?: Ping;
Expand All @@ -53,6 +55,8 @@ export const MonitorDetailsPanel = ({
hasBorder = true,
}: MonitorDetailsPanelProps) => {
const dispatch = useDispatch();
const { space } = useKibanaSpace();
const { spaceId } = useGetUrlParams();

if (!monitor) {
return <EuiSkeletonText lines={8} />;
Expand Down Expand Up @@ -81,7 +85,12 @@ export const MonitorDetailsPanel = ({
configId={configId}
monitor={monitor}
reloadPage={() => {
dispatch(getMonitorAction.get({ monitorId: configId }));
dispatch(
getMonitorAction.get({
monitorId: configId,
...(spaceId && spaceId !== space?.id ? { spaceId } : {}),
})
);
}}
/>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import { useFormContext } from 'react-hook-form';
import { i18n } from '@kbn/i18n';
import { v4 as uuidv4 } from 'uuid';
import { useFetcher } from '@kbn/observability-shared-plugin/public';
import { useKibanaSpace } from '../../../../../hooks/use_kibana_space';
import { TestNowModeFlyout, TestRun } from '../../test_now_mode/test_now_mode_flyout';
import { format } from './formatter';
import { MonitorFields as MonitorFieldsType } from '../../../../../../common/runtime_types';
import { runOnceMonitor } from '../../../state/manual_test_runs/api';
import { useGetUrlParams } from '../../../hooks';

export const RunTestButton = ({
canUsePublicLocations = true,
Expand All @@ -27,6 +29,8 @@ export const RunTestButton = ({

const [inProgress, setInProgress] = useState(false);
const [testRun, setTestRun] = useState<TestRun>();
const { space } = useKibanaSpace();
const { spaceId } = useGetUrlParams();

const handleTestNow = () => {
const config = getValues() as MonitorFieldsType;
Expand All @@ -50,9 +54,10 @@ export const RunTestButton = ({
return runOnceMonitor({
monitor: testRun.monitor,
id: testRun.id,
...(spaceId && spaceId !== space?.id ? { spaceId } : {}),
});
}
}, [testRun?.id, testRun?.monitor]);
}, [space?.id, spaceId, testRun?.id, testRun?.monitor]);

const { tooltipContent, isDisabled } = useTooltipContent(formState.isValid, inProgress);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { useParams, useRouteMatch } from 'react-router-dom';
import React, { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { i18n } from '@kbn/i18n';
import { useGetUrlParams } from '../../../hooks';
import { MONITOR_EDIT_ROUTE } from '../../../../../../common/constants';
import { SyntheticsMonitor } from '../../../../../../common/runtime_types';
import { createMonitorAPI, updateMonitorAPI } from '../../../state/monitor_management/api';
Expand All @@ -22,6 +23,7 @@ export const useMonitorSave = ({ monitorData }: { monitorData?: SyntheticsMonito
const dispatch = useDispatch();
const { refreshApp } = useSyntheticsRefreshContext();
const { monitorId } = useParams<{ monitorId: string }>();
const { spaceId } = useGetUrlParams();

const editRouteMatch = useRouteMatch({ path: MONITOR_EDIT_ROUTE });
const isEdit = editRouteMatch?.isExact;
Expand All @@ -31,6 +33,7 @@ export const useMonitorSave = ({ monitorData }: { monitorData?: SyntheticsMonito
if (isEdit) {
return updateMonitorAPI({
id: monitorId,
spaceId,
monitor: monitorData,
});
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ import { MonitorDetailsLinkPortal } from './monitor_details_portal';
import { useMonitorAddEditBreadcrumbs } from './use_breadcrumbs';
import { EDIT_MONITOR_STEPS } from './steps/step_config';
import { useMonitorNotFound } from './hooks/use_monitor_not_found';
import { useGetUrlParams } from '../../hooks';

export const MonitorEditPage: React.FC = () => {
useTrackPageview({ app: 'synthetics', path: 'edit-monitor' });
useTrackPageview({ app: 'synthetics', path: 'edit-monitor', delay: 15000 });
const { monitorId } = useParams<{ monitorId: string }>();
const { spaceId } = useGetUrlParams();
useMonitorAddEditBreadcrumbs(true);
const dispatch = useDispatch();
const { locationsLoaded, error: locationsError } = useSelector(selectServiceLocationsState);
Expand All @@ -53,8 +55,8 @@ export const MonitorEditPage: React.FC = () => {
const error = useSelector(selectSyntheticsMonitorError);

useEffect(() => {
dispatch(getMonitorAction.get({ monitorId }));
}, [dispatch, monitorId]);
dispatch(getMonitorAction.get({ monitorId, spaceId }));
}, [dispatch, monitorId, spaceId]);

const monitorNotFoundError = useMonitorNotFound(error, data?.id);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import { useEffect, useMemo } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useParams } from 'react-router-dom';
import { useKibanaSpace } from '../../../../../hooks/use_kibana_space';
import { ConfigKey } from '../../../../../../common/runtime_types';
import { useSyntheticsRefreshContext } from '../../../contexts';
import {
Expand All @@ -16,10 +17,13 @@ import {
selectorMonitorDetailsState,
selectorError,
} from '../../../state';
import { useGetUrlParams } from '../../../hooks';

export const useSelectedMonitor = (monId?: string) => {
let monitorId = monId;
const { monitorId: urlMonitorId } = useParams<{ monitorId: string }>();
const { space } = useKibanaSpace();
const { spaceId } = useGetUrlParams();
if (!monitorId) {
monitorId = urlMonitorId;
}
Expand Down Expand Up @@ -53,9 +57,22 @@ export const useSelectedMonitor = (monId?: string) => {

useEffect(() => {
if (monitorId && !availableMonitor && !syntheticsMonitorLoading && !isMonitorMissing) {
dispatch(getMonitorAction.get({ monitorId }));
dispatch(
getMonitorAction.get({
monitorId,
...(spaceId && spaceId !== space?.id ? { spaceId } : {}),
})
);
}
}, [dispatch, monitorId, availableMonitor, syntheticsMonitorLoading, isMonitorMissing]);
}, [
dispatch,
monitorId,
availableMonitor,
syntheticsMonitorLoading,
isMonitorMissing,
spaceId,
space?.id,
]);

useEffect(() => {
// Only perform periodic refresh if the last dispatch was earlier enough
Expand All @@ -66,7 +83,12 @@ export const useSelectedMonitor = (monId?: string) => {
syntheticsMonitorDispatchedAt > 0 &&
Date.now() - syntheticsMonitorDispatchedAt > refreshInterval * 1000
) {
dispatch(getMonitorAction.get({ monitorId }));
dispatch(
getMonitorAction.get({
monitorId,
...(spaceId && spaceId !== space?.id ? { spaceId } : {}),
})
);
}
}, [
dispatch,
Expand All @@ -76,6 +98,8 @@ export const useSelectedMonitor = (monId?: string) => {
monitorListLoading,
syntheticsMonitorLoading,
syntheticsMonitorDispatchedAt,
spaceId,
space?.id,
]);

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import React, { useCallback } from 'react';

import { useParams, useRouteMatch } from 'react-router-dom';
import { useKibana } from '@kbn/kibana-react-plugin/public';
import { useKibanaSpace } from '../../../../hooks/use_kibana_space';
import { useGetUrlParams } from '../../hooks';
import {
MONITOR_ALERTS_ROUTE,
Expand All @@ -34,7 +35,14 @@ export const MonitorDetailsLocation = ({ isDisabled }: { isDisabled?: boolean })
const isHistoryTab = useRouteMatch(MONITOR_HISTORY_ROUTE);
const isAlertsTab = useRouteMatch(MONITOR_ALERTS_ROUTE);

const params = `&dateRangeStart=${dateRangeStart}&dateRangeEnd=${dateRangeEnd}`;
const { space } = useKibanaSpace();
const { spaceId } = useGetUrlParams();

let params = `&dateRangeStart=${dateRangeStart}&dateRangeEnd=${dateRangeEnd}`;

if (spaceId && spaceId !== space?.id) {
params += `&spaceId=${spaceId}`;
}

return (
<MonitorLocationSelect
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,22 @@ import { EuiButton } from '@elastic/eui';
import { useCanEditSynthetics } from '../../../../../hooks/use_capabilities';
import { useSyntheticsSettingsContext } from '../../../contexts';
import { NoPermissionsTooltip } from '../../common/components/permissions';
import { useGetUrlParams } from '../../../hooks';

export const EditMonitorLink = () => {
const { basePath } = useSyntheticsSettingsContext();

const { monitorId } = useParams<{ monitorId: string }>();

const { spaceId } = useGetUrlParams();
const canEditSynthetics = useCanEditSynthetics();
const isLinkDisabled = !canEditSynthetics;
const linkProps = isLinkDisabled
? { disabled: true }
: { href: `${basePath}/app/synthetics/edit-monitor/${monitorId}` };
: {
href:
`${basePath}/app/synthetics/edit-monitor/${monitorId}` +
(spaceId ? `?spaceId=${spaceId}` : ''),
};

return (
<NoPermissionsTooltip canEditSynthetics={canEditSynthetics}>
Expand Down
Loading

0 comments on commit 2f67874

Please sign in to comment.