mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 09:28:54 +00:00
209 lines
6.4 KiB
TypeScript
209 lines
6.4 KiB
TypeScript
import React, { useState, useEffect, useContext, useCallback } from "react";
|
|
import { useQuery } from "react-query";
|
|
import { useErrorHandler } from "react-error-boundary";
|
|
import { InjectedRouter, Params } from "react-router/lib/Router";
|
|
import PATHS from "router/paths";
|
|
import useTeamIdParam from "hooks/useTeamIdParam";
|
|
|
|
import { AppContext } from "context/app";
|
|
import { QueryContext } from "context/query";
|
|
import { LIVE_QUERY_STEPS, DOCUMENT_TITLE_SUFFIX } from "utilities/constants";
|
|
import queryAPI from "services/entities/queries";
|
|
import hostAPI from "services/entities/hosts";
|
|
import { IHost, IHostResponse } from "interfaces/host";
|
|
import { ILabel } from "interfaces/label";
|
|
import { ITeam } from "interfaces/team";
|
|
import {
|
|
IGetQueryResponse,
|
|
ISchedulableQuery,
|
|
} from "interfaces/schedulable_query";
|
|
|
|
import MainContent from "components/MainContent";
|
|
import SelectTargets from "components/LiveQuery/SelectTargets";
|
|
|
|
import RunQuery from "pages/queries/live/screens/RunQuery";
|
|
|
|
interface IRunQueryPageProps {
|
|
router: InjectedRouter;
|
|
params: Params;
|
|
location: {
|
|
pathname: string;
|
|
query: { host_id: string; team_id?: string };
|
|
search: string;
|
|
};
|
|
}
|
|
|
|
const baseClass = "run-query-page";
|
|
|
|
const RunQueryPage = ({
|
|
router,
|
|
params: { id: paramsQueryId },
|
|
location,
|
|
}: IRunQueryPageProps): JSX.Element => {
|
|
const queryId = paramsQueryId ? parseInt(paramsQueryId, 10) : null;
|
|
|
|
const { currentTeamId } = useTeamIdParam({
|
|
location,
|
|
router,
|
|
includeAllTeams: true,
|
|
includeNoTeam: false,
|
|
});
|
|
|
|
const handlePageError = useErrorHandler();
|
|
const { config } = useContext(AppContext);
|
|
const {
|
|
editingExistingQuery,
|
|
selectedQueryTargets,
|
|
setSelectedQueryTargets,
|
|
selectedQueryTargetsByType,
|
|
setSelectedQueryTargetsByType,
|
|
setLastEditedQueryId,
|
|
setLastEditedQueryName,
|
|
setLastEditedQueryDescription,
|
|
setLastEditedQueryBody,
|
|
setLastEditedQueryObserverCanRun,
|
|
setLastEditedQueryFrequency,
|
|
setLastEditedQueryLoggingType,
|
|
setLastEditedQueryMinOsqueryVersion,
|
|
setLastEditedQueryPlatforms,
|
|
} = useContext(QueryContext);
|
|
|
|
const [queryParamHostsAdded, setQueryParamHostsAdded] = useState(false);
|
|
const [step, setStep] = useState(LIVE_QUERY_STEPS[1]);
|
|
const [targetedHosts, setTargetedHosts] = useState<IHost[]>(
|
|
selectedQueryTargetsByType.hosts
|
|
);
|
|
const [targetedLabels, setTargetedLabels] = useState<ILabel[]>(
|
|
selectedQueryTargetsByType.labels
|
|
);
|
|
const [targetedTeams, setTargetedTeams] = useState<ITeam[]>(
|
|
selectedQueryTargetsByType.teams
|
|
);
|
|
const [targetsTotalCount, setTargetsTotalCount] = useState(0);
|
|
|
|
const disabledLiveQuery = config?.server_settings.live_query_disabled;
|
|
|
|
// Reroute users out of live flow when live queries are globally disabled
|
|
if (disabledLiveQuery) {
|
|
queryId
|
|
? router.push(PATHS.QUERY_DETAILS(queryId, currentTeamId))
|
|
: router.push(PATHS.NEW_QUERY(currentTeamId));
|
|
}
|
|
|
|
// disabled on page load so we can control the number of renders
|
|
// else it will re-populate the context on occasion
|
|
const { data: storedQuery } = useQuery<
|
|
IGetQueryResponse,
|
|
Error,
|
|
ISchedulableQuery
|
|
>(["query", queryId], () => queryAPI.load(queryId as number), {
|
|
enabled: !!queryId && !editingExistingQuery,
|
|
refetchOnWindowFocus: false,
|
|
select: (data) => data.query,
|
|
onSuccess: (returnedQuery) => {
|
|
setLastEditedQueryId(returnedQuery.id);
|
|
setLastEditedQueryName(returnedQuery.name);
|
|
setLastEditedQueryDescription(returnedQuery.description);
|
|
setLastEditedQueryBody(returnedQuery.query);
|
|
setLastEditedQueryObserverCanRun(returnedQuery.observer_can_run);
|
|
setLastEditedQueryFrequency(returnedQuery.interval);
|
|
setLastEditedQueryPlatforms(returnedQuery.platform);
|
|
setLastEditedQueryLoggingType(returnedQuery.logging);
|
|
setLastEditedQueryMinOsqueryVersion(returnedQuery.min_osquery_version);
|
|
},
|
|
onError: (error) => handlePageError(error),
|
|
});
|
|
|
|
useQuery<IHostResponse, Error, IHost>(
|
|
"hostFromURL",
|
|
() =>
|
|
hostAPI.loadHostDetails(parseInt(location.query.host_id as string, 10)),
|
|
{
|
|
enabled: !!location.query.host_id && !queryParamHostsAdded,
|
|
select: (data: IHostResponse) => data.host,
|
|
onSuccess: (host) => {
|
|
setTargetedHosts((prevHosts) =>
|
|
prevHosts.filter((h) => h.id !== host.id).concat(host)
|
|
);
|
|
const targets = selectedQueryTargets;
|
|
host.target_type = "hosts";
|
|
targets.push(host);
|
|
setSelectedQueryTargets([...targets]);
|
|
if (!queryParamHostsAdded) {
|
|
setQueryParamHostsAdded(true);
|
|
}
|
|
router.replace(location.pathname);
|
|
},
|
|
}
|
|
);
|
|
|
|
useEffect(() => {
|
|
setSelectedQueryTargetsByType({
|
|
hosts: targetedHosts,
|
|
labels: targetedLabels,
|
|
teams: targetedTeams,
|
|
});
|
|
}, [targetedLabels, targetedHosts, targetedTeams]);
|
|
|
|
// Updates title that shows up on browser tabs
|
|
useEffect(() => {
|
|
// e.g., Run Discover TLS certificates | Queries | Fleet
|
|
if (storedQuery?.name) {
|
|
document.title = `Run ${storedQuery.name} | Queries | ${DOCUMENT_TITLE_SUFFIX}`;
|
|
} else {
|
|
document.title = `Queries | ${DOCUMENT_TITLE_SUFFIX}`;
|
|
}
|
|
}, [location.pathname, storedQuery?.name]);
|
|
|
|
const goToQueryEditor = useCallback(
|
|
() =>
|
|
queryId
|
|
? router.push(PATHS.EDIT_QUERY(queryId, currentTeamId))
|
|
: router.push(PATHS.NEW_QUERY(currentTeamId)),
|
|
[]
|
|
);
|
|
|
|
const renderScreen = () => {
|
|
const step1Props = {
|
|
baseClass,
|
|
queryId,
|
|
selectedTargets: selectedQueryTargets,
|
|
targetedHosts,
|
|
targetedLabels,
|
|
targetedTeams,
|
|
targetsTotalCount,
|
|
goToQueryEditor,
|
|
goToRunQuery: () => setStep(LIVE_QUERY_STEPS[2]),
|
|
setSelectedTargets: setSelectedQueryTargets,
|
|
setTargetedHosts,
|
|
setTargetedLabels,
|
|
setTargetedTeams,
|
|
setTargetsTotalCount,
|
|
isObserverCanRunQuery: storedQuery?.observer_can_run,
|
|
};
|
|
|
|
const step2Props = {
|
|
queryId,
|
|
selectedTargets: selectedQueryTargets,
|
|
storedQuery,
|
|
setSelectedTargets: setSelectedQueryTargets,
|
|
goToQueryEditor,
|
|
targetsTotalCount,
|
|
};
|
|
|
|
switch (step) {
|
|
case LIVE_QUERY_STEPS[2]:
|
|
return <RunQuery {...step2Props} />;
|
|
default:
|
|
return <SelectTargets {...step1Props} />;
|
|
}
|
|
};
|
|
|
|
return (
|
|
<MainContent className={baseClass}>
|
|
<div className={`${baseClass}_wrapper`}>{renderScreen()}</div>
|
|
</MainContent>
|
|
);
|
|
};
|
|
|
|
export default RunQueryPage;
|