diff --git a/frontend/pages/hosts/ManageHostsPage/helpers.ts b/frontend/pages/hosts/ManageHostsPage/helpers.ts index 59d6b96189..d312e937f7 100644 --- a/frontend/pages/hosts/ManageHostsPage/helpers.ts +++ b/frontend/pages/hosts/ManageHostsPage/helpers.ts @@ -24,7 +24,7 @@ export const isValidPemCertificate = (cert: string): boolean => { return regexPemHeader.test(cert) && regexPemFooter.test(cert); }; -const hasStatusKey = (value: unknown): value is { status: number } => { +export const hasStatusKey = (value: unknown): value is { status: number } => { return ( typeof value === "object" && value !== null && diff --git a/frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx b/frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx index 912dcaeb6d..e9a921cdf4 100644 --- a/frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx +++ b/frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx @@ -33,7 +33,7 @@ import { IHostPolicy } from "interfaces/policy"; import { IQueryStats } from "interfaces/query_stats"; import { IHostSoftware } from "interfaces/software"; import { ITeam } from "interfaces/team"; -import { IHostUpcomingActivity } from "interfaces/activity"; +import { ActivityType, IHostUpcomingActivity } from "interfaces/activity"; import { IHostCertificate, CERTIFICATES_DEFAULT_SORT, @@ -163,6 +163,7 @@ const HostDetailsPage = ({ config, currentUser, isGlobalAdmin = false, + isGlobalMaintainer, isGlobalObserver, isPremiumTier = false, isOnlyObserver, @@ -836,6 +837,12 @@ const HostDetailsPage = ({ router.push(navPath); }; + const isHostTeamAdmin = permissions.isTeamAdmin(currentUser, host?.team_id); + const isHostTeamMaintainer = permissions.isTeamMaintainer( + currentUser, + host?.team_id + ); + /* Context team id might be different that host's team id Observer plus must be checked against host's team id */ const isGlobalOrHostsTeamObserverPlus = @@ -969,6 +976,12 @@ const HostDetailsPage = ({ ? pastActivitiesIsError : upcomingActivitiesIsError } + canCancelActivities={ + isGlobalAdmin || + isGlobalMaintainer || + isHostTeamAdmin || + isHostTeamMaintainer + } upcomingCount={upcomingActivities?.count || 0} onChangeTab={onChangeActivityTab} onNextPage={() => setActivityPage(activityPage + 1)} @@ -1204,6 +1217,16 @@ const HostDetailsPage = ({ hostId={host.id} activity={selectedCancelActivity} onCancelActivity={() => refetchUpcomingActivities()} + onSuccessCancel={(activity) => { + // only for windows and linux hosts we want to refetch host details + if ( + (activity.type === ActivityType.RanScript && + host.platform === "windows") || + host.platform === "linux" + ) { + refetchHostDetails(); + } + }} onExit={() => setSelectedCancelActivity(null)} /> )} diff --git a/frontend/pages/hosts/details/HostDetailsPage/modals/CancelActivityModal/CancelActivityModal.tsx b/frontend/pages/hosts/details/HostDetailsPage/modals/CancelActivityModal/CancelActivityModal.tsx index c9eae117fd..ed9419e52e 100644 --- a/frontend/pages/hosts/details/HostDetailsPage/modals/CancelActivityModal/CancelActivityModal.tsx +++ b/frontend/pages/hosts/details/HostDetailsPage/modals/CancelActivityModal/CancelActivityModal.tsx @@ -17,7 +17,8 @@ const baseClass = "cancel-activity-modal"; interface ICancelActivityModalProps { hostId: number; activity: IHostUpcomingActivity; - onCancelActivity: () => void; + onCancelActivity: (activity: IHostUpcomingActivity) => void; + onSuccessCancel: (activity: IHostUpcomingActivity) => void; onExit: () => void; } @@ -25,6 +26,7 @@ const CancelActivityModal = ({ hostId, activity, onCancelActivity, + onSuccessCancel, onExit, }: ICancelActivityModalProps) => { const { renderFlash } = useContext(NotificationContext); @@ -37,10 +39,11 @@ const CancelActivityModal = ({ try { await activitiesAPI.cancelHostActivity(hostId, activity.uuid); renderFlash("success", "Activity successfully canceled."); + onSuccessCancel(activity); } catch (err) { renderFlash("error", getErrorMessage(err)); } - onCancelActivity(); + onCancelActivity(activity); onExit(); }; diff --git a/frontend/pages/hosts/details/HostDetailsPage/modals/CancelActivityModal/helpers.ts b/frontend/pages/hosts/details/HostDetailsPage/modals/CancelActivityModal/helpers.ts index d38446e394..5ac4761514 100644 --- a/frontend/pages/hosts/details/HostDetailsPage/modals/CancelActivityModal/helpers.ts +++ b/frontend/pages/hosts/details/HostDetailsPage/modals/CancelActivityModal/helpers.ts @@ -1,4 +1,4 @@ -import { isAxiosError } from "axios"; +import { hasStatusKey } from "pages/hosts/ManageHostsPage/helpers"; const DEFAULT_ERR_MESSAGE = "Couldn't cancel activity. Please try again."; const LOCK_WIPE_ERR_MESSAGE = @@ -8,7 +8,7 @@ const ACTIVITY_ALREADY_HAPPENED_ERR_MESSAGE = // eslint-disable-next-line import/prefer-default-export export const getErrorMessage = (err: unknown) => { - if (isAxiosError(err)) { + if (hasStatusKey(err)) { if (err.status === 404) return ACTIVITY_ALREADY_HAPPENED_ERR_MESSAGE; // display server error message if error is 400 diff --git a/frontend/pages/hosts/details/cards/Activity/Activity.tsx b/frontend/pages/hosts/details/cards/Activity/Activity.tsx index b5963e2696..a35a90891f 100644 --- a/frontend/pages/hosts/details/cards/Activity/Activity.tsx +++ b/frontend/pages/hosts/details/cards/Activity/Activity.tsx @@ -39,6 +39,7 @@ interface IActivityProps { isError?: boolean; className?: string; upcomingCount: number; + canCancelActivities: boolean; onChangeTab: (index: number, last: number, event: Event) => void; onNextPage: () => void; onPreviousPage: () => void; @@ -53,6 +54,7 @@ const Activity = ({ isError, className, upcomingCount, + canCancelActivities, onChangeTab, onNextPage, onPreviousPage, @@ -107,6 +109,7 @@ const Activity = ({ isError={isError} onNextPage={onNextPage} onPreviousPage={onPreviousPage} + canCancelActivities={canCancelActivities} /> diff --git a/frontend/pages/hosts/details/cards/Activity/UpcomingActivityFeed/UpcomingActivityFeed.tsx b/frontend/pages/hosts/details/cards/Activity/UpcomingActivityFeed/UpcomingActivityFeed.tsx index 083b93bbc7..8f0206c46e 100644 --- a/frontend/pages/hosts/details/cards/Activity/UpcomingActivityFeed/UpcomingActivityFeed.tsx +++ b/frontend/pages/hosts/details/cards/Activity/UpcomingActivityFeed/UpcomingActivityFeed.tsx @@ -1,8 +1,7 @@ -import React, { useContext } from "react"; +import React from "react"; import { IHostUpcomingActivity } from "interfaces/activity"; import { IHostUpcomingActivitiesResponse } from "services/entities/activities"; -import { AppContext } from "context/app"; import DataError from "components/DataError"; import Pagination from "components/Pagination"; @@ -16,6 +15,7 @@ const baseClass = "upcoming-activity-feed"; interface IUpcomingActivityFeedProps { activities?: IHostUpcomingActivitiesResponse; isError?: boolean; + canCancelActivities: boolean; onShowDetails: ShowActivityDetailsHandler; onCancel: (activity: IHostUpcomingActivity) => void; onNextPage: () => void; @@ -25,17 +25,12 @@ interface IUpcomingActivityFeedProps { const UpcomingActivityFeed = ({ activities, isError = false, + canCancelActivities, onShowDetails, onCancel, onNextPage, onPreviousPage, }: IUpcomingActivityFeedProps) => { - const { - isTeamMaintainerOrTeamAdmin, - isGlobalAdmin, - isGlobalMaintainer, - } = useContext(AppContext); - if (isError) { return ; } @@ -56,9 +51,6 @@ const UpcomingActivityFeed = ({ ); } - const canCancel = - isGlobalAdmin || isGlobalMaintainer || isTeamMaintainerOrTeamAdmin; - return (
@@ -71,7 +63,7 @@ const UpcomingActivityFeed = ({ tab="upcoming" activity={activity} onShowDetails={onShowDetails} - hideCancel={!canCancel} + hideCancel={!canCancelActivities} onCancel={() => onCancel(activity)} /> );