Fix policy automation activities missing from host activity feed
Closes #48616 Adds missing policy automation activities to host's details page.
This commit is contained in:
@@ -228,7 +228,15 @@ export type IHostPastActivityType =
|
||||
| ActivityType.RotatedManagedLocalAccountPassword
|
||||
| ActivityType.FailedToRotateManagedLocalAccountPassword
|
||||
| ActivityType.FailedEnrollmentProfileRenewal
|
||||
| ActivityType.RanCustomMdmCommand;
|
||||
| ActivityType.RanCustomMdmCommand
|
||||
| ActivityType.RanAutomationWebhook
|
||||
| ActivityType.RanAutomationTicket
|
||||
| ActivityType.RanAutomationCalendarEvent
|
||||
| ActivityType.RanAutomationConditionalAccess
|
||||
| ActivityType.FailedAutomationWebhook
|
||||
| ActivityType.FailedAutomationTicket
|
||||
| ActivityType.FailedAutomationCalendarEvent
|
||||
| ActivityType.FailedAutomationConditionalAccess;
|
||||
|
||||
/** This is a subset of ActivityType that are shown only for the host upcoming activities */
|
||||
export type IHostUpcomingActivityType =
|
||||
|
||||
@@ -36,6 +36,7 @@ import FailedToRotateManagedLocalAccountPasswordActivityItem from "./ActivityIte
|
||||
import FailedEnrollmentProfileRenewalActivityItem from "./ActivityItems/FailedEnrollmentProfileRenewalActivityItem";
|
||||
import MdmUnenrolledActivityItem from "./ActivityItems/MdmUnenrolledActivityItem";
|
||||
import RanCustomMdmCommandActivityItem from "./ActivityItems/RanCustomMdmCommandActivityItem";
|
||||
import PolicyAutomationActivityItem from "./ActivityItems/PolicyAutomationActivityItem";
|
||||
|
||||
/** The component props that all host activity items must adhere to */
|
||||
export interface IHostActivityItemComponentProps {
|
||||
@@ -92,6 +93,14 @@ export const pastActivityComponentMap: Record<
|
||||
[ActivityType.FailedEnrollmentProfileRenewal]: FailedEnrollmentProfileRenewalActivityItem,
|
||||
[ActivityType.MdmUnenrolled]: MdmUnenrolledActivityItem,
|
||||
[ActivityType.RanCustomMdmCommand]: RanCustomMdmCommandActivityItem,
|
||||
[ActivityType.RanAutomationWebhook]: PolicyAutomationActivityItem,
|
||||
[ActivityType.RanAutomationTicket]: PolicyAutomationActivityItem,
|
||||
[ActivityType.RanAutomationCalendarEvent]: PolicyAutomationActivityItem,
|
||||
[ActivityType.RanAutomationConditionalAccess]: PolicyAutomationActivityItem,
|
||||
[ActivityType.FailedAutomationWebhook]: PolicyAutomationActivityItem,
|
||||
[ActivityType.FailedAutomationTicket]: PolicyAutomationActivityItem,
|
||||
[ActivityType.FailedAutomationCalendarEvent]: PolicyAutomationActivityItem,
|
||||
[ActivityType.FailedAutomationConditionalAccess]: PolicyAutomationActivityItem,
|
||||
};
|
||||
|
||||
export const upcomingActivityComponentMap: Record<
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
import React from "react";
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { createMockHostPastActivity } from "__mocks__/activityMock";
|
||||
|
||||
import { ActivityType, IHostPastActivityType } from "interfaces/activity";
|
||||
|
||||
import PolicyAutomationActivityItem from "./PolicyAutomationActivityItem";
|
||||
|
||||
const renderItem = (type: IHostPastActivityType) =>
|
||||
render(
|
||||
<PolicyAutomationActivityItem
|
||||
activity={createMockHostPastActivity({
|
||||
type,
|
||||
actor_full_name: "",
|
||||
actor_id: 0,
|
||||
fleet_initiated: true,
|
||||
details: {},
|
||||
})}
|
||||
tab="past"
|
||||
/>
|
||||
);
|
||||
|
||||
describe("PolicyAutomationActivityItem", () => {
|
||||
const cases: Array<[IHostPastActivityType, RegExp]> = [
|
||||
[ActivityType.RanAutomationWebhook, /sent a webhook because this host/i],
|
||||
[ActivityType.RanAutomationTicket, /created a ticket because this host/i],
|
||||
[
|
||||
ActivityType.RanAutomationCalendarEvent,
|
||||
/created a calendar event because this host/i,
|
||||
],
|
||||
[
|
||||
ActivityType.RanAutomationConditionalAccess,
|
||||
/blocked single sign-on because this host/i,
|
||||
],
|
||||
[
|
||||
ActivityType.FailedAutomationWebhook,
|
||||
/failed to send a webhook after this host/i,
|
||||
],
|
||||
[
|
||||
ActivityType.FailedAutomationTicket,
|
||||
/failed to create a ticket after this host/i,
|
||||
],
|
||||
[
|
||||
ActivityType.FailedAutomationCalendarEvent,
|
||||
/failed to create a calendar event after this host/i,
|
||||
],
|
||||
[
|
||||
ActivityType.FailedAutomationConditionalAccess,
|
||||
/failed to block single sign-on after this host/i,
|
||||
],
|
||||
];
|
||||
|
||||
it.each(cases)("renders copy for %s", (type, expected) => {
|
||||
renderItem(type);
|
||||
expect(screen.getByText("Fleet")).toBeVisible();
|
||||
expect(screen.getByText(expected)).toBeVisible();
|
||||
});
|
||||
|
||||
it("does not render the cancel or show-details icons", () => {
|
||||
renderItem(ActivityType.RanAutomationWebhook);
|
||||
expect(screen.queryByTestId("close-icon")).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId("info-outline-icon")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
// These activities are always Fleet-initiated in practice; this documents the
|
||||
// defensive actor branch that keeps the bold name in sync with the avatar.
|
||||
it("renders the actor name when the activity is not Fleet-initiated", () => {
|
||||
render(
|
||||
<PolicyAutomationActivityItem
|
||||
activity={createMockHostPastActivity({
|
||||
type: ActivityType.RanAutomationWebhook,
|
||||
actor_full_name: "Admin User",
|
||||
actor_id: 1,
|
||||
fleet_initiated: false,
|
||||
details: {},
|
||||
})}
|
||||
tab="past"
|
||||
/>
|
||||
);
|
||||
expect(screen.getByText("Admin User")).toBeVisible();
|
||||
expect(screen.queryByText("Fleet")).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
import React from "react";
|
||||
|
||||
import { ActivityType, IHostPastActivityType } from "interfaces/activity";
|
||||
import ActivityItem from "components/ActivityItem";
|
||||
|
||||
import { IHostActivityItemComponentProps } from "../../ActivityConfig";
|
||||
|
||||
const baseClass = "policy-automation-activity-item";
|
||||
|
||||
type PolicyAutomationActivityType =
|
||||
| ActivityType.RanAutomationWebhook
|
||||
| ActivityType.RanAutomationTicket
|
||||
| ActivityType.RanAutomationCalendarEvent
|
||||
| ActivityType.RanAutomationConditionalAccess
|
||||
| ActivityType.FailedAutomationWebhook
|
||||
| ActivityType.FailedAutomationTicket
|
||||
| ActivityType.FailedAutomationCalendarEvent
|
||||
| ActivityType.FailedAutomationConditionalAccess;
|
||||
|
||||
const AUTOMATION_COPY: Record<PolicyAutomationActivityType, string> = {
|
||||
[ActivityType.RanAutomationWebhook]:
|
||||
"sent a webhook because this host failed a policy.",
|
||||
[ActivityType.RanAutomationTicket]:
|
||||
"created a ticket because this host failed a policy.",
|
||||
[ActivityType.RanAutomationCalendarEvent]:
|
||||
"created a calendar event because this host failed a policy.",
|
||||
[ActivityType.RanAutomationConditionalAccess]:
|
||||
"blocked single sign-on because this host failed a policy.",
|
||||
[ActivityType.FailedAutomationWebhook]:
|
||||
"failed to send a webhook after this host failed a policy.",
|
||||
[ActivityType.FailedAutomationTicket]:
|
||||
"failed to create a ticket after this host failed a policy.",
|
||||
[ActivityType.FailedAutomationCalendarEvent]:
|
||||
"failed to create a calendar event after this host failed a policy.",
|
||||
[ActivityType.FailedAutomationConditionalAccess]:
|
||||
"failed to block single sign-on after this host failed a policy.",
|
||||
};
|
||||
|
||||
const isPolicyAutomationActivityType = (
|
||||
type: IHostPastActivityType
|
||||
): type is PolicyAutomationActivityType => type in AUTOMATION_COPY;
|
||||
|
||||
const PolicyAutomationActivityItem = ({
|
||||
activity,
|
||||
isSoloActivity,
|
||||
}: IHostActivityItemComponentProps) => {
|
||||
if (!isPolicyAutomationActivityType(activity.type)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ActivityItem
|
||||
className={baseClass}
|
||||
activity={activity}
|
||||
isSoloActivity={isSoloActivity}
|
||||
hideCancel
|
||||
hideShowDetails
|
||||
>
|
||||
<b>{activity.fleet_initiated ? "Fleet" : activity.actor_full_name}</b>{" "}
|
||||
{AUTOMATION_COPY[activity.type]}
|
||||
</ActivityItem>
|
||||
);
|
||||
};
|
||||
|
||||
export default PolicyAutomationActivityItem;
|
||||
+1
@@ -0,0 +1 @@
|
||||
export { default } from "./PolicyAutomationActivityItem";
|
||||
Reference in New Issue
Block a user