diff --git a/frontend/context/policy.tsx b/frontend/context/policy.tsx index fcb96f6344..eae335dd0e 100644 --- a/frontend/context/policy.tsx +++ b/frontend/context/policy.tsx @@ -11,34 +11,44 @@ type Props = { }; type InitialStateType = { - selectedOsqueryTable: IOsqueryTable; lastEditedQueryName: string; lastEditedQueryDescription: string; lastEditedQueryBody: string; setLastEditedQueryName: (value: string) => void; setLastEditedQueryDescription: (value: string) => void; setLastEditedQueryBody: (value: string) => void; + policyTeamId: number; + setPolicyTeamId: (id: number) => void; + selectedOsqueryTable: IOsqueryTable; setSelectedOsqueryTable: (tableName: string) => void; }; const initialState = { - selectedOsqueryTable: find(osqueryTables, { name: "users" }), lastEditedQueryName: DEFAULT_POLICY.name, lastEditedQueryDescription: DEFAULT_POLICY.description, lastEditedQueryBody: DEFAULT_POLICY.query, setLastEditedQueryName: () => null, setLastEditedQueryDescription: () => null, setLastEditedQueryBody: () => null, + policyTeamId: 0, + setPolicyTeamId: () => null, + selectedOsqueryTable: find(osqueryTables, { name: "users" }), setSelectedOsqueryTable: () => null, }; const actions = { - SET_SELECTED_OSQUERY_TABLE: "SET_SELECTED_OSQUERY_TABLE", SET_LAST_EDITED_QUERY_INFO: "SET_LAST_EDITED_QUERY_INFO", + SET_POLICY_TEAM_ID: "SET_POLICY_TEAM_ID", + SET_SELECTED_OSQUERY_TABLE: "SET_SELECTED_OSQUERY_TABLE", }; const reducer = (state: any, action: any) => { switch (action.type) { + case actions.SET_POLICY_TEAM_ID: + return { + ...state, + policyTeamId: action.id, + }; case actions.SET_SELECTED_OSQUERY_TABLE: return { ...state, @@ -71,7 +81,6 @@ const PolicyProvider = ({ children }: Props) => { const [state, dispatch] = useReducer(reducer, initialState); const value = { - selectedOsqueryTable: state.selectedOsqueryTable, lastEditedQueryName: state.lastEditedQueryName, lastEditedQueryDescription: state.lastEditedQueryDescription, lastEditedQueryBody: state.lastEditedQueryBody, @@ -93,6 +102,11 @@ const PolicyProvider = ({ children }: Props) => { lastEditedQueryBody, }); }, + policyTeamId: state.policyTeamId, + setPolicyTeamId: (id: number) => { + dispatch({ type: actions.SET_POLICY_TEAM_ID, id }); + }, + selectedOsqueryTable: state.selectedOsqueryTable, setSelectedOsqueryTable: (tableName: string) => { dispatch({ type: actions.SET_SELECTED_OSQUERY_TABLE, tableName }); }, diff --git a/frontend/interfaces/policy.ts b/frontend/interfaces/policy.ts index d302cf3923..229a1b4db8 100644 --- a/frontend/interfaces/policy.ts +++ b/frontend/interfaces/policy.ts @@ -16,4 +16,5 @@ export interface IPolicyFormData { description?: string | number | boolean | any[] | undefined; name?: string | number | boolean | any[] | undefined; query?: string | number | boolean | any[] | undefined; + team_id?: number; } diff --git a/frontend/pages/policies/ManagePoliciesPage/ManagePoliciesPage.tsx b/frontend/pages/policies/ManagePoliciesPage/ManagePoliciesPage.tsx index daf27cfeb8..0f57655ace 100644 --- a/frontend/pages/policies/ManagePoliciesPage/ManagePoliciesPage.tsx +++ b/frontend/pages/policies/ManagePoliciesPage/ManagePoliciesPage.tsx @@ -14,6 +14,7 @@ import { ITeam } from "interfaces/team"; import { IUser } from "interfaces/user"; import { AppContext } from "context/app"; +import { PolicyContext } from "context/policy"; import fleetQueriesAPI from "services/entities/queries"; import globalPoliciesAPI from "services/entities/global_policies"; @@ -67,6 +68,8 @@ const ManagePolicyPage = (managePoliciesPageProps: { isPremiumTier, } = useContext(AppContext); + const { setPolicyTeamId } = useContext(PolicyContext); + const { isTeamMaintainer, isTeamAdmin } = permissionsUtils; const canAddOrRemovePolicy = (user: IUser | null, teamId: number | null) => isGlobalAdmin || @@ -74,12 +77,16 @@ const ManagePolicyPage = (managePoliciesPageProps: { isTeamMaintainer(user, teamId) || isTeamAdmin(user, teamId); - const { data: teams } = useQuery(["teams"], () => teamsAPI.loadAll({}), { - enabled: !!isPremiumTier, - select: (data) => data.teams, - refetchOnMount: false, - refetchOnWindowFocus: false, - }); + const { data: teams } = useQuery<{ teams: ITeam[] }, Error, ITeam[]>( + ["teams"], + () => teamsAPI.loadAll({}), + { + enabled: !!isPremiumTier, + select: (data) => data.teams, + refetchOnMount: false, + refetchOnWindowFocus: false, + } + ); const { data: fleetQueries } = useQuery( ["fleetQueries"], @@ -161,6 +168,7 @@ const ManagePolicyPage = (managePoliciesPageProps: { router.replace(path); setShowInheritedPolicies(false); setSelectedPolicyIds([]); + setPolicyTeamId(id); }; const toggleRemovePoliciesModal = () => diff --git a/frontend/pages/policies/PolicyPage/PolicyPage.tsx b/frontend/pages/policies/PolicyPage/PolicyPage.tsx index 8193f5d5fd..74aab808ca 100644 --- a/frontend/pages/policies/PolicyPage/PolicyPage.tsx +++ b/frontend/pages/policies/PolicyPage/PolicyPage.tsx @@ -8,6 +8,7 @@ import { AppContext } from "context/app"; import { PolicyContext } from "context/policy"; import { QUERIES_PAGE_STEPS, DEFAULT_POLICY } from "utilities/constants"; import globalPoliciesAPI from "services/entities/global_policies"; // @ts-ignore +import teamPoliciesAPI from "services/entities/team_policies"; // @ts-ignore import hostAPI from "services/entities/hosts"; // @ts-ignore import { IPolicyFormData, IPolicy } from "interfaces/policy"; import { ITarget } from "interfaces/target"; @@ -108,7 +109,9 @@ const PolicyPage = ({ const { mutateAsync: createPolicy, } = useMutation((formData: IPolicyFormData) => - globalPoliciesAPI.create(formData) + formData.team_id + ? teamPoliciesAPI.create(formData) + : globalPoliciesAPI.create(formData) ); useEffect(() => { diff --git a/frontend/pages/policies/PolicyPage/components/NewPolicyModal/NewPolicyModal.tsx b/frontend/pages/policies/PolicyPage/components/NewPolicyModal/NewPolicyModal.tsx index 437be91958..aee963cdcc 100644 --- a/frontend/pages/policies/PolicyPage/components/NewPolicyModal/NewPolicyModal.tsx +++ b/frontend/pages/policies/PolicyPage/components/NewPolicyModal/NewPolicyModal.tsx @@ -13,11 +13,11 @@ export interface INewPolicyModalProps { baseClass: string; queryValue: string; onCreatePolicy: (formData: IPolicyFormData) => void; - setIsSaveModalOpen: (isOpen: boolean) => void; + setIsNewPolicyModalOpen: (isOpen: boolean) => void; } const validatePolicyName = (name: string) => { - const errors: { [key: string]: any } = {}; + const errors: { [key: string]: string } = {}; if (!name) { errors.name = "Policy name must be present"; @@ -31,11 +31,11 @@ const NewPolicyModal = ({ baseClass, queryValue, onCreatePolicy, - setIsSaveModalOpen, -}: INewPolicyModalProps) => { + setIsNewPolicyModalOpen, +}: INewPolicyModalProps): JSX.Element => { const [name, setName] = useState(""); const [description, setDescription] = useState(""); - const [errors, setErrors] = useState<{ [key: string]: any }>({}); + const [errors, setErrors] = useState<{ [key: string]: string }>({}); useDeepEffect(() => { if (name) { @@ -43,7 +43,7 @@ const NewPolicyModal = ({ } }, [name]); - const handleUpdate = (evt: React.MouseEvent) => { + const handleSavePolicy = (evt: React.MouseEvent) => { evt.preventDefault(); const { valid, errors: newErrors } = validatePolicyName(name); @@ -59,12 +59,12 @@ const NewPolicyModal = ({ query: queryValue, }); - setIsSaveModalOpen(false); + setIsNewPolicyModalOpen(false); } }; return ( - setIsSaveModalOpen(false)}> + setIsNewPolicyModalOpen(false)}>
diff --git a/frontend/pages/policies/PolicyPage/components/PolicyForm/PolicyForm.tsx b/frontend/pages/policies/PolicyPage/components/PolicyForm/PolicyForm.tsx index 44ae34eadb..0abf5438d7 100644 --- a/frontend/pages/policies/PolicyPage/components/PolicyForm/PolicyForm.tsx +++ b/frontend/pages/policies/PolicyPage/components/PolicyForm/PolicyForm.tsx @@ -16,7 +16,6 @@ import Avatar from "components/Avatar"; import FleetAce from "components/FleetAce"; // @ts-ignore import validateQuery from "components/forms/validators/validate_query"; import Button from "components/buttons/Button"; -import Checkbox from "components/forms/fields/Checkbox"; import Spinner from "components/Spinner"; // @ts-ignore import InputField from "components/forms/fields/InputField"; import NewPolicyModal from "../NewPolicyModal"; @@ -42,7 +41,7 @@ interface IPolicyFormProps { } const validateQuerySQL = (query: string) => { - const errors: { [key: string]: any } = {}; + const errors: { [key: string]: string } = {}; const { error: queryError, valid: queryValid } = validateQuery(query); if (!queryValid) { @@ -66,8 +65,10 @@ const PolicyForm = ({ renderLiveQueryWarning, }: IPolicyFormProps): JSX.Element => { const isEditMode = !!policyIdForEdit; - const [errors, setErrors] = useState<{ [key: string]: any }>({}); - const [isSaveModalOpen, setIsSaveModalOpen] = useState(false); + const [errors, setErrors] = useState<{ [key: string]: string }>({}); + const [isNewPolicyModalOpen, setIsNewPolicyModalOpen] = useState( + false + ); const [showQueryEditor, setShowQueryEditor] = useState(false); const [compatiblePlatforms, setCompatiblePlatforms] = useState([]); const [isEditingName, setIsEditingName] = useState(false); @@ -135,7 +136,7 @@ const PolicyForm = ({ }); }; - const promptSaveQuery = (forceNew = false) => ( + const handleSavePolicy = (forceNew = false) => ( evt: React.MouseEvent ) => { evt.preventDefault(); @@ -160,7 +161,7 @@ const PolicyForm = ({ if (valid) { if (!isEditMode || forceNew) { - setIsSaveModalOpen(true); + setIsNewPolicyModalOpen(true); } else { onUpdate({ name: lastEditedQueryName, @@ -174,6 +175,8 @@ const PolicyForm = ({ setIsEditingName(false); setIsEditingDescription(false); } + + return null; }; const renderAuthor = (): JSX.Element | null => { @@ -221,6 +224,8 @@ const PolicyForm = ({ } else if (compatiblePlatforms[0] === "None") { return "No platforms (check your query for invalid tables or tables that are supported on different platforms)"; } + + return null; }; const displayFormattedPlatforms = compatiblePlatforms.map((string) => { @@ -422,7 +427,7 @@ const PolicyForm = ({ onChange={(sqlString: string) => { setLastEditedQueryBody(sqlString); }} - handleSubmit={promptSaveQuery} + handleSubmit={handleSavePolicy} /> {renderPlatformCompatibility()} {renderLiveQueryWarning()} @@ -444,7 +449,7 @@ const PolicyForm = ({